Konva中的位置与偏移(Offset)有什么区别
Konva 中有几个属性看起来类似,可能会引起一些困惑,但它们的作用和用途是不同的。
在本文中,我将解释位置(x 和 y 坐标)与偏移(offsetX 和 offsetY)之间的区别。
因此,x 和 y 属性定义了节点在画布上的位置。如果你设置了 draggable = true
属性并开始拖动,Konva 会改变节点的 x 和 y 属性。这个逻辑会应用于所有节点(甚至包括 Konva.Line)。
矩形形状的位置定义其左上角点。圆形的 posición 定义其中心点。
import Konva from 'konva';
const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 20,
y: 20,
width: 100,
height: 100,
fill: 'yellow',
stroke: 'black',
strokeWidth: 4,
draggable: true,
});
// 将图形添加到图层
layer.add(rect);
var circle = new Konva.Circle({
x: 150,
y: 120,
radius: 50,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true,
});
// 将图形添加到图层
layer.add(circle);
var text = new Konva.Text();
layer.add(text);
// 将图层添加到舞台
stage.add(layer);
function updateText(e) {
text.text('位置:x = ' + e.target.x() + ' y = ' + e.target.y());
}
rect.on('dragmove', updateText);
circle.on('dragmove', updateText);
为什么我们需要 offset
属性?
当你改变偏移(offset)属性时,可能看起来你是在改变节点的位置,但实际上不是。 你是在更改形状的“原点”。
什么是原点?你可以把它想象成“我们开始绘制一个形状的点”,或“形状的中心”或“围绕它旋转的点”。
提醒一句,很久以前,Konva 代码库中的 offset 属性被叫做“center”(当时是 KineticJS 项目)。但后来被重构为“offset”。
看看这个示例。这里所有的矩形都具有相同的 y
位置,但它们的 offset
属性不同。
import Konva from 'konva';
const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});
const layer = new Konva.Layer();
stage.add(layer);
const centerY = stage.height() / 2;
// 无偏移的矩形
const rect1 = new Konva.Rect({
x: 50,
y: centerY,
width: 100,
height: 100,
fill: 'red',
stroke: 'black',
strokeWidth: 2,
});
layer.add(rect1);
// 以中心为偏移的矩形
const rect2 = new Konva.Rect({
x: 200,
y: centerY,
width: 100,
height: 100,
fill: 'green',
stroke: 'black',
strokeWidth: 2,
offsetX: 50,
offsetY: 50,
rotation: 45
});
layer.add(rect2);
// 自定义偏移的矩形
const rect3 = new Konva.Rect({
x: 350,
y: centerY,
width: 100,
height: 100,
fill: 'blue',
stroke: 'black',
strokeWidth: 2,
offsetX: 100,
offsetY: 0,
rotation: 45
});
layer.add(rect3);
你应当理解,Konva 定义形状原点的主要方法有两种。
- “圆形类”形状(如 Circle、Ellipse、Wedge、Star、Ring 等)以实际中心点为原点。
- “矩形类”形状(如 Rectangle、Sprite、Text、Image 等)以左上角为原点。
当你设置 {x, y}
时,圆形是定义“中心点在哪里”。
而矩形是定义“左上角点在哪里”。
因此,形状将围绕其原点(“中心”或“左上角”)旋转。例如,将星形旋转 45°时,它会绕其实际中心旋转。
但如果你将矩形旋转 45°,它会绕左上角旋转。但在某些情况下,这并不方便。有时你希望将形状绕其中心旋转。
这时你就可以设置 offset
属性。通过它,我们告诉 Konva:“嘿,把这个点作为新原点”。
如何设置形状的旋转点?
现在假设你在 (x=0, y=0)
位置放置了一个 100x100 的矩形,你想让它绕其中心旋转。
如果没有使用 offset,你就需要重新计算其左上角的位置(还记得学校里的三角函数知识吗)。
可以用下面这种方式实现:
const rotatePoint = ({ x, y }, rad) => {
const rcos = Math.cos(rad);
const rsin = Math.sin(rad);
return { x: x * rcos - y * rsin, y: y * rcos + x * rsin };
};
// 适用于左上角原点的形状,如矩形
function rotateAroundCenter(node, rotation) {
// 当前旋转原点(0,0)相对于所需的原点——中心(node.width()/2, node.height()/2)
const topLeft = { x: -node.width() / 2, y: -node.height() / 2 };
const current = rotatePoint(topLeft, Konva.getAngle(node.rotation()));
const rotated = rotatePoint(topLeft, Konva.getAngle(rotation));
const dx = rotated.x - current.x,
dy = rotated.y - current.y;
node.rotation(rotation);
node.x(node.x() + dx);
node.y(node.y() + dy);
}
// 使用它
rotateAroundCenter(rect, 180);
或者你可以将 offsetX = width / 2
和 offsetY = height / 2
设置进去。但矩形会在画布上被移动(因为你改变了它的原点),所以你需要调整位置。
还有疑问?欢迎在评论区提问。