Как изменить непрозрачность (альфа, прозрачность) элемента в элементе canvas после его отрисовки?

196

Используя <canvas>элемент HTML5 , я хотел бы загрузить файл изображения (PNG, JPEG и т. Д.), Нарисовать его на холсте полностью прозрачно, а затем добавить его. Я выяснил, как загрузить изображение и нарисовать его в холст, но я не знаю, как изменить его непрозрачность, как только он был нарисован.

Вот код, который у меня есть:

var canvas = document.getElementById('myCanvas');

if (canvas.getContext)
{
    var c           = canvas.getContext('2d');
    c.globalAlpha   = 0;

    var img     = new Image();
    img.onload  = function() {
        c.drawImage(img, 0, 0);
    }
    img.src     = 'image.jpg';
}

Кто-нибудь, пожалуйста, укажите мне правильное направление, например, свойство для установки или функция для вызова, которая изменит непрозрачность?

Джо Ленсиони
источник

Ответы:

307

Я также ищу ответ на этот вопрос (чтобы уточнить, я хочу иметь возможность рисовать изображение с заданной пользователем непрозрачностью, например, как вы можете рисовать фигуры с непрозрачностью), если вы рисуете с примитивными фигурами, вы можете установить заливку и обводку цвет с альфа, чтобы определить прозрачность. Насколько я пришел к выводу, это никак не влияет на рисование изображений.

//works with shapes but not with images
ctx.fillStyle = "rgba(255, 255, 255, 0.5)";

Я пришел к выводу, что настройка globalCompositeOperationработает с изображениями.

//works with images
ctx.globalCompositeOperation = "lighter";

Интересно, есть ли какой-то третий способ настройки цвета, чтобы мы могли тонировать изображения и делать их прозрачными.

РЕДАКТИРОВАТЬ:

После дальнейших раскопок я пришел к выводу, что вы можете установить прозрачность изображения, установив globalAlphaпараметр ДО того, как вы нарисуете изображение:

//works with images
ctx.globalAlpha = 0.5

Если вы хотите добиться эффекта затухания с течением времени, вам нужен какой-то цикл, который изменяет значение альфа, это довольно просто, одним из способов достижения этого является setTimeoutфункция, ищите ее, чтобы создать цикл, из которого вы изменяете альфа через время.

djdolber
источник
7
globalAlpha работает отлично. Является частью стандарта: whatwg.org/specs/web-apps/current-work/multipage/…
Aleris
42
Чтобы быть точным, это не canvasэлемент, который имеет globalAlphaсвойство, а контекст, который вы получаете из холста.
Стив Блэквелл
8
Приведенный ниже комментарий Яна о ctx.save () и ctx.restore () предотвращает влияние globalAlpha на остальную часть холста.
Аросборо
1
Мне кажется, что вместо того, чтобы контролировать непрозрачность того, что нарисовано на холсте, это было бы проще и все еще служило бы цели просто контролировать непрозрачность всего холста после того, как изображение нарисовано (только один раз). Для этого используйте обычные методы CSS / style (canvaselement.style.opacity = '0.3' и т. Д.) Позже с помощью CSS3 вы даже можете вообще отказаться от цикла и просто позволить браузеру вместо этого обрабатывать замирание (что-то вроде - transition: NNNms непрозрачность, легкость входа-выхода) или даже "оживление" угасания.
Чак Колларс
1
К сожалению, canvas2d.fillStyle = "rgba(255, 255, 255, 0.5)";не работает. Значение должно быть в шестнадцатеричном виде.
WebWanderer
113

Несколько простых примеров кода для использования globalAlpha:

ctx.save();
ctx.globalAlpha = 0.4;
ctx.drawImage(img, x, y);
ctx.restore();

Если вам нужно imgзагрузить:

var img = new Image();
img.onload = function() {
    ctx.save();
    ctx.globalAlpha = 0.4;
    ctx.drawImage(img, x, y);
    ctx.restore()
};
img.src = "http://...";

Ноты:

  • Установите 'src'последнее, чтобы гарантировать, что ваш onloadобработчик вызывается на всех платформах, даже если изображение уже находится в кэше.

  • Оберните изменения в такие вещи, как globalAlphaмежду a saveи restore(на самом деле используйте их много), чтобы убедиться, что вы не забьете настройки из другого места, особенно когда биты кода рисования будут вызываться из событий.

Ян
источник
globalAlpha будет размыть все изображения или рисунки на холсте, это не то, что вы хотите.
Сердитый
6
@ Сердитый - нет, globalAlphaничего не стирает . Он установит альфа для всего последующего рисования (он не меняет ничего уже нарисованного), поэтому в коде примера я обертываю его saveи restoreограничиваю то, к чему он применяется.
Ян
не уверен, что ctx.restore () восстановит globalAlpha, возможно, вам также понадобится это сделать в конце (по крайней мере, в предыдущих версиях Chrome) ctx.globalAlpha = 1;
Шон
1
@Sean - Если вы не уверены, вы должны проверить. Должно быть, это был очень старый Chrome, теперь он работает на всех платформах: jsfiddle.net/y0z9h9m7
Ян
14

Редактировать: Ответ, помеченный как «правильный», не является правильным.

Это легко сделать. Попробуйте этот код, поменяв местами «ie.jpg» с любым изображением, которое у вас есть под рукой:

<!DOCTYPE HTML>
<html>
    <head>
        <script>
            var canvas;
            var context;
            var ga = 0.0;
            var timerId = 0;

            function init()
            {
                canvas = document.getElementById("myCanvas");
                context = canvas.getContext("2d");
                timerId = setInterval("fadeIn()", 100);
            }

            function fadeIn()
            {
                context.clearRect(0,0, canvas.width,canvas.height);
                context.globalAlpha = ga;
                var ie = new Image();
                ie.onload = function()
                {
                    context.drawImage(ie, 0, 0, 100, 100);
                };
                ie.src = "ie.jpg";

                ga = ga + 0.1;
                if (ga > 1.0)
                {
                    goingUp = false;
                    clearInterval(timerId);
                }
            }
        </script>
    </head>
    <body onload="init()">
        <canvas height="200" width="300" id="myCanvas"></canvas>
    </body>
</html>

Ключ - это свойство globalAlpha.

Протестировано с IE 9, FF 5, Safari 5 и Chrome 12 на Win7.

james.garriss
источник
13

Пост старый, пока я пойду с моим предложением. Предложение основано на манипулировании пикселями в контексте Canvas 2D. От MDN:

Вы можете напрямую манипулировать данными пикселей в холстах на уровне байтов.

Для управления пикселями мы будем использовать две функции: getImageData и putImageData

Использование функции getImageData:

var myImageData = context.getImageData (left, top, width, height);

и синтаксис putImageData:

context.putImageData (myImageData, dx, dy); // dx, dy - x и y смещение на вашем холсте

Где контекст - это ваш холст 2d контекст

Таким образом, чтобы получить значения красного, зеленого, синего и альфа, мы сделаем следующее:

var r = imageData.data[((x*(imageData.width*4)) + (y*4))];
var g = imageData.data[((x*(imageData.width*4)) + (y*4)) + 1];
var b = imageData.data[((x*(imageData.width*4)) + (y*4)) + 2];
var a = imageData.data[((x*(imageData.width*4)) + (y*4)) + 3];

Где x - смещение по x, y - смещение по y на холсте

Таким образом, у нас есть код, делающий изображение полупрозрачным

var canvas = document.getElementById('myCanvas');
var c = canvas.getContext('2d');
var img = new Image();
img.onload  = function() {
   c.drawImage(img, 0, 0);
   var ImageData = c.getImageData(0,0,img.width,img.height);
   for(var i=0;i<img.height;i++)
      for(var j=0;j<img.width;j++)
         ImageData.data[((i*(img.width*4)) + (j*4) + 3)] = 127;//opacity = 0.5 [0-255]
   c.putImageData(ImageData,0,0);//put image data back
}
img.src = 'image.jpg';

Вы можете сделать свои собственные "шейдеры" - см. Полную статью MDN здесь

Добродушный человек
источник
7

Ты можешь. Прозрачный холст можно быстро убрать, используя глобальную составную операцию назначения-выхода . Он не идеален на 100%, иногда оставляет некоторые следы, но его можно настроить, в зависимости от того, что необходимо (например, используйте «источник поверх» и залейте его белым цветом с альфа-каналом в 0,13, затем потушите, чтобы подготовить холст).

// Fill canvas using 'destination-out' and alpha at 0.05
ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = "rgba(255, 255, 255, 0.05)";
ctx.beginPath();
ctx.fillRect(0, 0, width, height);
ctx.fill();
// Set the default mode.
ctx.globalCompositeOperation = 'source-over';
Og2t
источник
3

Я думаю, что это лучше всего отвечает на вопрос, фактически изменяет альфа-значение того, что уже нарисовано. Может быть, это не было частью API, когда был задан этот вопрос.

заданный 2d контекст c.

function reduceAlpha(x, y, w, h, dA) {
    var screenData = c.getImageData(x, y, w, h);
    for(let i = 3; i < screenData.data.length; i+=4){
    screenData.data[i] -= dA; //delta-Alpha
    }
    c.putImageData(screenData, x, y );
}
Dillon
источник
Чем этот ответ отличается от ответа Soul_man, который был дан более подробно 7 лет назад?
BReddy
-2

Если вы используете библиотеку jCanvas, вы можете использовать свойство непрозрачности при рисовании. Если вам нужен эффект затухания, просто перерисуйте с разными значениями.

ЕКС
источник
-11

Ты не можешь Это графика в непосредственном режиме. Но вы можете имитировать его, рисуя поверх него прямоугольник в цвете фона с непрозрачностью.

Если изображение поверх чего-то другого, чем постоянный цвет, то оно становится немного сложнее. Вы должны быть в состоянии использовать методы манипуляции с пикселями в этом случае. Просто сохраните область перед тем, как нарисовать изображение, а затем смешайте его снова с непрозрачностью.

MPG
источник
5
Это неправильный ответ, см. Ниже
Райан Бадур
Вы правы, хотя вы не можете изменить непрозрачность одного из элементов, нарисованных на холсте, вы можете изменить непрозрачность всего холста. В некоторых случаях этого может быть достаточно.
MPG
2
MPG - ваш комментарий (11 мая) тоже неверен. Вы можете изменить прозрачность холста, но это не то, чего хотел ОП, и не то, что предлагается в ответах выше.
Ян