偏移线描边粗细d3.js

时间:2019-02-26 16:53:09

标签: javascript d3.js

我正在使用d3.js在地图SVG上绘制高速公路网络。我希望能够改变线条的笔触粗细,以基于值来说明需求。

公路链接被定义为一种方式,因此,例如,一条双向道路将具有两个重叠的线元素(具有单独的ID)。我可以使用笔触权重基于变量(如下所示)来编辑线条的粗细,但是在双向道路上,两个笔划权重中的较大者将始终覆盖较小的呈现它的不可见性。

是否有一种简单的方法可以将线条的笔触权重偏移到线条绘制方向的左侧一半? (方向由x1,y1 x2,y2表示)

d3.csv("links.csv", function (error, data) {
d3.select("#lines").selectAll("line")
    .data(data)
    .enter()
    .append("line")
    .each(function (d) {
        d.p1 = projection([d.lng1, d.lat1]);
        d.p2 = projection([d.lng2, d.lat2]);
    })
    .attr("x1", function (d) { return d.p1[0]; })
    .attr("y1", function (d) { return d.p1[1]; })
    .attr("x2", function (d) { return d.p2[0]; })
    .attr("y2", function (d) { return d.p2[1]; })
    .on('mouseover', tip_link.show)
    .on('mouseout', tip_link.hide)
    .style("stroke", "black")
    .style("stroke-width", lineweight)

});

1 个答案:

答案 0 :(得分:1)

一种选择是在绘制线条时仅创建新的起点/终点并使用这些起点/终点:

var offset = function(start,destination,distance) {
    // find angle of line
    var dx = destination[0] - start[0];  
    var dy = destination[1] - start[1];
    var angle = Math.atan2(dy,dx);
    // offset them:
    var newStart = [
      start[0] + Math.sin(angle-Math.PI)*distance,
      start[1] + Math.cos(angle)*distance
    ];
    var newDestination = [
      destination[0] + Math.sin(angle-Math.PI)*distance,  
      destination[1] + Math.cos(angle)*distance 
    ];
    // return the new start/end points
    return [newStart,newDestination]
}

此函数获取两个点,并根据两个点之间的角度将它们偏移特定量。负值移到另一侧,交换起点和终点将移到另一侧。

实际上,它的原始行为黑色:

var offset = function(start,destination,distance) {
    // find angle of line
    var dx = destination[0] - start[0];  
	var dy = destination[1] - start[1];
    var angle = Math.atan2(dy,dx);
	// offset them:
	var newStart = [
      start[0] + Math.sin(angle-Math.PI)*distance,
	  start[1] + Math.cos(angle)*distance
	];
	var newDestination = [
      destination[0] + Math.sin(angle-Math.PI)*distance,  
	  destination[1] + Math.cos(angle)*distance	
	];
	// return the new start/end points
	return [newStart,newDestination]
}

var line = [
	[10,10],
	[200,100]
];

var svg = d3.select("svg");

// To avoid repetition:
function draw(selection) {
  selection.attr("x1",function(d) { return d[0][0]; })
  .attr("x2",function(d) { return d[1][0]; })
  .attr("y1",function(d) { return d[0][1]; })
  .attr("y2",function(d) { return d[1][1]; })
}

svg.append("line")
  .datum(line)
  .call(draw)
  .attr("stroke","black")
  .attr("stroke-width",1)

svg.append("line")
  .datum(offset(...line,6))
  .call(draw)
  .attr("stroke","orange")
  .attr("stroke-width",10)
  
svg.append("line")
  .datum(offset(...line,-4))
  .call(draw)
  .attr("stroke","steelblue")
 .attr("stroke-width",5)  
<svg width="500" height="300"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>

您将需要使其适应数据结构,并且它需要的行数是以前的两倍,因为您不是在使用笔划宽度,而是在使用行。如果您想使用画布,这将非常有利。