使用 D3 加载页面后出现首次缩放故障

问题描述 投票:0回答:1

我使用

D3
在单击和鼠标滚轮上放大图像。一切工作正常,但第一次变焦出现很多故障。

这是应用程序的演示

这就是我放大物体的方式:

const star = "https://gmg-world-media.github.io/skymap-v1dev/static/media/star.19b34dbf.svg";
const galaxy = "https://gmg-world-media.github.io/skymap-v1dev/static/media/galaxy.c5e7b011.svg";
const nebula = "https://gmg-world-media.github.io/skymap-v1dev/static/media/nebula.d65f45e5.svg";
const exotic = "https://gmg-world-media.github.io/skymap-v1dev/static/media/exotic.21ad5d39.svg";

const sWidth = window.innerWidth;
const sHeight = window.innerHeight;

const x = d3.scaleLinear().range([0, sWidth]).domain([-180, 180]);
const y = d3.scaleLinear().range([0, sHeight]).domain([-90, 90]);

const svg = d3.select("#render_map").append("svg").attr("width", sWidth).attr("height", sHeight);
const node = svg.append("g").attr('class', 'scale-holder');

const zoom = d3
  .zoom()
  .scaleExtent([1, 30])
  .translateExtent([
    [0, 0],
    [sWidth, sHeight]
  ])

svg.call(zoom);

const imgG = node.append("g");
imgG
  .insert("svg:image")
  .attr("preserveAspectRatio", "none")
  .attr("x", 0)
  .attr("y", 0)
  .attr("width", sWidth)
  .attr("height", sHeight)
  .attr("xlink:href", "https://gmg-world-media.github.io/skymap-v1dev/img-set/image-1.jpg");
imgG
  .insert("svg:image")
  .attr("preserveAspectRatio", "none")
  .attr("x", 0)
  .attr("y", 0)
  .attr("width", sWidth)
  .attr("height", sHeight)
  .attr("xlink:href", "https://gmg-world-media.github.io/skymap-v1dev/img-set/image.jpg");


// Draw objects on map with icon size 8
drawObjects(8)

function drawObjects(size) {
  const dataArray = [];
  const to = -180;
  const from = 180;
  const fixed = 3;
  const objectType = ["ST", "G", "N", "E"];

  // Following loop is just for demo.
  // Actual data comes from a JSON file.
  for (let i = 0; i < 350; i++) {
    const latitude = (Math.random() * (to - from) + from).toFixed(fixed) * 1;
    const longitude = (Math.random() * (to - from) + from).toFixed(fixed) * 1;
    const random = Math.floor(Math.random() * objectType.length);
    dataArray.push({
      "Longitude": longitude,
      "Latitude": latitude,
      "Category": objectType[random]
    })
  }

  for (let index = 0; index < dataArray.length; index++) {
    // Loop over the data
    const item = dataArray[index]
    const mY = y(Number(item.Latitude))
    const mX = x(Number(item.Longitude))

    if (node.select(".coords[index='" + index + "']").size() === 0) {
      let shape = star;

      // Plot various icons based on Category
      switch (item.Category) {
        case "ST":
          shape = star;
          break;
        case "G":
          shape = galaxy;
          break;
        case "N":
          shape = nebula;
          break;
        case "E":
          shape = exotic;
          break;
      }

      const rect = node
        .insert("svg:image")
        .attr("class", "coords")
        .attr("preserveAspectRatio", "none")
        .attr("x", mX)
        .attr("y", mY)
        .attr("width", size)
        .attr("height", size)
        .attr("cursor", "pointer")
        .attr("index", index)
        .attr("xlink:href", shape)
        .attr("opacity", "0")
        .on("click", function() {
          handleObjectClick(index, mX, mY)
        })

      // Add the objects on the map
      rect.transition().duration(Math.random() * (2000 - 500) + 500).attr("opacity", "1")
    }

  }

}

function boxZoom(x, y) {
  // Zoom towards the selected object
  // This is the part responsible for zooming
  svg
    .transition()
    .duration(1000)
    .call(
      zoom.transform,
      d3.zoomIdentity
      .translate(sWidth / 2, sHeight / 2)
      .scale(6)
      .translate(-x, -y)
    );

}

function handleObjectClick(currentSelect, x, y) {

  // Appending some thumbnails to the clicked object here...
  //Call the zoom function
  boxZoom(x, y)

}
#render_map {
  width: 100vw;
  height: 100vh;
  margin: 0 auto;
  overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<div id="render_map">
</div>

这个缩放在这里似乎不起作用。但它在应用程序中确实有效。我没有修改负责缩放的代码段。 (请参阅此演示。) 问题是,当您在页面加载后第一次执行缩放操作时,缩放会跳转,然后它会自行修复。

我不明白我在这里做错了什么。任何提示都会很可爱。
蒂亚!

javascript css reactjs d3.js
1个回答
1
投票

这个问题似乎是由非常昂贵的 CSS 重绘周期引起的。我在 Firefox 中对此进行了测试,方法是转到 DEV 工具中的

Performance
并开始录制,然后首次缩放。

enter image description here

我看到 fps 大幅下降,并且重绘花费了多达 250 毫秒。通常为 10-50 毫秒。

我有一些建议:

  1. 为什么有两张图像彼此重叠?大图像绝对是重新绘制需要这么长时间的原因,而您的图像是 8000x4000 像素!首先删除我们看不到的图像;
  2. 尝试将初始值
    transform="translate(0, 0) scale(1)"
    添加到
    .scale-holder
    。我有一种感觉,第一次添加这个会迫使整个屏幕重新绘制。也许更改现有的比例值比将比例值应用于之前未缩放的内容更容易;
  3. 如果这没有帮助,请将图像压缩到最多 1600 甚至 1080 像素宽。我们凡人甚至不应该看出差异。
© www.soinside.com 2019 - 2024. All rights reserved.