无需使用HTML5画布,实现动态渲染圆形扇区的方法
P粉731861241
2023-09-02 10:43:07
<p>我正在制作一个幸运轮盘,我需要根据扇区数量创建一个轮盘或圆圈,并填充奖品名称。</p>
<p>我已经完成了固定扇区数量的圆圈的代码。这是一个包含6个扇区的圆圈的示例。</p>
<p>
<pre class="brush:css;toolbar:false;">.wheel_container {
position: relative;
--wheel-size: 360px;
width: var(--wheel-size);
height: var(--wheel-size);
margin-bottom: 2.4em;
}
.wheel {
display: flex;
justify-content: center;
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: aquamarine;
--segment-deg: 60deg;
}
.wheel div {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
width: calc((2 * 3.141592653589793 * (var(--wheel-size) / 2)) / 6);
height: 50%;
clip-path: polygon(0 0, 50% 100%, 100% 0);
transform-origin: bottom;
writing-mode: vertical-rl;
}
.wheel div > span {
font-weight: 500;
font-size: 1rem;
text-align: center;
color: rgba(0, 0, 0, 0.7);
}
.wheel div:nth-child(1) {
background-color: beige;
transform: rotate(calc(-1 * var(--segment-deg) / 2));
}
.wheel div:nth-child(2) {
background-color: blueviolet;
transform: rotate(calc(-3 * var(--segment-deg) / 2));
}
.wheel div:nth-child(3) {
background-color: crimson;
transform: rotate(calc(-5 * var(--segment-deg) / 2));
}
.wheel div:nth-child(4) {
background-color: orange;
transform: rotate(calc(-7 * var(--segment-deg) / 2));
}
.wheel div:nth-child(5) {
background-color: violet;
transform: rotate(calc(-9 * var(--segment-deg) / 2));
}
.wheel div:nth-child(6) {
background-color: yellow;
transform: rotate(calc(-11 * var(--segment-deg) / 2));
}</pre>
<pre class="brush:html;toolbar:false;"><div class='wheel_container'>
<div class='wheel'>
<div><span>苹果</span></div>
<div><span>榴莲</span></div>
<div><span>香蕉</span></div>
<div><span>芒果</span></div>
<div><span>草莓</span></div>
<div><span>菠萝蜜</span></div>
</div>
</div></pre>
</p>
<p>我尝试通过计算轮盘的周长除以扇区数量来确定<code>.wheel div</code>的<code>width</code>属性。但是,这不起作用,因为<code>clip-path</code>中的多边形不是弯曲的,而包含它的<code><div></code>仍然是一个盒子。</p>
<p>我可以通过在<code><div></code>的宽度上添加一些像素来实现我想要的6个扇区圆圈的效果。</p>
<p>
<pre class="brush:css;toolbar:false;">.wheel_container {
position: relative;
--wheel-size: 360px;
width: var(--wheel-size);
height: var(--wheel-size);
margin-bottom: 2.4em;
}
.wheel {
display: flex;
justify-content: center;
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: aquamarine;
--segment-deg: 60deg;
}
.wheel div {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
/* Modification */
width: calc((2 * 3.141592653589793 * ((var(--wheel-size) + 37px) / 2)) / 6);
height: 50%;
clip-path: polygon(0 0, 50% 100%, 100% 0);
transform-origin: bottom;
writing-mode: vertical-rl;
}
.wheel div>span {
font-weight: 500;
font-size: 1rem;
text-align: center;
color: rgba(0, 0, 0, 0.7);
}
.wheel div:nth-child(1) {
background-color: beige;
transform: rotate(calc(-1 * var(--segment-deg) / 2));
}
.wheel div:nth-child(2) {
background-color: blueviolet;
transform: rotate(calc(-3 * var(--segment-deg) / 2));
}
.wheel div:nth-child(3) {
background-color: crimson;
transform: rotate(calc(-5 * var(--segment-deg) / 2));
}
.wheel div:nth-child(4) {
background-color: orange;
transform: rotate(calc(-7 * var(--segment-deg) / 2));
}
.wheel div:nth-child(5) {
background-color: violet;
transform: rotate(calc(-9 * var(--segment-deg) / 2));
}
.wheel div:nth-child(6) {
background-color: yellow;
transform: rotate(calc(-11 * var(--segment-deg) / 2));
}</pre>
<pre class="brush:html;toolbar:false;"><div class='wheel_container'>
<div class='wheel'>
<div><span>苹果</span></div>
<div><span>榴莲</span></div>
<div><span>香蕉</span></div>
<div><span>芒果</span></div>
<div><span>草莓</span></div>
<div><span>菠萝蜜</span></div>
</div>
</div></pre>
</p>
<p>但是,适用于6个扇区的代码无法适用于8个扇区等等...</p>
<p>我认为解决方案可能在使用<code>clip-path</code>的SVG填充规则中。然而,我对SVG的了解仅限于此处,我需要一些帮助。其他解决方案也受欢迎。</p>
您遇到的问题是计算
.wheel div
的宽度和高度的方式不正确。如果高度是圆的半径:--radius: calc(var(--wheel-size) / 2 );
,那么宽度就是width: calc( 2 * var(--radius ) / 1.732);
,其中 1.732 是Math.sqrt(3)
。这适用于一个有 6 个部分的轮子,其中三角形(用于剪切路径)是等边三角形。在您的示例中,宽度等于半径。这是不够的,因为 div 超出了圆形,并且您根据 div 的大小计算了剪切路径。
为了了解发生了什么,请删除 border-radius: 50%;,并向轮子添加一个半透明的未剪切的部分(clip-path: none;)
为了进行 8 个部分的轮子,您将需要一个 --segment-deg:45 和不同的
.wheel div
的宽度。我使用的是width: calc( 2 * var(--radius ) / 2.414);
,其中 2.414 是 (180 - 45) / 2 的正切值。