¿Cómo cambiar la opacidad (alfa, transparencia) de un elemento en un elemento de lienzo después de que se ha dibujado?

196

Usando el <canvas>elemento HTML5 , me gustaría cargar un archivo de imagen (PNG, JPEG, etc.), dibujarlo en el lienzo completamente transparente y luego desvanecerlo. He descubierto cómo cargar la imagen y dibujarla en el lienzo, pero no sé cómo cambiar su opacidad una vez que se ha dibujado.

Aquí está el código que tengo hasta ahora:

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';
}

¿Alguien me indicará en la dirección correcta como una propiedad para establecer o una función para llamar que cambiará la opacidad?

Joe Lencioni
fuente

Respuestas:

307

También estoy buscando una respuesta a esta pregunta (para aclarar, quiero poder dibujar una imagen con una opacidad definida por el usuario, como la forma de dibujar formas con opacidad) si dibuja con formas primitivas, puede establecer relleno y trazo color con alfa para definir la transparencia. Hasta donde he concluido en este momento, esto no parece afectar el dibujo de la imagen.

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

He concluido que configurar las globalCompositeOperationobras con imágenes.

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

Me pregunto si hay una tercera forma de configurar el color para que podamos teñir las imágenes y hacerlas transparentes fácilmente.

EDITAR:

Después de excavar más, he concluido que puede establecer la transparencia de una imagen configurando el globalAlphaparámetro ANTES de dibujar la imagen:

//works with images
ctx.globalAlpha = 0.5

Si desea lograr un efecto de desvanecimiento con el tiempo, necesita algún tipo de bucle que cambie el valor alfa, esto es bastante fácil, una forma de lograrlo es la setTimeoutfunción, búsquelo para crear un bucle desde el cual altere el alfa hora.

djdolber
fuente
77
globalAlpha funciona perfectamente. Es parte del estándar: whatwg.org/specs/web-apps/current-work/multipage/…
Aleris
42
Para ser precisos, no es el canvaselemento el que tiene la globalAlphapropiedad, sino el contexto que se obtiene del lienzo.
Steve Blackwell
8
El comentario de Ian a continuación sobre ctx.save () y ctx.restore () evita que globalAlpha afecte al resto del lienzo.
Arosboro
1
Me parece que en lugar de controlar la opacidad de lo que se dibuja en el lienzo, sería más simple y seguiría teniendo el propósito de controlar la opacidad de todo el lienzo en sí después de dibujar la imagen (solo una vez). Utilice los métodos habituales de CSS / estilo para hacer esto (canvaselement.style.opacity = '0.3'; etc.) Más tarde con CSS3 puede incluso prescindir del bucle por completo y dejar que el navegador maneje el desvanecimiento (algo así como transición: NNNms opacidad, facilidad de entrada), o incluso "animar" el desvanecimiento.
Chuck Kollars el
1
Lamentablemente, canvas2d.fillStyle = "rgba(255, 255, 255, 0.5)";no funciona. El valor debe estar en hexadecimal.
WebWanderer
113

Algún código de ejemplo más simple para usar globalAlpha:

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

Si necesitas img ser cargado:

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

Notas:

  • Configure el 'src'último, para garantizar que onloadse llame a su controlador en todas las plataformas, incluso si la imagen ya está en el caché.

  • Envuelva los cambios a cosas como globalAlphaentre a savey restore(de hecho, úselos mucho), para asegurarse de no cambiar la configuración desde otro lugar, particularmente cuando se llamarán fragmentos de código de dibujo desde eventos.

Ian
fuente
globalAlpha borrará todas las imágenes o dibujos en un lienzo, eso no es lo que desea.
Gruñón
66
@Grumpy: no, globalAlphano difumina nada. Establecerá el alfa para todos los dibujos posteriores (no cambia nada que ya esté dibujado), por lo que en el código de ejemplo lo envuelvo savey restore, para limitar a qué se aplica.
Ian
no estoy seguro de que ctx.restore () restaurará globalAlpha, es posible que también deba hacer esto al final (al menos tenía que hacerlo en versiones anteriores de Chrome) ctx.globalAlpha = 1;
Sean
1
@Sean: si no está seguro, debe verificarlo. Debe haber sido un Chrome muy antiguo, ahora funciona en todas las plataformas: jsfiddle.net/y0z9h9m7
Ian
14

Editar: La respuesta marcada como "correcta" no es correcta.

Es facil de hacer. Pruebe este código, intercambiando "ie.jpg" con cualquier imagen que tenga a mano:

<!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>

La clave es la propiedad globalAlpha.

Probado con IE 9, FF 5, Safari 5 y Chrome 12 en Win7.

james.garriss
fuente
13

La publicación es antigua, hasta ahora iré con mi sugerencia. La sugerencia se basa en la manipulación de píxeles en el contexto 2D del lienzo. De MDN:

Puede manipular directamente datos de píxeles en lienzos a nivel de byte

Para manipular píxeles usaremos dos funciones aquí: getImageData y putImageData

Uso de la función getImageData:

var myImageData = context.getImageData (izquierda, arriba, ancho, alto);

y sintaxis putImageData:

context.putImageData (myImageData, dx, dy); // dx, dy - x e y offset en tu lienzo

Donde el contexto es tu lienzo contexto 2D

Entonces, para obtener valores rojo, verde, azul y alfa, haremos lo siguiente:

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];

Donde x es x offset, y es y offset en lienzo

Entonces tenemos un código que hace que la imagen sea medio transparente

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';

Puede hacer sus propios "sombreadores" - vea el artículo completo de MDN aquí

Alma de hombre
fuente
7

Usted puede. El lienzo transparente se puede desvanecer rápidamente mediante el uso de la operación global compuesta de destino . No es 100% perfecto, a veces deja algunas huellas, pero podría modificarse, dependiendo de lo que sea necesario (es decir, use 'source-over' y llénelo de color blanco con alfa a 0.13, luego se desvanecen para preparar el lienzo).

// 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
fuente
3

Creo que esto responde mejor a la pregunta, en realidad cambia el valor alfa de algo que ya se ha dibujado. Tal vez esto no era parte de la API cuando se hizo esta pregunta.

contexto 2d dado 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
fuente
¿Cómo es esta respuesta diferente de la respuesta de Soul_man dada con más detalle 7 años antes?
BReddy
-2

Si usa la biblioteca jCanvas , puede usar la propiedad de opacidad al dibujar. Si necesita un efecto de desvanecimiento además de eso, simplemente vuelva a dibujar con diferentes valores.

cen
fuente
-11

No puedes Se trata de gráficos de modo inmediato. Pero puede simularlo dibujando un rectángulo sobre él en el color de fondo con una opacidad.

Si la imagen está sobre algo que no sea un color constante, entonces se vuelve un poco más complicado. Debería poder utilizar los métodos de manipulación de píxeles en este caso. Simplemente guarde el área antes de dibujar la imagen y luego vuelva a mezclarla con una opacidad.

MPG
fuente
55
Esta no es la respuesta correcta, ver a continuación
Ryan Badour
Tienes razón, aunque no puedes cambiar la opacidad de uno de los elementos que has dibujado en el lienzo, puedes cambiar la opacidad de todo el lienzo. En algunos casos eso podría ser suficiente.
MPG
2
MPG: su comentario (11 de mayo) también es incorrecto. Puede cambiar la opacidad del lienzo, pero eso no es lo que quería el OP, ni lo que se sugiere en las respuestas anteriores.
Ian