Bagaimana cara mengubah opacity (alfa, transparansi) elemen dalam elemen kanvas setelah elemen tersebut digambar?

196

Menggunakan <canvas>elemen HTML5 , saya ingin memuat file gambar (PNG, JPEG, dll.), Menggambarnya ke kanvas sepenuhnya secara transparan, dan kemudian memudar. Saya telah menemukan cara untuk memuat gambar dan menariknya ke kanvas, tapi saya tidak tahu bagaimana mengubah opacity setelah digambar.

Inilah kode yang saya miliki sejauh ini:

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

Akankah seseorang tolong tunjukkan saya ke arah yang benar seperti properti untuk diatur atau fungsi untuk memanggil yang akan mengubah opacity?

Joe Lencioni
sumber

Jawaban:

307

Saya juga mencari jawaban untuk pertanyaan ini, (untuk memperjelas, saya ingin dapat menggambar gambar dengan opacity yang ditentukan pengguna seperti bagaimana Anda dapat menggambar bentuk dengan opacity) jika Anda menggambar dengan bentuk primitif Anda dapat mengatur fill dan stroke warna dengan alpha untuk menentukan transparansi. Sejauh yang saya simpulkan sekarang, ini tampaknya tidak memengaruhi gambar.

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

Saya telah menyimpulkan bahwa pengaturan globalCompositeOperationkarya dengan gambar.

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

Saya bertanya-tanya apakah ada semacam cara ketiga pengaturan warna sehingga kita dapat mewarnai gambar dan membuatnya transparan dengan mudah.

EDIT:

Setelah penggalian lebih lanjut, saya menyimpulkan bahwa Anda dapat mengatur transparansi gambar dengan mengatur globalAlphaparameter SEBELUM Anda menggambar gambar:

//works with images
ctx.globalAlpha = 0.5

Jika Anda ingin mencapai efek fading dari waktu ke waktu Anda membutuhkan semacam loop yang mengubah nilai alpha, ini cukup mudah, salah satu cara untuk mencapainya adalah setTimeoutfungsinya, lihat itu untuk membuat loop dari mana Anda mengubah alpha lebih dari waktu.

djdolber
sumber
7
globalAlpha bekerja dengan sempurna. Merupakan bagian dari standar: whatwg.org/specs/web-apps/current-work/multipage/…
Aleris
42
Lebih tepatnya, itu bukan canvaselemen yang memiliki globalAlphaproperti, tetapi konteks yang Anda dapatkan dari kanvas.
Steve Blackwell
8
Komentar Ian di bawah ini tentang ctx.save () dan ctx.restore () mencegah globalAlpha memengaruhi sisa kanvas.
Arosboro
1
Menurut saya daripada mengontrol opacity dari apa yang digambar di atas kanvas, akan lebih sederhana dan masih melayani tujuan untuk hanya mengontrol opacity dari seluruh kanvas itu sendiri setelah gambar digambar (hanya sekali). Gunakan metode CSS / style biasa untuk melakukan ini (canvaselement.style.opacity = '0.3'; dll.) Kemudian dengan CSS3 Anda bahkan dapat membuang loop sekaligus dan biarkan browser menangani fading sebagai gantinya (sesuatu seperti- transisi: NNNms opaciity easy-in-out), atau bahkan "menghidupkan" fading
Chuck Kollars
1
Sayangnya, canvas2d.fillStyle = "rgba(255, 255, 255, 0.5)";tidak berfungsi. Nilai harus dalam hex.
WebWanderer
113

Beberapa kode contoh sederhana untuk menggunakan globalAlpha:

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

Jika Anda perlu img dimuat:

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

Catatan:

  • Tetapkan yang 'src'terakhir, untuk menjamin bahwa onloadpawang Anda dipanggil di semua platform, bahkan jika gambar sudah ada dalam cache.

  • Bungkus perubahan ke hal-hal seperti globalAlphaantara a savedan restore(sebenarnya gunakan banyak), untuk memastikan Anda tidak merusak pengaturan dari tempat lain, terutama ketika bit kode gambar akan dipanggil dari acara.

Ian
sumber
globalAlpha akan mengaburkan semua gambar atau gambar pada kanvas, bukan itu yang Anda inginkan.
Grumpy
6
@ Grumpy - tidak, globalAlphatidak mengaburkan apa pun. Ini akan mengatur alpha untuk semua gambar berikutnya (itu tidak mengubah apa pun yang sudah ditarik), itulah sebabnya dalam contoh kode saya membungkusnya savedan restore, untuk membatasi apa yang berlaku.
Ian
tidak yakin bahwa ctx.restore () akan mengembalikan globalAlpha Anda mungkin juga perlu melakukan ini di akhir (setidaknya saya harus di versi Chrome sebelumnya) ctx.globalAlpha = 1;
Sean
1
@Sean - Jika Anda tidak yakin, Anda harus memeriksa. Pasti Chrome yang sangat lama, sekarang berfungsi di semua platform: jsfiddle.net/y0z9h9m7
Ian
14

Edit: Jawaban yang ditandai "benar" tidak benar.

Itu mudah dilakukan. Coba kode ini, ganti "ie.jpg" dengan gambar apa pun yang berguna:

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

Kuncinya adalah properti globalAlpha.

Diuji dengan IE 9, FF 5, Safari 5, dan Chrome 12 pada Win7.

james.garriss
sumber
13

Posting sudah lama sejauh ini saya akan pergi dengan saran saya. Saran didasarkan pada manipulasi piksel dalam konteks kanvas 2d. Dari MDN:

Anda dapat secara langsung memanipulasi data piksel dalam kanvas di tingkat byte

Untuk memanipulasi piksel, kami akan menggunakan dua fungsi di sini - getImageData dan putImageData

penggunaan fungsi getImageData:

var myImageData = context.getImageData (kiri, atas, lebar, tinggi);

dan sintaks putImageData:

context.putImageData (myImageData, dx, dy); // dx, dy - x dan y offset pada kanvas Anda

Di mana konteks adalah konteks kanvas 2d Anda

Jadi untuk mendapatkan nilai merah hijau biru dan alfa, kami akan melakukan hal berikut:

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

Di mana x adalah x offset, y adalah y offset di atas kanvas

Jadi kami memiliki kode yang membuat gambar setengah transparan

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

Anda dapat membuat Anda memiliki "bayangan" - lihat artikel MDN lengkap di sini

Soul_man
sumber
7

Kamu bisa. Kanvas transparan dapat dengan cepat pudar dengan menggunakan operasi komposit global tujuan-keluar . Ini tidak 100% sempurna, kadang-kadang meninggalkan beberapa jejak tetapi bisa di-tweak, tergantung apa yang dibutuhkan (yaitu menggunakan 'sumber-lebih' dan mengisinya dengan warna putih dengan alfa di 0,13, kemudian memudar untuk menyiapkan kanvas).

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

Saya pikir ini menjawab pertanyaan terbaik, itu sebenarnya mengubah nilai alpha dari sesuatu yang telah ditarik. Mungkin ini bukan bagian dari api ketika pertanyaan ini diajukan.

diberikan konteks 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
sumber
Bagaimana jawaban ini berbeda dari jawaban Soul_man yang diberikan dengan lebih rinci 7 tahun sebelumnya?
BReddy
-2

Jika Anda menggunakan perpustakaan jCanvas, Anda dapat menggunakan properti opacity saat menggambar. Jika Anda membutuhkan efek fade di atas itu, cukup menggambar ulang dengan nilai yang berbeda.

cen
sumber
-11

Kamu tidak bisa Ini grafis mode langsung. Tetapi Anda dapat mensimulasikannya dengan menggambar persegi panjang di atasnya dengan warna latar belakang dengan opacity.

Jika gambar lebih dari sesuatu yang bukan warna konstan, maka itu menjadi sedikit lebih rumit. Anda harus dapat menggunakan metode manipulasi piksel dalam kasus ini. Simpan saja area tersebut sebelum menggambar gambar, dan kemudian haluskan kembali di atas dengan opacity sesudahnya.

MPG
sumber
5
Ini bukan jawaban yang tepat, lihat di bawah ini
Ryan Badour
Anda benar, meskipun Anda tidak dapat mengubah opacity dari salah satu elemen yang telah Anda gambar di kanvas, Anda dapat mengubah opacity dari seluruh kanvas. Dalam beberapa kasus itu mungkin cukup.
MPG
2
MPG - komentar Anda (11 Mei) juga salah. Anda dapat mengubah opacity kanvas, tetapi bukan itu yang diinginkan OP, atau apa yang disarankan dalam jawaban di atas.
Ian