问答详情
源自:4-2 图像变换和状态保存

谁能回答我为什么第一种写法只出现了极少数的星星呢?

563b4566000110c205000268.jpg

563b45680001f77f05000270.jpg

第一张图片用的是逆转的方式,时canvas回到原点,并且我用console打印出来,确实循环绘制了200次星星,每次星星的位置也在画布中,但是画面却只出现数颗星星。

第二张图,采用了save和restore,就画出了大量的星星,请问是怎么回事呢?

提问者:cesiya23 2015-11-05 20:04

个回答

  • 时夏
    2015-12-17 01:26:51

    你好! 关于这个问题, 其实是因为Canvas的rotate的中心点是固定不变的,永远在canvas的 坐标为(0,0)处,并且也无法设置旋转中心点,而不是像CSS里面那样默认在元素的中心点。

    回到你的源代码中,由于每一次的旋转中心点是一样的,而代码中每一次旋转之前都有一个translate,这样的话肯定会导致fillRect之后,context 复位出现问题。

    做了一张图,解释了这么问题,图中 方块1 和方块5 最终位置不一样,所以说明在循环中,每次循环都会影响下一次的Context (context 没有复位成功),所以会导致下一次的渲染位置出现问题,导致位置误差越来越大,并且由于每次rotate的旋转的中心点在(0 ,0), 所以星星的消失很可能是因为后面的星星位置被渲染到了画布之外,其实就是没有啦。

    http://img.mukewang.com/56719177000162bd24802805.jpg

    解决办法就是把 源码中的25 ,26行互换吧,这样先复位rotate ,再复位translate 就没问题啦,不过其实还有一个问题,就是本来直接这样用rotate,很容易会把对象旋转到画布以外,特别是里原点较远的 星星,所以 建议还是 通过简单的变换 来实现 绕自身中心点进行旋转。

    比如对象的位置是在( x , y ),宽度为rectWidth,高度为rectHeight, 我们想让他沿着自身旋转 deg个角度;

    context.translate(x + rectWidth / 2, y + rectHeight / 2);
    context.rotate(deg);
    context.beginPath();
    context.fillRect(-rectWidth/2, -rectHeight/2, rectWidth, rectHeight);
    context.rotate(-deg);
    context.translate(-(x + rectWidth / 2), -(y + rectHeight / 2));

    或者

    context.save();
    context.translate(x + rectWidth / 2, y + rectHeight / 2);
    context.rotate(deg);
    context.beginPath();
    context.fillRect(-rectWidth/2, -rectHeight/2, rectWidth, rectHeight);
    context.restore()


    自己研究的,写的不是很专业 , ~~有些东西自己表达的不是很清楚,见谅哈