我正在使用d3.js v4.我目前正在实施程序化缩放.这Panning and Zooming Tutorial有很大的帮助.我的缩放适用于滚轮,但我想创建缩放按钮.我知道缩放和平移的必要条件是平移[tx,ty]和比例因子k.我正在为x-Axis使用时间刻度.通过在x轴上获取p1(点1)和p2(点2)的像素值,然后使用这些值得到k(比例因子),我设法得到tx和比例因子k.像这样:
var k = 500 / (xScale(p2) - xScale(p1)); //500 is desired pixel diff. between p1 and p2,and xScale is my d3.scaleTime() accessor function.
// for this zoom i just want the first value and last value to be at scale difference of the entire width.
然后我用这个计算tx:
var tx = 0 - k * p1;
然后将其输入d3.zoomIdentity()并重新调整我的xdomain.我创建了一个缩小按钮的按钮.问题是当我放大然后尝试使用按钮缩小时,它会缩小,但缩小x轴.我似乎无法找到为什么它缩小x轴而不是正确缩小.
我的JSFiddle
https://jsfiddle.net/codekhalifah/Lmdfrho7/2/
我试过的
>阅读zoom Documentation
>阅读有关放大D3.js in action的章节
我的守则
应用滚轮缩放后,我运行此功能:
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
console.log(t);
console.log(xScale.domain());
xScale.domain(t.rescaleX(x2).domain());
usageAreaPath.attr("d",area);
usageLinePath.attr('d',line);
weatherAreaPath.attr('d',weatherChart.area);
focus.select(".axis--x").call(xAxis);
focus.selectAll('.circle')
.attr('cx',function(d) { return xScale(getDate(d)); })
.attr('cy',function(d) { return yScale(d.kWh); })
.attr("transform","translate(0," + 80 + ")");
... other non related items
}
缩放工作正常,但放大后然后手动尝试缩放我想要的正常位置.
我的手动变焦按钮功能
function programmaticZoom(){
var currDataSet = usageLinePath.data()[0],//current data set
currDataSetLength = currDataSet.length,//current data set length
x1 = currDataSet[0].usageTime,//getting first data item
x2 = currDataSet[currDataSetLength-1].usageTime,//2nd data item
x1px = xScale(moment(x1)),//Get current point 1
x2px = xScale(moment(x2)); // Get current point 2
// calculate scale factor
var k = width / (x2px - x1px); // get scale factor
var tx = 0 - k * x1px; // get tx
var t = d3.zoomIdentity.translate(tx).scale(k); //create zoom identity
xScale.domain(t.rescaleX(window.x2).domain());
usageAreaPath.attr("d",area);
usageLinePath.attr('d',line);
weatherAreaPath.attr('d',weatherChart.area);
focus.select(".axis--x").call(xAxis);
focus.selectAll('.circle')
.attr('cx',function(d) { return xScale(getDate(d)); })
.attr('cy',function(d) { return yScale(d.kWh); })
.attr("transform"," + 80 + ")");
}
var k = width /(x2px – x1px); //获得规模
var tx = 0 – k * x1px; //得到tx
var t = d3.zoomIdentity.translate(tx).scale(k);
至
var k = 1;
var t = d3.zoomIdentity.scale(k);
首先,当k = 1.0时,图形将完美地适合窗口.我认为将k设置为其以前的值是错误的原因是,当你增加k的值使得k> 1.0,它拉伸图形的宽度超过屏幕.必须重新调整图表上的内容,以便它可以占用图表上尽可能多的空间,同时仍然在屏幕的范围内.用k < 1,这是宽度/(x2px - x1px);,图形缩小到小于屏幕的大小.像这样重新调整只会使图形的内容适合于在图形中占据最大值,但由于图形小于屏幕,因此它将被重新调整以适应缩小的图形并且看起来比屏幕小. 我完全摆脱了tx,因为它抵消了图表开始的位置.当图形放大时,它的宽度会超出屏幕.在此处进行偏移是有意义的,因为您需要将偏移量等于要开始查看图形的位置,并允许不需要保留的部分不在屏幕之外.在您一直缩小的情况下,图形是屏幕的大小,因此偏移将导致图形不在屏幕的开头处开始,而是将其中的一部分从屏幕上移开.在您的情况下,如果k已经缩小了图形,则偏移会使缩小的图形出现在屏幕中间.但是,如果图形没有收缩,则偏移会将图形的一部分推离屏幕. 通过更改它,缩小按钮似乎可以工作,但仍然存在问题.在zoomed()函数中,设置var t = d3.event.transform;. d3.event.transform包含k,x和y的值,当完全缩小时,它们分别需要为1,0和0.我无法在programmaticZoom()函数中更改这些值,因为d3.event.transform仅在触发事件后才存在,特别是鼠标滚轮.如果您只能在单击缩放按钮时将这些值设为k = 1,x = 0,y = 0,则应完全修复该问题. 希望这对一些人有所帮助,我对d3不是很熟悉,但这应该可以解决你的大部分问题,并希望能让你知道出了什么问题.