Javascript 使用d3在旋转线上画笔以创建缩放效果

Javascript 使用d3在旋转线上画笔以创建缩放效果,javascript,d3.js,rotation,brush,Javascript,D3.js,Rotation,Brush,我正在工作。我有三条线,角度是30,45和60。我想在这些线上应用画笔,这样当图表被刷时,这些线会在它与刷过的矩形相交的地方被重新绘制,并且在轴上有适当的值。非常感谢您对解决此问题的任何帮助或提示 编辑:如果您有不同的解决方案来绘制旋转线,并在其上画笔,这也是受欢迎的。请帮忙 var ga = d3.select("svg") .append("g") .attr("class", "a axis") .attr("transform", "translate(" + m

我正在工作。我有三条线,角度是30,45和60。我想在这些线上应用画笔,这样当图表被刷时,这些线会在它与刷过的矩形相交的地方被重新绘制,并且在轴上有适当的值。非常感谢您对解决此问题的任何帮助或提示

编辑:如果您有不同的解决方案来绘制旋转线,并在其上画笔,这也是受欢迎的。请帮忙

var ga = d3.select("svg")
    .append("g")
    .attr("class", "a axis")
    .attr("transform", "translate(" + margin.left + "," + (height + margin.top) + ")")
    .selectAll("g")
    .data([30, 45, 60])
    .enter()
    .append("g")
    .attr("class", "rotatedlines")
    .attr("transform", function(d) { return "rotate(" + -d + ")"; })
    .attr("stroke-width", 1)
    .attr("stroke", "black")
    .attr("stroke-dasharray", "5,5");

您可以通过
d3.event.target.extent()
访问画笔范围。绘制比例的流程如下所示:

  • 设定比例
  • 设定轴
  • 画轴
画笔完成后,必须修改比例,然后根据当前的x和y域重新绘制轴。这就是你的意思吗


我稍微整理了一下代码并做了一些演示:

来解释我的解决方案:

应采取的基本步骤如下:

  • 将x和y比例的域更新到笔刷范围
  • 重新绘制轴
  • 计算线的比例因子和平移
  • 相应地缩放和平移行容器
  • 重设电刷
请注意,第3步和第4步之所以必要,是因为您没有使用比例绘制所有内容——更好的方法是为每条线定义两个点作为绑定到元素的数据,然后使用比例重新绘制。这将使代码更简单

不过,用你的方法还是有可能的。为了方便起见,我对您的代码做了一些修改——特别是,我清理了具有不同翻译的各种嵌套
g
元素,并通过它们的
x1
x2
y1
y2
属性定义了行,而不是通过容器的翻译。这两种更改都使您更容易实现的功能,因为只有一个转换需要不需要考虑其他多个转换的地方。我还将这些行嵌套在多个
g
元素中,以便可以更轻松地缩放和转换它们

笔刷处理程序函数现在如下所示:

// update scales, redraw axes
var extent = brush.extent();
x.domain(brush.empty() ? x2.domain() : [ extent[0][0], extent[1][0] ]);
y.domain(brush.empty() ? y2.domain() : [ extent[0][1], extent[1][1] ]);
xAxisG.call(xAxis);
yAxisG.call(yAxis);
这个代码应该是相当自解释的——缩放的域根据笔刷的当前范围进行更新,轴被重新绘制

// compute and apply scaling and transformation of the g elements containing the lines
var sx = (x2.domain()[1] - x2.domain()[0])/(x.domain()[1] - x.domain()[0]),
    sy = (y2.domain()[1] - y2.domain()[0])/(y.domain()[1] - y.domain()[0]),
    dx = -x2(x.domain()[0]) - x2.range()[0],
    dy = -y2(y.domain()[1]) - y2.range()[1];
d3.selectAll("g.container")
  .attr("transform", "translate(" + [sx * dx, sy * dy] + ")scale(" + [sx, sy] + ")");
这是一个棘手的部分——基于新的比例域,我们需要计算线条的比例和平移。缩放因子只是旧范围与新范围的比率(请注意,我制作了未修改的范围的副本),即大于1的数字。平移确定(0,0)坐标的偏移,并通过旧(0,0)坐标(我从原始比例的范围中得到)和新域原点根据原始比例的位置的差来计算

当同时应用平移和缩放时,我们需要将偏移与缩放因子相乘

// reset brush
brush.clear();
d3.select(".brush").call(brush);
最后,我们清除画笔并重置它以去除灰色矩形


完成演示。

是否要用新的缩放视图覆盖现有图表,类似于?是-我想完全按照示例中所示进行覆盖。在您的示例中,您使用旋转30、45、60…绘制了线,这是真实的数据集,还是有一些真实的x(日期)和y(点)如图中所示的值当图表加载时,线以我要求的角度(30,45,60)绘制-但当画笔事件发生时,图表应重新绘制并显示与画笔区域相交的旋转线hmmm,因此没有x域或y域谢谢您的回答。。我还需要重新绘制旋转的线-它与拉丝区域相交的地方。如果画笔区域不与旋转的线相交,则它不应出现在重新绘制的图表上。你知道如何做到这一点吗?这是简单的部分,我想你可能已经解决了这个问题:-)请看这个版本:第116行。我分割画布和线条,然后你可以用类似于
transform=“translate(-50470)scale(2)”的东西缩放
g
元素。顺便说一句,d3还有一个缩放库,你可以从中借用数学。translate(-50470)是x0和y0?参见第156行的plnkr,我添加了平移变换功能。我仍然不知道如何重新定位旋转的线条?将
g
元素想象成手机屏幕。您可以通过挤压和平移来正确调整图形,从而放大图形。这正是您需要做的-使用
缩放(因子)
放大,并使用
平移(x,y)
将其正确定位。你明白我什么意思吗?但是要找到正确的位置(你的画笔选择的位置),你需要做一点研究:-)这就是我对
缩放行为的意思:他们在那里做了这种计算,也许源代码会对你有所帮助。