跳到主要内容

如何使用锚点修改线条的点?

本示例演示如何创建可通过拖动锚点修改的交互式曲线(二次曲线和贝塞尔曲线)。矢量图形编辑器经常使用此技术,让用户可以创建和调整自定义曲线。

操作说明: 使用鼠标或手指拖放锚点,以修改二次曲线(红色)和贝塞尔曲线(蓝色)的曲率。

import Konva from 'konva';

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

// Create stage and layer
const stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});

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

// Function to build anchor point
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);

// Add hover styling
anchor.on('mouseover', function () {
document.body.style.cursor = 'pointer';
this.strokeWidth(4);
});

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

// Update curves when anchor is moved
anchor.on('dragmove', function () {
updateDottedLines();
});

return anchor;
}

// Function to update dashed line points (showing control points)
function updateDottedLines() {
const q = quad;
const b = bezier;

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

// Update control point lines for quadratic curve
quadLinePath.points([
q.start.x(),
q.start.y(),
q.control.x(),
q.control.y(),
q.end.x(),
q.end.y(),
]);

// Update control point lines for bezier curve
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(),
]);
}

// Create quadratic curve with custom shape
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);

// Create bezier curve with custom shape
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);

// Create dashed line to show control points for quadratic curve
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);

// Create dashed line to show control points for bezier curve
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);

// Create anchor points for the quadratic curve
const quad = {
start: buildAnchor(60, 30),
control: buildAnchor(240, 110),
end: buildAnchor(80, 160),
};

// Create anchor points for the bezier curve
const bezier = {
start: buildAnchor(280, 20),
control1: buildAnchor(530, 40),
control2: buildAnchor(480, 150),
end: buildAnchor(300, 150),
};

// Update the control point lines
updateDottedLines();