首页 > 解决方案 > 动态更新可缩放区域图的 y 轴

问题描述

在缩放和平移时,y 轴不会更新为可见缩放数据集中的最大值,例如,当最大值为 3500 时,y 轴仍然有 3500、4000、4500、5000 和 5500 的刻度,这会限制显示。可以更准确地更新过滤数据的新最大值吗?

const height = 400,
  width = 800;
const margin = {
  top: 20,
  right: 20,
  bottom: 30,
  left: 50
};
const parser = d3.timeParse("%Y-%m-%d");

const url = "https://static.observableusercontent.com/files/4e532df03705fa504e8f95c1ab1c114ca9e89546bf14d697c73a10f72028aafd9eb3d6ea2d87bb6b421d9707781b8ac70c2bf905ccd60664f9e452a775fe50ed?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27Book1%25401.csv";
d3.csv(url, function(d) {
  return {
    date: parser(d.date),
    value: +d.value
  };
}).then(function(data) {
  const x = d3.scaleUtc()
    .domain(d3.extent(data, d => d.date))
    .range([margin.left, width - margin.right]),
    y = d3.scaleLinear()
    .domain([0, d3.max(data, d => d.value)])
    .range([height - margin.bottom, margin.top]),
    xAxis = (g, x) => g
    .attr("transform", `translate(0,${height - margin.bottom})`)
    .call(d3.axisBottom(x).ticks(width / 80).tickSizeOuter(0)),
    yAxis = (g, y) => g
    .attr("transform", `translate(${margin.left},0)`)
    .call(d3.axisLeft(y).ticks(5))
    .call(g => g.select(".domain").remove())
    .call(g => g.select(".tick:last-of-type text").clone()
      .attr("x", 3)
      .attr("text-anchor", "start")
      .attr("font-weight", "bold")
      .text(data.y)),
    area = (data, x) => d3.area()
    .curve(d3.curveStepAfter)
    .x(d => x(d.date))
    .y0(y(0))
    .y1(d => y(d.value))
    (data)

  const zoom = d3.zoom()
    .scaleExtent([1, 32])
    .extent([
      [margin.left, 0],
      [width - margin.right, height]
    ])
    .translateExtent([
      [margin.left, -Infinity],
      [width - margin.right, Infinity]
    ])
    .on("zoom", zoomed);

  const svg = d3.select("svg")
    .attr("width", width)
    .attr("height", height);

  svg.append("clipPath")
    .attr("id", "myclip")
    .append("rect")
    .attr("x", margin.left)
    .attr("y", margin.top)
    .attr("width", width - margin.left - margin.right)
    .attr("height", height - margin.top - margin.bottom);

  const path = svg.append("path")
    .attr("clip-path", "url('#myclip')")
    .attr("fill", "steelblue")
    .attr("d", area(data, x));

  const gx = svg.append("g")
    .call(xAxis, x);

  const gy = svg.append("g")
    .call(yAxis, y);

  svg.call(zoom)
    .transition()
    .duration(750)
    .call(zoom.scaleTo, 1, [x(Date.UTC(2020, 8, 1)), 0]);

  function zoomed(event) {
    const xz = event.transform.rescaleX(x);
    const yz = event.transform.rescaleY(y);
    path.attr("d", area(data, xz));
    gx.call(xAxis, xz);
    gy.call(yAxis, yz);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.js"></script>
<svg></svg>

标签: d3.js

解决方案


感谢指导: https ://observablehq.com/@steve-pegg/zoomable-area-chart

下面的更改已经奏效。

function zoomed(event) {
                var xz = event.transform.rescaleX(x);
                var startDate = xz.domain()[0];
                var endDate = xz.domain()[1];
                var fData = data.filter(function (d) {
                    var date = new Date(d.date);
                    return (date >= startDate && date <= endDate);});
                y.domain([0, d3.max(fData, function (d) { return d.value; })]);
                path.attr("d", area(data, xz));
                gx.call(xAxis, xz);
                gy.call(yAxis, y);
               }

推荐阅读