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

som*_*ame 13 javascript brush rotation d3.js

我正在研究这个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");
Run Code Online (Sandbox Code Playgroud)

示例结果

Lar*_*off 5

解释我的解决方案:

采取的基本步骤如下:

  • 将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);
Run Code Online (Sandbox Code Playgroud)

此代码应该是相当不言自明的 - 比例的域根据画笔的当前范围更新并重新绘制轴.

// 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] + ")");
Run Code Online (Sandbox Code Playgroud)

这是一个棘手的部分 - 基于尺度的新领域,我们需要计算线的比例和平移.缩放因子只是旧范围与新范围的比率(请注意,我已经制作了未修改的标度的副本),即大于1的数字.平移确定(0,0)的偏移坐标和计算通过旧(0,0)坐标(我从原始尺度范围得到这个)和新域原点根据原始尺度的位置的差值来计算.

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

// reset brush
brush.clear();
d3.select(".brush").call(brush);
Run Code Online (Sandbox Code Playgroud)

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

在这里完成演示.