进修 canvas 的 globalCompositeOperation 做出的奇异结果

申明

最早晓得 canvas 的 globalCompositeOperation 属性,是在须要完成一个刮刮卡结果的时刻,当时也就是网上找到刮刮卡的结果赶忙完成任务就完了,此次又进修一次,希望能加深明白吧。

先来看下 canvas 的 globalCompositeOperation属性,细致是干什么的。

定义

globalCompositeOperation 属性设置或返回如何将一个源(新的)图象绘制到目的(已有)的图象上。

源图象 = 您盘算安排到画布上的画图。

目的图象 = 您已安排在画布上的画图。

这个属性用来设置要在绘制新外形时运用的合成操纵的范例,比如在一个蓝色的矩形上画一个赤色的圆形,是赤色在上显现,照样蓝色在上显现,堆叠的部份显现照样不显现,不堆叠的部份又怎样显现,等一些状况,在面临这些状况的时刻,就是 globalCompositeOperation 属性起作用的时刻了。
在取默许值的状况下,都是显现的,新画的图形会掩盖本来的图形。

用法

默许值: source-over
语法: context.globalCompositeOperation="source-in";

表格中的蓝色矩形为目的图象,赤色圆形为源图象。

属性值 形貌 结果
source-over 默许。在目的图象上显现源图象。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》
source-atop 在目的图象顶部显现源图象。源图象位于目的图象以外的部份是不可见的。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》
source-in 在目的图象中显现源图象。只要目的图象内的源图象部份会显现,目的图象是通明的。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》
source-out 在目的图象以外显现源图象。只会显现目的图象以外源图象部份,目的图象是通明的。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》
destination-over 在源图象上方显现目的图象。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》
destination-atop 在源图象顶部显现目的图象。源图象以外的目的图象部份不会被显现。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》
destination-in 在源图象中显现目的图象。只要源图象内的目的图象部份会被显现,源图象是通明的。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》
destination-out 在源图象外显现目的图象。只要源图象外的目的图象部份会被显现,源图象是通明的。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》
lighter 显现源图象 + 目的图象。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》
copy 显现源图象。疏忽目的图象。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》
xor 运用异或操纵对源图象与目的图象举行组合。 《进修 canvas 的 globalCompositeOperation 做出的奇异结果》

好的,下来完成一个水滴散布的结果
结果图
《进修 canvas 的 globalCompositeOperation 做出的奇异结果》

完成思绪

在一个 canvas 上先画出是非色的图片,然后设置背景是一张彩色的图片,鼠标点击时,设置 canvas 的 globalCompositeOperation 属性值为 destination-out,依据鼠标在 canvas 中的 坐标,用一个不规则的图形逐步增大,来擦撤除是非色的图片,就能够逐步显现彩色的背景了。

也就是说我们须要三张图片

是非的图片

《进修 canvas 的 globalCompositeOperation 做出的奇异结果》

彩色的图片

《进修 canvas 的 globalCompositeOperation 做出的奇异结果》

不规则外形的图片

《进修 canvas 的 globalCompositeOperation 做出的奇异结果》

代码

<!doctype html>
<html>

<head>
    <meta charset="UTF-8">
    <style>
        canvas {
            /* 设置鼠标的光标是一张图片, 16和22 离别示意热门的X坐标和Y坐标 */
            /* https://developer.mozilla.org/zh-CN/docs/Web/CSS/cursor/url */
            cursor: url('https://www.kkkk1000.com/images/mouse.png') 16 22, auto;
        }
    </style>
</head>

<body>
    <canvas id="canvas" width="400px" height="250px"></canvas>

    <script type="text/javascript"> 
        var canvas = document.getElementById("canvas");
        var context = canvas.getContext("2d");

        // 保留图片途径的数组
        var urlArr = ["https://www.kkkk1000.com/images/bg2.png", "https://www.kkkk1000.com/images/clear.png"];
        // imgArr 保留加载后的图片的数组,imgArr中保留的是实在的图片
        // loadImg 函数用来加载 urlArr 中一切的图片
        // 并返回一个保留一切图片的数组
        var imgArr = loadImg(urlArr);
        // flag 用来限定 点击事宜,一张图片只会发生一次结果
        var flag = false;
 

        function loadImg(urlArr) {
            var index = 0;
            var res = [];
            // 每次给 load 函数传入一个图片途径,来加载图片
            load(urlArr[index]);
            function load(url) {
                // 假如 index 即是 urlArr.length,
                // 示意加载完 悉数图片了,就完毕 load函数
                if (index == urlArr.length) {
                    // 加载完悉数图片,挪用 init 函数
                    init();
                    return;
                }

                var img = new Image();
                img.src = url;
                // 不论当前图片是不是加载胜利,都要加载下一张图片
                img.onload = next;
                img.onerror = function () {
                    console.log(res[index] + "加载失利");
                    next();
                }
                // next 用来加载下一张图片
                function next() {
                    // 把加载后的图片,保留到 res 中
                    res[index] = img;
                    load(urlArr[++index])
                }
            }
            // 末了返回保留一切实在图片的数组
            return res;
        }

        function init() {
            // 先在canvas上画是非的图片,然后再设置背景是彩色的图片
            // 防止先显现出彩色图片,再显现出是非的图片
            context.globalCompositeOperation = "source-over";
            context.drawImage(imgArr[0], 0, 0, 400, 250);
            canvas.style.background = 'url(https://www.kkkk1000.com/images/bg.jpg)';
            canvas.style.backgroundSize = "100% 100%";

            // flag 是 true 时,鼠标点击才有水滴散布的结果
            flag = true;
            // canvas 绑定点击事宜,点击时发生水滴散布结果
            canvas.onclick =  diffusion;
        }

        // width 示意 不规则外形的图片的尺寸
        var width = 0;
        // speed 示意散布结果的速率
        var speed = 8;
        // diffusion 函数依据鼠标坐标,发生结果
        function  diffusion (e) {
            if (flag) {
                flag = false;
                context.globalCompositeOperation = "destination-out";
                window.requestAnimationFrame(draw);
                // 依据鼠标坐标,画散布结果
                function draw() {
                    // 这里不肯定须如果 1800 ,但必需是一个足够大的数,能够散布出整张背景图
                    if (width > 1800) {
                        flag = true;
                        return;
                    }
                    width += speed;
                    // 猎取鼠标相对于 canvas 的坐标
                    var x = e.layerX;
                    var y = e.layerY;

                    // 画不规则外形的图片,逐步增大图片尺寸
                    context.drawImage(imgArr[1], x - (width / 2), y - (width / 2), width, width);
                    window.requestAnimationFrame(draw);
                }
            }
        }
    </script>
</body>

</html>

我们继承来完成一个刮刮卡的结果

结果图

《进修 canvas 的 globalCompositeOperation 做出的奇异结果》

刮刮卡结果完成的思绪:

一个 canvas 上先画一层灰色,然后设置canvas的背景图,设置 canvas 的 globalCompositeOperation属性值为 destination-out,点击并挪动时,依据挪动点的坐标,擦撤除灰色,当擦掉一部份时,再自动擦撤除悉数灰色,显现出背景来。

刮刮卡的结果和水滴散布的结果,在最先的时刻几乎是一样的,不过水滴散布结果,用的是一张不规则外形的图片来消灭是非图片,而刮刮卡结果,是经由过程画线的体式格局,线比较粗罢了,来消灭上面的灰色。
重要的不同是,刮刮卡结果末了须要自动擦撤除悉数灰色,这里有两种体式格局。

第一种
运用 canvas 的 getImageData 要领,来猎取 canvas 上的像素信息,这个要领返回的对象的 data 属性是一个一维数组,包括以 RGBA 递次的数据,数据运用 0 至 255(包括)的整数示意,细致的能够看看 canvas 的像素操纵
用这个要领来推断有若干已擦撤除了,也就是经由过程一个变量来纪录有若干像素的RGBA的值是0,当变量的值凌驾某一个值时,就消灭悉数灰色。

代码在这里

第二种
就直接看挪动了若干,鼠标挪动时,会有一个变量举行自增运算,当这个变量,凌驾肯定值时,就擦除悉数灰色。

代码在这里

注重:
第一种体式格局运用 getImageData 存在跨域题目,不过由于这个结果中,没有在canvas上画图片,而是设置canvas的 background 为一张图片,所以这个还没有影响,然则假如canvas上画了其他图片,就可能须要处置惩罚跨域的题目了。
运用 getImageData 能猎取到 canvas 上的像素信息,就能够依据刮刮卡上灰色的面积,决议擦除悉数灰色的机遇,越发天真。

第二种体式格局,虽然不存在跨域的题目,然则,不能很好的依据刮刮卡上灰色的面积,掌握末了擦除悉数灰色的机遇。

总结

文章中的结果主如果运用 globalCompositeOperation属性取值为 destination-out ,而取值为其他值的时刻,一样也是能够制作出种种结果的,人人也能够发挥本身的想象力,去尝尝别的值,或许有新发现呢。

《进修 canvas 的 globalCompositeOperation 做出的奇异结果》

    原文作者:FEWY
    原文地址: https://segmentfault.com/a/1190000016214908
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞