網(wǎng)站首頁 Vue 正文
文件BezierMaker.js
var BezierMaker = function(canvas, bezierCtrlNodesArr, color) {
// this.canvas = canvas
this.ctx = canvas
this.bezierCtrlNodesArr = bezierCtrlNodesArr ? bezierCtrlNodesArr : []
this.color = color ? color: '#ffffff'
this.bezierArr = []
}
BezierMaker.prototype.bezier = function(t) { //貝塞爾公式調(diào)用
var x = 0,
y = 0,
bezierCtrlNodesArr = this.bezierCtrlNodesArr,
n = bezierCtrlNodesArr.length - 1,
self = this
bezierCtrlNodesArr.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() { //通過控制點(diǎn)算出實(shí)時(shí)xy值渲染到canvas
var 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.color
this.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.color
this.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.color
this.ctx.stroke()
} else {
var self = this
for(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.y
self.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.color
self.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(){
retrun{
ctx:{},
canvas:{},
clickNodes:[],//點(diǎn)擊的控制點(diǎn)對(duì)象數(shù)組
bezier:null,
num: 0, //控制點(diǎn)數(shù)
isPrinting :false, //正在繪制中
t:0,//貝塞爾函數(shù)涉及的占比比例,0<=t<=1
bezierNodes: [], //繪制內(nèi)部控制點(diǎn)的數(shù)組
}
},
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 = [] //點(diǎn)擊的控制點(diǎn)對(duì)象數(shù)組
var bezierNodes = [] //繪制內(nèi)部控制點(diǎn)的數(shù)組
var isPrinted = false //當(dāng)前存在繪制的曲線
var isDrag = false //是否進(jìn)入拖拽行為
var isDragNode = false //是否點(diǎn)擊到了控制點(diǎn)
var dragIndex = 0 //被拖拽的點(diǎn)的索引
var clickon = 0 //鼠標(biāo)按下時(shí)間戳
var clickoff = 0 //鼠標(biāo)抬起
function down(evt) {
isDrag = true
clickon = new Date().getTime()
var
x = evt.offsetX,
y = evt.offsetY
// x = clientX - diffLeft,
// y = clientY - diffTop
that.clickNodes.forEach(function(item, index) {
var absX = Math.abs(item.x - x),
absY = Math.abs(item.y - y)
if(absX < 10 && absY < 10) {
isDragNode = true
dragIndex = index
}
})
}
function move(e){
if(isDrag && isDragNode) {
var
x = e.offsetX,
y = e.offsetY
// x = clientX - diffLeft,
// y = clientY - diffTop
that.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) + 1
that.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].y
that.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.y
that.ctx.beginPath()
that.ctx.moveTo(startX, startY)
that.ctx.lineTo(x, y)
that.ctx.strokeStyle = 'red'
that.ctx.stroke()
}
})
}
}
}
function up(e){
isDrag = false
isDragNode = false
clickoff = new Date().getTime()
if(clickoff - clickon < 200) {
var
x = e.offsetX,
y = e.offsetY
if(!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].y
that.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=0
this.t=0
},
// 確定
sureBtn(){
//確定是 請(qǐng)畫板上的點(diǎn)去掉 要清空畫板 所以線要重新繪畫
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()
},
}
上面的點(diǎn)是可以點(diǎn)擊滑動(dòng)的 改變線的走向 這里用到的是貝塞爾曲線
原文鏈接:https://blog.csdn.net/j244233138/article/details/123425367
相關(guān)推薦
- 2023-12-06 Access denied for user root @ localhost (using p
- 2023-01-05 使用sqlplus連接Oracle數(shù)據(jù)庫問題_oracle
- 2022-07-19 詳解的wc find xargs zip gzip bzip2 xz tar sftp命令或者協(xié)議
- 2022-08-29 python中內(nèi)置函數(shù)ord()返回字符串的ASCII數(shù)值實(shí)例詳解_python
- 2022-06-01 一起來學(xué)習(xí)C++的動(dòng)態(tài)內(nèi)存管理_C 語言
- 2022-06-10 SQL?Server使用導(dǎo)出向?qū)Чδ躝MsSql
- 2022-09-19 React?Hook?四種組件優(yōu)化總結(jié)_React
- 2023-03-04 通過column-count和break-inside的CSS3屬性實(shí)現(xiàn)瀑布流
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支