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>