使用d3在旋转的线条上绘制以创建缩放效果

时间:2015-09-24 00:35:01

标签: javascript d3.js rotation brush

我正在研究this plnkr。我有三条线在角度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");

Example result

2 个答案:

答案 0 :(得分:5)

解释我的解决方案:

采取的基本步骤如下:

  • 将x和y比例的域更新为画笔范围
  • 重绘轴
  • 计算线的比例因子和平移
  • 相应地缩放和转换行容器
  • 重置画笔

请注意,步骤3和4仅是必要的,因为您没有使用比例绘制所有内容 - 更好的方法是为每行定义两个点作为绑定到元素的数据然后使用比例重绘。这会使代码更简单。

通过你的方法,它仍然可以。为了方便起见,我对您的代码进行了一些修改 - 特别是,我已经清理了具有不同翻译的各种嵌套g元素,并通过x1定义了这些行, x2y1y2属性,而非通过翻译容器。这两个更改都使您想要的功能更容易实现,因为只需要进行单个转换,而不需要考虑多个其他转换。我还在多个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);

最后,我们清除画笔并重置它以摆脱灰色矩形。

完整演示here

答案 1 :(得分:2)

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

  • 设置比例
  • 设置轴
  • 绘制轴

刷完成后,您必须修改比例,然后根据当前的x和y域重新绘制轴。那是你的意思吗?

我稍微清理了一下代码并进行了一些演示:http://plnkr.co/edit/epKbXbcBR2MiwUOMlU5A?p=preview