文件BezierMaker.js

var BezierMaker = function(canvas, bezierCtrlNodesArr, color) {// this.canvas = canvasthis.ctx = canvasthis.bezierCtrlNodesArr = bezierCtrlNodesArr ? bezierCtrlNodesArr : []this.color = color ? color: '#ffffff'this.bezierArr = []}
BezierMaker.prototype.bezier = function(t) { //贝塞尔公式调用var x = 0,y = 0,bezierCtrlNodesArr = this.bezierCtrlNodesArr,n = bezierCtrlNodesArr.length - 1,self = thisbezierCtrlNodesArr.forEach(function(item, index) {if(!index) {x += item.x * Math.pow(( 1 - t ), n - index) * Math.pow(t, index) y += item.y * Math.pow(( 1 - t ), n - index) * Math.pow(t, index) } else {x += self.factorial(n) / self.factorial(index) / self.factorial(n - index) * item.x * Math.pow(( 1 - t ), n - index) * Math.pow(t, index) y += self.factorial(n) / self.factorial(index) / self.factorial(n - index) * item.y * Math.pow(( 1 - t ), n - index) * Math.pow(t, index) }})return {x: x,y: y}
}
BezierMaker.prototype.drawBezier = function() { //通过控制点算出实时xy值渲染到canvasvar nodeArr = this.bezierCtrlNodesArr  if(nodeArr.length === 2) {console.warn('Control nodes should be more then two!')var startNode = nodeArr[0],endNode = nodeArr[1]this.ctx.moveTo(startNode.x, startNode.y)this.ctx.lineTo(endNode.x, endNode.y)this.ctx.strokeStyle = this.colorthis.ctx.stroke()} else if(nodeArr.length === 3) {var startNode = nodeArr[0],ctrlNode = nodeArr[1],endNode = nodeArr[2]this.ctx.beginPath()this.ctx.lineWidth = 6;this.ctx.lineJoin = 'round';this.ctx.lineCap = 'round';this.ctx.moveTo(startNode.x, startNode.y)this.ctx.quadraticCurveTo(ctrlNode.x, ctrlNode.y, endNode.x, endNode.y)this.ctx.strokeStyle = this.colorthis.ctx.stroke()} else if(nodeArr.length === 4) {var startNode = nodeArr[0],ctrlNodeA = nodeArr[1],ctrlNodeB = nodeArr[2],endNode = nodeArr[3]this.ctx.beginPath()this.ctx.lineWidth = 6;this.ctx.lineJoin = 'round';this.ctx.lineCap = 'round';this.ctx.moveTo(startNode.x, startNode.y)this.ctx.bezierCurveTo(ctrlNodeA.x, ctrlNodeA.y, ctrlNodeB.x, ctrlNodeB.y, endNode.x, endNode.y)this.ctx.strokeStyle = this.colorthis.ctx.stroke()} else {var self = thisfor(i = 0; i < 1; i+=0.01) {this.bezierArr.push(this.bezier(i))}this.bezierArr.forEach(function(obj, index) {if (index) {var startX = self.bezierArr[index - 1].x,startY = self.bezierArr[index - 1].y,x = obj.x,y = obj.yself.ctx.beginPath()self.ctx.lineWidth = 6;self.ctx.lineJoin = 'round';self.ctx.lineCap = 'round';self.ctx.moveTo(startX, startY)self.ctx.lineTo(x, y)self.ctx.strokeStyle = self.colorself.ctx.stroke()}})}}
BezierMaker.prototype.factorial = function(num) { //递归阶乘if (num <= 1) {return 1;} else {return num * this.factorial(num - 1);}
}
export default BezierMaker
<canvas id="canvasBg" height="1026" width="1148"></canvas>
import BezierMaker from './BezierMaker.js'
data(){return{ctx:{},canvas:{},clickNodes:[],//点击的控制点对象数组bezier:null,num: 0, //控制点数isPrinting :false, //正在绘制中t:0,//贝塞尔函数涉及的占比比例,0<=t<=1bezierNodes: [], //绘制内部控制点的数组}},
mounted(){this.canvas=document.querySelector('#canvasBg')this.ctx = this.canvas.getContext('2d');// this.canvas.style.transform= `scale(.5)`;this.canvas.addEventListener('mousedown', down, false);this.canvas.addEventListener('mousemove', move, false);this.canvas.addEventListener('mouseup', up, false);// this.canvas.addEventListener('mouseout', up, false);let that = this// this.clickNodes = [] //点击的控制点对象数组var bezierNodes = [] //绘制内部控制点的数组var isPrinted = false //当前存在绘制的曲线var isDrag = false //是否进入拖拽行为var isDragNode = false //是否点击到了控制点var dragIndex = 0 //被拖拽的点的索引var clickon = 0 //鼠标按下时间戳var clickoff = 0 //鼠标抬起function down(evt) {isDrag = trueclickon = new Date().getTime()var x = evt.offsetX,y = evt.offsetY// x = clientX - diffLeft,// y = clientY - diffTopthat.clickNodes.forEach(function(item, index) {var absX = Math.abs(item.x - x),absY = Math.abs(item.y - y)if(absX < 10 && absY < 10) {isDragNode = truedragIndex = index}})}function move(e){if(isDrag && isDragNode) {var x = e.offsetX,y = e.offsetY// x = clientX - diffLeft,// y = clientY - diffTopthat.clickNodes[dragIndex] = {x: x,y: y}that.ctx.clearRect(0, 0, that.canvas.width, that.canvas.height)if( that.setDate.length>0){that.setDate.forEach(item=>{that.bezier= new BezierMaker(that.ctx,item,'red')that.bezier.drawBezier()})}that.clickNodes.forEach(function(item, index) {var x = item.x,y = item.y,i = parseInt(index, 10) + 1that.ctx.fillText("p" + i, x, y + 20)that.ctx.beginPath()that.ctx.arc(x, y, 10, 0, Math.PI * 2, false)that.ctx.fill()that.ctx.beginPath()that.ctx.moveTo(startX, startY)that.ctx.lineTo(x, y)that.ctx.strokeStyle = '#696969'that.ctx.stroke()if (index) {var startX = that.clickNodes[index - 1].x,startY = that.clickNodes[index - 1].ythat.ctx.beginPath()that.ctx.moveTo(startX, startY)that.ctx.lineTo(x, y)that.ctx.stroke()}})if(isPrinted) {var bezierArr = []for(i = 0; i < 1; i+=0.01) {bezierArr.push(that.bezierFun(that.clickNodes, i))}bezierArr.forEach(function(obj, index) {if (index) {var startX = bezierArr[index - 1].x,startY = bezierArr[index - 1].y,x = obj.x,y = obj.ythat.ctx.beginPath()that.ctx.moveTo(startX, startY)that.ctx.lineTo(x, y)that.ctx.strokeStyle = 'red'that.ctx.stroke()}})}}}function up(e){isDrag = falseisDragNode = falseclickoff = new Date().getTime()if(clickoff - clickon < 200) {var x = e.offsetX,y = e.offsetYif(!isPrinted && !isDragNode) {that.num++that.ctx.fillStyle = '#696969'that.ctx.font = "30pt Calibri";that.ctx.fillText("p" + that.num, x, y + 20);// that.ctx.fillText("p" + that.num + ': ('+ x +', '+ y +')', 10, that.num * 30)that.ctx.beginPath()that.ctx.arc(x, y, 10, 0, Math.PI * 2, false)that.ctx.fill()if(that.clickNodes.length) {var startX = that.clickNodes[that.clickNodes.length - 1].x,startY = that.clickNodes[that.clickNodes.length - 1].ythat.ctx.beginPath() that.ctx.moveTo(startX, startY)that.ctx.lineTo(x, y)that.ctx.strokeStyle = '#696969'that.ctx.stroke()} that.clickNodes.push({x: x,y: y})}}}
},
methods:{//绘画ligature(){this.bezier= new BezierMaker(this.ctx,this.clickNodes,'red')this.bezier.drawBezier()}//清除removeBtn(){this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)this.clickNodes = []this.setDate=[]this.num=0this.t=0},// 确定sureBtn(){//确定是 请画板上的点去掉 要清空画板 所以线要重新绘画this.clickNodes=[]this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)this.bezier= new BezierMaker(this.ctx,this.clickNodes,'red')this.bezier.drawBezier()},
}

上面的点是可以点击滑动的 改变线的走向 这里用到的是贝塞尔曲线

vue 中canvas 根据点画出圆滑的曲线相关推荐

  1. vue中canvas签名

    vue用canvas横屏签名 最近遇到一个签名需求由于canvas一些特性,横屏签名不好控制,也是多方借鉴才解决,写真就是为了记录下,方便有需要的同学. js代码如下: import Draw fro ...

  2. vue 中 canvas 和svg合用制作地图

    <template><div class="contents"><div class="lefttop1-title">区域 ...

  3. vue中怎样实现弹出层动画效果?由上而下渐渐显示---封装成复用组件

    子组件: <template><div class="home"><!-- 首先将要过渡的元素用transition包裹,并设置过渡的name --& ...

  4. vue中怎样实现弹出层动画效果?由上而下渐渐显示

    1 <template><div class="home"><!-- 首先将要过渡的元素用transition包裹,并设置过渡的name --> ...

  5. Vue中的computed属性

    1.前言 本篇是Vue中最常用到的API之一computed属性,转载信息如下: 作者:gunelark 链接:https://www.cnblogs.com/gunelark/p/8492468.h ...

  6. Element组件引发的Vue中mixins使用,写出高复用组件

    我们都知道 Vue 采用的是一种组件化开发模式,组件在 Vue 中一个非常重要的核心概念.每个组件都是一个完整的实例,组件的创建,组件间的通讯,组件如何更好的复用,以及整个的生命周期的钩子.所以你会发 ...

  7. vue 中利用canvas 给pdf文件加水印---详细教程(附上完整代码)

    需求:在h5网页中打开pdf文件,要求给文件添加水印 实现技术及插件:vue,vue-pdf,canvas 插件安装: npm i vue-pdf --save npm i pdf-lib --sav ...

  8. Vue中如何根据svg内容显示图片

    概述 在写前端项目中,我们免不了需要在页面上显示图片,有的是静态图片,需要直接访问项目内的文件:有的需要从后端接口动态获取图片信息,再在页面上显示. 因为svg图片有:矢量图形,不受像素影响:SVG的 ...

  9. 【3d地图】vue中使用echarts geo3D

    文章目录 前言 一.echarts是什么? 二.使用步骤 1.引入echarts库,3d地图必须安装echarts-gl依赖 2.制作地图JSON文件 2.1 制作自己的json 3.引入到vue组件 ...

最新文章

  1. K近邻(KNN)算法是基于实例的算法,如果训练样本数量庞大,预测的时候挨个计算距离效率会很低下,如何破解?
  2. pycharm控制台调试程序
  3. sqlserver2008登录sa失败
  4. cg word List2
  5. js 匿名函数_编写高质量箭头函数的5个最佳做法
  6. 持续集成部署工具jenkins简介
  7. Mysql查询结果导出为Excel的几种方法
  8. python 最准确的图片转文字软件_图片转文字软件哪个好用?免费的图片转文字软件...
  9. 计算机发展史说课ppt,创新杯 计算机类 说课ppt课件.ppt
  10. GPT转换MBR,MBR转换GPT
  11. php7列目录_linkinfo()
  12. compiled.php,laravel compiled.php 缓存 命令行
  13. thinkAdmin 微信公众号授权
  14. DHCP与DHCP中继
  15. 将png图片转化为icon
  16. 如何批量检测查询域名或者网址是否被微信屏蔽拦截
  17. JAVA将图片转成Base64
  18. CMT2380F32模块开发6-flash例程
  19. Python 身体质量指数BMI
  20. Debian设置root开机不用输密码自动登录

热门文章

  1. Devops持续化集成
  2. GRU预测股票价格,附带例子和完整代码
  3. 用计算机唱樱花下的重逢,抖音樱花树下的重逢是谁唱的
  4. Redis键-值数据库 nosql 数据建模(4)------ 如何存储主从表数据 一对超级多关系
  5. mysqld_safe 启动数据库报找不到 mysqld 启动文件
  6. 数字信号处理学习(二):振动与信号
  7. python做工控机_[Micropython]TPYBoard v202 利用单片机快速实现家庭智能控制平台
  8. 计算机应用基础的题库,计算机应用基础题库
  9. MongoDB 文档数据库
  10. Matlab似然函数