Comment changer l'opacité (alpha, transparence) d'un élément dans un élément canvas après qu'il ait été dessiné?

196

En utilisant l' <canvas>élément HTML5 , je voudrais charger un fichier image (PNG, JPEG, etc.), le dessiner sur la toile de manière complètement transparente, puis le fondre dedans. J'ai compris comment charger l'image et la dessiner dans le toile, mais je ne sais pas comment changer son opacité une fois qu'il a été dessiné.

Voici le code que j'ai jusqu'à présent:

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

Quelqu'un pourra-t-il m'orienter dans la bonne direction comme une propriété à définir ou une fonction à appeler qui changera l'opacité?

Joe Lencioni
la source

Réponses:

307

Je cherche également une réponse à cette question, (pour clarifier, je veux pouvoir dessiner une image avec une opacité définie par l'utilisateur, par exemple comment vous pouvez dessiner des formes avec opacité) si vous dessinez avec des formes primitives, vous pouvez définir le remplissage et le trait couleur avec alpha pour définir la transparence. Pour autant que je l'ai conclu en ce moment, cela ne semble pas affecter le dessin de l'image.

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

J'ai conclu que mettre les globalCompositeOperationœuvres en images.

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

Je me demande s'il existe une troisième sorte de réglage des couleurs pour que nous puissions teinter les images et les rendre transparentes facilement.

ÉDITER:

Après avoir creusé davantage, j'ai conclu que vous pouvez définir la transparence d'une image en définissant le globalAlphaparamètre AVANT de dessiner l'image:

//works with images
ctx.globalAlpha = 0.5

Si vous voulez obtenir un effet de décoloration au fil du temps, vous avez besoin d'une sorte de boucle qui modifie la valeur alpha, c'est assez facile, une façon d'y parvenir est la setTimeoutfonction, recherchez cela pour créer une boucle à partir de laquelle vous modifiez l'alpha temps.

djdolber
la source
7
globalAlpha fonctionne parfaitement. Fait partie de la norme: whatwg.org/specs/web-apps/current-work/multipage/…
Aleris
42
Pour être précis, ce n'est pas l' canvasélément qui a la globalAlphapropriété, mais le contexte que vous obtenez du canevas.
Steve Blackwell
8
Le commentaire d'Ian ci-dessous à propos de ctx.save () et ctx.restore () empêche le globalAlpha d'affecter le reste du canevas.
Arosboro
1
Il me semble plutôt que de contrôler l'opacité de ce qui est dessiné sur la toile, ce serait plus simple et servirait toujours à contrôler l'opacité de toute la toile elle-même après le dessin de l'image (une seule fois). Utilisez les méthodes CSS / style habituelles pour ce faire (canvaselement.style.opacity = '0.3'; etc.) Plus tard avec CSS3, vous pouvez même supprimer complètement la boucle et laisser le navigateur gérer la décoloration à la place (quelque chose comme - transition: NNNms opaciity easy-in-out), voire "animer" la décoloration.
Chuck Kollars
1
Malheureusement, canvas2d.fillStyle = "rgba(255, 255, 255, 0.5)";cela ne fonctionne pas. La valeur doit être en hexadécimal.
WebWanderer
113

Un exemple de code plus simple à utiliser globalAlpha:

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

Si vous devez imgêtre chargé:

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

Remarques:

  • Définissez le 'src'dernier, pour garantir que votre onloadgestionnaire est appelé sur toutes les plates-formes, même si l'image est déjà dans le cache.

  • Enveloppez les modifications dans des choses comme globalAlphaentre a saveet restore(en fait, utilisez-les beaucoup), pour vous assurer que vous n'encombrez pas les paramètres ailleurs, en particulier lorsque des bits de code de dessin vont être appelés à partir d'événements.

Ian
la source
globalAlpha rendra floues toutes les images ou dessins sur une toile, ce n'est pas ce que vous voulez.
Grincheux
6
@Grumpy - non, globalAlphane brouille rien. Il définira l'alpha pour tous les dessins suivants (cela ne change rien de déjà dessiné), c'est pourquoi dans l'exemple de code je l'enveloppe saveet restore, pour limiter ce à quoi il s'applique.
Ian
pas sûr que ctx.restore () restaurera globalAlpha, vous devrez peut-être également le faire à la fin (du moins, je devais le faire dans les versions antérieures de Chrome) ctx.globalAlpha = 1;
Sean
1
@Sean - Si vous n'êtes pas sûr, vous devriez vérifier. Ce devait être un très vieux Chrome, il fonctionne maintenant sur toutes les plateformes: jsfiddle.net/y0z9h9m7
Ian
14

Éditer: La réponse marquée comme "correcte" n'est pas correcte.

C'est facile à faire. Essayez ce code, en remplaçant "ie.jpg" par l'image que vous avez à portée de main:

<!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 clé est la propriété globalAlpha.

Testé avec IE 9, FF 5, Safari 5 et Chrome 12 sur Win7.

james.garriss
la source
13

Le message est ancien jusqu'à présent, je vais suivre ma suggestion. La suggestion est basée sur la manipulation de pixels dans le contexte de canvas 2d. De MDN:

Vous pouvez manipuler directement les données de pixels dans les toiles au niveau des octets

Pour manipuler les pixels, nous utiliserons deux fonctions ici - getImageData et putImageData

Utilisation de la fonction getImageData:

var myImageData = context.getImageData (gauche, haut, largeur, hauteur);

et la syntaxe putImageData:

context.putImageData (myImageData, dx, dy); // dx, dy - décalage x et y sur votre toile

Où le contexte est votre contexte 2D Canvas

Donc, pour obtenir des valeurs bleu vert rouge et alpha, nous ferons ce qui suit:

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 est le décalage x, y est le décalage y sur le canevas

Nous avons donc du code rendant l'image semi-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';

Vous pouvez créer vos propres "shaders" - voir l'article complet de MDN ici

Soul_man
la source
7

Vous pouvez. Le canevas transparent peut être rapidement effacé à l'aide d' une opération composite globale de destination . Ce n'est pas parfait à 100%, parfois il laisse des traces mais il pourrait être modifié, selon ce qui est nécessaire (c'est-à-dire utiliser 'source-over' et le remplir de couleur blanche avec alpha à 0,13, puis s'estomper pour préparer la toile).

// 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
la source
3

Je pense que cela répond le mieux à la question, cela change en fait la valeur alpha de quelque chose qui a déjà été dessiné. Peut-être que cela ne faisait pas partie de l'API lorsque cette question a été posée.

compte tenu du contexte 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
la source
En quoi cette réponse est-elle différente de la réponse de Soul_man donnée plus en détail 7 ans auparavant?
BReddy
-2

Si vous utilisez la bibliothèque jCanvas , vous pouvez utiliser la propriété d' opacité lors du dessin. Si vous avez besoin d'un effet de fondu en plus, redessinez simplement avec des valeurs différentes.

cen
la source
-11

Tu ne peux pas. Ce sont des graphiques en mode immédiat. Mais vous pouvez en quelque sorte le simuler en dessinant un rectangle dessus dans la couleur d'arrière-plan avec une opacité.

Si l'image est sur autre chose qu'une couleur constante, cela devient un peu plus délicat. Dans ce cas, vous devriez pouvoir utiliser les méthodes de manipulation des pixels. Enregistrez simplement la zone avant de dessiner l'image, puis mélangez-la en haut avec une opacité par la suite.

MPG
la source
5
Ce n'est pas la bonne réponse voir ci
Ryan Badour
Vous avez raison, bien que vous ne puissiez pas changer l'opacité de l'un des éléments que vous avez dessinés dans la toile, vous pouvez changer l'opacité de la toile entière. Dans certains cas, cela pourrait suffire.
MPG
2
MPG - votre commentaire (11 mai) est également faux. Vous pouvez changer l'opacité de la toile, mais ce n'est pas ce que le PO voulait, ni ce qui est suggéré dans les réponses ci-dessus.
Ian