【问题标题】:d3 zoom relative to viewport sized3 相对于视口大小的缩放
【发布时间】:2021-07-09 18:27:17
【问题描述】:

我目前正在尝试使用 d3 缩放库为我的画布元素添加平滑缩放和平移。它应该适用于不同的视口大小,所以我需要画布元素相对于视口的大小。

当尽可能缩小(由 scaleExtent 控制)时,元素应在所有设备上很好地填充屏幕宽度。

const canvas = document.querySelector('canvas')
const context = canvas.getContext('2d')

canvas.width = canvas.offsetWidth
canvas.height = canvas.offsetHeight

const zoom = d3.zoom()
  .scaleExtent([0.4, 2])
  .on('zoom', ({transform}) => zoomed(transform))

d3.select(canvas).call(zoom)
zoomed(d3.zoomIdentity)

function zoomed(transform)  {
  console.log(transform);

  context.save()
  context.clearRect(0,0, canvas.width, canvas.height)
  const scale = transform.k * canvas.width/2000

  context.translate(transform.x, transform.y)
  context.scale(scale, scale)
  
  drawPaths()

  context.restore()
}

我尝试将某种值(相对于画布宽度)添加到比例值,但我只是在猜测 2000,我担心以后当我不操作时它可能会弄乱我的代码d3 变换对象。

这是一个 Codepen: https://codepen.io/lkssmnt-the-lessful/pen/wvgjmbw

【问题讨论】:

  • 这个问题有一个简单的SVG解决方案:获取每条路径的BBox,组合它们,从边界框和SVG的宽度和高度计算最小缩放范围。我不确定 Canvas 是否可行...

标签: d3.js canvas zooming


【解决方案1】:

我通过在初始化时使用缩放以适应方法解决了这个问题:

function initCanvas() {
  const midX = bbox.x + bbox.width / 2;
  const midY = bbox.y + bbox.height / 2;

  const scale = Math.min(viewportWidth / bbox.width, viewportHeight / bbox.height);
  const translateX = viewportWidth / 2 - midX * scale;
  const translateY = viewportHeight / 2 - midY * scale;

  d3.select(canvas).call(
    zoom_function.transform,
    d3.zoomIdentity.translate(translateX, translateY).scale(scale)
  );
}

这将使您的路径以初始化为中心,但不会使 zoomExtent 相对于视口大小。然而,这也可以通过给 scaleExtent 函数一个相对值来完成。

关于边界框的其他信息: 就我而言,由于路径没有改变,因此我不必以编程方式确定边界框,但有一些方法可以做到这一点: https://codepen.io/TomashKhamlai/pen/KNrjqE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-16
    • 1970-01-01
    相关资源
    最近更新 更多