Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<title>Page Title</title>
<style>
circle {
fill: steelblue;
stroke: #fff;
stroke-width: 3px;
}
path {
fill: none;
stroke: #000;
stroke-width: 1px;
}
</style>
</head>
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var svg = d3.select("body").append("svg")
.attr("width", 1000)
.attr("height", 500)
.attr("viewBox", "0 0 500 250");
var path = svg.append("path")
.attr("d", "m 82.393993,102.36183 c -13.481701,0.0332 -35.416429,-15.12149 -35.446705,-28.75598 -0.03028,-13.63449 20.096934,-32.30487 35.446705,-32.64203 15.349771,-0.33716 49.390017,61.33466 61.043907,61.39801 11.65389,0.0634 39.30246,-15.12148 39.33273,-28.75598 0.0303,-13.6345 -23.98295,-32.30489 -39.33273,-32.64203 -15.34978,-0.33714 -47.562206,61.36486 -61.043907,61.39801 z"
);
function getRandomColorRgb() {
let red = Math.floor(Math.random() * 256);
let green = Math.floor(Math.random() * 256);
let blue = Math.floor(Math.random() * 256);
return `rgb(${red}, ${green}, ${blue})`;
}
function pointDist(point, distance, rad) {
return { x: point.x + distance * Math.cos(rad), y: point.y + distance * Math.sin(rad) };
}
// from https://github.com/d3/d3-shape/blob/master/src/curve/natural.js
function controlPoints(x) {
var i,
n = x.length - 1,
m,
a = new Array(n),
b = new Array(n),
r = new Array(n);
a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
a[n - 1] = r[n - 1] / b[n - 1];
for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
b[n - 1] = (x[n] + a[n - 1]) / 2;
for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1];
return [a, b];
}
class ArowOnPath {
constructor(path, start, length, parts = 3, thickness = 5, angle = 2, padding = 1) {
this.path = path;
this.angle = angle;
this.thickness = thickness;
var partlen = (length - (2 * padding)) / (2 * parts);
this.p = [this.pointsAt(start + padding, (-1 * padding))];
for (var i = 1; i < (2 * parts); i++) {
this.p.push(this.pointsAt(start + length - padding, (-1 * padding)));
}
pointAngle(length) {
var p1 = this.path.getPointAtLength(length);
var p2 = this.path.getPointAtLength(length + 0.01);
return Math.atan2((p2.y - p1.y), (p2.x - p1.x));
}
pointsAt(length, angleoffset = 0) {
var m = this.path.getPointAtLength(length);
var m_angle = this.pointAngle(length + angleoffset)
var a = {
x: m.x + (this.thickness * Math.cos(m_angle + this.angle))
, y: m.y + (this.thickness * Math.sin(m_angle + this.angle))
};
var b = {
x: m.x + (this.thickness * Math.cos(m_angle - this.angle))
, y: m.y + (this.thickness * Math.sin(m_angle - this.angle))
};
return { a: a, m: m, b: b }
}
p2s(point) {
return point.x.toString() + "," + point.y.toString();
}
d3path() {
var path = d3.path();
console.log(this.p.length);
var i = 0
path.moveTo(this.p[i].m.x, this.p[i].m.y);
path.lineTo(this.p[i].a.x, this.p[i].a.y);
var nat = d3.curveNatural(path);
nat.lineStart();
for (var i = 0; i < this.p.length; i++) {
nat.point(this.p[i].a.x, this.p[i].a.y);
}
var px = controlPoints(nat._x),
py = controlPoints(nat._y);
var n = this.p.length;
var x = nat._x,
y = nat._y;
for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
path.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
}
console.log(i)
i = this.p.length - 1;
path.lineTo(this.p[i].m.x, this.p[i].m.y);
path.lineTo(this.p[i].b.x, this.p[i].b.y);
nat.lineStart();
console.log("blah")
for (var i = this.p.length - 1; i >= 0; --i) {
console.log(i)
nat.point(this.p[i].b.x, this.p[i].b.y);
}
var px = controlPoints(nat._x),
py = controlPoints(nat._y);
var n = this.p.length;
var x = nat._x,
y = nat._y;
for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
path.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
}
//line.context(path)(this.p);
path.closePath();
return path;
}
toString() {
return this.d3path().toString();
}
}
for (var i = 0; i < segs; i++) {
ar = new ArowOnPath(s, (i * seg_l), seg_l);
svg.append("path")
.attr("d", ar.toString())
.attr("style", "fill:" + getRandomColorRgb());
}