问题描述
我正在尝试建立星级评定功能,但很惊讶地发现,给我最大麻烦的部分是弄清楚如何获得星形。在我看来,考虑到我已经构建的内容,最直接的方法是尝试使用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>