利用canvas影像合成实现刮刮卡效果

深藏阁楼爱情的钟 2023-07-19 10:37 133阅读 0赞

文章目录

    • Canvas对象
    • CanvasRenderingContext2D
    • 合成
    • 刮刮乐效果的实现

Canvas对象

HTML的canvas元素;
它定义了一个在客户端使用脚本绘图的API,可以直接为这个对象定义width和height。
也可以用toDataURL()方法从画布中导出图片。
不过实际绘图API是由getContent()方法返回的一个独立“上下文”对象 —> CanvasRenderingContext2D

CanvasRenderingContext2D

通过Canvas的getContext方法获得

  1. lat canvas =document.getElementById('canvas');
  2. let ctx = canvas.getContext('2d');

以下合成都是基于该对象操作的

合成

通常在画布上绘制图像时,新画的图像会在之前绘制内容上的上面,并根据透明度,部分或者全部遮住旧的。
通过设置属性globalCompositeOperation的值来控制合成效果

学习合成前先了解几个概念
源:正要在画布上画的像素 S
目标:画布上现有像素 D
结果:源像素与目标像素混合之后的像素 R

常用的3个属性:

  • ‘source-over’:
    默认值,源像素绘制在目标像素上面,如果源像素是半透明的,目标像素也会受到影响

计算公式R= S + (1 - 源像素的透明度)* D

  • ‘copy’:
    关闭合成,源像素原封不动的绘制到画布上(目标像素会被清空)

合成公式 R= S

  • ‘destination-over’:
    源像素绘制到目标像素下面,如果目标像素是半透明的,源像素颜色会受到影响

计算公式 R=(1 - 目标像素的透明度)* S + D

其他属性

  • lighter
    混合后的颜色是目标像素和源像素的简单相加,如果和大于最大值则舍去超出部分
  • destination-atop
    在目标像素下面绘制源像素,如果源像素是透明的,结果也是透明的(即不在源像素区域内的目标像素会变透明)
  • source-atop
    在目标像素上面绘制源像素,透明度是源像素与目标像素的透明的乘积,如果目标像素是透明的则什么都不画(即只能在目标像素区域内绘制源像素)
  • destination-out
    如果源像素不透明则目标像素转为透明的,如果源像素透明则目标像素不变,忽略颜色(把目标像素与源像素相交的部分抹掉,只留下目标里不相交的部分,即擦除效果)

计算公式 R= (1 - 源像素透明度) * D

可用于实现刮刮乐效果

  • source-out
    跟上面的刚好相反,如果目标像素是透明的,结果是源像素,忽略目标像素的颜色(只绘制源像素里与目标像素不相交的内容)

计算公式 R = (1 - 目标像素透明度) * S

  • destination-in
    将目标像素的值与源像素的透明度相乘,忽略源像素颜色(留下相交部分)
  • source-in
    将源像素的值与目标元素的透明度相乘,目标像素的颜色忽略。如果目标像素是透明的,结果也是透明的

刮刮乐效果的实现

本demo是针对于PC端,移动端需要把监听事件改成对应的touchstart, touchmove, touchend。

以下demo里包含了两种实现思路:

  1. 通过globalCompositeOperation = ‘destination-out’
  2. 通过ctx.clearRect(x, y, width, height)



    谢谢惠顾!


    let canvas = document.getElementById(‘canvas’)
    let ctx = canvas.getContext(‘2d’);
    let { width, height, offsetLeft, offsetTop } = canvas;
    ctx.fillStyle = ‘gray’;
    let parentNode = canvas.offsetParent;
    while (parentNode !== document.body) {
    offsetTop += parentNode.offsetTop;
    parentNode = parentNode.offsetParent;
    }
    ctx.fillRect(0,0,width, height);
    ctx.save();

    // 关键点
    ctx.globalCompositeOperation = ‘destination-out’;

    ctx.beginPath();
    ctx.strokeStyle = ‘red’;
    ctx.lineCap = ‘round’;
    ctx.lineJoin = ‘round’;
    ctx.lineWidth= 30;
    function handleGua (e) {

    1. let { clientX, clientY } = e;
    2. let x = clientX - offsetLeft, y = clientY - offsetTop;
    3. ctx.lineTo(x, y);
    4. ctx.stroke();
    5. // 不用合成的话,可以通过清除来达到刮刮乐的效果
    6. // ctx.clearRect(clientX, clientY, 20,20);

    }
    canvas.addEventListener(‘mousedown’, function (e) {

    1. canvas.addEventListener('mousemove', handleGua);

    }, false)
    document.body.addEventListener(‘mouseup’, function (e) {

    1. canvas.removeEventListener('mousemove', handleGua);

    }, false)

发表评论

表情:
评论列表 (有 0 条评论,133人围观)

还没有评论,来说两句吧...

相关阅读

    相关 H5之canvas

    原理:利用globalCompositeOperation 抠出来那个画出来的那个图像设置为透明,然后就能看到这个画布下层的图片 api: globalCompositeO