文章目录
- 直线/弧线 箭头
直线/弧线 箭头
// startX,startY 起始坐标
// endX,endY 结束坐标
// radian 圆弧角度,取值[0,PI]; 0表示画直线箭头,否则画圆弧箭头
CanvasRenderingContext2D.prototype.drawArrow = function(startX,startY,endX,endY,radian,options){
if(startX===endX&&startY===endY){return;}
options = options||{'leg':10,'up':true,'lineCap':'round','lineWidth':3,'strokeStyle':'red'}// options.up 弧线是否向上拱
// 备份线条属性
const {lineCap:defaultLineCap,lineWidth:defaultLineWidth,strokeStyle:defaultStrokeStyle} = this;
this.lineCap = options.lineCap;
this.lineWidth = options.lineWidth;
this.strokeStyle = options.strokeStyle
this.beginPath();
let rotatedRadian;
if(!radian){ // radian = 0, 画直线
// 画长直线
this.moveTo(startX,startY);
this.lineTo(endX,endY);
// 计算以结束点为中心点的旋转角度(atan只能返回-PI/2,PI/2,我们需要0,PI,使用atan2)
rotatedRadian = (Math.atan2((startY-endY),(startX-endX)));
}else{// 画圆弧
// 计算圆弧圆心,半径
let [middlePointX,middlePointY] = [(startX+endX)/2,(startY+endY)/2]
let rotatedRadian1
if(options.up){
rotatedRadian1 = (Math.atan2((endY-startY),(endX-startX)))+Math.PI/2;
}else{
rotatedRadian1 = (Math.atan2((startY-endY),(startX-endX)))+Math.PI/2;
}
let len = Math.atan(radian/2)*Math.sqrt(Math.pow(middlePointX-endX,2)+Math.pow(middlePointY-endY,2));
let [radiusPointX,radiusPointY] = [middlePointX + len*Math.cos(rotatedRadian1),middlePointY + len*Math.sin(rotatedRadian1)]
let radius = Math.sqrt(Math.pow(radiusPointX-endX,2)+Math.pow(radiusPointY-endY,2));
// 画弧线
this.arc(radiusPointX,radiusPointY,radius,Math.atan2((startY-radiusPointY),(startX-radiusPointX)),Math.atan2((endY-radiusPointY),(endX-radiusPointX)),!options.up)
if(options.up){
rotatedRadian = (Math.atan2((endY-radiusPointY),(endX-radiusPointX)))-Math.PI/2;
}else{
rotatedRadian = (Math.atan2((radiusPointY-endY),(radiusPointX-endX)))-Math.PI/2;
}
}
// 计算2个箭头线的端点
let x1 = endX + options.leg * Math.cos(rotatedRadian-Math.PI/4);
let y1 = endY + options.leg * Math.sin(rotatedRadian-Math.PI/4);
let x2 = endX + options.leg * Math.cos(rotatedRadian+Math.PI/4);
let y2 = endY + options.leg * Math.sin(rotatedRadian+Math.PI/4);
// 画2个箭头线
this.moveTo(x1,y1);
this.lineTo(endX,endY);
this.moveTo(x2,y2);
this.lineTo(endX,endY);
this.stroke();
// 恢复线条属性
this.lineCap = defaultLineCap
this.lineWidth = defaultLineWidth;
this.strokeStyle = defaultStrokeStyle
}
context.drawArrow(0,0,220,120,Math.PI*3)
context.drawArrow(0,0,120,80,Math.PI/4)
context.drawArrow(60,130,60,20)
context.drawArrow(257,50,50,133)
此文将持续更新…