d3.js - 如果要缩放,要计算缩放和平移的转换值
问题描述
我在看这个例子,它展示了如何使用缩放功能来放大指定的域范围
https://bl.ocks.org/mbostock/431a331294d2b5ddd33f947cf4c81319
我对这部分感到困惑:
var d0 = new Date(2003, 0, 1),
d1 = new Date(2004, 0, 1);
// Gratuitous intro zoom!
svg.call(zoom).transition()
.duration(1500)
.call(zoom.transform, d3.zoomIdentity
.scale(width / (x(d1) - x(d0))) // I think this is to caulcuate k which is the zoom factor
.translate(-x(d0), 0)); // but what is this?
我无法理解所做的计算。如果我的假设是错误的,请纠正我
d3.zoomIdentity
这是一种在应用时不执行任何操作的转换。
.scale(width / (x(d1) - x(d0)))
这是通过计算两个数据点之间的比率和width
像素差之间的比率来计算要应用的比例d0
d1
.translate(-x(d0), 0))
我不明白这部分。为什么被x(d0)
否定? 的x
坐标d(0)
与需要应用多少翻译有什么关系?
解决方案
平移值正在对齐图形,因此x(d0)
是绘图区域中可见的最左边的 x 值。这确保了绘图区域的可见部分从d0
穿过d1
(可见子域)延伸。如果我们的 x 尺度的整个域的最小值为 0,则将x(0)
向左移动(负移)x(d0)
像素。
我将使用一个片段来演示:
var svg = d3.select("svg"),
margin = {top: 10, right: 50, bottom: 70, left: 200},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
// Scale for Data:
var x = d3.scaleLinear()
.range([0, width])
.domain([0,20]);
// Scale for Zoom:
var xZoom = d3.scaleLinear()
.range([0,width])
.domain([0,width]);
var xAxis = d3.axisBottom(x).ticks(5);
var xZoomAxis = d3.axisBottom(xZoom);
var zoom = d3.zoom()
.scaleExtent([1, 32])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// plot area
g.append("rect")
.attr("width",width)
.attr("height",height)
.attr("fill","url(#stripes)");
g.append("text")
.attr("x",width/2)
.attr("y",height/2)
.style("text-anchor","middle")
.text("plot area");
g.append("line")
.attr("y1",0)
.attr("y2",height)
.attr("stroke-width",1)
.attr("stroke","black");
// zoomed plot area:
var rect = g.append("rect")
.attr("width",width)
.attr("height",height)
.attr("fill","lightgrey")
.attr("opacity",0.4);
// Axis for plot:
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Axis for zoom:
g.append("g")
.attr("class", "axis axis-zoom-x")
.attr("transform", "translate(0,"+(height+30)+")")
.call(xZoomAxis);
var text = g.append("text")
.attr("y", height+60)
.attr("text-anchor","middle")
.text("zoom units")
.attr("x",width/2);
// Gratuitous intro zoom:
var d1 = 18;
var d0 = 8;
svg.call(zoom).transition()
.duration(2000)
.call(zoom.transform, d3.zoomIdentity
.scale(width / (x(d1) - x(d0)))
.translate(-x(d0), 0));
function zoomed() {
var t = d3.event.transform, xt = t.rescaleX(x);
xZoom.range([xt(0),xt(20)]);
g.select(".axis--x").call(xAxis.scale(xt));
g.select(".axis-zoom-x").call(xZoomAxis.scale(xZoom));
rect.attr("x", xt(0));
rect.attr("width", xt(20) - xt(0));
text.attr("x", xt(10));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="180">
<defs>
<pattern id="stripes" patternUnits="userSpaceOnUse" width="8" height="8" patternTransform="rotate(45 0 0)">
<rect width="3" height="8" fill="orange"></rect>
</pattern>
</defs>
</svg>
片段解释:
- 地块区域:橙色条纹
- 数据的全尺寸范围:灰色框。
g
对于拥有一切的父级,绘图区域的左侧是 x=0(像素) 。
当我们放大数据的范围时,超出了绘图区域。我们想显示我们数据的特定子域。我们通过比例实现了其中的一部分(正如您正确推断的那样),但另一部分是通过平移:我们将小于 x 子域的最小值的值推到左侧。通过将整个图形向左推等于x(d0)
,x(d0)
显示为绘图区域的最左侧坐标。
推荐阅读
- powershell - PowerShell SSL/TLS 错误与 Invoke-RestMethod 命令
- node.js - process.uncaughtException 不能在 express 中工作
- terraform - 将值动态注入 Terraform 中的变量
- python-2.7 - 创建类似对象的 csv DictReader
- email - 设置 hMailServer 以发送和接收电子邮件
- c# - 在 2 种相同的方法中从 matrix1 * matrix2 得到不同的结果?
- react-native - 杀死应用程序 React-Native 后 Axios 未附加标头
- python - 使用 arviz 和 pymc3 mcmc 的有效样本大小二维数组
- php - 我在将数据更新到 Yii2 中的表时遇到问题
- sql - 比较两个数组并计算相同字符串的数量