Open mbostock opened 8 years ago
On a side note, I noticed interpolate("step")
does listen to tension
, with the effect of steps aligning perfectly half-way between points – no doubt a(n undocumented) feature.
A constant radius would most likely dominate use-cases, however how should the function handle radii that exceed the shortest vector component between two points?
If the desired radius is too big to fit, reduce it to fit; arcs use a similar strategy with arc.cornerRadius as shown in the arc corners animation.
Wow, mesmerizing example...
On another side note, I'm using arc.cornerRadius
in my rest-loaded sunburst menu.
I've noticed the arc.cornerRadius
implementation tends to flicker when used on sunbursts with exactly two partitions. Cosmetics, so I haven't gotten around to exploring the bug further.
You’re still using D3 3.x; the flickering has been fixed in 4.0.
I've made an attempt at an implementation. My question is whether the parameter really should be EDIT: realised Mike's six months ahead of me as usual – the tension discussion was closed in June last year..tension
. That term is better aligned with the cardinal implementation, however .radius
is more straight-forward in describing what to actually pass in the function call (at least in my implementation below).
Thoughts?
lineEnd: function() {
if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
},
point: function(x, y) {
x = +x, y = +y;
switch (this._point) {
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
case 1: this._point = 2; // proceed
default: {
if (this._t <= 0) {
this._context.arcTo(this._x, y, this._x-this._tension, y, this._tension);
this._context.lineTo(x, y);
} else {
var x1 = this._x * (1 - this._t) + x * this._t;
if (this._y < y-this._tension) {
this._context.arcTo(x1, this._y, x1, this._y+this._tension, this._tension);
if (0 < this._t && this._t < 1) this._context.arcTo(x1, y, x1-this._tension, y, this._tension);
else this._context.lineTo(x, y);
} else if (this._y > y+this._tension) {
this._context.arcTo(x1, this._y, x1, this._y-this._tension, this._tension);
if (0 < this._t && this._t < 1) this._context.arcTo(x1, y, x1-this._tension, y, this._tension);
else this._context.lineTo(x, y);
} else {
this._context.lineTo(x, y);
}
}
break;
}
}
this._x = x, this._y = y;
}
I am using step graph and wants to change corner radius like above design, I applied this above given code in step.js but not getting expected result. So how can I get this can I get this rounded corner radius in my step graph.
The following step function works for d3-shape 1.0.4. It needs some attention to play with the current version (1.3.7).
export function Step(context, t, radius) {
this._context = context;
this._t = t;
this._radius = radius;
}
Step.prototype = {
areaStart: function() {
this._line = 0;
},
areaEnd: function() {
this._line = NaN;
},
lineStart: function() {
this._x = this._y = NaN;
this._point = 0;
},
lineEnd: function() {
if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
},
point: function(x, y) {
x = +x, y = +y;
switch (this._point) {
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
case 1: this._point = 2; // proceed
default: {
if (this._t <= 0) {
this._context.arcTo(this._x, y, this._x-this._radius, y, this._radius);
this._context.lineTo(x, y);
} else {
var x1 = this._x * (1 - this._t) + x * this._t;
if (this._y < y-this._radius) {
this._context.arcTo(x1, this._y, x1, this._y+this._radius, this._radius);
if (0 < this._t && this._t < 1) this._context.arcTo(x1, y, x1-this._radius, y, this._radius);
else this._context.lineTo(x, y);
} else if (this._y > y+this._radius) {
this._context.arcTo(x1, this._y, x1, this._y-this._radius, this._radius);
if (0 < this._t && this._t < 1) this._context.arcTo(x1, y, x1-this._radius, y, this._radius);
else this._context.lineTo(x, y);
} else { // ∆y < radius
this._context.lineTo(x, y);
}
}
break;
}
}
this._x = x, this._y = y;
}
};
export default (function custom(radius) {
function step(context) {
return radius ? new Step(context, 0.5, radius) : new Step(context, 0.5, 0);
}
step.radius = function(radius) {
return custom(+radius);
};
return step;
})(0);
This is how I invoke it:
d3.curveStepBefore.radius(10)
Thank's for help, I applied this code and it is working fine, I need one more help, actually the curve is appearing on right side of step, can we make it to appear both the side's?
Thanks for this @lgrkvst
So your example here is really close to what I'm after, but I see that the lines are oriented left of the nodes instead of right. Do you have any ideas of how I can solve this please?
Many thanks!
function Step(context, t, radius) {
this._context = context;
this._t = t;
this._radius = radius;
}
Step.prototype = {
areaStart: function () {
this._line = 0;
},
areaEnd: function () {
this._line = NaN;
},
lineStart: function () {
this._x = this._y = NaN;
this._point = 0;
},
lineEnd: function () {
if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
},
point: function (x_, y_) {
x = +x_, y = + y_;
switch (this._point) {
case 0:
this._point = 1;
this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
break;
case 1:
this._point = 2;
default: {
var x1, y1;
if (this._t <= 0) {
this._context.arcTo(this._x, y, this._x - this._radius, y, this._radius);
this._context.lineTo(x, y);
} else {
// Intermediate inference content between previous point and current point
x1 = this._x * (1 - this._t) + x * this._t;
y1 = this._y * (1 - this._t) + y * this._t;
// check angle
if (this._y < y - this._radius) {
// (Top to Bottom Arc)
this._context.arcTo(this._x, this._y, x, y1, this._radius);
} else if (this._y > y + this._radius) {
// (Bottom to Top Arc)
this._context.arcTo(this._x, this._y, x, y1, this._radius);
} else if (this._x < x - this._radius) {
// (Left to Right Arc)
this._context.arcTo(this._x, this._y, x1, y, this._radius);
} else if (this._x > x + this._radius) {
// (Right to Left Arc)
this._context.arcTo(this._x, this._y, x1, y, this._radius);
} else {
// spacing lower with radiant draw line
this._context.lineTo(x, y);
}
}
break;
}
}
this._x = x, this._y = y;
}
};
stepRound = function (context) {
radius = 100
return new Step(context, 0.5, radius);
};
// And here i was used
const line = d3.line()
.x(d => d.x)
.y(d => d.y)
.curve(stepRound);
I have same problem, and i was found solution in 2days. It depend of code of @lgrkvst , tks u so much.
Hope will help another go after
From d3/d3#2864 by @lgrkvst, it might be nice to support a radius for rounded corners on d3.curveStep and related curves. Example:
The radius would probably need to be constant for the whole curve, although it’s interesting to speculate whether it could also be defined per-point.