Puedo aplicar un zoom a una ruta en d3v7. Sin embargo, ¿cómo puedo hacer zoom solo en el eje x en lugar de un zoom estándar?
(1) Cómo llamo a la función de zoom:
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);(2) Función de acercamiento
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); } }En su función de zoom, puede cambiar la escala del eje x y luego usarlo para volver a dibujar el gráfico completo:
const zoom = d3.zoom() .on("zoom", function(event) { x2 = event.transform.rescaleX(x); xAxisG.call(xAxis.scale(x2)); path.attr("d", line); }) x2 se refiere a una escala de trabajo (que también se usa con d3.line()). La escala x se utiliza como escala de referencia para el reescalado (no queremos reescalar x2 usándose a sí mismo, ya que obtendríamos un valor de zoom incorrecto). Al hacer esto, solo manipulamos los valores de x mientras que los valores de y siguen siendo los mismos.
A continuación, agregué un trazado de recorte para evitar que el gráfico se desborde del área de trazado.
No puede usar la transformación de zoom para manipular el gráfico, ya que aplica el mismo valor de escala a los ejes x e y. Solo amplía la geometría. El enfoque propuesto aquí es un zoom semántico: usar los datos y volver a escalarlos en una dimensión dado el estado de una transformación de zoom.
Aquí hay un ejemplo de trabajo:
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); path { fill: none; stroke-width: 1px; stroke: black; } <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.1.0/d3.min.js"></script> <svg></svg>