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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM