在下面的代码中,我在页面加载后设置了一个初始缩放级别,如下所示:
svg.transition().delay(500).duration(750)
.call(zooming.transform, transform)
function transform() {
return d3.zoomIdentity
.translate(-210, 0)
.scale(2);
}
问题是d3.zoomIdentity.translate(x, y)
中的x
值是硬编码的。
我想知道的是,是否有办法设置它,以便它始终根据提供的数据放大到最后六个条形?(在合理范围内(
使用d3.zoomIdentity
是正确的方法,还是有其他方法可以使其更容易?
这是我的代码:
const data = [
{name: "A", value: 67},
{name: "B", value: 92},
{name: "C", value: 82},
{name: "D", value: 53},
{name: "E", value: 20},
{name: "F", value: 88},
{name: "G", value: 15},
{name: "H", value: 94},
{name: "I", value: 66},
{name: "J", value: 53}
];
var svg = d3.select("#chart"),
margin = {top: 35, left: 35, bottom: 35, right: 35},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand()
.domain(data.map(d => d.name))
.range([margin.left, width - margin.right])
.padding(0.1)
var y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)]).nice()
.range([height - margin.bottom, margin.top])
var xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).tickSizeOuter(0))
svg.append("g")
.attr("class", "bars")
.attr("fill", "steelblue")
.selectAll("rect").data(data).enter().append("rect")
.attr("x", d => x(d.name))
.attr("y", d => y(d.value))
.attr("height", d => y(0) - y(d.value))
.attr("width", x.bandwidth());
svg.append("g")
.attr("class", "x-axis")
.call(xAxis);
svg.call(zoom);
function zoom(svg) {
const extent = [
[margin.left, margin.top],
[width - margin.right, height - margin.top]];
var zooming = d3.zoom()
.scaleExtent([1, 3])
.translateExtent(extent)
.extent(extent)
.on("zoom", zoomed)
svg.call(zooming);
svg.transition().delay(500).duration(750)
.call(zooming.transform, transform)
function transform() {
return d3.zoomIdentity
.translate(-210, 0)
.scale(2);
}
function zoomed() {
x.range([
margin.left, width - margin.right]
.map(d => d3.event.transform.applyX(d)));
svg.selectAll(".bars rect")
.attr("x", d => x(d.name))
.attr("width", x.bandwidth());
svg.selectAll(".x-axis").call(xAxis);
}
}
body {
margin: auto;
width: 850px;
}
<meta charset ="utf-8">
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg id="chart" width="400" height="420"></svg>
如果我正确理解您的问题,您可以通过简单地获取倒数第六个的 x 位置来获得最后六个柱线:
-x(data[data.length - 6].name)
由于您正在缩放 2,因此我们必须相应地将其相乘:
-x(data[data.length - 6].name) * 2
以下是更改的代码:
const data = [
{name: "A", value: 67},
{name: "B", value: 92},
{name: "C", value: 82},
{name: "D", value: 53},
{name: "E", value: 20},
{name: "F", value: 88},
{name: "G", value: 15},
{name: "H", value: 94},
{name: "I", value: 66},
{name: "J", value: 53}
];
var svg = d3.select("#chart"),
margin = {top: 35, left: 35, bottom: 35, right: 35},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand()
.domain(data.map(d => d.name))
.range([margin.left, width - margin.right])
.padding(0.1)
var y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)]).nice()
.range([height - margin.bottom, margin.top])
var xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).tickSizeOuter(0))
svg.append("g")
.attr("class", "bars")
.attr("fill", "steelblue")
.selectAll("rect").data(data).enter().append("rect")
.attr("x", d => x(d.name))
.attr("y", d => y(d.value))
.attr("height", d => y(0) - y(d.value))
.attr("width", x.bandwidth());
svg.append("g")
.attr("class", "x-axis")
.call(xAxis);
svg.call(zoom);
function zoom(svg) {
const extent = [
[margin.left, margin.top],
[width - margin.right, height - margin.top]];
var zooming = d3.zoom()
.scaleExtent([1, 3])
.translateExtent(extent)
.extent(extent)
.on("zoom", zoomed)
svg.call(zooming);
svg.transition().delay(500).duration(750)
.call(zooming.transform, transform);
var xValue = -x(data[data.length - 6].name)*2;
function transform() {
return d3.zoomIdentity
.translate(xValue, 0)
.scale(2);
}
function zoomed() {
x.range([
margin.left, width - margin.right]
.map(d => d3.event.transform.applyX(d)));
svg.selectAll(".bars rect")
.attr("x", d => x(d.name))
.attr("width", x.bandwidth());
svg.selectAll(".x-axis").call(xAxis);
}
}
body {
margin: auto;
width: 850px;
}
<meta charset ="utf-8">
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg id="chart" width="400" height="250"></svg>