canvas 仿迷盘旋转对称

canvas 仿迷盘旋转对称

不知道大家玩没玩过迷盘这类的画图娱乐软件,前几天陪我家小孩子玩的时候,感觉挺有趣的,然后萌发了自己写一个类似的程序玩玩,然后就有了以下的这个程序。
话不多说,先奉上效果图看下:
canvas

demo地址:https://liuxiaochaogit.github.io/demo/fandisk/index.html

起初开始是想用多张canvas来实现这个功能,后来看别人的帖子,发现早就类似的程序了,然后还发现别人的思路更清晰,再然后就无耻的借用了别人的思路(请原谅我)。

主要使用了canvas的translate和rotate方法,如有对canvas不了解的小伙伴请自行百度。

过程:

  1. 首先需要准备两张画布,一张用来显示分割的扇形区域,另一张绘制

     // 绘制主体
     <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 = {};
    
  2. 分割扇形区域很简单,其实就是根据数量计算角度,然后旋转到指定角度,画一半径,直至一圈画完

     // 绘制扇形分区  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();
     }
    
  3. 这样的话你会发现是旋转了,但是他是围绕着(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();
     }
    
  4. 接下来就是主体了,首先我们需要监听鼠标事件,得到鼠标运动路径,并在画布上将轨迹画出来

     // 监听事件 画图
     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);
         });
     });
    
  5. 是可以随意涂鸦了,但是怎么才能做到对称呢,这还得依靠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();
         }
     }            
    
  6. 现在一个可以对称涂鸦的画板就成功了,有点注释,虽然不是很完美,有点注释,虽然不是很完美,但是相信差不多都能看懂,完整demo代码在这里 https://github.com/liuxiaochaoGit/demo/tree/master/fandisk

本文纯手打,有不当之处请留言!如果对小伙伴们有帮助的话,点赞啊,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值