d3v4 - масштабирование (эквивалент d3.zoom.x)
Я переношу свой код d3 с версии v3 на версию v4 и у меня возникли проблемы с поиском эквивалента свойств d3.zoom.x, d3.zoom.y.
Вот короткая часть кода, включая самые важные элементы:
this.init = function(obj, def) {
/* X-axis */
x = d3.scaleTime()
.range([0, width]);
xAxis = d3.axisBottom(x)
.ticks(ticks);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")");
/* Y-axis */
for (var i = 0; i < 1; i++) {
// Returns the y and yAxis as arrays
createYAxis(i);
}
initZoom();
};
// Zoom trigger
var drawUpdXY = function(){
setPause(true);
drawUpd();
zoomY.y(y[0]);
zoomX.x(x);
zoom = d3.zoom()
.on("zoom", drawUpdXY);
zoomX = d3.zoom()
.on("zoom", drawUpdX);
zoomY = d3.zoom()
.on("zoom", drawUpdY);
};
Я пытался использовать это, чтобы заменить "zoom.x(x); zoom.y(y[0])"
xAxis.scale(d3.event.transform.rescaleX(x));
yAxis[0].scale(d3.event.transform.rescaleY(y[0]));
Однако они только изменяют масштаб оси, оставляя данные без увеличения.
1 ответ
Я не могу говорить о том, как d3 v3 обрабатывал масштабирование, поскольку я только недавно начал работать с D3, но приведенный ниже код должен указать вам правильное направление. Я сделаю все возможное, чтобы описать, что происходит. Я приглашаю исправления, улучшения и лучшие объяснения.
Во-первых, MCVE
<html>
<head>
<meta charset="UTF-8">
<title>Energy Visualizer</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<style>
body {
background-color: #4e5965;
}
</style>
</svg>
</head>
<body>
<div class="chart" />
<script>
var svg = d3.select(".chart").append("svg")
.attr("width", 200)
.attr("height", 200);
var data = [{
"x": 2,
"y": 8,
"color": "green"
}, {
"x": 4,
"y": 6,
"color": "red"
}];
var width = svg.attr("width");
var height = svg.attr("height");
x_scale = d3.scaleLinear().domain([0, 10]).range([0, width]);
y_scale = d3.scaleLinear().domain([0, 10]).range([0, height]);
var circles = svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return x_scale(d.x);
})
.attr("cy", function(d) {
return y_scale(d.y);
})
.attr("r", 5)
.attr("fill", function(d) {
return d.color
});
var xAxis = d3.axisBottom(x_scale);
var yAxis = d3.axisRight(y_scale);
var x_axis = svg.append("g").call(xAxis);
var y_axis = svg.append("g").call(yAxis);
</script>
</body>
</html>
Это простой график рассеяния с красным и зеленым кругом. Вы можете видеть, как я разбил компоненты оси X и Y. Это входит в игру с d3.zoom()
,
Далее давайте добавим компонент масштабирования.
<html>
<head>
<meta charset="UTF-8">
<title>Energy Visualizer</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<style>
body {
background-color: #4e5965;
}
</style>
</svg>
</head>
<body>
<div class="chart" />
<script>
var svg = d3.select(".chart").append("svg")
.attr("width", 200)
.attr("height", 200);
var zoom = d3.zoom()
.on("zoom", zoomed);
svg.call(zoom);
var data = [{
"x": 2,
"y": 8,
"color": "green"
}, {
"x": 4,
"y": 6,
"color": "red"
}];
var width = svg.attr("width");
var height = svg.attr("height");
x_scale = d3.scaleLinear().domain([0, 10]).range([0, width]);
y_scale = d3.scaleLinear().domain([0, 10]).range([0, height]);
var circles = svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return x_scale(d.x);
})
.attr("cy", function(d) {
return y_scale(d.y);
})
.attr("r", 5)
.attr("fill", function(d) {
return d.color
});
var xAxis = d3.axisBottom(x_scale);
var yAxis = d3.axisRight(y_scale);
var x_axis = svg.append("g").call(xAxis);
var y_axis = svg.append("g").call(yAxis);
function zoomed() {
var new_x_scale = d3.event.transform.rescaleX(x_scale);
var new_y_scale = d3.event.transform.rescaleY(y_scale);
x_axis.transition()
.duration(0)
.call(xAxis.scale(new_x_scale));
y_axis.transition()
.duration(0)
.call(yAxis.scale(new_y_scale));
circles
.attr("cx", function(d) {
return new_x_scale(d.x)
})
.attr("cy", function(d) {
return new_y_scale(d.y)
});
}
</script>
</body>
</html>
Здесь вы можете видеть, что диаграмма позволяет увеличивать, уменьшать и перемещать по обеим осям. Я полагаю, что вам нужно только масштабирование по одной оси, поэтому в этом случае необходимо только изменить масштаб оси X и компонента x каждой позиции окружности.
Последний фрагмент делает то, что я думаю, что вы хотите.
<html>
<head>
<meta charset="UTF-8">
<title>Energy Visualizer</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<style>
body {
background-color: #4e5965;
}
</style>
</svg>
</head>
<body>
<div class="chart" />
<script>
var svg = d3.select(".chart").append("svg")
.attr("width", 200)
.attr("height", 200);
var zoom = d3.zoom()
.on("zoom", zoomed);
svg.call(zoom);
var data = [{
"x": 2,
"y": 8,
"color": "green"
}, {
"x": 4,
"y": 6,
"color": "red"
}];
var width = svg.attr("width");
var height = svg.attr("height");
x_scale = d3.scaleLinear().domain([0, 10]).range([0, width]);
y_scale = d3.scaleLinear().domain([0, 10]).range([0, height]);
var circles = svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return x_scale(d.x);
})
.attr("cy", function(d) {
return y_scale(d.y);
})
.attr("r", 5)
.attr("fill", function(d) {
return d.color
});
var xAxis = d3.axisBottom(x_scale);
var yAxis = d3.axisRight(y_scale);
var x_axis = svg.append("g").call(xAxis);
var y_axis = svg.append("g").call(yAxis);
function zoomed() {
var new_x_scale = d3.event.transform.rescaleX(x_scale);
x_axis.transition()
.duration(0)
.call(xAxis.scale(new_x_scale));
circles
.attr("cx", function(d) {
return new_x_scale(d.x)
});
}
</script>
</body>
</html>