<!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" ); //transition(); 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) }; } 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 (i = 1; i < (2 * parts); i++) { this.p.push(this.pointsAt(start + (i * partlen))); } this.p.push(this.pointsAt(start + length-padding,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 console.log(i); path.moveTo(this.p[i].m.x, this.p[i].m.y); path.lineTo(this.p[i].a.x, this.p[i].a.y); do { i++; path.bezierCurveTo(this.p[i].a.x, this.p[i].a.y, this.p[i].a.x, this.p[i].a.y, this.p[i + 1].a.x, this.p[i + 1].a.y); i++; } while (i < (this.p.length - 1)); console.log(i); path.lineTo(this.p[i].m.x, this.p[i].m.y); path.lineTo(this.p[i].b.x, this.p[i].b.y); do { i--; path.bezierCurveTo(this.p[i].b.x, this.p[i].b.y, this.p[i].b.x, this.p[i].b.y, this.p[i - 1].b.x, this.p[i - 1].b.y); i--; } while (i > 1); path.closePath(); return path; } toString() { return this.d3path().toString(); } } var i; var s = path.node() ar = new ArowOnPath(s, 0, 10); svg.append("path") .attr("d", ar.toString()) .attr("style", "fill:" + getRandomColorRgb()); var l = s.getTotalLength(); var segs = 8; var thickness = 5; </script> </body>