Fabric js:单击按钮时居中 canvas 并缩放到对象
Fabric js: when button is clicked center canvas and zoom to object
我正在尝试将视口置于对象的中心并在单击按钮时缩放 in/out。我想要一个动画。为此,我使用 setInterval 并像这样以增量方式移动视口:
const objectCenterCoordenates = {
x: Math.round(rect1.left + rect1.width / 2),
y: Math.round(rect1.top + rect1.height / 2)
};
const centeredCanvasCoordenates = {
x: objectCenterCoordenates.x - canvas.width / 2,
y: objectCenterCoordenates.y - canvas.height / 2
};
let currentPoint = {
x: Math.round(canvas.viewportTransform[4]) * -1,
y: Math.round(canvas.viewportTransform[5]) * -1
};
console.log("Start animation");
let animation = setInterval(() => {
console.log("New frame");
if (canvas.getZoom() !== 2) {
let roundedZoom = Math.round(canvas.getZoom() * 100) / 100;
let zoomStep = roundedZoom > 2 ? -0.01 : 0.01;
let newZoom = roundedZoom + zoomStep;
canvas.zoomToPoint(
new fabric.Point(currentPoint.x, currentPoint.y),
newZoom
);
}
let step = 5;
let vpCenter = {
x: Math.round(canvas.getVpCenter().x),
y: Math.round(canvas.getVpCenter().y)
};
if (
vpCenter.x === objectCenterCoordenates.x &&
vpCenter.y === objectCenterCoordenates.y
) {
console.log("Animation Finish");
clearInterval(animation);
}
let xDif = Math.abs(vpCenter.x - objectCenterCoordenates.x);
let yDif = Math.abs(vpCenter.y - objectCenterCoordenates.y);
let stepX =
Math.round(vpCenter.x) > Math.round(objectCenterCoordenates.x)
? -step
: step;
if (Math.abs(xDif) < step)
stepX =
Math.round(vpCenter.x) > Math.round(objectCenterCoordenates.x)
? -xDif
: xDif;
let stepY =
Math.round(vpCenter.y) > Math.round(objectCenterCoordenates.y)
? -step
: step;
if (Math.abs(yDif) < step)
stepY =
Math.round(vpCenter.y) > Math.round(objectCenterCoordenates.y)
? -yDif
: yDif;
currentPoint = {
x: currentPoint.x + stepX,
y: currentPoint.y + stepY
};
canvas.absolutePan(new fabric.Point(currentPoint.x, currentPoint.y));
}, 4);
但有时,我无法确定原因,它会卡在一个循环中,先向一个方向移动几个像素,然后再向另一个方向移动几个像素。并且缩放实现得很好,因为可以在对象完成缩放之前到达对象 in/out。
这是我的代码的代码笔:https://codepen.io/nilsilva/pen/vYpPrgq
如果有任何关于改进我的算法的建议,我将不胜感激。
看起来您对 clearInterval 有完全匹配要求...
if (
vpCenter.x === objectCenterCoordenates.x &&
vpCenter.y === objectCenterCoordenates.y
) {
console.log("Animation Finish");
clearInterval(animation);
}
您描述的情况 stuck in a loop moving one way then going back the other
是因为它从未完成过完全匹配,可能是因为您正在采取的步骤,也可能是舍入问题
您可以使用 Math.hypot
检查两点是否足够接近,请在此处阅读更多内容:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/hypot
条件如下:
if (Math.hypot(
vpCenter.x - objectCenterCoordenates.x,
vpCenter.y - objectCenterCoordenates.y
) < step) {
console.log("Animation Finish");
clearInterval(animation);
}
我正在尝试将视口置于对象的中心并在单击按钮时缩放 in/out。我想要一个动画。为此,我使用 setInterval 并像这样以增量方式移动视口:
const objectCenterCoordenates = {
x: Math.round(rect1.left + rect1.width / 2),
y: Math.round(rect1.top + rect1.height / 2)
};
const centeredCanvasCoordenates = {
x: objectCenterCoordenates.x - canvas.width / 2,
y: objectCenterCoordenates.y - canvas.height / 2
};
let currentPoint = {
x: Math.round(canvas.viewportTransform[4]) * -1,
y: Math.round(canvas.viewportTransform[5]) * -1
};
console.log("Start animation");
let animation = setInterval(() => {
console.log("New frame");
if (canvas.getZoom() !== 2) {
let roundedZoom = Math.round(canvas.getZoom() * 100) / 100;
let zoomStep = roundedZoom > 2 ? -0.01 : 0.01;
let newZoom = roundedZoom + zoomStep;
canvas.zoomToPoint(
new fabric.Point(currentPoint.x, currentPoint.y),
newZoom
);
}
let step = 5;
let vpCenter = {
x: Math.round(canvas.getVpCenter().x),
y: Math.round(canvas.getVpCenter().y)
};
if (
vpCenter.x === objectCenterCoordenates.x &&
vpCenter.y === objectCenterCoordenates.y
) {
console.log("Animation Finish");
clearInterval(animation);
}
let xDif = Math.abs(vpCenter.x - objectCenterCoordenates.x);
let yDif = Math.abs(vpCenter.y - objectCenterCoordenates.y);
let stepX =
Math.round(vpCenter.x) > Math.round(objectCenterCoordenates.x)
? -step
: step;
if (Math.abs(xDif) < step)
stepX =
Math.round(vpCenter.x) > Math.round(objectCenterCoordenates.x)
? -xDif
: xDif;
let stepY =
Math.round(vpCenter.y) > Math.round(objectCenterCoordenates.y)
? -step
: step;
if (Math.abs(yDif) < step)
stepY =
Math.round(vpCenter.y) > Math.round(objectCenterCoordenates.y)
? -yDif
: yDif;
currentPoint = {
x: currentPoint.x + stepX,
y: currentPoint.y + stepY
};
canvas.absolutePan(new fabric.Point(currentPoint.x, currentPoint.y));
}, 4);
但有时,我无法确定原因,它会卡在一个循环中,先向一个方向移动几个像素,然后再向另一个方向移动几个像素。并且缩放实现得很好,因为可以在对象完成缩放之前到达对象 in/out。
这是我的代码的代码笔:https://codepen.io/nilsilva/pen/vYpPrgq
如果有任何关于改进我的算法的建议,我将不胜感激。
看起来您对 clearInterval 有完全匹配要求...
if (
vpCenter.x === objectCenterCoordenates.x &&
vpCenter.y === objectCenterCoordenates.y
) {
console.log("Animation Finish");
clearInterval(animation);
}
您描述的情况 stuck in a loop moving one way then going back the other
是因为它从未完成过完全匹配,可能是因为您正在采取的步骤,也可能是舍入问题
您可以使用 Math.hypot
检查两点是否足够接近,请在此处阅读更多内容:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/hypot
条件如下:
if (Math.hypot(
vpCenter.x - objectCenterCoordenates.x,
vpCenter.y - objectCenterCoordenates.y
) < step) {
console.log("Animation Finish");
clearInterval(animation);
}