我正在使用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)


});

最佳答案

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

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>





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

10-02 14:06