如何使用SVG作为剪辑路径

问题描述

我正在尝试建立星级评定功能,但很惊讶地发现,给我最大麻烦的部分是弄清楚如何获得星形。在我看来,考虑到我已经构建的内容,最直接的方法是尝试使用SVG星形在显示等级的div元素上创建剪切路径。我对一般意义上的clip-path很熟悉,并已将其用于更基本的形状,但是要了解如何将其与svg一起使用以及为什么我的当前代码无法正常工作(我不完全了解svg)我典型的驾驶室)。

代码:

const stars = document.getElementsByClassName('star');

function fillStars(starClasses,placeRating) {
   const wholeFill = Math.floor(placeRating);
   const decimalFill = placeRating % 1;
   const yellowFill = decimalFill.toFixed(2).toString().replace('0.','');

   for (let i = 0; i < wholeFill; i++) {
      starClasses[i].style.backgroundColor = '#fbff01';
   }

   if (placeRating - wholeFill !== 0) {
      starClasses[starClasses.length - 1].style.background = `linear-gradient(90deg,#fbff01 ${yellowFill}%,#FFFFFF 0%)`;
   } 
 }

fillStars(stars,4.3);
.star {
  width: 30px;
  height: 30px;
  border: solid 1px gray;
  clip-path: url(#star-clip);
}
      
#rating {
  display: flex;
}
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
    <defs>
        <clipPath id="star-clip" clipPathUnits="objectBoundingBox">
            <rect fill="#fff" id="canvas_background" height="40" width="41" y="-1" x="-1"/>
              <rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%"/>
              <path id="svg_1" d="m3.885,14.64105l11.84103,0l3.65897,-12.22295l3.65897,12.22295l11.84103,0l-9.57958,7.55411l3.65916,12.22295l-9.57958,-7.55431l-9.57958,7.55431l3.65916,-12.22295l-9.57958,-7.55411z" stroke-width="1.5" stroke="#000" fill="#fff"/>
        </clipPath>
    </defs>
    </svg>
    <div id="header">
      <div id="rating">
        <div id="star-1" class="star"></div>
        <div id="star-2" class="star"></div>
        <div id="star-3" class="star"></div>
        <div id="star-4" class="star"></div>
        <div id="star-5" class="star"></div>
      </div>
    </div>

解决方法

关于从原始SVG尺寸计算clipPath的0-1范围,有一个很好的答案here

.star {
  width: 30px;
  height: 30px;
  clip-path: url(#star-clip);
  background: Gold;
}

#rating {
  display: flex;
}
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
  <defs>
    <clipPath id="star-clip" clipPathUnits="objectBoundingBox" transform="scale(0.025,0.02439)">
      <path d="m3.885,14.64105l11.84103,0l3.65897,-12.22295l3.65897,12.22295l11.84103,0l-9.57958,7.55411l3.65916,12.22295l-9.57958,-7.55431l-9.57958,7.55431l3.65916,-12.22295l-9.57958,-7.55411z" />
    </clipPath>
  </defs>
</svg>

<div id="rating">
  <div id="star-1" class="star"></div>
  <div id="star-2" class="star"></div>
  <div id="star-3" class="star"></div>
  <div id="star-4" class="star"></div>
  <div id="star-5" class="star"></div>
</div>

,

您可以使用clip-path: polygon();吗?

我认为url(#id)不受完全支持,或者很难得到正确的答案。

与边框无关:边框将应用于边框

看到最后一颗星星

.star {
  width: 50px;
  height: 50px;
  background-color: pink;
  border: solid 1px gray;
  clip-path: polygon(54.5% 24.5%,80.25% 24.27%,60.73% 34.91%,75% 52.25%,44.5% 41.24%,15% 52.75%,30.00% 34.75%,1.5% 25.25%,31.77% 24.86%,41.82% 9.01%);
 
}

.star-last {
  background-color: #f1e745;
  height: 50px;
  width: 50px;
  clip-path: polygon(54.5% 24.5%,30% 34.75%,-200.42% 25.25%,41.82% 9.01%);
  border: 1px solid black;
}
      
#rating {
  display: flex;
}
   
    <div id="header">
      <div id="rating">
        <div id="star-1" class="star"></div>
        <div id="star-2" class="star"></div>
        <div id="star-3" class="star"></div>
        <div id="star-4" class="star"></div>
        <div id="star-5" class="star-last"></div>
      </div>
    </div>

,

编辑:正如我之前所述,很难使用标准的SVG路径,但是如选择的答案中指出的那样,您需要做的就是添加变换比例,这是我现在学到的。以下是达到相同目的的其他方法,但选择的答案是最好的方法。

也许这是您的路径定义,正如我在其他答案中所说的那样,使用标准SVG路径似乎很难正确理解

我从MDN复制了一条心脏路径,并删除了直肠,您的代码正常工作。

编辑:如果您无法为星形路径计算出正确的定义语法,则可以使用CSS中的polygon()代码作为十进制代替svg中的路径。 从svg中删除<path>并替换为。

 <polygon points="0.545 0.245,0.8025 0.2427,0.6073 0.3491,0.75 0.5225,0.445 0.4124,0.15 0.5275,0.3000 0.3475,0.15 0.2525,0.3177 0.2486,0.4182 0.0901" />

const stars = document.getElementsByClassName('star');

function fillStars(starClasses,placeRating) {
   const wholeFill = Math.floor(placeRating);
   const decimalFill = placeRating % 1;
   const yellowFill = decimalFill.toFixed(2).toString().replace('0.','');

   for (let i = 0; i < wholeFill; i++) {
      starClasses[i].style.backgroundColor = '#fbff01';
   }

   if (placeRating - wholeFill !== 0) {
      starClasses[starClasses.length - 1].style.background = `linear-gradient(90deg,#fbff01 ${yellowFill}%,#FFFFFF 0%)`;
   } 
 }

fillStars(stars,4.3);
.star {
  width: 30px;
  height: 30px;
  border: solid 1px gray;
  clip-path: url(#star-clip);
}
  
#rating {
  display: flex;
}

  
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
    <defs>
      <clipPath id="star-clip" clipPathUnits="objectBoundingBox">
         <path d="M0.5,1
                    C 0.5,1,0.7,0.3
                    A 0.25,0.25,0.5,0.3
                    C 1,1 Z" ></path>     
      </clipPath>
    </defs>
    </svg>
    <div id="header">
      <div id="rating">
        <div id="star-1" class="star"></div>
        <div id="star-2" class="star"></div>
        <div id="star-3" class="star"></div>
        <div id="star-4" class="star"></div>
        <div id="star-5" class="star"></div>
      </div>
    </div>

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...