正确缩放 css 的 svg 剪辑路径

问题描述 投票:0回答:1

我想创建一个顶部弯曲的 div。我想为此使用剪辑路径。 我已经在 Inkscape 中创建了路径,但我不明白我需要如何缩放/更改路径,以便它根据 div 的大小进行缩放/拉伸。

我尝试了各种方法,转换为多边形列表最接近我想要的,但它要么是 % 中的一长串点,要么是块状的。愚蠢的是因为支持曲线。

// taken from https://stackoverflow.com/questions/78172810/algorithm-to-convert-svg-path-to-css-clip-path-polygon

let path = document.querySelector('path');

let pathLength = Math.floor(path.getTotalLength());
let steps = 10;
let scaled = Math.floor(pathLength / steps);
let bbox = path.getBBox();

let points = Object.keys([...new Array(scaled)]).map(num => {
  let point = path.getPointAtLength(num * steps);
  let x = (point.x / bbox.width * 100).toFixed(2);
  let y = (point.y / bbox.height * 100).toFixed(2);
  return `${x}% ${y}%`;
}).join(',');

document.querySelector('style[title="s1"]').innerHTML = `.clipped
{clip-path: polygon(${points});}`;

console.log(`.clipped
{clip-path: polygon(${points});}`)
body {
  display: block;
}

svg {
  background-color: green
}

.clip_inline {
  clip-path: path("m 29.15,0.57 h 42.26 c 0,0 28.02,0 28.02,98.85 H 0.58 C 0.06,5.71 29.17,0.57 29.15,0.57 Z");
  width: 700px;
  height: 100px;
  background-color: blue
}

.clip_url {

  background-color: green;
  clip-path: url(#path1);
}

.clip_url2{



  background-color: yellow;
  clip-path: url(#svgPath);
}
<style title="s1"></style>

<p>the svg file</p>
<svg
   width="100mm"
   height="10mm"
   version="1.1"
   viewBox="0 0 101 101"
   id="svg1"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg">
  <defs
     id="defs1" />
 <path
     d="m 29.15,0.57
h 42.26
c 0,0 28.02,0 28.02,98.85
H 0.58
C 0.06,5.71 29.17,0.57 29.15,0.57
Z"
     fill="none"
     stroke="#000000"
     stroke-linejoin="round"
     stroke-miterlimit="4.5"
     stroke-width="0.0115947"
     style="fill:#000000;stroke:#ff0000;paint-order:stroke fill markers"
     id="path1" />
</svg>

<svg height="0" width="0">
    <defs>
        <clipPath id="svgPath">
            <path fill="#FFFFFF" stroke="#000000" stroke-width="1.5794" stroke-miterlimit="10" d="m 29.15,0.57
h 42.26
c 0,0 28.02,0 28.02,98.85
H 0.58
C 0.06,5.71 29.17,0.57 29.15,0.57
Z"/>
        </clipPath>
    </defs>
</svg>
<p>the  d string from the svg copied into the css, too small</p>
<div class="clip_inline" style="background-color:blue; "></div>
<p>the svg path converted it to a list of polygons</p>
<div class="clipped" style="background-color: orange; width:300px;height:200px"></div>

<p>clip path via url</p>
<div class="clip_url" style=" width:200px;height:200px"></div>


<p>clip path via url2</p>
<div class="clip_url2" style=" width:400px;height:200px"></div>

当减少多边形转换中的步长时,我得到一个非常长的离散点列表,但这看起来很愚蠢,因为曲线器显然被支持作为剪切路径。我只能弄清楚如何将路径从 inkscape 创建的 svg 相关转换为剪辑路径路径格式。通过 url 应用剪辑路径也会失败。

css svg clip-path
1个回答
0
投票

好问题。这是网络开发中最让我烦恼的方面之一。我们有这些很棒的工具来定义复杂的曲线,但很难将它们应用到 HTML 中。在 HTML 中,我们只是希望能够在矩形框上拥有一个精美的边缘,但我们必须诉诸技巧和技巧才能做到这一点。

preserveAspectRatio 属性很有用,特别是值 none

,它使 SVG 可以自由地扭曲视图框以匹配元素的尺寸。与您的问题中演示的多边形转换方法进行比较来演示这一点的片段。

// taken from https://stackoverflow.com/questions/78172810/algorithm-to-convert-svg-path-to-css-clip-path-polygon let path = document.querySelector('path'); let pathLength = Math.floor(path.getTotalLength()); let steps = 10; let scaled = Math.floor(pathLength / steps); let bbox = path.getBBox(); let points = Object.keys([...new Array(scaled)]).map(num => { let point = path.getPointAtLength(num * steps); let x = (point.x / bbox.width * 100).toFixed(2); let y = (point.y / bbox.height * 100).toFixed(2); return `${x}% ${y}%`; }).join(','); document.querySelector('style[title="s1"]').innerHTML = `.clipped {clip-path: polygon(${points});}`; console.log(`.clipped {clip-path: polygon(${points});}`)
body {
  display: block;
}

.svg1 {
  width: 120px;
  aspect-ratio: 1;
}

.clip_inline {
  clip-path: path("M 0 500 L 0 250 C 0 150 12.925 46.036 71.023 8.394 C 126.75 -27.712 224.23 82.289 275.277 82.289 C 319.174 82.289 384.17 37.448 429.402 56.469 C 491.391 82.537 500 150 500 250 L 500 500 L 0 500 Z");
  width: 200px;
  height: 200px;
  background-color: blue
}

.clipped, .via-absolute {
  width: 50%;
  color: white;
  box-sizing: border-box;
  padding: 2em 1em 1px;
  display: flex;
  align-items: end;
}

.clipped {
  background-color: orange;
}

.via-absolute {
  position: relative;
}

.via-absolute svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
}
<style title="s1"></style>

<svg style="position: absolute;">
  <defs>
    <symbol id="sym1" viewBox="0 0 500 500" preserveAspectRatio="none">
      <path style="stroke: rgb(0, 0, 0); stroke-width: 0px; fill: rgb(255, 0, 0);" d="M 0 500 L 0 250 C 0 150 12.925 46.036 71.023 8.394 C 126.75 -27.712 224.23 82.289 275.277 82.289 C 319.174 82.289 384.17 37.448 429.402 56.469 C 491.391 82.537 500 150 500 250 L 500 500 L 0 500 Z" transform="matrix(1, 0, 0, 1, 5.684341886080802e-14, 0)"/>
    </symbol>
  </defs>
</svg>

<p>the svg path converted to a list of polygons</p>
<div class="clipped">
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas tempor nunc mauris, sit amet placerat tortor lobortis dapibus. Nam lectus eros, maximus ac magna vel, congue consequat eros. Fusce id pretium diam.</p>
</div>

<p>via absolute positioning and preserveAspectRatio=none (no script required)</p>
<div class="via-absolute">
  <svg><use href="#sym1"/></svg>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas tempor nunc mauris, sit amet placerat tortor lobortis dapibus. Nam lectus eros, maximus ac magna vel, congue consequat eros. Fusce id pretium diam.</p>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.