canvas 仿迷盘旋转对称
canvas 仿迷盘旋转对称
不知道大家玩没玩过迷盘这类的画图娱乐软件,前几天陪我家小孩子玩的时候,感觉挺有趣的,然后萌发了自己写一个类似的程序玩玩,然后就有了以下的这个程序。
话不多说,先奉上效果图看下:
demo地址:https://liuxiaochaogit.github.io/demo/fandisk/index.html
起初开始是想用多张canvas来实现这个功能,后来看别人的帖子,发现早就类似的程序了,然后还发现别人的思路更清晰,再然后就无耻的借用了别人的思路(请原谅我)。
主要使用了canvas的translate和rotate方法,如有对canvas不了解的小伙伴请自行百度。
过程:
-
首先需要准备两张画布,一张用来显示分割的扇形区域,另一张绘制
// 绘制主体 <canvas id="cvs" width="600" height="600"> 您的浏览器太low了,建议升级或者更换浏览器 </canvas> // 用来分割扇形区域 <canvas id="lineCvs" width="600" height="600"> 您的浏览器太low了,建议升级或者更换浏览器 </canvas> // script let canvas = document.getElementById('cvs'), lineCanvas = document.getElementById('lineCvs'), partition = document.getElementById('partition'), color = document.getElementById('color'), extent = document.getElementById('extent'), cvs = canvas.getContext('2d'), lineCvs = lineCanvas.getContext('2d'), radius = canvas.width, ob = {};
-
分割扇形区域很简单,其实就是根据数量计算角度,然后旋转到指定角度,画一半径,直至一圈画完
// 绘制扇形分区 num drawLine(num) { let _ob = {}, centerX = _ob.startX = radius / 2, centerY = _ob.startY = radius / 2, moveX = _ob.moveX = radius / 2, moveY = _ob.moveY = 0, _this = this; // 角度 let deg = 360 / num; for (var i = 0; i < num; i++) { // 弧度 deg * Math.PI / 180 lineCvs.rotate(deg * Math.PI / 180); _this.draw(lineCvs, _ob); lineCvs.save(); } } // 绘制 draw(cvs, ob) { let _cvs = cvs, _ob = ob; _cvs.beginPath(); // 坐标 _cvs.moveTo(_ob.startX, _ob.startY); _cvs.lineTo(_ob.moveX, _ob.moveY); _cvs.stroke(); }
-
这样的话你会发现是旋转了,但是他是围绕着(0,0)坐标旋转的,我们想要的是围绕中心旋转,这就用到了translate方法
// 将中心点移动到画布的中心 lineCvs.translate(lineCvs.canvas.width / 2, lineCvs.canvas.height / 2); // 绘制坐标也需要减去位移的距离 draw(cvs, ob) { let _cvs = cvs, _ob = ob; _cvs.beginPath(); // 坐标减去位移的长度 _cvs.moveTo(_ob.startX - radius / 2, _ob.startY - radius / 2); _cvs.lineTo(_ob.moveX - radius / 2, _ob.moveY - radius / 2); _cvs.stroke(); }
-
接下来就是主体了,首先我们需要监听鼠标事件,得到鼠标运动路径,并在画布上将轨迹画出来
// 监听事件 画图 canvas.addEventListener('mousedown', (e) => { let ob = {}; let startX = ob.startX = ob.moveX = e.clientX - canvas.parentElement.offsetLeft + window.scrollX, startY = ob.startY = ob.moveY = e.clientY - canvas.parentElement.offsetTop + window.scrollY; document.addEventListener('mousemove', moveE = (e) => { ob.startX = ob.moveX; ob.startY = ob.moveY; let moveX = ob.moveX = e.clientX - canvas.parentElement.offsetLeft + window.scrollX, moveY = ob.moveY = e.clientY - canvas.parentElement.offsetTop + window.scrollY; draw(cvs, ob); }); document.addEventListener('mouseup', (e) => { document.removeEventListener('mousemove', moveE); }); });
-
是可以随意涂鸦了,但是怎么才能做到对称呢,这还得依靠rotate()这个牛叉的方法,我的思路是这样的,比如说被分成了6个扇形区域,那么这六个扇形区域内部的所有都必须是对称的,
我们可以将一个区域复制六份,每个区域一份不就完了(为自己的机智点赞),其实就是旋转六次,每次都保存住画布状态,下次画的时候再取出状态,然后不就行了// 旋转 rotateDraw(num, ob) { let deg = 360 / num, _this = this; // 位移 坐标定于圆心 让旋转围绕圆心旋转 cvs.translate(radius / 2, radius / 2); for (var i = 0; i < 360; i++) { // 取出之前保存的状态 cvs.restore(); cvs.rotate(deg * Math.PI / 180); this.draw(cvs, ob); // 绘制完保存状态 cvs.save(); } }
-
现在一个可以对称涂鸦的画板就成功了,有点注释,虽然不是很完美,有点注释,虽然不是很完美,但是相信差不多都能看懂,完整demo代码在这里 https://github.com/liuxiaochaoGit/demo/tree/master/fandisk
本文纯手打,有不当之处请留言!如果对小伙伴们有帮助的话,点赞啊,谢谢!