Wie ändere ich die Deckkraft (Alpha, Transparenz) eines Elements in einem Canvas-Element, nachdem es gezeichnet wurde?

196

Mit dem HTML5- <canvas>Element möchte ich eine Bilddatei (PNG, JPEG usw.) laden, sie vollständig transparent auf die Leinwand zeichnen und dann einblenden. Ich habe herausgefunden, wie das Bild geladen und in die Leinwand, aber ich weiß nicht, wie ich die Deckkraft ändern soll, wenn sie einmal gezeichnet wurde.

Hier ist der Code, den ich bisher habe:

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

Kann mich bitte jemand in die richtige Richtung weisen, z. B. eine zu setzende Eigenschaft oder eine aufzurufende Funktion, die die Deckkraft ändert?

Joe Lencioni
quelle

Antworten:

307

Ich suche auch nach einer Antwort auf diese Frage (zur Verdeutlichung möchte ich in der Lage sein, ein Bild mit benutzerdefinierter Deckkraft zu zeichnen, z. B. wie Sie Formen mit Deckkraft zeichnen können), wenn Sie mit primitiven Formen zeichnen, können Sie Füllung und Strich festlegen Farbe mit Alpha, um die Transparenz zu definieren. Soweit ich jetzt zu dem Schluss gekommen bin, scheint dies die Bildzeichnung nicht zu beeinflussen.

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

Ich bin zu dem Schluss gekommen, dass das Einstellen der globalCompositeOperationWerke mit Bildern funktioniert.

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

Ich frage mich, ob es eine dritte Möglichkeit gibt, Farben einzustellen, damit wir Bilder tönen und sie leicht transparent machen können.

BEARBEITEN:

Nach dem weiteren Graben bin ich zu dem Schluss gekommen, dass Sie die Transparenz eines Bildes einstellen können, indem Sie den globalAlphaParameter VOR dem Zeichnen des Bildes einstellen :

//works with images
ctx.globalAlpha = 0.5

Wenn Sie im Laufe der Zeit einen Fading-Effekt erzielen möchten, benötigen Sie eine Art Schleife, die den Alpha-Wert ändert. Dies ist ziemlich einfach. Eine Möglichkeit, dies zu erreichen, ist die setTimeoutFunktion. Schauen Sie nach, um eine Schleife zu erstellen, aus der Sie das Alpha ändern Zeit.

djdolber
quelle
7
globalAlpha funktioniert perfekt. Ist Teil des Standards: whatwg.org/specs/web-apps/current-work/multipage/…
Aleris
42
Um genau zu sein, ist es nicht das canvasElement, das die globalAlphaEigenschaft hat, sondern der Kontext, den Sie von der Zeichenfläche erhalten.
Steve Blackwell
8
Ians Kommentar zu ctx.save () und ctx.restore () verhindert, dass globalAlpha den Rest der Zeichenfläche beeinflusst.
Arosboro
1
Mir scheint, anstatt die Deckkraft der auf der Leinwand gezeichneten Bilder zu steuern, wäre es einfacher und dient dennoch dazu, die Deckkraft der gesamten Leinwand selbst nach dem Zeichnen des Bildes (nur einmal) zu steuern. Verwenden Sie dazu die üblichen CSS / style-Methoden (canvaselement.style.opacity = '0.3'; etc.). Später mit CSS3 können Sie sogar ganz auf die Schleife verzichten und stattdessen den Browser das Überblenden übernehmen lassen (so etwas wie Übergang: NNNms Trübung (Easy-In-Out) oder sogar "Beleben" des Verblassens.
Chuck Kollars
1
Funktioniert leider canvas2d.fillStyle = "rgba(255, 255, 255, 0.5)";nicht. Der Wert muss hexadezimal sein.
WebWanderer
113

Einige einfachere Beispielcodes für die Verwendung von globalAlpha:

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

Wenn Sie imggeladen werden müssen:

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

Anmerkungen:

  • Stellen Sie die 'src'letzte ein, um sicherzustellen, dass Ihr onloadHandler auf allen Plattformen aufgerufen wird, auch wenn sich das Image bereits im Cache befindet.

  • Schließen Sie Änderungen an Dingen wie globalAlphaa saveund restore(verwenden Sie sie tatsächlich häufig) ein, um sicherzustellen, dass Sie keine Einstellungen von anderen Stellen vornehmen, insbesondere wenn Teile des Zeichencodes von Ereignissen aufgerufen werden.

Ian
quelle
globalAlpha verwischt alle Bilder oder Zeichnungen auf einer Leinwand, das ist nicht das, was Sie wollen.
Mürrisch
6
@Grumpy - nein, globalAlphaverwischt nichts. Es wird das Alpha für alle nachfolgenden Zeichnungen festgelegt (es ändert nichts, was bereits gezeichnet wurde), weshalb ich es im Beispielcode einpacke saveund restoreeinschränke, worauf es angewendet wird.
Ian
Ich bin mir nicht sicher, ob ctx.restore () globalAlpha wiederherstellt. Möglicherweise müssen Sie dies auch am Ende tun (zumindest musste ich dies in früheren Versionen von Chrome tun). ctx.globalAlpha = 1;
Sean
1
@ Sean - Wenn Sie nicht sicher sind, sollten Sie überprüfen. Es muss ein sehr altes Chrome gewesen sein, es funktioniert jetzt auf allen Plattformen: jsfiddle.net/y0z9h9m7
Ian
14

Bearbeiten: Die als "richtig" gekennzeichnete Antwort ist nicht korrekt.

Es ist einfach zu machen. Probieren Sie diesen Code aus und tauschen Sie "ie.jpg" mit dem Bild aus, das Sie zur Hand haben:

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

Der Schlüssel ist die Eigenschaft globalAlpha.

Getestet mit IE 9, FF 5, Safari 5 und Chrome 12 unter Win7.

james.garriss
quelle
13

Die Post ist alt, bis jetzt werde ich mit meinem Vorschlag gehen. Der Vorschlag basiert auf der Pixelmanipulation im 2D-Canvas-Kontext. Von MDN:

Sie können Pixeldaten in Leinwänden auf Byte-Ebene direkt bearbeiten

Um Pixel zu bearbeiten, verwenden wir hier zwei Funktionen - getImageData und putImageData

Verwendung der Funktion getImageData:

var myImageData = context.getImageData (links, oben, Breite, Höhe);

und putImageData-Syntax:

context.putImageData (myImageData, dx, dy); // dx, dy - x und y versetzen sich auf deiner Leinwand

Wo Kontext ist Ihre Leinwand 2d Kontext

Um Rot-Grün-Blau- und Alpha-Werte zu erhalten, gehen wir wie folgt vor:

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

Wo x ist x Offset, y ist y auf Leinwand Offset

Wir haben also Code, der das Bild halbtransparent macht

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

Sie können Ihre eigenen "Shader" erstellen - den vollständigen MDN-Artikel finden Sie hier

Soul_man
quelle
7

Sie können. Transparente Zeichenflächen können mithilfe der globalen zusammengesetzten Ziel-Out- Operation schnell ausgeblendet werden . Es ist nicht 100% perfekt, manchmal hinterlässt es einige Spuren, aber es kann je nach Bedarf optimiert werden (dh verwenden Sie 'Source-Over' und füllen Sie es mit weißer Farbe mit Alpha bei 0,13 und verblassen Sie dann, um die Leinwand vorzubereiten).

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

Ich denke, dies beantwortet die Frage am besten, es ändert tatsächlich den Alpha-Wert von etwas, das bereits gezeichnet wurde. Vielleicht war dies nicht Teil der API, als diese Frage gestellt wurde.

gegeben 2d Kontext 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
quelle
Wie unterscheidet sich diese Antwort von der Antwort von Soul_man, die 7 Jahre zuvor ausführlicher gegeben wurde?
BReddy
-11

Das kannst du nicht. Es ist Grafik im Sofortmodus. Sie können es jedoch simulieren, indem Sie ein Rechteck in der Hintergrundfarbe mit einer Deckkraft darüber zeichnen.

Wenn das Bild über etwas anderem als einer konstanten Farbe liegt, wird es etwas schwieriger. In diesem Fall sollten Sie in der Lage sein, die Pixelmanipulationsmethoden zu verwenden. Speichern Sie einfach den Bereich, bevor Sie das Bild zeichnen, und mischen Sie ihn anschließend wieder mit einer Deckkraft.

MPG
quelle
5
Dies ist nicht die richtige Antwort siehe unten
Ryan Badour
Sie haben Recht, obwohl Sie die Deckkraft eines der Elemente, die Sie in die Leinwand gezeichnet haben, nicht ändern können, können Sie die Deckkraft der gesamten Leinwand ändern. In einigen Fällen kann dies ausreichen.
MPG
2
MPG - Ihr Kommentar (11. Mai) ist ebenfalls falsch. Sie können die Deckkraft der Leinwand ändern, aber das ist weder das, was das OP wollte, noch das, was in den obigen Antworten vorgeschlagen wird.
Ian