javascript - Fabricjs 在调整大小时捕捉到网格

标签 javascript jquery fabricjs

我在尝试让对象根据网格大小调整大小时遇到​​了一些问题。

这是我的 fiddle :http://jsfiddle.net/csh6c6fw/1/

这是我正在应用的代码:

canvas.on('object:scaling', (options) => {
  var newWidth = (Math.round(options.target.getWidth() / grid)) * grid;
  var newHeight = (Math.round(options.target.getHeight() / grid)) * grid;

  if (options.target.getWidth() !== newWidth) {
    options.target.set({ width: newWidth, height: newHeight });
  }

});

预期结果

它应该像运动一样捕捉到网格。

最佳答案

可能看起来很复杂,但是,以下将完成工作:

canvas.on('object:scaling', options => {
   var target = options.target,
      w = target.width * target.scaleX,
      h = target.height * target.scaleY,
      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,
      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.top)) / target.height;
            attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
            attrs.left = attrs.left + (w - target.width * attrs.scaleX);
            attrs.top = snap.top;
         }
         break;
      case 'mt':
         if (dist.top < threshold) {
            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 = 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;
   }
   target.set(attrs);
});

这是一个工作示例:

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,
   width: 50,
   height: 50,
   fill: '#faa',
   originX: 'left',
   originY: 'top',
   centeredRotation: true
}));

canvas.add(new fabric.Circle({
   left: 300,
   top: 300,
   radius: 50,
   fill: '#9f9',
   originX: 'left',
   originY: 'top',
   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,
      w = target.width * target.scaleX,
      h = target.height * target.scaleY,
      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,
      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.top)) / target.height;
            attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
            attrs.left = attrs.left + (w - target.width * attrs.scaleX);
            attrs.top = snap.top;
         }
         break;
      case 'mt':
         if (dist.top < threshold) {
            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 = 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;
   }
   target.set(attrs);
});
canvas {border: 1px solid #ccc}
<script src="https://rawgithub.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="600" height="600"></canvas>

关于javascript - Fabricjs 在调整大小时捕捉到网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44147762/

相关文章:

javascript 从 .text 方法设置变量

javascript - 如何在循环中动态获取第一个可用数字?

javascript - textarea 属性值更改时触发过程

javascript - jQuery .each() 方法或 .html() 方法

html - Youtube 视频 内部 Canvas

javascript - Safari 为 Date toISOString() 返回不正确的值

javascript - 使用 Ajax 加载 html 后调用 jquery 插件

fabricjs - Fabric.js : How to remove padding and format selection box?(缩放后填充仍然存在)

javascript - 如何使用 Canvas css 属性导出 Fabric JS?

javascript - 使用 Jquery 搜索 JSON