【问题标题】:Moving dynamically created grouped object within contained area? (html5canvas - fabric.js)在包含的区域内移动动态创建的分组对象? (html5canvas-fabric.js)
【发布时间】:2017-03-07 13:22:32
【问题描述】:

我正在尝试创建的是一个小型画布小部件,它允许用户在图像上动态创建形状,然后将其放置在他们感兴趣的区域上方,实际上它是一个荧光笔。

问题在于添加缩放功能,因为当我放大图像时我想确保这一点;

  1. 动态创建的形状不可能 拖动到图像区域外的任意位置。 (已完成 - ish,依赖于第二步)
  2. 您无法将图像拖出页面视图,画布区域无法显示空白。必须始终显示部分图像,并填充整个画布区域。 (问题)

这是我拟定的两个例子,但都不能正常工作;

First example - getBoundingRect does not update and is bound to the image

Second example - getBoundingRect does update and is bound to the grouped object

从链接描述中,您可以看到我认为我已经缩小了问题的范围,或者至少注意到脚本与 getBoundingRect 行为方式之间的关键区别。

第一个 plunk 似乎工作正常,直到您尝试放大多次并以更大的缩放级别放大,然后它似乎开始出现问题(可能需要点击几下并有点乱七八糟,这是非常不一致的)。第二个 plunk 非常紧张,效果不太好。

我已经在这个问题上坚持了一周左右,而且我正处于崩溃的边缘!所以真的希望有人能指出我做错了什么?

下面的代码 sn-p 用于第一次插入;

  // creates group

  var objs = canvas.getObjects();


  var group = new fabric.Group(objs, {
    status: 'moving'
  });

  // sets grouped object position

  var originalX = active.left,
    originalY = active.top,
    mouseX = evt.e.pageX,
    mouseY = evt.e.pageY;

  active.on('moving', function(evt) {
    group.left += evt.e.pageX - mouseX;
    group.top += evt.e.pageY - mouseY;
    active.left = originalX;
    active.top = originalY;
    originalX = active.left;
    originalY = active.top;
    mouseX = evt.e.pageX;
    mouseY = evt.e.pageY;


    // sets boundary area for image when zoomed
    // THIS IS THE PART THAT DOESN'T WORK

    active.setCoords();

    // SET BOUNDING RECT TO 'active'

    var boundingRect = active.getBoundingRect();

    var zoom = canvas.getZoom();
    var viewportMatrix = canvas.viewportTransform;

    // scales bounding rect when zoomed

    boundingRect.top = (boundingRect.top - viewportMatrix[5]) / zoom;
    boundingRect.left = (boundingRect.left - viewportMatrix[4]) / zoom;
    boundingRect.width /= zoom;
    boundingRect.height /= zoom;

    var canvasHeight = canvas.height / zoom,
      canvasWidth = canvas.width / zoom,
      rTop = boundingRect.top + boundingRect.height,
      rLeft = boundingRect.left + boundingRect.width;

    // checks top left

    if (rTop < canvasHeight || rLeft < canvasWidth) {
      group.top = Math.max(group.top, canvasHeight - boundingRect.height);
      group.left = Math.max(group.left, canvasWidth - boundingRect.width);
    }

    // checks bottom right

    if (rTop > 0 || rLeft > 0) {
      group.top = Math.min(group.top, canvas.height - boundingRect.height + active.top - boundingRect.top);
      group.left = Math.min(group.left, canvas.width - boundingRect.width + active.left - boundingRect.left);
    }


  });

  // deactivates all objects on mouseup

  active.on('mouseup', function() {
    active.off('moving');
    canvas.deactivateAll().renderAll();

  })

  // sets group

  canvas.setActiveGroup(group.setCoords()).renderAll();


}

编辑:

我添加了 cmets 并尝试简化 plunks 中的代码。

相关代码在if (active.id == "img") { 代码块内开始。

我把不相关的代码作为函数放在了底部,它们在很大程度上可以被忽略。 (createNewRect() + preventRectFromLeaving())

为了避免混淆,我删除了其中一个。

让我知道它是否有帮助,或者我是否应该尝试进一步简化。

谢谢!

【问题讨论】:

  • 每个示例中都有大量代码。有什么方法可以用更少的代码将其归结为更简单的示例?很难说每个人发生了什么。
  • @StefanHayden 完成!代码并不少,但我已经移动了一些东西并添加了 cmets 以尝试使其更容易,让我知道它是否更容易阅读? (还添加了问题的编辑部分)谢谢!

标签: javascript html canvas html5-canvas fabricjs


【解决方案1】:

我认为分组弄乱了背景图像的位置。因此,我尝试在图像移动时删除该组并手动更新矩形的位置。

它设置图像在移动之前的最后位置

var lastLeft = active.left,
    lastTop = active.top;

然后每次图像移动时它都会更新这些和矩形的位置

rect.left += active.left - lastLeft;
rect.top += active.top - lastTop;
// I think this is needed so the rectangle can be re-selected
rect.setCoords();
lastLeft = active.left;
lastTop = active.top;

由于图像必须保留在画布内,因此只要图像移动,矩形也会保留在画布内。您编写的其余代码似乎运行良好。

http://plnkr.co/edit/6GGcUxGC7CjcyQzExMoK?p=preview

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-03
    • 2015-02-22
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 2013-12-16
    相关资源
    最近更新 更多