箭头线
vue+uni-app+canvas 画带箭头可拖动的线段
利用canvas画板绘制一条带有箭头的线段 能够自由拖拽方向和距离的线段
<template>
<div>
<canvas ref="canvas" class="canvas" width="600px" height="400px" @mousedown="startDrawing" @mousemove="draw" @mouseup="stopDrawing"></canvas>
</div>
</template>
<script>
export default {
data() {
return {
drawing: false,
context: null,
startX: 0,
startY: 0,
endX: 0,
endY: 0
};
},
mounted() {
this.initializeCanvas();
},
methods: {
initializeCanvas() {
this.context = this.$refs.canvas.getContext('2d');
this.context.strokeStyle = 'red';
this.context.lineWidth = 2;
this.context.strokeRect(300, 150, 10, 100);
},
startDrawing(event) {
this.drawing = true;
let rect = this.$refs.canvas.getBoundingClientRect()
this.startX = event.clientX - rect.left;
this.startY = event.clientY - rect.top;
},
draw(event) {
if (!this.drawing) return;
let rect = this.$refs.canvas.getBoundingClientRect()
this.endX = event.clientX - rect.left;
this.endY = event.clientY - rect.top;
this.clearCanvas();
this.drawLineArrow(this.context, this.startX, this.startY, this.endX, this.endY);
},
stopDrawing() {
this.drawing = false;
this.clearCanvas();
this.startX = 0
this.startY = 0
this.endX = 0
this.endY = 0
},
clearCanvas() {
this.context.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height);
},
drawArrowLine(startX, startY, endX, endY) {
this.context.beginPath();
this.context.moveTo(startX, startY);
this.context.lineTo(endX, endY);
// 计算箭头的角度
const angle = Math.atan2(endY - startY, endX - startX);
// 绘制箭头部分
const arrowSize = 10;
this.context.lineTo(endX - arrowSize * Math.cos(angle - Math.PI / 6), endY - arrowSize * Math.sin(angle - Math.PI / 6));
this.context.moveTo(endX, endY);
this.context.lineTo(endX - arrowSize * Math.cos(angle + Math.PI / 6), endY - arrowSize * Math.sin(angle + Math.PI / 6));
this.context.stroke();
},
/**
*
* @param {*canvas context 对象} ctx
* @param {*起点横坐标} fromX
* @param {*起点纵坐标} fromY
* @param {*终点横坐标} toX
* @param {*终点纵坐标} toY
* 以下注释以终点在坐标第一象限内,且方向为右上方
*/
drawLineArrow(ctx, fromX, fromY, toX, toY) {
var headlen = 0.2 * 1.41 * Math.sqrt((fromX - toX) * (fromX - toX) + (fromY - toY) * (fromY - toY));//箭头头部长度
headlen = headlen > 40 ? 40 : headlen;//40是箭头头部最大值
var theta = 30;//自定义箭头线与直线的夹角
var arrowX, arrowY;//箭头线终点坐标
// 计算各角度和对应的箭头终点坐标
var angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI;
var angle1 = (angle + theta) * Math.PI / 180;
var angle2 = (angle - theta) * Math.PI / 180;
var topX = headlen * Math.cos(angle1);
var topY = headlen * Math.sin(angle1);
var botX = headlen * Math.cos(angle2);
var botY = headlen * Math.sin(angle2);
var toLeft = fromX > toX;
var toUp = fromY > toY;
//箭头最上点
arrowX = toX + topX;
arrowY = toY + topY;
//箭头下拐点
var arrowX1 = toX + botX;
var arrowY1 = toY + botY;
//箭头上拐点
var arrowX2 = toUp ? arrowX + 0.25 * Math.abs(arrowX1 - arrowX) : arrowX - 0.25 * Math.abs(arrowX1 - arrowX);
var arrowY2 = toLeft ? arrowY - 0.25 * Math.abs(arrowY1 - arrowY) : arrowY + 0.25 * Math.abs(arrowY1 - arrowY);
//箭头最下点
var arrowX3 = toUp ? arrowX + 0.75 * Math.abs(arrowX1 - arrowX) : arrowX - 0.75 * Math.abs(arrowX1 - arrowX);
var arrowY3 = toLeft ? arrowY - 0.75 * Math.abs(arrowY1 - arrowY) : arrowY + 0.75 * Math.abs(arrowY1 - arrowY);
ctx.beginPath();
//起点-起点,闭合
ctx.moveTo(fromX, fromY);
ctx.lineTo(arrowX2, arrowY2);
ctx.lineTo(arrowX, arrowY);
ctx.lineTo(toX, toY);
ctx.lineTo(arrowX1, arrowY1);
ctx.lineTo(arrowX3, arrowY3);
ctx.lineTo(fromX, fromY);
ctx.closePath();
ctx.strokeStyle = "#FB8978";
ctx.fillStyle = "rgba(255,197,179,0.3)";
ctx.fill();
ctx.stroke();
}
}
};
</script>
<style scoped>
/* 可以添加一些样式 */
.canvas {
/* width: 800px;
height: 500px; */
background: #ccc;
}
</style>
本文暂时没有评论,来添加一个吧(●'◡'●)