fabricjs - 对角度对象捕捉网格缩放

时间:2017-09-18 02:13:00

标签: javascript fabricjs

所以我有下面的捕捉网格功能。当对象具有0角度时它可以正常工作,但是一旦它成角度(仅对于左侧和顶侧),它不会正确地捕捉到网格。这是因为它现在考虑了left和top属性,而不仅仅是左边或顶边。

我正在考虑的解决方案是使用三角形数学(毕达哥拉斯)但不确定如何获得当前的左/顶属性,因为target.lefttarget.top保存当前缩放对象的数据。

var canvas = new fabric.Canvas('c', {
   selection: false
});
var grid = 50;

// create grid
for (var i = 0; i < (600 / grid); i++) {
   canvas.add(new fabric.Line([i * grid, 0, i * grid, 600], {
      stroke: '#ccc',
      selectable: false
   }));
   canvas.add(new fabric.Line([0, i * grid, 600, i * grid], {
      stroke: '#ccc',
      selectable: false
   }))
}

// add objects
canvas.add(new fabric.Rect({
   left: 100,
   top: 100,
   strokeWidth: 0,
   width: 50,
   height: 50,
   fill: '#faa',
   originX: 'left',
   angle: 50,
   originY: 'top',
   centeredRotation: true
}));

canvas.add(new fabric.Circle({
   left: 300,
   top: 300,
   radius: 50,
   fill: '#9f9',
   originX: 'left',
   originY: 'top',
   strokeWidth: 0,
   centeredRotation: true
}));

// snap to grid
canvas.on('object:moving', options => {
   options.target.set({
      left: Math.round(options.target.left / grid) * grid,
      top: Math.round(options.target.top / grid) * grid
   });
});

canvas.on('object:scaling', options => {
 

          var target = options.target;
          let grid = 50;


          var w = target.getWidth(),
            h = target.getHeight(),
            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
            },
            threshold = grid, // add a multiplier to change closeness e.g. * 2
            dist = {		// Distance from snapping points
               top: Math.abs(snap.top - target.top),
               left: Math.abs(snap.left - target.left),
               bottom: Math.abs(snap.bottom - target.top - h),
               right: Math.abs(snap.right - target.left - w)
            },
            attrs = {
               scaleX: target.scaleX,
               scaleY: target.scaleY,
               top: target.top,
               left: target.left
            };
          switch (target.__corner) {
            case 'tl':
               if (dist.left < dist.top && dist.left < threshold) {
                  attrs.scaleX = (w - (snap.left - target.left)) / target.width;
                  attrs.scaleY = (attrs.scaleX / target.scaleX) * target.scaleY;
                  attrs.top = target.top + (h - target.height * attrs.scaleY);
                  attrs.left = snap.left;
               } else if (dist.top < threshold) {
                  attrs.scaleY = (h - (snap.top)) / target.height;
                  attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
                  attrs.left += (w - target.width * attrs.scaleX);
                  attrs.top = snap.top;
               }
               break;
            case 'mt':
               if (dist.top < threshold) {
                  console.log("scaling");
                  attrs.scaleY = (h - (snap.top - target.top)) / target.height;
                  attrs.top = snap.top;
               }
               break;
            case 'tr':
               if (dist.right < dist.top && dist.right < threshold) {
                  attrs.scaleX = (snap.right - target.left) / target.width;
                  attrs.scaleY = (attrs.scaleX / target.scaleX) * target.scaleY;
                  attrs.top = target.top + (h - target.height * attrs.scaleY);
               } else if (dist.top < threshold) {
                  attrs.scaleY = (h - (snap.top - target.top)) / target.height;
                  attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
                  attrs.top = snap.top;
               }
               break;
            case 'ml':
               if (dist.left < threshold) {
                  attrs.scaleX = (w - (snap.left - target.left)) / target.width;
                  attrs.left = snap.left;
               }
               break;
            case 'mr':
               if (dist.right < threshold) attrs.scaleX = (snap.right - target.left) / target.width;
               break;
            case 'bl':
               if (dist.left < dist.bottom && dist.left < threshold) {
                  attrs.scaleX = (w - (snap.left - target.left)) / target.width;
                  attrs.scaleY = (attrs.scaleX / target.scaleX) * target.scaleY;
                  attrs.left = snap.left;
               } else if (dist.bottom < threshold) {
                  attrs.scaleY = (snap.bottom - target.top) / target.height;
                  attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
                  attrs.left += (w - target.width * attrs.scaleX);
               }
               break;
            case 'mb':
               if (dist.bottom < threshold) attrs.scaleY = (snap.bottom - target.top) / target.height;
               break;
            case 'br':
               if (dist.right < dist.bottom && dist.right < threshold) {
                  attrs.scaleX = (snap.right - target.left) / target.width;
                  attrs.scaleY = (attrs.scaleX / target.scaleX) * target.scaleY;
               } else if (dist.bottom < threshold) {
                  attrs.scaleY = (snap.bottom - target.top) / target.height;
                  attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
               }
               break;
            default:
              break;
          }
          target.set(attrs);
      });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.min.js"></script>
<canvas id="c" width="600" height="600"></canvas>

0 个答案:

没有答案