D3 увеличение части линейного графика - PullRequest
1 голос
/ 09 марта 2020

Я пытаюсь увеличить с помощью функции onclick часть графика. Я прочитал много статей и вопросов по этому вопросу, но большинство из них касаются масштабирования с колесом, и мне нужно только увеличение при нажатии кнопки. Что-то вроде в этой статье (линейный график). Что я не могу понять, так это как вычислить точное положение, в которое масштаб должен быть переведен и правильно масштабирован (мне нужна правая сторона графика, начиная с определенного значения оси X, чтобы увеличить его). Надеюсь, кто-нибудь может помочь. Я включил фиктивные данные в свой код, но реальные данные гораздо более детализированы.

Мой код: также здесь

    <!DOCTYPE html>
<html lang="en">
    <head>
      <meta charset="utf-8">
      <script src="https://d3js.org/d3.v5.min.js"></script>

    </head>

    <body>
      <div id="wrapper" class="wrapper"></div>

      <button id="zoom">Zoom</button>

<script>
dataset = [
    {
    "num": 100,
    "month": 1,
    "year": 2016,
    "mmyy": "2016 _ 1",
    "group": "one",
    "mmyy_rec": "Jan 2016"
  },
      {
    "num": 80,
    "month": 1,
    "year": 2017,
    "mmyy": "2017 _ 1",
    "group": "one",
    "mmyy_rec": "Jan 2017"
  },
      {
    "num": 10,
    "month": 1,
    "year": 2018,
    "mmyy": "2018 _ 1",
    "group": "one",
    "mmyy_rec": "Jan 2018"
  }
]

 let dimensions = {
    width: 800,
    height: 400,
    margin: {
      top: 20,
      right: 15,
      bottom: 40,
      left: 60,
    },
}

dimensions.boundedWidth = dimensions.width - dimensions.margin.left - dimensions.margin.right
dimensions.boundedHeight = dimensions.height - dimensions.margin.top - dimensions.margin.bottom

  const wrapper = d3.select("#wrapper")
    .append("svg")
    .attr("width", dimensions.width)
    .attr("height", dimensions.height);

  const bounds = wrapper.append("g")
    .style("transform", `translate(${dimensions.margin.left}px, ${dimensions.margin.top}px)`)
    .attr("class", "test");

  const xScale = d3.scalePoint() 
    .domain(dataset.map(d=> d.mmyy_rec))
    .range([0, dimensions.boundedWidth]);


  const yScale = d3.scaleLinear()
    .domain([0, d3.max(dataset,d=>d.num)])
    .range([dimensions.boundedHeight,0]);

  const line = d3.line()
    .curve(d3.curveNatural)
    .x(d => xScale(d.mmyy_rec))
    .y(d => yScale(d.num)); 


      const path1 = bounds
     .append('path')
     .datum(dataset)
     .attr('fill', 'none')
     .attr('stroke', 'green')
     .attr("class", "line1") 
     .attr('d', line)


const yAxisGenerator = d3.axisLeft().scale(yScale)
bounds.call(yAxisGenerator);

  d3.select("#zoom").on("click", function() {

   const d0 = "Jan 2017";
    const d1 = "Dec 2018";

   const k = dimensions.boundedWidth / (xScale(d1) - xScale(d0));
   const length = dimensions.boundedHeight - yScale(100);
   const centerX = dimensions.boundedWidth /2;
   const centerY = dimensions.boundedHeight /2;
   const translate = [dimensions.boundedWidth / 2 - centerX * k, dimensions.boundedHeight / 2 - centerY * k]


       const zoom = d3.zoom()
    .scaleExtent([1, 2])
    .translateExtent([[0, 0], [dimensions.boundedWidth, dimensions.boundedHeight]])
    .extent([[0, 0], [dimensions.boundedWidth, dimensions.boundedHeight]])
    .on('zoom', function() {
      path1.attr('transform', d3.event.transform);

    });

     zoom.scaleBy(path1.transition().duration(750), k)
     .translate(centerX,centerY); 


  });

</script>
    </body>


</html>
...