简体   繁体   English

在 SVG 路径中填充形状/图标 (js)

[英]Fill Shapes/Icon In SVG Path (js)

I have a SVG with path我有一个带路径的 SVG

<svg width="100" height="100" stroke="black" fill="transparent">
  <path d="M 10 10 H 90 V 90 H 10 L 10 10"/>
</svg>

SVG图像

and I have to fill some svg shapes / icons in the path with a gap .我必须在路径中用gap填充一些 svg 形状/图标。 For example I have filled the svg path with the circle shape with a gap=2px例如,我用gap=2px的圆形填充了 svg 路径

SVG 编辑图像

is there any javascript function or can we do it with just SVGs and the gap between the circle should be customizable and it should work for all the svg with paths.有没有 javascript function 或者我们可以只用 SVG 来做吗?圆圈之间的gap应该是可定制的,它应该适用于所有带路径的 svg。 (thanks in advance) (提前致谢)

Instead of filling you will need a special stroke.你需要一个特殊的行程而不是填充。 The stroke-dasharray is similar to the border-style in css. However it will create only dashed lines. stroke-dasharray类似于 css 中的 border-style。但是它只会创建虚线。 In the following example I'm using stroke-dasharray="0.1, 9.9" meaning lines of 0.1 units and gaps of 9.9在下面的示例中,我使用stroke-dasharray="0.1, 9.9"表示 0.1 单位的线和 9.9 的间隙

To make them look like dotted I'm using stroke-linecap="round" and a thick line: stroke-width="6"为了使它们看起来像虚线,我使用了 stroke-linecap="round" 和一条粗线: stroke-width="6"

Please observe that line + gap = 0.1 + 9.9 = 10 and the square side length is 80 (a multiple of 10) ensuring that you have a dot in every corner.请注意线 + 间隙 = 0.1 + 9.9 = 10,正方形边长为 80(10 的倍数),确保每个角都有一个点。

 <svg width="100" height="100" stroke="black" fill="transparent"> <path d="M 10 10 H 90 V 90 H 10 L 10 10" stroke-dasharray="0.1, 9.9" stroke-width="6" stroke-linecap="round" ></line>/> </svg>

Not using:不使用:

  • <marker>
  • getTotalLength / getPointAtLength getTotalLength / getPointAtLength

Using:使用:

  • <defs> to define any (compound) SVG group "markN" <defs>定义任何(复合) SVG 组“markN”
    global IDs in whole DOM page!整个 DOM 页面中的全局 ID!
  • a native JS Web Component <svg-path-markers> to proces <path>原生 JS Web 组件<svg-path-markers>处理<path>
    customElements.define script can be executed at any moment you want! customElements.define脚本可以随时执行!
  • <path marker="mark1" markers="4"> attributes indicating which markN to use <path marker="mark1" markers="4">指示使用哪个 markN 的属性
  • a unique ID for each <path> to link it to an <mpath> (motionpath)每个<path>唯一 ID将其链接到<mpath> (运动路径)
  • <animateMotion> to animate a "marker" <animateMotion>为“标记”设置动画
  • keyPoints="0,${dist}" to position the "marker" keyPoints="0,${dist}"position “标记”

Output: Output:

With:和:

 <svg-path-markers> <svg viewBox="0 0 100 100" style="background:pink;max-height:180px"> <defs> <g id="mark1"><circle fill="red" cx="0" cy="0" r="8" /></g> <g id="mark2"><rect fill="green" x="-4" y="-4" width="8" height="8" /></g> <g id="mark3"><circle fill="yellow" cx="0" cy="0" r="2" /></g> </defs> <style>path{ stroke:green; fill:none }</style> <path marker="mark1" markers="4" d="M 10 10 H 90 V 90 H 10 L 10 10" /> <path marker="mark2" markers="8" d="M 10 10 H 90 V 90 H 10 L 10 10" /> <path marker="mark3" markers="16" d="M 10 10 H 90 V 90 H 10 L 10 10" /> </svg> </svg-path-markers> <script> customElements.define("svg-path-markers", class extends HTMLElement { connectedCallback() { setTimeout(() => { // wait till innerHTML is parsed this.querySelectorAll("[marker]").forEach( path => { let duration = "2"; // set to 0.00001 for instant display let count = ~~path.getAttribute("markers") || 4; let id = path.id || (path.id = this.localName + Math.random()*1e9); let marker = dist => `<use href="#${path.getAttribute("marker")}"> <animateMotion dur="${duration}" fill="freeze"calcMode="linear" keyPoints="0;${dist}" keyTimes="0;1" > <mpath href="#${id}"/></animateMotion></use>`; path.insertAdjacentHTML("afterend", Array(count).fill(0).map((_,i) => marker(i*(1/count))).join("")); } ) })}}) </script>

You can use getTotalLength() to find the length of the path and getPointAtLength() to find points along the path where you place the elements.您可以使用getTotalLength()查找路径的长度,使用getPointAtLength()查找放置元素的路径上的点。

In this example I append <use> elements to a <g> .在此示例中,我将 append <use>元素添加到<g>中。

 const p1 = document.getElementById('p1'); const p2 = document.getElementById('p2'); const c1 = document.getElementById('c1'); const c2 = document.getElementById('c2'); setIcons(p1, 'r1', c1, 10); setIcons(p2, 'p3', c2, 10); function setIcons(path, id, container, numb){ let total = parseInt(path.getTotalLength()); let gap = total / numb; [...Array(numb).keys()].map(i => { let point = path.getPointAtLength(i*gap); let use = document.createElementNS('http://www.w3.org/2000/svg','use'); use.setAttribute('href', `#${id}`); use.setAttribute('transform', `translate(${point.x} ${point.y})`); container.appendChild(use); }); }
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 100" height="100" stroke="black" fill="transparent"> <defs> <rect id="r1" x="-5" y="-5" width="10" height="10" fill="red" /> <path id="p3" d="M -10 -12.5 A 5 5 90 0 0 10 -12.5 V 12.5 A 5 5 90 0 0 -10 12.5 Z" fill="red" /> </defs> <path id="p1" d="M 10 10 H 90 V 90 H 10 L 10 10" /> <g id="c1"></g> <g transform="translate(120 0)"> <path id="p2" d="m 0 90 V 50 A 1 1 1 0 1 90 50 V 90" /> <g id="c2"></g> </g> </svg>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM