首页 > 解决方案 > 使用 fabricjs 执行语义缩放

问题描述

我想使用fabricjs实现语义缩放。

我在画布上有一个密集点图。但是,当我们放大或缩小时,点的大小应该保持不变,但它们之间的距离应该分别增加或减少。

看看这2个例子

画布几何缩放 https://bl.ocks.org/mbostock/3680958

画布语义缩放 https://bl.ocks.org/mbostock/3681006

我想使用fabricjs实现类似于语义缩放的缩放。

我已经尝试过使用fabricjs的解决方案,到目前为止似乎工作正常。我想知道或验证是否有更好的方法可以使用fabricjs 实现相同的目标。

我们还希望保留相对于图像(平面图)的点位置,这不会发生。请检查更新的小提琴。

我的解决方案小提琴链接 https://jsfiddle.net/bharatpatil/v7658dn9/43/

HTML

<button id="zoomIn">Zoom In</button>
<button id="zoomOut">Zoom Out</button>
<br>
<canvas id="c"></canvas>

Javascript

var i, dot,
  getRandomInt = fabric.util.getRandomInt,
  rainbow = ["#ffcc66", "#ccff66", "#66ccff", "#ff6fcf", "#ff6666"],
  rainbowEnd = rainbow.length - 1;

var circle1Radius = 20;

// create canvas instance
var canvas2 = new fabric.Canvas('c', {
  backgroundColor: "#fff",
  renderOnAddRemove: false
});


fabric.Image.fromURL('https://upload.wikimedia.org/wikipedia/commons/9/9a/Sample_Floorplan.jpg', function(img) {

  img.scaleX = canvas2.width / img.width;
  img.scaleY = canvas2.height / img.height;
  img.set('selectable', false);
  img.opacity = 0.3;
  canvas2.add(img);

  createDots();
});


function createDots() {
  // draw random dots
  for (i = 100; i >= 0; i--) {
    dot = new fabric.Circle({
      left: getRandomInt(0, 400),
      top: getRandomInt(0, 350),
      radius: circle1Radius,
      selectable: false,
      lockScalingX: true,
      lockScalingY: true,
      lockRotation: true,
      hasControls: false,
      hasBorders: true,
      hasRotatingPoint: false,
      objectType: 'AppCircle'
    });
    dot.setGradient('fill', {
      type: 'radial',
      r1: 0,
      r2: circle1Radius,
      x1: circle1Radius,
      y1: circle1Radius,
      x2: circle1Radius,
      y2: circle1Radius,
      colorStops: {
        0: 'rgb(85, 196, 255, 1)',
        0.1: 'rgb(85, 196, 255, 0.5)',
        0.2: 'rgb(85, 196, 255, 0.4)',
        0.3: 'rgb(85, 196, 255, 0.3)',
        0.4: 'rgb(85, 196, 255, 0.2)',
        1: 'rgba(85, 196, 255, 0.1)',
      }
    });
    canvas2.add(dot);
  }
  canvas2.renderAll(); // Note, calling renderAll() is important in this case
}

function zoom(isZoomingIn) {
  var SCALE_FACTOR = 1.1;
  var objects = canvas2.getObjects();
  var dd = 1;
  if (isZoomingIn) dd = SCALE_FACTOR;
  if (!isZoomingIn) dd = 1 / SCALE_FACTOR;
  for (var i in objects) {
    if (objects[i].objectType !== 'AppCircle') {
      console.log(objects[i]);
      objects[i].scaleX = objects[i].scaleX * dd;
      objects[i].scaleY = objects[i].scaleY * dd;
    }
    objects[i].left = objects[i].left * dd;
    objects[i].top = objects[i].top * dd;
    objects[i].setCoords();
  }
  canvas2.setHeight(canvas2.height * dd);
  canvas2.setWidth(canvas2.width * dd);
  canvas2.renderAll();
  canvas2.calcOffset();
}

document.getElementById('zoomIn').addEventListener('click', () => {
  zoom(true);
});
document.getElementById('zoomOut').addEventListener('click', () => {
  zoom(false);
});

更新

我们还希望保留相对于图像(平面图)的点位置,这不会发生。请检查更新的小提琴。

https://jsfiddle.net/bharatpatil/v7658dn9/43/

标签: javascripthtml5-canvaszoomingfabricjs

解决方案


推荐阅读