• canvas离屏、旋转效果实践——旋转的雪花


    效果展示
    理论基础——“常见的canvas优化——模糊问题、旋转效果”

    用离屏canvas画基础部分

    1、封装画线函数

    function drawLine(ctx,x1,y1,x2,y2,color){
      ctx.save();
      ctx.beginPath();
      ctx.strokeStyle = color;
      ctx.lineTo(x1, y1);
      ctx.lineTo(x2, y2);
      ctx.stroke();
      ctx.restore();
    }

    2、画雪花的六条线

    function canvasSingleSnow(snowSize){
      var singleSnow = document.createElement('canvas');
      var ctxSingle = singleSnow.getContext('2d');
      singleSnow.setAttribute('width', snowSize * 2);
      singleSnow.setAttribute('height', snowSize * 2);
      ctxSingle.translate(snowSize, snowSize);//定位原点到画布中心
      for(var i = 0; i < 6; i++){//画六条线
        ctxSingle.save();
        ctxSingle.rotate(Math.PI*2 * i/6);
        drawLine(ctxSingle, 0, 0, snowSize, 0,"#656565");
        ctxSingle.restore();
      }
      return singleSnow;
    }

    首先这里用到了离屏canvas,我们通过传参的方式确定离屏canvas的尺寸,是为了尽可能避免canvas图案缩放导致的显示效果问题。

    另外这里for循环中用到了canvas的旋转效果,所以我们可以很轻易的画出6条有角度的线。效果如下图所示

    clipboard.png

    3、画出完整的雪花

    function drawCanvasSnow(centerSnow){
      var canvasSnow = document.createElement('canvas');
      var ctxSnow = canvasSnow.getContext('2d');
      canvasSnow.setAttribute('width', centerSnow * 2);
      canvasSnow.setAttribute('height', centerSnow * 2);
      //画一个大雪花
      var bigSnow = canvasSingleSnow(centerSnow);
      ctxSnow.drawImage(bigSnow, 0, 0, bigSnow.width, bigSnow.height,
        0, 0, centerSnow * 2, centerSnow * 2);
      //画六个小雪花
      var smallSnow = canvasSingleSnow(centerSnow/3);
      var sizeSnow = centerSnow * 3/5;//小雪花的尺寸(直径)
      var rSnow = centerSnow - sizeSnow/2;//小雪花的位置(离大雪花中心的距离)
      for(var i = 0; i < 6; i++){
        ctxSnow.save();
        ctxSnow.translate(centerSnow, centerSnow);
        ctxSnow.rotate(Math.PI*2 * i/6);
        ctxSnow.drawImage(smallSnow, 0, 0, smallSnow.width, smallSnow.height,
          rSnow - sizeSnow/2, -sizeSnow/2, sizeSnow, sizeSnow);
        ctxSnow.restore();
      }
      return canvasSnow;
    }

    上述代码中尺寸部分说明:小雪花的尺寸比大雪花小,用比例可以方便缩放;小雪花的位置则固定在大雪花六条线的端点处。效果如下图所示

    clipboard.png

    将离屏canvas作为资源画到实际显示的canvas上

    1、封装一个根据旋转加载离屏canvas的函数

    //r为雪花图案中心距画布中心的距离
    //angle为雪花图案在画布上的安放角度
    //size为雪花图案的显示尺寸
    function drawSnowAngle(ctx,r,angle,size){
      ctx.save();
      ctx.rotate(Math.PI*2 * angle);
      drawLine(ctx,0,0,r,0,"#656565");
      ctx.drawImage(canvasSnow, 0, 0, canvasSnow.width, canvasSnow.height,
        r - size/2, -size/2, size, size);
      ctx.restore();
    }

    2、可以将离屏canvas画的雪花图案画到实际显示的canvas上了

    //center为实际显示canvas的画布中心(半径)
    //rSnow为雪花图案的半径
    drawSnowAngle(ctx, center - rSnow, i/snowNum, rSnow * 2);

    3、加上动态旋转效果

    var snowNum = 1;
    var isAdd = true;
    var loop = setInterval('drawCanvas()', 10);//定时器,每10ms绘制一次
    function drawCanvas(){
      //设置旋转效果
      if(snowNum >= 18){isAdd = false;}//最大个数为18
      else if(snowNum <= 1){isAdd = true;}//最小个数为1
      if(isAdd){snowNum += snowNum/200;}//达到最大后开始递减
      else{snowNum -= snowNum/100;}//达到最少后开始递增
      //画图
      var rSnow = center/2 * (snowNum - 6)/6;//设置雪花图案显示尺寸
      canvasSnow = drawCanvasSnow(rSnow);//画出离屏雪花图案
      ctx.clearRect(-center, -center, center * 2, center * 2);//清除画布
      for(var i = 0; i < snowNum; i++){//开始画图
        drawSnowAngle(ctx, center - rSnow, i/snowNum, rSnow * 2);
      }
    }

    旋转的雪花就这样完成了。效果见文章开头的效果展示链接

  • 相关阅读:
    formValidator表单验证
    js中判断一个对象的类型的种种方法
    利用jQuery中的serialize方法大量获取页面中表单的数据,发送的服务器
    用html和css写一个头部header和左侧菜单栏menu-bar固定的的页面
    关于刚才那个全选问题的解决
    关于input[type='checkbox']全选的问题
    用CSS来定义<p>标签,要求实现以下效果:字体颜色再IE6下为黑色,IE7下为红色,IE8下为绿色,其他浏览器下为黄色。
    Vue.js(20)之 封装字母表(是这个名字吗0.0)
    Vue.js之calendar组件
    书:构造器模式
  • 原文地址:https://www.cnblogs.com/10manongit/p/12892140.html
Copyright © 2020-2023  润新知