如何使用canvas画一个可以调节大小,箭头向上的S型虚线的曲线箭头
时间: 2024-06-11 11:07:53 浏览: 127
绿色箭头雨Canvas特效
以下是使用canvas画一个可以调节大小、箭头向上的S型虚线的曲线箭头的步骤:
1. 创建canvas元素并获取上下文
```
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
</script>
```
2. 定义曲线的起点、终点和控制点
```
const startX = 100;
const startY = 50;
const endX = 400;
const endY = 250;
const controlX = 250;
const controlY = 50;
```
3. 定义箭头的大小和颜色
```
const arrowSize = 10;
const arrowColor = 'red';
```
4. 定义虚线的样式
```
ctx.setLineDash([5, 5]);
ctx.strokeStyle = 'black';
```
5. 画曲线
```
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.quadraticCurveTo(controlX, controlY, endX, endY);
ctx.stroke();
```
6. 画箭头
```
// 计算箭头的坐标
const angle = Math.atan2(endY - controlY, endX - controlX);
const arrowX = endX - arrowSize * Math.cos(angle);
const arrowY = endY - arrowSize * Math.sin(angle);
ctx.fillStyle = arrowColor;
ctx.beginPath();
ctx.moveTo(arrowX, arrowY);
ctx.lineTo(arrowX - arrowSize * Math.cos(angle - Math.PI / 6), arrowY - arrowSize * Math.sin(angle - Math.PI / 6));
ctx.lineTo(arrowX - arrowSize * Math.cos(angle + Math.PI / 6), arrowY - arrowSize * Math.sin(angle + Math.PI / 6));
ctx.fill();
```
7. 添加大小调节功能
```
canvas.addEventListener('mousemove', function(e) {
const x = e.pageX - canvas.offsetLeft;
const y = e.pageY - canvas.offsetTop;
const distance = Math.sqrt(Math.pow(x - controlX, 2) + Math.pow(y - controlY, 2));
if (distance < arrowSize) {
canvas.style.cursor = 'nwse-resize';
} else {
canvas.style.cursor = 'default';
}
});
canvas.addEventListener('mousedown', function(e) {
const x = e.pageX - canvas.offsetLeft;
const y = e.pageY - canvas.offsetTop;
const distance = Math.sqrt(Math.pow(x - controlX, 2) + Math.pow(y - controlY, 2));
if (distance < arrowSize) {
canvas.addEventListener('mousemove', resizeCurve);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', resizeCurve);
});
}
});
function resizeCurve(e) {
const x = e.pageX - canvas.offsetLeft;
const y = e.pageY - canvas.offsetTop;
controlX = x;
controlY = y;
drawCurve();
}
function drawCurve() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setLineDash([5, 5]);
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.quadraticCurveTo(controlX, controlY, endX, endY);
ctx.stroke();
const angle = Math.atan2(endY - controlY, endX - controlX);
const arrowX = endX - arrowSize * Math.cos(angle);
const arrowY = endY - arrowSize * Math.sin(angle);
ctx.fillStyle = arrowColor;
ctx.beginPath();
ctx.moveTo(arrowX, arrowY);
ctx.lineTo(arrowX - arrowSize * Math.cos(angle - Math.PI / 6), arrowY - arrowSize * Math.sin(angle - Math.PI / 6));
ctx.lineTo(arrowX - arrowSize * Math.cos(angle + Math.PI / 6), arrowY - arrowSize * Math.sin(angle + Math.PI / 6));
ctx.fill();
}
```
完整代码如下:
```
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const startX = 100;
const startY = 50;
const endX = 400;
const endY = 250;
let controlX = 250;
let controlY = 50;
const arrowSize = 10;
const arrowColor = 'red';
canvas.addEventListener('mousemove', function(e) {
const x = e.pageX - canvas.offsetLeft;
const y = e.pageY - canvas.offsetTop;
const distance = Math.sqrt(Math.pow(x - controlX, 2) + Math.pow(y - controlY, 2));
if (distance < arrowSize) {
canvas.style.cursor = 'nwse-resize';
} else {
canvas.style.cursor = 'default';
}
});
canvas.addEventListener('mousedown', function(e) {
const x = e.pageX - canvas.offsetLeft;
const y = e.pageY - canvas.offsetTop;
const distance = Math.sqrt(Math.pow(x - controlX, 2) + Math.pow(y - controlY, 2));
if (distance < arrowSize) {
canvas.addEventListener('mousemove', resizeCurve);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', resizeCurve);
});
}
});
function resizeCurve(e) {
const x = e.pageX - canvas.offsetLeft;
const y = e.pageY - canvas.offsetTop;
controlX = x;
controlY = y;
drawCurve();
}
function drawCurve() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setLineDash([5, 5]);
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.quadraticCurveTo(controlX, controlY, endX, endY);
ctx.stroke();
const angle = Math.atan2(endY - controlY, endX - controlX);
const arrowX = endX - arrowSize * Math.cos(angle);
const arrowY = endY - arrowSize * Math.sin(angle);
ctx.fillStyle = arrowColor;
ctx.beginPath();
ctx.moveTo(arrowX, arrowY);
ctx.lineTo(arrowX - arrowSize * Math.cos(angle - Math.PI / 6), arrowY - arrowSize * Math.sin(angle - Math.PI / 6));
ctx.lineTo(arrowX - arrowSize * Math.cos(angle + Math.PI / 6), arrowY - arrowSize * Math.sin(angle + Math.PI / 6));
ctx.fill();
}
drawCurve();
</script>
```
阅读全文