Tôi đã tạo trình kết xuất đường dẫn tùy chỉnh vẽ một mũi tên giữa các nút trong biểu đồ d3 của tôi như được hiển thị trong đoạn mã. Tôi gặp vấn đề cuối cùng mà tôi gặp phải,Làm cách nào để vẽ mũi tên giữa hai điểm trong d3v4?
Làm cách nào để xoay phần mũi tên để nó hướng từ đường cong thay vì hướng của nguồn?
var w2 = 6,
ar2 = w2 * 2,
ah = w2 * 3,
baseHeight = 30;
// Arrow function
function CurvedArrow(context, index) {
this._context = context;
this._index = index;
}
CurvedArrow.prototype = {
areaStart: function() {
this._line = 0;
},
areaEnd: function() {
this._line = NaN;
},
lineStart: function() {
this._point = 0;
},
lineEnd: function() {
if (this._line || (this._line !== 0 && this._point === 1)) {
this._context.closePath();
}
this._line = 1 - this._line;
},
point: function(x, y) {
x = +x, y = +y; // jshint ignore:line
switch (this._point) {
case 0:
this._point = 1;
this._p1x = x;
this._p1y = y;
break;
case 1:
this._point = 2; // jshint ignore:line
default:
var p1x = this._p1x,
p1y = this._p1y,
p2x = x,
p2y = y,
dx = p2x - p1x,
dy = p2y - p1y,
px = dy,
py = -dx,
pr = Math.sqrt(px * px + py * py),
nx = px/pr,
ny = py/pr,
dr = Math.sqrt(dx * dx + dy * dy),
wx = dx/dr,
wy = dy/dr,
ahx = wx * ah,
ahy = wy * ah,
awx = nx * ar2,
awy = ny * ar2,
phx = nx * w2,
phy = ny * w2,
//Curve figures
alpha = Math.floor((this._index - 1)/2),
direction = p1y < p2y ? -1 : 1,
height = (baseHeight + alpha * 3 * ar2) * direction,
// r5
//r7 r6|\
// ------------ \
// ____________ /r4
//r1 r2|/
// r3
r1x = p1x - phx,
r1y = p1y - phy,
r2x = p2x - phx - ahx,
r2y = p2y - phy - ahy,
r3x = p2x - awx - ahx,
r3y = p2y - awy - ahy,
r4x = p2x,
r4y = p2y,
r5x = p2x + awx - ahx,
r5y = p2y + awy - ahy,
r6x = p2x + phx - ahx,
r6y = p2y + phy - ahy,
r7x = p1x + phx,
r7y = p1y + phy,
//Curve 1
c1mx = (r2x + r1x)/2,
c1my = (r2y + r1y)/2,
m1b = (c1mx - r1x)/(r1y - c1my),
den1 = Math.sqrt(1 + Math.pow(m1b, 2)),
mp1x = c1mx + height * (1/den1),
mp1y = c1my + height * (m1b/den1),
//Curve 2
c2mx = (r7x + r6x)/2,
c2my = (r7y + r6y)/2,
m2b = (c2mx - r6x)/(r6y - c2my),
den2 = Math.sqrt(1 + Math.pow(m2b, 2)),
mp2x = c2mx + height * (1/den2),
mp2y = c2my + height * (m2b/den2);
this._context.moveTo(r1x, r1y);
this._context.quadraticCurveTo(mp1x, mp1y, r2x, r2y);
this._context.lineTo(r3x, r3y);
this._context.lineTo(r4x, r4y);
this._context.lineTo(r5x, r5y);
this._context.lineTo(r6x, r6y);
this._context.quadraticCurveTo(mp2x, mp2y, r7x, r7y);
break;
}
}
};
var w = 600,
h = 220;
var t0 = Date.now();
var points = [{
R: 100,
r: 3,
speed: 2,
phi0: 190
}];
var path = d3.line()
.curve(function(ctx) {
return new CurvedArrow(ctx, 1);
});
var svg = d3.select("svg");
var container = svg.append("g")
.attr("transform", "translate(" + w/2 + "," + h/2 + ")")
container.selectAll("g.planet").data(points).enter().append("g")
.attr("class", "planet").each(function(d, i) {
d3.select(this).append("circle").attr("r", d.r).attr("cx", d.R)
.attr("cy", 0).attr("class", "planet");
});
container.append("path");
var planet = d3.select('.planet circle');
d3.timer(function() {
var delta = (Date.now() - t0);
planet.attr("transform", function(d) {
return "rotate(" + d.phi0 + delta * d.speed/50 + ")";
});
var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
g.setAttributeNS(null, "transform", planet.attr('transform'));
var matrix = g.transform.baseVal.consolidate().matrix;
svg.selectAll("path").attr('d', function(d) {
return path([
[0, 0],
[matrix.a * 100, matrix.b * 100]
])
});
});
path {
stroke: #11a;
fill: #eee;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="600" height="220"></svg>
Sẽ không [một cái gì đó như thế này (bằng dấu chọn)] (http://bl.ocks.org/mbostock/1153292) được dễ dàng hơn nhiều? – Mark
Tôi đoán sử dụng một điểm đánh dấu với một cái gì đó như 'orient = auto' sẽ đơn giản hơn vẽ/xoay đầu nhưng tôi không biết làm thế nào khi vẽ trên' canvas' như bạn. Trên một phần tử svg, hãy xem http://bl.ocks.org/tomgp/d59de83f771ca2b6f1d4 ví dụ nếu bạn không nhìn thấy nó (không phải của tôi). – mgc
@ Dấu mốc chỉ trông xấu, chúng khó tùy chỉnh IMO hơn. Khi làm nổi bật, họ sẽ không nhận được đường viền xung quanh chính xác như thế này. Chúng cũng sẽ không hoạt động khi tôi áp dụng gradient cho đường dẫn. – Andrew