今天看啥  ›  专栏  ›  遁地龙卷风

canvas中的数学3

遁地龙卷风  · 掘金  ·  · 2018-11-12 06:11

codepen.io/xiaodun/pen…

缓慢的拖动滑块,这是一个有人体视觉加成的效果! 用截图工具无法保留它的美,因为它本身由4个元素组成,两根线。

就在我写这篇文章时,发现调出开发者工具,使得画布的高度出现变化,由于两根线交点位置发生变化,会有更有意思的效果!

填充元素

if(this.isStart && this.data.length == 0){
    for (var i = 0; i < 4; i++) {
      
      this.data[i] = {
        x: this.width / 2,
        y: this.height / 2,
        c: this.color,
      };
   
    }
        this.rotate = 0;
        this.elementWidth = Math.sqrt(Math.pow(this.width / 2, 2) + Math.pow(this.height / 2, 2));
        this.data[0].x1 = this.width / 2 - this.elementWidth;
        this.data[0].y1 = this.height / 2;
        this.data[1].x1 = this.width / 2 + this.elementWidth;
        this.data[1].y1 = this.height / 2;
        this.data[2].x1 = this.width / 2;
        this.data[2].y1 = this.height / 2 + this.elementWidth;
        this.data[3].x1 = this.width / 2;
        this.data[3].y1 = this.height / 2 - this.elementWidth;
  }

this.elementWidth = Math.sqrt(Math.pow(this.width / 2, 2) + Math.pow(this.height / 2, 2));

让产生的值既大于高度也大于宽度,因为this.width / 2的二次方大于this.width * 2 ,大于this.width, this.height / 2的二次方大于this.height*2 大于this.height。

剩下的代码是初始化起始点。

画图逻辑

 this.pen.clearRect(0, 0, this.width, this.height);
 this.pen.lineWidth = 5;
 
 this.pen.globalAlpha = this.opacity;
 this.pen.save();
 this.pen.translate(this.width / 2, this.height / 2);
 this.pen.rotate((this.rotate * Math.PI) / 180);
 this.pen.translate(-this.width / 2, -this.height / 2);
 for(let i=0;i<this.data.length;i++){
    let item = this.data[i];
    this.pen.strokeStyle = item.c;
    this.pen.beginPath();
    this.pen.moveTo(item.x, item.y);
    this.pen.lineTo(item.x1, item.y1);
    this.pen.closePath();
    this.pen.stroke();
 }
 this.pen.restore();
 this.rotate += this.perAddrad;

围绕画布的中心进行旋转

  this.pen.translate(this.width / 2, this.height / 2);
 this.pen.rotate((this.rotate * Math.PI) / 180);
 this.pen.translate(-this.width / 2, -this.height / 2);

注意前面的this.pen.save(); 和后面 this.pen.restore(); 前者是保存画布的状态,后者是恢复,每次清空之前的绘画也很重this.pen.clearRect(0, 0, this.width, this.height); 可以注释掉,看看效果!

有一个会引起争议的地方

 this.rotate += this.perAddrad;

这个变量记录旋转的角度,让它一直这么加下去,是会超出最大值

这个问题 在后面加上

if(this.rotate > 180){
   this.rotate  -= 180;
 }

因为rotate 接受得是弧度,(this.rotate * Math.PI) / 180) 是做转换用的,而旋转是360度的倍数和没旋转的效果是一样的,比如rotate为0,perAddrad是180 也是不动的。变为180.1 动了,变为180.000001看不到明显得转动,如果有耐心,多看一会,会发现抖动的越来越明显,js对小数的计算是不精准的。

是不是不加就会造成多大的问题呢,甚至视为一个bug或者是低级错误,其实在编码中,有很多类似这样的问题,该不该声明一个变量啊,抽调函数啊,我的看法是,知道溢出这个问题就好!但有些时候啊,有些人啊,未必知道其中要害,只是照本宣读!

比如,perAddrad这个命名是不好的... 但是专门为了这个去改程序,是没有必要的,有些美好要留给未来,当然,若是哪天心情好...,有些标准确实是好,但是当感受不到它的好时,不要为了用而用,多做多练多学习,心存敬畏,想着光明前行,早晚会感受到它的好。也会用的舒坦。有些跑题...

rotate从0开始 ,perAddrad 为 1800000000000000000000000000000000000(35个0),往后每增加一个0,看不到明显旋转的时间越快,但也远小于1.7976931348623157e + 308

requestAnimationFrame 尽量保证每秒执行60次,粗略的算一下,以2.8799999999999928e+38为例 2.8799999999999928e+38 / 100 / 60 /60/60/24/365 为 1.5220700152206965e+27年 别说人了,世界可能都没了。

有趣的是。

如果使得初始值为12222234567左右,会看到旋转变的很慢,并不是停止,要很长时间才动一动,当增大perAddrad时,又能够愉快得旋转了。当perAddrad值为1.7976931348623157e+306时,可以明显的看到,旋转了一下,而当rotate为15.909999999999899e+190,perAddrad为4时,你会发现打印已变成 image.png

这时我在chrome 68.0.3440.106 做的实验。




原文地址:访问原文地址
快照地址: 访问文章快照