Я пытаюсь увеличить с помощью функции 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>