gpt4 book ai didi

javascript - 通过鼠标拖动创建多边形形状不会使形状以其选择边框框为中心

转载 作者:行者123 更新时间:2023-11-28 18:10:39 33 4
gpt4 key购买 nike

版本

1.7.3

测试用例

https://jsfiddle.net/human_a/twdgya93/

在这个 fiddle 中,我还尝试使用以下代码创建形状以避免创建空多边形,但结果是相同的:

const polygon = new fabric.Polygon(calcPolygonPoints(8, Math.abs( origX - pointer.x ) / 2 ), {
objectCaching: false,
left: origX,
top: origY,
originX: 'center',
originY: 'center',
fill: 'rgba(255,255,255, 1)',
perPixelTargetFind: false,
strokeWidth: 1,
strokeDashArray: [0,0],
objType: 'shape',
stroke: 'rgba(17,17,17,1)',
hasControls: false,
hasBorders: false
})

重现步骤

单击绿色按钮进入绘图模式,在 Canvas 内拖动鼠标开始创建形状,松开鼠标,然后尝试选择新创建的形状。边界框大小与新多边形的大小匹配,但位置不正确。

预期行为

如果我尝试创建任何其他类型的形状(矩形、圆形或三 Angular 形)而不是多边形,那么效果非常好。

实际行为

由于多边形使用不同的方法通过计算点来计算宽度和高度,并且由于在这种创建形状的方法中,宽度/高度是在创建形状后计算的(使用鼠标:移动事件)边界矩形将无法正确定位。

此外,即使我尝试更改多边形的大小(我不想缩放形状,这是一个坏主意),边界矩形的位置再次不正确,您可以在上面的演示中使用按钮旁边的数字输入字段。

PS

我没有编写 calcPolygonPoints 函数,我不久前在网络上的某个地方找到了它,不幸的是,我无法再次找到它的链接来感谢这个神奇函数的创建者。

最佳答案

当你有一个 fiddle 时,可以非常好且快速地将其转换为工作片段,因为这样得到答案就非常容易了。

这么说,重点是fabric.js中的多边形不支持点更新。您已经调用了_calcDimensions(),但这还不够。

要使多边形在边界框中正确居中,您还必须使用更新的值填充其 pathOffset 属性。

我在 mouseUp 事件的代码片段中添加了此内容。

var canvas = new fabric.Canvas();
var el = document.getElementById('my-canvas');
var drawPoly = document.getElementById('draw-poly');
var changeSize = document.getElementById('change-size');
var origX, origY;

var calcPolygonPoints = (sideCount,radius) => {
var sweep=Math.PI*2/sideCount;
var cx=radius;
var cy=radius;
var points=[]

for(var i=0;i<sideCount;i++){
var x=cx+radius*Math.cos( i*sweep )
var y=cy+radius*Math.sin( i*sweep )
points.push( { x:x, y:y } )
}
return(points)
}

canvas.initialize(el, {
backgroundColor: '#fff',
width: 600,
height: 600
});
canvas.renderAll();

drawPoly.addEventListener('click', (e)=>{
canvas.defaultCursor = "crosshair";
canvas.selection = false;
canvas.discardActiveObject();
canvas.discardActiveGroup();
canvas.forEachObject(object=>{ object.selectable = false; });
canvas.renderAll();

canvas.on('mouse:down', opt => {

if (canvas.selection) return;
var pointer = canvas.getPointer(opt.e)

origX = pointer.x;
origY = pointer.y;

// I have also tried initial calculations here
// by using calcPolygonPoints(8, Math.abs( origX - pointer.x ) / 2 ) instead of []
// The result is the same
const polygon = new fabric.Polygon(calcPolygonPoints(8, Math.abs( origX - pointer.x ) / 2 ), {
objectCaching: false,
left: origX,
top: origY,
originX: 'center',
originY: 'center',
fill: 'rgba(255,255,255, 1)',
perPixelTargetFind: false,
strokeWidth: 1,
strokeDashArray: [0,0],
objType: 'shape',
stroke: 'rgba(17,17,17,1)',
hasControls: false,
hasBorders: false
})
// polygon._calcDimensions()
canvas.add(polygon).setActiveObject(polygon)

}).on('mouse:move', opt => {

if (canvas.selection || !canvas.getActiveObject()) return;
const newShape = canvas.getActiveObject()
var pointer = canvas.getPointer(opt.e)

if (newShape) {
newShape.set({
points: calcPolygonPoints(8, Math.abs( origX - pointer.x ) / 2 )
})
newShape._calcDimensions()
}
changeSize.value = Math.abs( origX - pointer.x ) / 2;
canvas.renderAll()

}).on('mouse:up', opt => {
// In my app I am using redux stores to turn off the drawing
// Here I used the following if statement to turn off the drawing
if (canvas.selection) return;

const newShape = canvas.getActiveObject()
if (newShape) {
newShape.set({
hasControls: true,
hasBorders: true
})
newShape.pathOffset = {
x: newShape.minX + newShape.width / 2,
y: newShape.minY + newShape.height / 2
};
var pointer = canvas.getPointer(opt.e);
var center = { x: (pointer.x + origX)/2, y: (pointer.y + origY)/2}
newShape.setPositionByOrigin(center, 'center', 'center')
newShape.setCoords()
canvas.renderAll()
}
canvas.renderAll()
canvas.selection = true;

canvas.off('mouse:down').off('mouse:move')
canvas.defaultCursor = "default";
canvas.discardActiveObject()
canvas.forEachObject(object=>{
if (object.evented) object.selectable = true;
})
})
})

changeSize.addEventListener('input', (e)=>{
if (!canvas.getActiveObject()) return;

canvas.getActiveObject().set({
points: calcPolygonPoints(8, parseInt(e.target.value, 10) )
})
canvas.getActiveObject()._calcDimensions()
canvas.renderAll()
})
button {
border: 0 none;
background: #2ecc70;
border-radius: 5px;
cursor: pointer;
color: #fff;
box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
text-transform: uppercase;
padding: 11px 22px;
font-weight: 600;
font-size: 13px;
letter-spacing: 1px;
margin: 10px auto;
outline: 0 none;
}

input {
border: 1px solid #ddd;
box-shadow: none;
padding: 11px;
font-size: 13px;
border-radius: 5px;
margin-left: 10px;
max-width: 50px;
outline: 0 none !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.3/fabric.min.js"></script>
<div id="wrapper">
<canvas id="my-canvas"></canvas>
<button id="draw-poly">Draw Polygon</button>
<input type="number" id="change-size" value="0" />
</div>

关于javascript - 通过鼠标拖动创建多边形形状不会使形状以其选择边框框为中心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41678349/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com