Can I style dashes in my SVG path, so that each of them would be slightly irregular? As in the image above?
Tried looking for a CSS-only solution. But adding individual elements along the path would work as well
CodePudding user response:
You can make them irregular with a displacement map (see below), or you can find a font with a glyph that you can use and use text along a textPath with that font to make it look like a customized dash. But you can't style each individual dash in a normal path.
<svg width="600px" height="400px">
<filter id="custom-stroke">
<feTurbulence baseFrequency= "0.02" type="turbulence" numOctaves="2"/>
<feDisplacementMap in="SourceGraphic" xChannelSelector="R" yChannelSelector="G" scale="15"/>
<feMorphology operator="erode" radius="1"/>
<feMorphology operator="dilate" radius="1" />
<feGaussianBlur stdDeviation="1.5" />
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 11 -7" result="goo" />
</filter>
<g filter="url(#custom-stroke)">
<path fill="none" stroke="blue" stroke-dasharray="10 10" stroke-width="8" d="M 10 10 a 100 80 0 0 1 100 40 200 300 0 0 0 200 100"/>
</g>
</svg>
CodePudding user response:
<animateMotion rotate="auto">
rotates an SVG element on a <path>
I took my yesterdays answer (see that SO answer for explanation),
simplified it, added Michael his filter, and dabbled a bit with the filter settings.
Question for the SVG experts: Can we get that rotate="auto"
value for each "marker" with JS?
If so, each "marker" could be customized to make it "curve" better
JSFiddle: https://jsfiddle.net/WebComponents/7muns9La/
<svg-path-markers count="25" filter>
<svg viewBox="0 0 500 300" style="background:pink;max-height:180px">
<defs><g id="marker"><path fill="green" d="m0 -10q29 4 0 10a8 7 90 110-10z"/></g></defs>
<filter id="F">
<feTurbulence baseFrequency= "0.001" type="turbulence" numOctaves="1"/>
<feDisplacementMap in="SourceGraphic" xChannelSelector="R" yChannelSelector="G" scale="15"/>
<feMorphology operator="erode" radius=".1"/><feMorphology operator="dilate" radius=".1" />
<feGaussianBlur stdDeviation="1"/><feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 11 -7"/>
</filter>
<path fill="none" stroke="black" d="m50 20a10 10 90 00230 100c30-140-160 0-90 120 30 50 370 40 260-60" />
<g id="markers"/>
</svg>
</svg-path-markers>
<script>
customElements.define("svg-path-markers", class extends HTMLElement {
connectedCallback() {
setTimeout(() => { // wait till innerHTML is parsed
this.querySelectorAll("path").forEach( path => {
let duration = "2"; // set to 0.00001 for instant display
let count = ~~this.getAttribute("count");
let filter = this.hasAttribute("filter") ? 'filter="url(#F)"' : '';
let id = path.id || (path.id = this.localName Math.random()*1e9);
let marker = dist =>
`<use href="#marker" ${filter}>
<animateMotion dur="${duration}" fill="freeze"calcMode="linear"
rotate="auto" keyPoints="0;${dist}" keyTimes="0;1">
<mpath href="#${id}"/></animateMotion></use>`;
this.querySelector("#markers").innerHTML =Array(count).fill(0)
.map((_,i) => marker(i*(1/(count-1)))).join("");
} )
})}})
</script>