简体   繁体   English

动态更新fabric.js路径点

[英]Update fabric.js Path points dynamically

I'm trying to add points to a path object dynamically. 我试图动态地将点添加到路径对象。 When I do, the path renders correctly, but the bounding rectangle never gets updated, making it nearly impossible for a user to select and move the path on canvas. 当我这样做时,路径将正确呈现,但是边界矩形永远不会更新,这使得用户几乎不可能在画布上选择和移动路径。

As you can see in the code below, the path is initially created with a single point, then I dynamically add a second point as well as a control point. 如您在下面的代码中看到的,路径最初是用单个点创建的,然后我动态地添加了第二个点以及一个控制点。 After doing this, the bounding rectangle never updates: 完成此操作后,边界矩形将永远不会更新:

var canvas = new fabric.Canvas('c');
canvas.backgroundColor = '#f5f5f5';
var path = new fabric.Path('M 0 20',{
    left: 100,
    top: 100,
    stroke: 'black',
    fill: ''
});

canvas.add(path);

var commandArray = [];
commandArray[0] = 'Q';
commandArray[1] = 50;
commandArray[2] = 100;
commandArray[3] = 100;
commandArray[4] = 20;

path.path[1] = commandArray;

canvas.renderAll();

I also tried calling path.setCoords() , but that did not make any difference. 我也尝试调用path.setCoords() ,但这没有任何区别。 How can I get the bounding rectangle to update its dimensions after adding points to a path? 将点添加到路径后,如何获取边界矩形以更新其尺寸?

Here's a fiddle: http://jsfiddle.net/flyingL123/17ueLva2/2/ 这是一个小提琴: http : //jsfiddle.net/flyingL123/17ueLva2/2/

Please, fabricjs does not support adding point dinamically as of now. 请注意,fabricjs目前不支持动态添加点。 To make it work you can add points like you are doing and then use internal method path._parseDimensions() each time you add points and desire to update bounding box dimension. 为了使其正常工作,您可以像添加操作一样添加点,然后在每次添加点并希望更新边界框尺寸时使用内部方法path._parseDimensions()

var dims = path._parseDimensions();
path.setWidth(dims.width);
path.setHeight(dims.height);
path.pathOffset.x = path.width/2;
path.pathOffset.y = path.height/2;
path.setCoords();

Look this updated fiddle that has the necessary code to solve your problem. 查看此更新的小提琴,其中包含解决您的问题的必要代码。 I hope it works for every situation. 我希望它适用于每种情况。

http://jsfiddle.net/17ueLva2/6/ http://jsfiddle.net/17ueLva2/6/

It ended up being more complicated. 最终变得更加复杂。 If a point is added to the path that results in _parseDimensions returning a left value that is negative, the path would jump around the screen. 如果在路径上添加了一个点,导致_parseDimensions返回的left值为负,则该路径将在屏幕上跳转。 For my use case, I need the path to stay in place while points are added and manipulated. 对于我的用例,我需要在添加和操纵点时保持原样的路径。 This fiddle shows my working solution: 这个小提琴显示了我的工作解决方案:

http://jsfiddle.net/flyingL123/8763bx2q/8/ http://jsfiddle.net/flyingL123/8763bx2q/8/

If you run it with a JS console open, you will see the script pausing after each additional point is added, or current point is manipulated. 如果在打开JS控制台的情况下运行它,则在添加每个附加点或操纵当前点后,您将看到脚本暂停。 As this happens you will see that the path does not get moved along the canvas, which is the desired behavior. 发生这种情况时,您将看到路径不会沿着画布移动,这是所需的行为。 After all the break points complete, you will see that the curve is centered within its selection box. 所有断点完成后,您将看到曲线在其选择框中居中。

If there is an easier way to achieve this behavior, I would love to know. 如果有更简单的方法来实现此行为,我很想知道。

Here's the function I'm using to set the dimensions just in case the fiddle link ever goes away: 这是我用来设置尺寸的功能,以防万一小提琴链接消失了:

function updateDims() {
    var dims = path._parseDimensions(),
        prevDims = path.prevDims || {},
        leftDiff = dims.left - (prevDims.left || 0),
        topDiff = dims.top - (prevDims.top || 0);

    path.setWidth(dims.width);
    path.setHeight(dims.height);

    if (dims.left < 0) {
        path.pathOffset.x = path.width/2 + dims.left;
        path.left = path.left + leftDiff;
    } else {
        path.pathOffset.x = path.width/2;
    }

    if (dims.top < 0) {
        path.pathOffset.y = path.height/2 + dims.top;
        path.top = path.top + topDiff;
    } else {
         path.pathOffset.y = path.height/2;   
    }

    path.prevDims = dims;
    path.setCoords();
}

I couldn't find any new way to do this. 我找不到任何新方法来执行此操作。 But I figured out something like below; 但是我发现下面这样的东西;

  1. create an SVG path string with modifications. 创建带有修改的SVG路径字符串。
  2. create a new fabric path object. 创建一个新的结构路径对象。
  3. replace path, width, height and pathOffset properties of the original path object with the properties of the new path object. 用新路径对象的属性替换原始路径对象的path,width,height和pathOffset属性。
  4. setCoords. setCoords。 renderAll etc... renderAll等...

It may not be much efficient. 它可能效率不高。 But it was the solution for me. 但这是我的解决方案。

    var pathObject = new fabric.Path("M0,0 L100,100 ~ Z");

    var updatedPath =  new fabric.Path("M50,100 L120,46 ~ Z");

    pathObject.set({
      path : updatedPath.path,
      width : updatedPath.width,
      height : updatedPath.height,
      pathOffset: updatedPath.pathOffset
    });
    pathObject.setCoords();

On my setup, it says path._parseDimensions is not a function . 在我的设置中,它说path._parseDimensions不是一个函数 I didn't try to solve it. 我没有尝试解决它。 I have to change all path content. 我必须更改所有路径内容。 So my solution seems better for me :) 所以我的解决方案对我来说似乎更好:)

In fabric 3.3.2 I solved it combining the answers above: 在Fabric 3.3.2中,我结合以上答案解决了它:

var dims = path._calcDimensions()
path.set({
  width: dims.width,
  height: dims.height,
  left: dims.left,
  top: dims.top,
  pathOffset: {
    x: dims.width / 2 + dims.left,
    y: dims.height / 2 + dims.top
  },
  dirty: true
})
path.setCoords()

This correctly updates my path bounding box after adding points like: 在添加如下所示的点之后,这可以正确更新我的路径边界框:

path.set({path: points})

I am not sure though, if this works with negative top and left values, but I didn't need that in my case. 不过,我不确定这是否适用于负的top和left值,但是在我的情况下我不需要。 I guess the main thing is that the _parseDimensions() method was renamed to _calcDimensions() . 我猜最主要的是_parseDimensions()方法已重命名为_calcDimensions()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM