Skip to main content

如何使用锚点修改曲线点?

本演示展示了如何创建可以通过拖动锚点进行修改的交互式曲线(抛物线和贝塞尔曲线)。这种技术通常用于矢量图形编辑器,使用户能够创建和调整自定义曲线。

说明: 使用鼠标或手指拖动锚点,以修改抛物线(红色)和贝塞尔曲线(蓝色)的曲率。

import Konva from 'konva';

const width = window.innerWidth;
const height = window.innerHeight;

// 创建舞台和图层
const stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});

const layer = new Konva.Layer();
stage.add(layer);

// 构建锚点的函数
function buildAnchor(x, y) {
const anchor = new Konva.Circle({
x: x,
y: y,
radius: 20,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
draggable: true,
});
layer.add(anchor);

// 添加悬停样式
anchor.on('mouseover', function () {
document.body.style.cursor = 'pointer';
this.strokeWidth(4);
});

anchor.on('mouseout', function () {
document.body.style.cursor = 'default';
this.strokeWidth(2);
});

// 当锚点移动时更新曲线
anchor.on('dragmove', function () {
updateDottedLines();
});

return anchor;
}

// 更新虚线点(显示控制点)的函数
function updateDottedLines() {
const q = quad;
const b = bezier;

const quadLinePath = layer.findOne('#quadLinePath');
const bezierLinePath = layer.findOne('#bezierLinePath');

// 更新抛物线的控制点线
quadLinePath.points([
q.start.x(),
q.start.y(),
q.control.x(),
q.control.y(),
q.end.x(),
q.end.y(),
]);

// 更新贝塞尔曲线的控制点线
bezierLinePath.points([
b.start.x(),
b.start.y(),
b.control1.x(),
b.control1.y(),
b.control2.x(),
b.control2.y(),
b.end.x(),
b.end.y(),
]);
}

// 创建具有自定义形状的抛物线
const quadraticLine = new Konva.Shape({
stroke: 'red',
strokeWidth: 4,
sceneFunc: (ctx, shape) => {
ctx.beginPath();
ctx.moveTo(quad.start.x(), quad.start.y());
ctx.quadraticCurveTo(
quad.control.x(),
quad.control.y(),
quad.end.x(),
quad.end.y()
);
ctx.fillStrokeShape(shape);
},
});
layer.add(quadraticLine);

// 创建具有自定义形状的贝塞尔曲线
const bezierLine = new Konva.Shape({
stroke: 'blue',
strokeWidth: 5,
sceneFunc: (ctx, shape) => {
ctx.beginPath();
ctx.moveTo(bezier.start.x(), bezier.start.y());
ctx.bezierCurveTo(
bezier.control1.x(),
bezier.control1.y(),
bezier.control2.x(),
bezier.control2.y(),
bezier.end.x(),
bezier.end.y()
);
ctx.fillStrokeShape(shape);
},
});
layer.add(bezierLine);

// 创建虚线以显示抛物线的控制点
const quadLinePath = new Konva.Line({
dash: [10, 10, 0, 10],
strokeWidth: 3,
stroke: 'black',
lineCap: 'round',
id: 'quadLinePath',
opacity: 0.3,
points: [0, 0],
});
layer.add(quadLinePath);

// 创建虚线以展示贝塞尔曲线的控制点
const bezierLinePath = new Konva.Line({
dash: [10, 10, 0, 10],
strokeWidth: 3,
stroke: 'black',
lineCap: 'round',
id: 'bezierLinePath',
opacity: 0.3,
points: [0, 0],
});
layer.add(bezierLinePath);

// 为抛物线创建锚点
const quad = {
start: buildAnchor(60, 30),
control: buildAnchor(240, 110),
end: buildAnchor(80, 160),
};

// 为贝塞尔曲线创建锚点
const bezier = {
start: buildAnchor(280, 20),
control1: buildAnchor(530, 40),
control2: buildAnchor(480, 150),
end: buildAnchor(300, 150),
};

// 更新控制点线
updateDottedLines();