如何在 d3.js (v7) 中仅缩放折线图中的 X 轴

SKC*_*SKC 2 javascript d3.js

我可以对 d3v7 中的路径应用缩放。但是,如何才能仅在 x 轴上缩放而不是标准缩放呢?

(1)我如何调用缩放功能:

var svgArea = d3.select('#svg');
const path = svgArea.append("path");
const line = d3.line()
    .x(d => scale.x(d.sample))
    .y(d => scale.y(d.value));
path
    .datum(dataset)
    .attr("fill", fillColor)
    .attr("stroke", color)
    .attr("d", line);
svgArea.call(zoom, padding, width, height, path);
Run Code Online (Sandbox Code Playgroud)

(2) 变焦功能

function zoom(svg, padding, width, height, path) {

    var extent = [
        [padding, padding],
        [width, height]
    ];

    var zooming = d3.zoom()
        .scaleExtent([1, 3])
        .translateExtent(extent)
        .extent(extent)
        .on("zoom", zoomed);

    svg.call(zooming);

    function zoomed(e) {
        path.attr("transform", e.transform);
    }
}
Run Code Online (Sandbox Code Playgroud)

And*_*eid 5

在缩放函数中,您可以重新缩放 x 轴,然后使用它来重新绘制整个图形:

const zoom = d3.zoom()
  .on("zoom", function(event) {
    x2 = event.transform.rescaleX(x); 
    xAxisG.call(xAxis.scale(x2));
    path.attr("d", line);
  })
Run Code Online (Sandbox Code Playgroud)

x2指工作比例(也与 d3.line() 一起使用)。该比例x用作重新缩放的参考比例(我们不想x2使用自身重新缩放,因为这样我们会得到错误的缩放值)。通过这样做,我们仅操纵 x 值,而 y 值保持不变。

下面我添加了一个剪切路径来阻止图形从绘图区域溢出。

您不能使用缩放变换本身来操作图形,因为它对 x 轴和 y 轴应用相同的缩放值。它仅缩放几何图形。这里提出的方法是语义缩放:使用数据并在给定缩放变换状态的一维中重新缩放它。

这是一个工作示例:

const zoom = d3.zoom()
  .on("zoom", function(event) {
    x2 = event.transform.rescaleX(x); 
    xAxisG.call(xAxis.scale(x2));
    path.attr("d", line);
  })
Run Code Online (Sandbox Code Playgroud)
const width = 500;
const height = 180;
const padding = {top: 10, bottom: 50, left: 40, right: 20};

const svg = d3.select("svg")
  .attr("width", width + padding.right + padding.left)
  .attr("height", height + padding.top + padding.bottom)
  
const plotArea = svg.append("g").attr("transform","translate("+[padding.left,padding.top]+")")  

const clippingRect = plotArea
  .append("clipPath")
  .attr("id", "clippy")
  .append("rect")
  .attr("width",width)
  .attr("height",height)
  .attr("fill","none")

  
const data = d3.range(100).map(function(d) {
  return { value: Math.random(), sample: d }
})

const x = d3.scaleLinear().range([0,width]).domain([0,100]);
let x2 = x.copy();
const y = d3.scaleLinear().range([height,0]).domain([0,1]);

const line = d3.line()
    .x(d => x2(d.sample))
    .y(d => y(d.value));
    
const xAxis = d3.axisBottom(x2);
const xAxisG = plotArea.append("g")
  .attr("transform","translate("+[0,height]+")")
  .call(xAxis);
  
const yAxis = d3.axisLeft(y);
const yAxisG = plotArea.append("g").call(yAxis)

  
const path = plotArea.append("path")
  .datum(data)
  .attr("d", line)
  .attr("clip-path","url(#clippy)")
  
 
const zoom = d3.zoom()
  .on("zoom", function(event) {
    x2 = event.transform.rescaleX(x); 
    xAxisG.call(xAxis.scale(x2));
    path.attr("d", line);
  })

svg.call(zoom);
Run Code Online (Sandbox Code Playgroud)
path {
  fill: none;
  stroke-width: 1px;
  stroke: black;
}
Run Code Online (Sandbox Code Playgroud)