zoukankan      html  css  js  c++  java
  • Canvas 橡皮擦效果

    引子

    解决了第一个问题图像灰度处理之后,接着就是做擦除的效果。

    思路

    一开始想到 Canvas 的画布可以相互覆盖的特性,彩色原图作为背景,灰度图渲染到 Canvas 画布上,然后手指滑动的时候,把接触的部分清除掉,就显示出了背景图。关键的部分是怎么清除画布上已有图像,查询资料发现有两种方式:

    1. 使用 clearRect 方法,会把指定范围所有像素变成透明,并擦除之前绘制的所有内容。
    2. 使用 globalCompositeOperation 属性,该属性设置在绘制新形状时应用合成操作的类型,值为 destination-out 时效果如下:

    66-destination-out

    在上面两种方式中,第一种方式正是功能实现所需要的,但擦除时的边角效果没有第二种方式理想。下面以第二种方式作为示例。

    实现

    在实现的过程中,发现有几点需要注意:

    • 手机端高清显示处理。
    • 注意 globalCompositeOperation 属性设置的时机,过早设置,可能画布上无法显示内容。
    • 擦除状态的控制,特别是在 PC 端,如果不设置相应状态,鼠标移动的时候就可能发生擦除。

    这是示例页面,移动端访问如下:

    66-normal

    优化一

    一般用户都不会全部进行擦除,而且这种体验也不好,所以擦除面积达到一定百分比时,自动擦除剩余的部分。

    擦除效果实际上是改变了已有图像的透明度,可以通过 getImageData 方法查看 Canvas 上图像的像素数据。通过统计符合透明度要求的像素所占百分比,就等效擦除面积的百分比。至于透明度多少算擦除有效,看实际应用场景和所需效果。下面是主要的实现:

      /**
       * 获取透明所占百分比,返回一个 <= 1 的值
       * @param {object} context canvas 上下文对象
       * @param {number} opacity 透明度参考值,初始参考透明值是 128
       */
      function getOpacityPercentage (context, opacity = 128) {
        var imageData = context.getImageData(0,0,248,415);
        var colorDataArr = imageData.data;
        var colorDataArrLen = colorDataArr.length;
        var eraseArea = [];
        // rgba 显示的模式,所以一个像素表示有 4 个分量,透明度是最后一个分量
        for(var i = 0; i < colorDataArrLen; i += 4) {
          // 严格上来说,判断像素点是否透明需要判断该像素点的 a 值是否等于0,
          if(colorDataArr[i + 3] < opacity) {
            eraseArea.push(colorDataArr[i + 3]);
          }
        }
        var divResult = eraseArea.length / (colorDataArrLen/4);
        // 处理除不尽的情况
        var pointIndex = String(divResult).indexOf('.');
        if (pointIndex>-1) {
          divResult = String(divResult).slice(0,pointIndex+5);
        }
        return Number(divResult).toFixed(2);
    
      }
    

    这是示例页面,移动端访问如下:

    66-percentage

    优化二

    优化一中擦除全部的效果是一下子就不见了,但我在那个游戏里面看到的擦除效果是有一个过程的。于是再折腾了一下。

    这是示例页面,移动端访问如下:

    66-progress

    参考资料

  • 相关阅读:
    Java面试
    md5加密
    CSS3画苹果手机
    CSS3的表格布局 文字居中 圆角
    CSS3的新特性 行内盒子before和after
    DIV CSS Sprites精灵 CSS图像拼合 CSS背景贴图定位教程案例
    DAY30
    DedeCMS织梦修改数据库密码和数据库连接失败解决方法
    学习计划
    【原】雅虎前端优化的35条军规
  • 原文地址:https://www.cnblogs.com/thyshare/p/12272855.html
Copyright © 2011-2022 走看看