Làm cách nào để thay đổi độ mờ (alpha, độ trong suốt) của một phần tử trong phần tử canvas sau khi nó được vẽ?


196

Sử dụng <canvas>phần tử HTML5 , tôi muốn tải một tệp hình ảnh (PNG, JPEG, v.v.), vẽ nó vào khung vẽ hoàn toàn trong suốt và sau đó làm mờ nó đi. Tôi đã tìm ra cách tải hình ảnh và vẽ nó vào canvas, nhưng tôi không biết làm thế nào để thay đổi độ mờ đục của nó một khi nó được vẽ.

Đây là mã tôi có cho đến nay:

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

Ai đó vui lòng chỉ cho tôi đi đúng hướng như một tài sản để thiết lập hoặc một chức năng để gọi sẽ thay đổi độ mờ?

Câu trả lời:


307

Tôi cũng đang tìm câu trả lời cho câu hỏi này, (để làm rõ, tôi muốn có thể vẽ một hình ảnh với độ mờ do người dùng xác định, chẳng hạn như làm thế nào bạn có thể vẽ các hình với độ mờ) nếu bạn vẽ bằng các hình dạng nguyên thủy bạn có thể đặt fill và Stroke màu với alpha để xác định độ trong suốt. Theo như tôi đã kết luận ngay bây giờ, điều này dường như không ảnh hưởng đến việc vẽ hình ảnh.

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

Tôi đã kết luận rằng thiết lập các globalCompositeOperationtác phẩm với hình ảnh.

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

Tôi tự hỏi nếu có một số cách thiết lập màu thứ ba để chúng ta có thể tô màu hình ảnh và làm cho chúng trong suốt dễ dàng.

BIÊN TẬP:

Sau khi đào sâu hơn, tôi đã kết luận rằng bạn có thể đặt độ trong suốt của hình ảnh bằng cách đặt globalAlphatham số TRƯỚC KHI bạn vẽ hình ảnh:

//works with images
ctx.globalAlpha = 0.5

Nếu bạn muốn đạt được hiệu ứng mờ dần theo thời gian, bạn cần một loại vòng lặp thay đổi giá trị alpha, điều này khá dễ dàng, một cách để đạt được nó là setTimeoutchức năng, hãy tìm cách tạo ra một vòng lặp để bạn thay đổi alpha thời gian.


7
globalAlpha hoạt động hoàn hảo. Là một phần của tiêu chuẩn: whatwg.org/specs/web-apps/current-work/multipage/...
Aleris

42
Nói chính xác, đó không phải là canvasyếu tố có thuộc globalAlphatính, mà là bối cảnh mà bạn có được từ khung vẽ.
Steve Blackwell

8
Bình luận của Ian bên dưới về ctx.save () và ctx.restore () ngăn chặn GlobalAlpha ảnh hưởng đến phần còn lại của khung vẽ.
Arosboro

1
Dường như với tôi thay vì kiểm soát độ mờ đục của những gì được vẽ trên khung vẽ, nó sẽ đơn giản hơn và vẫn phục vụ mục đích chỉ kiểm soát độ mờ đục của toàn bộ khung vẽ sau khi hình ảnh được vẽ (chỉ một lần). Sử dụng các phương thức CSS / kiểu thông thường để thực hiện việc này (canvaselement.style.opacity = '0,3'; v.v.) Sau này với CSS3, bạn thậm chí có thể phân phối hoàn toàn với vòng lặp và chỉ để trình duyệt xử lý mờ dần (thay vào đó là: quá trình chuyển đổi: NNNms opaciity easy-in-out), hoặc thậm chí "animate" sự mờ dần.
Chuck Kollars

1
Thật không may, canvas2d.fillStyle = "rgba(255, 255, 255, 0.5)";không hoạt động. Giá trị phải ở dạng hex.
WebWanderer

113

Một số mã ví dụ đơn giản hơn để sử dụng globalAlpha:

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

Nếu bạn cần imgđược tải:

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

Ghi chú:

  • Đặt 'src'cuối cùng, để đảm bảo rằng onloadtrình xử lý của bạn được gọi trên tất cả các nền tảng, ngay cả khi hình ảnh đã có trong bộ đệm.

  • Kết hợp các thay đổi với nội dung như globalAlphagiữa a saverestore(trên thực tế sử dụng chúng rất nhiều), để đảm bảo bạn không cài đặt ghi đè từ nơi khác, đặc biệt là khi các bit của mã bản vẽ sẽ được gọi từ các sự kiện.


globalAlpha sẽ làm mờ tất cả hình ảnh hoặc hình vẽ trên khung vẽ, đó không phải là điều bạn muốn.
Grumpy

6
@Grumpy - không, globalAlphakhông làm mờ bất cứ điều gì. Nó sẽ đặt alpha cho tất cả các bản vẽ tiếp theo (nó không thay đổi bất cứ thứ gì đã vẽ), đó là lý do tại sao trong mã ví dụ tôi bọc nó saverestore, để hạn chế những gì nó áp dụng.
Ian

không chắc chắn rằng ctx.restore () sẽ khôi phục globalAlpha, bạn cũng có thể cần phải làm điều này ở cuối (ít nhất là tôi phải có trong các phiên bản trước của Chrome) ctx.globalAlpha = 1;
Sean

1
@Sean - Nếu bạn không chắc chắn, bạn nên kiểm tra. Nó phải là một Chrome rất cũ, nó hoạt động trên tất cả các nền tảng bây giờ: jsfiddle.net/y0z9h9m7
Ian

14

Biên tập: Câu trả lời được đánh dấu là "chính xác" là không chính xác.

Thật dễ dàng để làm. Hãy thử mã này, hoán đổi "eg.jpg" với bất kỳ hình ảnh nào bạn có:

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

Chìa khóa là tài sản globalAlpha.

Đã thử nghiệm với IE 9, FF 5, Safari 5 và Chrome 12 trên Win7.


13

Bài viết đã cũ cho đến nay tôi sẽ đi với đề xuất của tôi. Đề xuất dựa trên thao tác pixel trong bối cảnh canvas 2d. Từ MDN:

Bạn có thể trực tiếp thao tác dữ liệu pixel trong khung vẽ ở mức byte

Để thao tác với pixel, chúng tôi sẽ sử dụng hai hàm tại đây - getImageData và putImageData

Sử dụng chức năng getImageData:

var myImageData = bối cảnh.getImageData (trái, trên cùng, chiều rộng, chiều cao);

và cú pháp putImageData:

bối cảnh.putImageData (myImageData, dx, dy); // dx, dy - x và y offset trên khung vẽ của bạn

Trường hợp bối cảnh là bối cảnh 2d canvas của bạn

Vì vậy, để có được giá trị alpha và xanh lục đỏ, chúng tôi sẽ làm như sau:

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

Trong đó x là x offset, y là y offset trên canvas

Vì vậy, chúng tôi có mã làm cho hình ảnh trong suốt một nửa

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

Bạn có thể khiến bạn sở hữu "shader" - xem toàn bộ bài viết MDN tại đây


7

Bạn có thể. Canvas trong suốt có thể được làm mờ nhanh chóng bằng cách sử dụng hoạt động tổng hợp toàn cầu đích . Nó không hoàn hảo 100%, đôi khi nó để lại một số dấu vết nhưng nó có thể được điều chỉnh, tùy thuộc vào những gì cần thiết (ví dụ: sử dụng 'nguồn-over' và tô màu trắng bằng alpha ở 0,13, sau đó mờ dần để chuẩn bị khung vẽ).

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

3

Tôi nghĩ rằng điều này trả lời tốt nhất câu hỏi, nó thực sự thay đổi giá trị alpha của một cái gì đó đã được rút ra. Có lẽ đây không phải là một phần của api khi câu hỏi này được hỏi.

bối cảnh 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 );
}

Câu trả lời này khác với câu trả lời của Soul_man như thế nào với chi tiết hơn 7 năm trước?
BReddy

-2

Nếu bạn sử dụng thư viện jCanvas, bạn có thể sử dụng thuộc tính opacity khi vẽ. Nếu bạn cần hiệu ứng mờ dần trên đó, chỉ cần vẽ lại với các giá trị khác nhau.


-11

Bạn không thể. Đó là đồ họa chế độ ngay lập tức. Nhưng bạn có thể sắp xếp mô phỏng nó bằng cách vẽ một hình chữ nhật trên nó bằng màu nền với độ mờ.

Nếu hình ảnh trên một cái gì đó không phải là một màu không đổi, thì nó sẽ khá phức tạp hơn một chút. Bạn sẽ có thể sử dụng các phương thức thao tác pixel trong trường hợp này. Chỉ cần lưu khu vực trước khi vẽ hình ảnh, và sau đó trộn nó trở lại trên cùng với độ mờ sau đó.


5
Đây không phải là câu trả lời đúng xem bên dưới
Ryan Badour

Bạn đã đúng, mặc dù bạn không thể thay đổi độ mờ của một trong các yếu tố bạn đã vẽ vào khung vẽ, bạn có thể thay đổi độ mờ của toàn bộ khung vẽ. Trong một số trường hợp có thể là đủ.
MPG

2
MPG - nhận xét của bạn (ngày 11 tháng 5) cũng sai. Bạn có thể thay đổi độ mờ đục của khung vẽ, nhưng đó không phải là điều OP muốn, cũng không phải điều được đề xuất trong các câu trả lời ở trên.
Ian
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.