SVG Dashes at Corners
HTML
<span>Set dash length:</span><input type="range" min="4" max="60" value="60"/>
<span id="len">60</span>
<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg">
<g stroke="red" stroke-width="20" transform="scale(0.7)">
<path id="one" transform="translate(-200, -40)"
d="M350,75 C
360,140 420,161 469,161
400,200 410,260 423,301
380,270 330,270 277,301
280,250 280,200 231,161
280,160 320,140 350,75
Z"
/>
<path id="two" transform="translate(200, -40)"
d="M350,75 C
360,140 420,161 469,161
400,200 410,260 423,301
380,270 330,270 277,301
280,250 280,200 231,161
280,160 320,140 350,75
Z"
/>
<path id="three" transform="translate(600, -40)"
d="M350,75 C
360,140 420,161 469,161
400,200 410,260 423,301
380,270 330,270 277,301
280,250 280,200 231,161
280,160 320,140 350,75
Z"
/>
</g>
<text transform="translate(55, 230)">Normal dashes</text>
<text transform="translate(330, 230)">Dashes at corners</text>
<text transform="translate(595, 230)">No dashes at corners</text>
</svg>
JavaScript
// ========================== START OF POLYFILL ==========================
// @info
// Polyfill for SVG 2 getPathData() and setPathData() methods. Based on:
// - SVGPathSeg polyfill by Philip Rogers (MIT License)
// https://github.com/progers/pathseg
// - SVGPathNormalizer by Tadahisa Motooka (MIT License)
// https://github.com/motooka/SVGPathNormalizer/tree/master/src
// - arcToCubicCurves() by Dmitry Baranovskiy (MIT License)
// https://github.com/DmitryBaranovskiy/raphael/blob/v2.1.1/raphael.core.js#L1837
// @author
// Jarosław Foksa
// @license
// MIT License
if (!SVGPathElement.prototype.getPathData || !SVGPathElement.prototype.setPathData) {
let commandsMap = {
"Z":"Z", "M":"M", "L":"L", "C":"C", "Q":"Q", "A":"A", "H":"H", "V":"V", "S":"S", "T":"T",
"z":"Z", "m":"m", "l":"l", "c":"c", "q":"q", "a":"a", "h":"h", "v":"v", "s":"s", "t":"t"
};
class Source {
constructor(string) {
this._string = string;
this._currentIndex = 0;
this._endIndex = this._string.length;
this._prevCommand = null;
this._skipOptionalSpaces();
}
parseSegment() {
let char = this._string[this._currentIndex];
let command = commandsMap[char] ? commandsMap[char] : null;
if (command === null) {
if (this._prevCommand === null) {
return null;
}
if (
(char === "+" || char === "-" || char === "." || (char >= "0" && char <= "9")) && this._prevCommand !== "Z"
) {
if (this._prevCommand === "M") {
command = "L";
}
else if (this._prevCommand === "m") {
command = "l";
}
else {
command = this._prevCommand;
}
}
else {
command = null;
}
if (command === null) {
return null;
}
}
else...