如何根据数据 d3js 设置初始确定的缩放级别



在下面的代码中,我在页面加载后设置了一个初始缩放级别,如下所示:

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>

最新更新