画布:矩形 - 对齐网格/对齐对象

时间:2014-01-27 15:54:37

标签: javascript canvas fabricjs

我设法通过以下方式操作Fabric.js来添加捕捉和缩放到网格功能:

var grid = 100;
//Snap to Grid
canvas.on('object:moving', function (options) {
    options.target.set({
        left: Math.round(options.target.left / grid) * grid,
        top: Math.round(options.target.top / grid) * grid
    });
});
canvas.on('object:scaling', function (options) {
    options.target.set({
        left: Math.round(options.target.left / grid) * grid,
        top: Math.round(options.target.top / grid) * grid
    });
});

现在我想添加对象功能。我的想法是检查两个物体的交叉点,然后以某种方式锁定运动。我知道它不是最好的尝试,但至少它会抓住它,但不允许再移动物体了。并且:现在它没有很好地实施。请参阅:http://jsfiddle.net/gcollect/y9kyq/

我有三个问题:

  1. “snap”不能正常工作,因为对象left属性以某种方式依赖于指针。通过拖动对象并观察我的控件输出进行复制。例如,当将红色矩形移动到左侧位置时:62,矩形不与蓝色矩形相交,仍然可以移开。如何重新加载矩形的实际左值。由于我对网格线的捕捉,它位于左边:100而不是左边:62。
  2. 知道如何添加对象功能的快照吗?并禁止交叉?
  3. 如何检查n个对象,而不仅仅是两个?
  4. 感谢您的评论。

    PS: jsfiddle示例没有显示网格功能的比例,因为它需要在行中进行Fabric.js操作:11100

    var distroundedforgrid = Math.round(dist/100)*100;      
          transform.newScaleX = Math.round((transform.original.scaleX * distroundedforgrid / lastDist)*10)/10;
          transform.newScaleY = Math.round((transform.original.scaleY * distroundedforgrid / lastDist)*10)/10;
    
          target.set('scaleX', transform.newScaleX);
          target.set('scaleY', transform.newScaleY);
        }
    

3 个答案:

答案 0 :(得分:4)

对于那些仍然对解决方案感兴趣的人: 我在这里解决了这个问题:https://stackoverflow.com/a/22649022/3207478 见jsfiddle:http://jsfiddle.net/gcollect/FD53A/

使用.oCoords.tl .tr .bl. and .br solved it.

答案 1 :(得分:3)

根据网格重新缩放,请参阅this JSfiddle

function snapScaling(options) {
    var target = options.target;
    var type = canvas.getActiveObject().get('type');
    var corner = target.__corner;
    var w = target.getWidth();
    var h = target.getHeight();
    var snap = {   // Closest snapping points
      top: Math.round(target.top / grid) * grid,
      left: Math.round(target.left / grid) * grid,
      bottom: Math.round((target.top + h) / grid) * grid,
      right: Math.round((target.left + w) / grid) * grid,
    };
    snap.height = snap.top - snap.bottom;
    if(snap.height < 0) {
      snap.height *= - 1;
    }
    snap.width = snap.left - snap.right;
    if(snap.width < 0) {
      snap.width *= - 1;
    }
    switch (corner) {
      case 'mt':
      case 'mb':
          target.top = snap.top;
          target.height = snap.height;
          target.scaleY = 1;
        break;
      case 'ml':
      case 'mr':
        target.left = snap.left;
        target.width = snap.width;
        target.scaleX = 1;
        break;
      case 'tl':
      case 'bl':
      case 'tr':
      case 'br':
        target.top = snap.top;
        target.left = snap.left;

        target.height = snap.height;
        target.width = snap.width;

        target.scaleY = 1;
        target.scaleX = 1;
    }

    if(type == 'ellipse') {
      target.rx = (target.width / 2);
      target.ry = (target.height / 2);
    }
  }

答案 2 :(得分:-1)

我想出来解决x轴上对象的捕捉问题,并将解决y轴的解决方案。 See JSfiddle here.

当我检测到一个交叉点时,我通过为活动对象设置一个新的“左”值来做到这一点。

        if (options.target.isContainedWithinObject(obj)||options.target.intersectsWithObject(obj)||obj.isContainedWithinObject(options.target)) {

            var distx = ((obj.left + obj.width)/2) - ((options.target.left + options.target.width)/2);
            var disty = ((obj.top + obj.height)/2) - ((options.target.top + options.target.height)/2);                  

            if (distx > 0){
                options.target.left = obj.left - options.target.width;
            } else {
                options.target.left = obj.left + obj.width;
            }

        }