html5 canvas 让物体随物体中心旋转

  canvas的旋转(rotate)是绕画布的左上角(0,0)开始旋转的,所以直接旋转无法得到想要的效果。

 

  旋转的步骤:

    1. 将(0, 0)偏移到物体的中心: ctx.translate(centerX, centerY);

    2. 执行旋转: ctx.rotate(deg * Math.PI / 180)

    3.偏移到物体中心负值: ctx.translate(-centerX, -centerY)

  

  具体如下:

  html:

<canvas class="cv"></canvas>

  javascript:

let cv = document.querySelector('.cv'),
    ctx = cv.getContext('2d'),
    /*
    * @param Number sx 物体开始绘制的x点
    * @param Number sy 物体开始绘制的y点
    * @param Number width 物体开始绘制的宽
    * @param Number height 物体开始绘制的高
    */
    getCenter = (sx, sy, width, height) => { // 返回物体的中心点
        return {
            x: sx + (width / 2),
            y: sy + (height / 2)
        };
    },
    /*
    * 绘制图形
    */
    draw = () => {
        let x = 50, // 矩形x起点
            y = 50, // 矩形y起点
            width = 50, // 矩形宽
            height = 50,
            deg = 45,
            center = getCenter(x, y, width, height); // 中心

        ctx.clearRect(0, 0, cv.width, cv.height);

        // 绘制
        ctx.save(); // 保存状态,以免影响其它物体
        ctx.fillStyle = 'skyblue';
        ctx.translate(center.x, center.y); // 将画布偏移到物体中心
        ctx.rotate(deg * Math.PI / 180); // 旋转角度
        ctx.translate(-center.x, -center.y); // 将画布偏移回来
        ctx.beginPath(); // 开启路径
        ctx.fillRect(x, y, width, height);
        ctx.closePath(); // 关闭路径
        ctx.stroke(); // 描边绘制
        ctx.restore();// 恢复状态
    };

// 画布大小
cv.width = 800;
cv.height = 500;
draw(); // 开始绘制缩放

 

完整代码:

  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4     <title></title>
  5 </head>
  6 <body>
  7     <canvas class="cv"></canvas>
  8 
  9     <script type="text/javascript">
 10         let cv = document.querySelector('.cv'),
 11             ctx = cv.getContext('2d'),
 12             rects = [], // 保存矩形的数组
 13             n = 50, // 矩形个数
 14             width, height, center, rect,
 15             /*
 16             * @param Number sx 物体开始绘制的x点
 17             * @param Number sy 物体开始绘制的y点
 18             * @param Number width 物体开始绘制的宽
 19             * @param Number height 物体开始绘制的高
 20             */
 21             getCenter = (sx, sy, width, height) => { // 返回物体的中心点
 22                 return {
 23                     x: sx + (width / 2),
 24                     y: sy + (height / 2)
 25                 };
 26             },
 27             /*
 28             * 绘制图形
 29             */
 30             draw = () => {
 31                 ctx.clearRect(0, 0, cv.width, cv.height);
 32 
 33                 for (let i = 0; i < rects.length; i ++) {
 34                     rect = rects[i];
 35                     center = getCenter(rect.x, rect.y, rect.width, rect.height); // 获取矩形的中心
 36 
 37                     // 绘制
 38                     ctx.save(); // 保存状态,以免影响其它物体
 39                     ctx.fillStyle = rect.color;
 40                     ctx.translate(center.x, center.y); // 将画布偏移到物体中心
 41                     ctx.rotate(rect.deg * Math.PI / 180); // 旋转角度
 42                     ctx.translate(-center.x, -center.y); // 将画布偏移回来
 43                     ctx.beginPath(); // 开启路径
 44                     ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
 45                     ctx.closePath(); // 关闭路径
 46                     ctx.stroke(); // 描边绘制
 47                     ctx.restore();// 恢复状态
 48 
 49                     rect.deg += rect.v; // 增加角度
 50                     rect.v += rect.speed;
 51 
 52                     if (rect.v >= 180) { // 旋转180度后删除并重新生成
 53                         rects.splice(i, 1);
 54                         i --;
 55                         create();
 56                     }
 57                 }
 58 
 59                 requestAnimationFrame(draw);
 60             },
 61             /*
 62             * 生成随机颜色
 63             */
 64             randColor = () => {
 65                 let r = Math.floor(Math.random() * 255),
 66                     g = Math.floor(Math.random() * 255),
 67                     b = Math.floor(Math.random() * 255);
 68 
 69                 return `rgb(${r},${g},${b})`;
 70             },
 71             /*
 72             * 创建一个随机矩形
 73             */
 74             create = () => {
 75                 width = (Math.random() * 20) + 20;
 76                 height = (Math.random() * 20) + 20;
 77 
 78                 rects.push({
 79                     x: (Math.random() * (cv.width - (2 * width))) + (2 * width),
 80                     y: (Math.random() * (cv.height - (2 * height))) + (2 * height),
 81                     width, height,
 82                     color: randColor(),
 83                     deg: Math.random() * 360,
 84                     v: 0,
 85                     speed: Math.random()
 86                 });
 87             };
 88 
 89         for (let i = 0; i < n; i ++) {
 90             create();
 91         }
 92 
 93         // 画布大小
 94         cv.width = 800;
 95         cv.height = 500;
 96 
 97         window.requestAnimationFrame = window.requestAnimationFrame
 98                                        || window.webkitRequestAnimationFrame
 99                                        || window.oRequestAnimationFrame
100                                        || window.mozRequestAnimationFrame
101                                        || window.msRequestAnimationFrame
102                                        || function (callback) {
103                                                setTimeout(callback, 1000 / 60);
104                                            };
105 
106         draw(); // 开始绘制缩放
107     </script>
108 </body>
109 </html>

 

posted @ 2019-11-02 10:18  nowtd  阅读(2827)  评论(0编辑  收藏  举报