对象捕捉到Fabric.js上的客户网格

2022-04-07 00:00:00 javascript fabricjs

我正在构建一个应用程序,我需要在MouseMove上将对象捕捉到一个网格,但我不需要一个常规的网格,而是一个自定义的网格。我找到了这个Fiddle,并试图放置我自己的栅格,但对象没有捕捉到它。我需要的是对象的中心,以便捕捉到由两条网格线形成的十字。

这是我的代码:

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
var canvas = new fabric.Canvas('c', { selection: false });
var grid = 20;

// create grid

for (var i = 0; i < (canvas.height / grid); i++) {
  canvas.add(new fabric.Path('m 260.75,122.82188 0,349.31925', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 309.75,122.82188 0,349.31925', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 353.75,122.82188 0,349.31925', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 391.25,122.82188 0,349.31925', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 419.25,122.82188 0,349.31925', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 435.25,122.82188 0,349.31925', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 216.5,122.82188 0,349.31925', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 179,122.82188 0,349.31925', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 151,122.82188 0,349.31925', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 135,122.82188 0,349.31925 ', { stroke: '#ccc', selectable: false }));

  canvas.add(new fabric.Path('m 110.91682,147.25 348.63852,0', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 110.91682,161.25 348.63852,0', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 110.91682,188 348.63852,0', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 110.91682,224.75 348.63852,0', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 110.91682,269.75 348.63852,0', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 110.91682,326.05147 348.63852,0', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 110.91682,370.83102 348.63852,0', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 110.91682,407.75 348.63852,0', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 110.91682,434.25 348.63852,0', { stroke: '#ccc', selectable: false }));
  canvas.add(new fabric.Path('m 110.91682,448.5 348.63852,0', { stroke: '#ccc', selectable: false }));
}

// add objects

canvas.add(new fabric.Rect({
  left: 100,
  top: 100,
  width: 20,
  height: 20,
  fill: '#faa',
  originX: 'center',  originY: 'center',
  centeredRotation: true
}));

// 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
  });
});
<html>
<head>
<script src="https://rawgithub.com/kangax/fabric.js/master/dist/fabric.js"></script>


</head>
<body>
<canvas id="c" width="600" height="600"></canvas>

如果有人能帮上忙,我们将予以欢迎。

再次分析后,我发现SVG正在捕捉到varvar grid = 20;中可能给出的网格,但不是我使用canvas.add(new fabric.Path('m 110.91682,147.25 348.63852,0', { stroke: '#ccc', selectable: false }));创建的网格。这很可能是罪魁祸首,但我不确定。


解决方案

确实是var grid = 20导致您的问题,因为您的网格间距不同。您已经静态创建了网格,但是使用定义起点和间距的对象会更加动态,并允许您使用相同的对象将事件捕捉到动态创建的网格点。

我可以使用网格间距的对象数组,并使用x和的数组实例化开始和坐标对象,将线条放入每个坐标键下的坐标对象中。

坐标对象实际上是从起始位置开始的每行之间的空格。开始对象是在x和y轴上绘制的线条边缘的开始位置。

我们将使用这些对象动态创建网格和一个点对象以供稍后用于捕捉鼠标的引用移动到网格。

使用gridSpacing[0]['start']['x']gridSpacing[0]['start']['y']定义起点。然后使用两个数组来保存动态创建的x轴线和y轴线-xArryArr的值。

然后创建嵌套的for循环,在xArr和yarr上循环以创建点对象。

另外两个for循环使用xArr*和yarr数组动态创建网格。

最后是object:moving事件中的捕捉部分。实例化将保存the event.target.leftevent.target.top属性作为键/值对的轴对象。我们使用它来迭代Points对象,并使用条件来检查鼠标移动事件相对于x轴和值相对于x轴和点对象键/值的位置。

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
var canvas = new fabric.Canvas('c', {
  selection: false
});

// insantiate object for starting and coordinates of spacing
const gridSpacing = [{
  start: {
    x: 111,
    y: 123.25
  },
  coords: {
    x: [24, 16, 28, 37.5, 44.25, 49, 44, 37.5, 28, 16],
    y: [24, 16, 28, 37.5, 44.25, 49, 44, 37.5, 28, 16]
  }
}]

// create grid

// define the starting coords
let xCoords = gridSpacing[0]['start']['x'];
let yCoords = gridSpacing[0]['start']['y'];

// instantiate x axis and y axis arrays
let xArr = []
let yArr = []

// fill xArr with values using gridSpacing object
for (let x = 0; x < gridSpacing[0].coords['x'].length; x++) {
  let spacing = gridSpacing[0].coords['x'][x]
  xArr.push(xCoords += spacing)
}
// fill yArr with values using gridSpacing object
for (let y = 0; y < gridSpacing[0].coords['y'].length; y++) {
  let spacing = gridSpacing[0].coords['y'][y]
  yArr.push(yCoords += spacing)
}
// instantiate points obj using xArr and yArr for in loops
const points = []
for (let i in xArr) {
  for (let y in yArr) {
    points.push({
      [xArr[i]]: yArr[y]
    })
  }
}

/* EDIT: This is the section that draws the grid lines. No need for it as you are using the points object and xArr and yArr to make your mouse snap to the spacing. 

// create and draw x axis grid dynamically using xArr
for (let x = 0; x < xArr.length; x++) {
  canvas.add(new fabric.Path(`m ${xArr[x]},122.82188 0,349.31925`, {
    stroke: '#ccc',
    selectable: false
  }));
}
// create and draw y axis grid dynamically using yArr
for (let y = 0; y < gridSpacing[0].coords['y'].length; y++) {
  canvas.add(new fabric.Path(`m 110.91682,${yArr[y]} 348.63852,0`, {
    stroke: '#ccc',
    selectable: false
  }));
}
*/

// add objects

canvas.add(new fabric.Rect({
  left: 100,
  top: 100,
  width: 20,
  height: 20,
  fill: '#faa',
  originX: 'center',
  originY: 'center',
  centeredRotation: true
}));

canvas.add(new fabric.Circle({
  left: xArr[5],
  top: yArr[5],
  radius: 60,
  fill: '#9f9',
  originX: 'center',
  originY: 'center',
  centeredRotation: true
}));

// snap to grid

canvas.on('object:moving', function(event) {
  // create objbect that will hold current mouse move events x and y
  let axis = {
    [event.target.left]: event.target.top
  }  
  let x, y = '';
  // iterate over our points and check event.target values
  points.forEach((point, i) => {
    // conditional to check x axis boundaries and point variations
    // left
    if (parseInt(Object.keys(axis)) < xArr[1] - xArr[1] * .1 || parseInt(Object.keys(axis)) < xArr[0]) {
      x = xArr[0]
    // right
    }else if (parseInt(Object.keys(axis)) > xArr[xArr.length - 1]) {
      x = xArr[xArr.length - 1]
    // boundaries
    }else if (Object.keys(axis) < Object.keys(points[i]) && Object.keys(axis) > Object.keys(points[i - 1]) && Object.keys(axis) > xArr[0]) {
      x = Object.keys(points[i])
    }
    
    // conditional to check y axis boundaries and point variations
    // up
    if (parseInt(Object.values(axis)) < yArr[1] - yArr[1] * .1 || parseInt(Object.values(axis)) < yArr[0]) {
      y = yArr[0]
    // down
    }else if (parseInt(Object.values(axis)) > yArr[yArr.length - 1]) {
      y = yArr[yArr.length - 1]
      // boundaries
    }else if (Object.values(axis) < Object.values(points[i]) && Object.values(axis) > Object.values(points[i - 1]) && Object.values(axis) > xArr[0]) {
      y = Object.values(points[i])
    }
  }) 
  // set event.target left and top properties
  event.target.set({
    left: parseInt(x),
    top: parseInt(y)
  })
})
<html>

<head>
  <script src="https://rawgithub.com/kangax/fabric.js/master/dist/fabric.js"></script>


</head>

<body>
  <canvas id="c" width="600" height="600"></canvas>
</body>

相关文章