在包含区域内动态创建分组对象? (html5canvas - fabric.js)

时间:2016-10-25 13:09:18

标签: javascript html5 canvas html5-canvas fabricjs

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

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

  1. 动态创建的形状没有可能的方法 拖到图像区域外的任何地方。 (已完成 - 依赖第二步)
  2. 您无法将图像拖出页面视图,画布区域无法显示空白区域。必须始终显示部分图像,并填充整个画布区域。 (问题)
  3. 以下是我编写的两个示例,其中两个都没有正常工作;

    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行为方式之间的关键区别。

    第一个插件似乎工作正常,直到你尝试放大多次并以更大的缩放级别,然后它似乎开始窃听(可能需要点击几下并且有点乱,它是非常不一致的)。第二个插头非常紧张,不能很好地工作。

    我已经坚持了一个星期左右,而且我正处于突破点!所以真的希望有人可以指出我做错了什么?

    下面的第一个插件的代码段;

      // 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();
    
    
    }
    

    编辑:

    我添加了评论并试图简化插件中的代码。

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

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

    我已经删除了其中一个以避免混淆。

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

    谢谢!

1 个答案:

答案 0 :(得分:4)

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

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

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