จะเปลี่ยน opacity (alpha, transparent) ขององค์ประกอบในองค์ประกอบ canvas ได้อย่างไร


196

เมื่อใช้<canvas>องค์ประกอบHTML5 ฉันต้องการโหลดไฟล์รูปภาพ (PNG, JPEG และอื่น ๆ ) วาดลงในผืนผ้าใบอย่างสมบูรณ์แล้วจางหายไปฉันได้คิดวิธีการโหลดรูปภาพและวาดลงใน ผืนผ้าใบ แต่ฉันไม่รู้วิธีเปลี่ยนความทึบเมื่อวาดแล้ว

นี่คือรหัสที่ฉันมี:

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

ใครบางคนจะโปรดชี้ฉันในทิศทางที่ถูกต้องเช่นสถานที่ให้ตั้งหรือฟังก์ชั่นการโทรที่จะเปลี่ยนความทึบ?

คำตอบ:


307

ฉันกำลังมองหาคำตอบสำหรับคำถามนี้ (เพื่อชี้แจงฉันต้องการให้สามารถวาดภาพด้วยความทึบที่กำหนดโดยผู้ใช้เช่นวิธีที่คุณสามารถวาดรูปร่างด้วยความทึบ) ถ้าคุณวาดด้วยรูปทรงดั้งเดิมคุณสามารถตั้งค่าเติมและลากเส้น สีด้วยอัลฟาเพื่อกำหนดความโปร่งใส เท่าที่ฉันได้ข้อสรุปในขณะนี้ดูเหมือนจะไม่ส่งผลกระทบต่อการวาดภาพ

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

ฉันได้ข้อสรุปว่าการตั้งค่าการglobalCompositeOperationทำงานกับภาพ

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

ฉันสงสัยว่ามีวิธีที่สามในการตั้งค่าสีเพื่อให้เราสามารถระบายสีภาพและทำให้มันโปร่งใสได้ง่ายหรือไม่

แก้ไข:

หลังจากขุดต่อไปฉันได้ข้อสรุปว่าคุณสามารถตั้งค่าความโปร่งใสของภาพโดยการตั้งค่าglobalAlphaพารามิเตอร์ก่อนที่จะวาดภาพ

//works with images
ctx.globalAlpha = 0.5

หากคุณต้องการให้เอฟเฟ็กต์สีซีดจางเมื่อเวลาผ่านไปคุณต้องการลูปบางอย่างที่เปลี่ยนค่าอัลฟานี่เป็นวิธีที่ค่อนข้างง่ายวิธีหนึ่งที่จะทำให้มันเป็นsetTimeoutฟังก์ชั่นให้ดูที่การสร้างลูป เวลา.


7
globalAlpha ทำงานได้อย่างสมบูรณ์แบบ เป็นส่วนหนึ่งของมาตรฐาน: whatwg.org/specs/web-apps/current-work/multipage/ …
Aleris

42
เพื่อความแม่นยำมันไม่ใช่canvasองค์ประกอบที่มีglobalAlphaคุณสมบัติ แต่เป็นบริบทที่คุณได้รับจากผืนผ้าใบ
Steve Blackwell

8
ความคิดเห็นของเอียนด้านล่างเกี่ยวกับ ctx.save () และ ctx.restore () ป้องกันไม่ให้ globalAlpha ส่งผลกระทบต่อส่วนที่เหลือของผืนผ้าใบ
Arosboro

1
ดูเหมือนกับฉันมากกว่าการควบคุมความทึบของสิ่งที่วาดบนผืนผ้าใบมันจะง่ายกว่าและยังคงมีวัตถุประสงค์เพื่อควบคุมความทึบของผืนผ้าใบทั้งหมดหลังจากวาดภาพ (เพียงครั้งเดียว) ใช้วิธีการ CSS / style ปกติเพื่อทำสิ่งนี้ (canvaselement.style.opacity = '0.3'; ฯลฯ ) ในภายหลังด้วย CSS3 คุณสามารถแจกจ่ายด้วยการวนซ้ำไปเรื่อย ๆ และให้เบราว์เซอร์จัดการกับการซีดจางแทน (เช่นการเปลี่ยน: NNNms ความง่ายในการเข้า - ออก) หรือแม้แต่ "เคลื่อนไหว" ความซีดจาง
Chuck Kollars

1
น่าเสียดายที่canvas2d.fillStyle = "rgba(255, 255, 255, 0.5)";มันใช้ไม่ได้ ค่าต้องเป็นเลขฐานสิบหก
WebWanderer

113

โค้ดตัวอย่างที่ง่ายกว่าสำหรับการใช้globalAlpha:

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

หากคุณจำเป็นต้องimgโหลด:

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

หมายเหตุ:

  • ตั้งค่า'src'ล่าสุดเพื่อรับประกันว่าonloadตัวจัดการของคุณถูกเรียกใช้บนแพลตฟอร์มทั้งหมดแม้ว่าภาพจะอยู่ในแคชแล้ว

  • ห่อการเปลี่ยนแปลงกับสิ่งต่าง ๆ เช่นglobalAlphaระหว่างsaveและrestore(อันที่จริงใช้จำนวนมาก) เพื่อให้แน่ใจว่าคุณไม่ได้ปิดการตั้งค่าจากที่อื่นโดยเฉพาะอย่างยิ่งเมื่อบิตของการวาดรหัสจะถูกเรียกจากเหตุการณ์


globalAlpha จะเบลอภาพหรือภาพวาดทั้งหมดบนผืนผ้าใบซึ่งไม่ใช่สิ่งที่คุณต้องการ
พอใจ

6
@Grumpy - globalAlphaไม่ไม่เบลออะไรเลย มันจะตั้งค่าอัลฟาสำหรับการวาดภาพที่ตามมาทั้งหมด(มันไม่ได้เปลี่ยนแปลงอะไรที่วาดแล้ว) ซึ่งเป็นเหตุผลในรหัสตัวอย่างที่ฉันห่อมันsaveและrestoreเพื่อ จำกัด สิ่งที่มันนำไปใช้
เอียน

ไม่แน่ใจว่า ctx.restore () จะคืนค่า globalAlpha คุณอาจต้องทำสิ่งนี้ในตอนท้าย (อย่างน้อยฉันต้องใช้ Chrome รุ่นก่อนหน้านี้) ctx.globalAlpha = 1;
ฌอน

1
@Sean - หากคุณไม่แน่ใจคุณควรตรวจสอบ มันต้องเป็น Chrome ที่เก่าแก่มากมันใช้งานได้กับทุกแพลตฟอร์มทันที: jsfiddle.net/y0z9h9m7
เอียน

14

แก้ไข: คำตอบที่ทำเครื่องหมายว่า "ถูกต้อง" ไม่ถูกต้อง

มันง่ายที่จะทำ ลองใช้รหัสนี้สลับ "ie.jpg" กับรูปภาพที่คุณมีประโยชน์:

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

กุญแจสำคัญคือคุณสมบัติ globalAlpha

ทดสอบกับ IE 9, FF 5, Safari 5 และ Chrome 12 บน Win7


13

โพสต์เก่าแล้วฉันจะไปกับคำแนะนำของฉัน คำแนะนำจะขึ้นอยู่กับการจัดการพิกเซลในบริบท Canvas 2d จาก MDN:

คุณสามารถจัดการข้อมูลพิกเซลโดยตรงในผืนผ้าที่ระดับไบต์

ในการจัดการพิกเซลเราจะใช้สองฟังก์ชั่นที่นี่ - getImageData และ putImageData

การใช้งานฟังก์ชั่น getImageData:

var myImageData = context.getImageData (ซ้าย, ด้านบน, ความกว้าง, ความสูง);

และไวยากรณ์ putImageData:

context.putImageData (myImageData, dx, dy); // dx, dy - x และ y ชดเชยบนผืนผ้าใบของคุณ

โดยบริบทคือบริบท Canvas 2d ของคุณ

เพื่อรับค่าแดงเขียวน้ำเงินและอัลฟาเราจะทำสิ่งต่อไปนี้:

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คือ x ชดเชยyคือ y ชดเชยบนผืนผ้าใบ

ดังนั้นเราจึงมีรหัสทำให้ภาพโปร่งใสครึ่งหนึ่ง

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

คุณสามารถทำให้คุณเป็นเจ้าของ "ผู้ให้ร่มเงา" - ดูบทความ MDN ฉบับสมบูรณ์ได้ที่นี่


7

คุณสามารถ. ผ้าใบโปร่งใสสามารถจางหายไปได้อย่างรวดเร็วโดยใช้การดำเนินการคอมโพสิตส่วนกลางปลายทาง มันไม่ได้สมบูรณ์แบบ 100% บางครั้งก็ทิ้งร่องรอยไว้บ้าง แต่มันอาจถูกปรับแต่งขึ้นอยู่กับสิ่งที่ต้องการ (เช่นใช้ 'source-over' และเติมด้วยสีขาวด้วยอัลฟาที่ 0.13 จากนั้นจางหายเพื่อเตรียมผืนผ้าใบ)

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

ฉันคิดว่าสิ่งนี้ตอบคำถามได้ดีที่สุดจริง ๆ แล้วมันเปลี่ยนค่าอัลฟ่าของบางสิ่งที่ถูกวาดไปแล้ว บางทีนี่อาจไม่ใช่ส่วนหนึ่งของ API เมื่อมีการถามคำถามนี้

cรับบริบท 2d

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

คำตอบนี้แตกต่างจากคำตอบของ Soul_man ที่ให้รายละเอียดเพิ่มเติมเมื่อ 7 ปีก่อนอย่างไร
BReddy

-2

หากคุณใช้ไลบรารีjCanvasคุณสามารถใช้คุณสมบัติความทึบเมื่อวาด หากคุณต้องการจางหายไปด้านบนของที่นั่นเพียงแค่วาดใหม่ด้วยค่าที่แตกต่างกัน


-11

คุณทำไม่ได้ มันเป็นโหมดกราฟิกทันที แต่คุณสามารถเรียงลำดับของการจำลองโดยการวาดรูปสี่เหลี่ยมผืนผ้าบนสีพื้นหลังด้วยความทึบ

หากภาพอยู่เหนือสิ่งอื่นที่ไม่ใช่สีคงที่ก็จะค่อนข้างยุ่งยาก คุณควรใช้วิธีการจัดการพิกเซลในกรณีนี้ เพียงบันทึกพื้นที่ก่อนที่จะวาดภาพจากนั้นผสมผสานที่ด้านบนด้วยความทึบแสงหลังจากนั้น


5
นี่ไม่ใช่คำตอบที่ถูกต้องดูด้านล่าง
Ryan Badour

คุณถูกต้องแม้ว่าคุณจะไม่สามารถเปลี่ยนความทึบขององค์ประกอบหนึ่งที่คุณวาดลงในผืนผ้าใบ แต่คุณสามารถเปลี่ยนความทึบของผืนผ้าใบทั้งหมดได้ ในบางกรณีที่อาจจะเพียงพอ
MPG

2
MPG - ความคิดเห็นของคุณ (11 พฤษภาคม) ก็ผิดเช่นกัน คุณสามารถเปลี่ยนความทึบของผืนผ้าใบ แต่นั่นไม่ใช่สิ่งที่ OP ต้องการหรือสิ่งที่ถูกแนะนำในคำตอบข้างต้น
เอียน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.