我正在尝试在强制布局中创建一个具有上升笔触宽度属性的路径。如果目标值高于源值,则链接在目标端应该更宽。
我能找到的唯一例子是this => http://jsfiddle.net/bfzsaL3m/2/
我也遇到过这个问题Decreasing Polyline Stroke Width。它说这不可能,但它有点旧。
现在我的代码使用.style("stroke-width", function(d) { return Math.sqrt(d.value); })
所以任何帮助都表示赞赏。
这是我的简单小提琴:
答案 0 :(得分:2)
要在画布中创建可变宽度折线,您必须执行以下两项操作之一:
后者将是两者中最简单的解决方案:
var ctx = c.getContext("2d"),
line = [116,34,116,37,116,39,116,49,119,71,126,103,140,141,160,181,190,224,226,263,263,
293,312,316,363,327,416,328,458,322,491,313,515,295,537,272,557,244,570,
224,580,208,586,196,591,188,595,182,596,178,598,176,601,174,604,172,605,171],
line2 = [], // the interpolated segments
maxSubSeg = 16, // number of sub-segements
minThick = 2, // taper thickness
maxThick = 16;
// interpolate the line to create more segments
for(var i = 0; i < line.length - 2; i += 2) {
var x1 = line[i], // get line positions
y1 = line[i+1],
x2 = line[i+2],
y2 = line[i+3];
for(var j = 0; j < maxSubSeg; j++) {
line2.push(
x1 + (x2-x1) * (j/maxSubSeg), // interpolate X
y1 + (y2-y1) * (j/maxSubSeg) // interpolate Y
)
}
}
// render new line
ctx.lineCap = "round";
for(var i = 0; i < line2.length - 2; i += 2) {
ctx.beginPath();
ctx.moveTo(line2[i], line2[i+1]);
ctx.lineTo(line2[i+2], line2[i+3]);
ctx.lineWidth = minThick + maxThick * (i/line2.length); // use length as t [0,1]
ctx.stroke();
}
<canvas id=c width=640 height=400></canvas>
答案 1 :(得分:1)
如果有人想知道如何做到这一点。这是我的小提琴:
https://jsfiddle.net/tekh27my/2/
我在tick函数中计算了路径的M和L属性:
d3.selectAll(".link")
.attr("d", function (d) {
var radius = 10;
if(d.target.x > d.source.x && d.target.y < d.source.y){
return "M" + d.source.x + "," + d.source.y + " L" + (d.target.x - radius) + "," + (d.target.y - radius) + " L" + (d.target.x + radius) + "," + (d.target.y + radius) + " L" + d.source.x + ", " + d.source.y;
}else if(d.target.x < d.source.x && d.target.y > d.source.y){
return "M" + d.source.x + "," + d.source.y + " L" + (d.target.x + radius) + "," + (d.target.y + radius) + " L" + (d.target.x - radius) + "," + (d.target.y - radius) + " L" + d.source.x + ", " + d.source.y;
}else{
return "M" + d.source.x + "," + d.source.y + " L" + (d.target.x - radius) + "," + (d.target.y + radius) + " L" + (d.target.x + radius) + "," + (d.target.y - radius) + " L" + d.source.x + ", " + d.source.y;}
});