<div class="graph-container" >
<div class="half-donut">
<div class="slice">
<i class="fa-regular fa-face-grimace"></i>
</div>
<div class="slice">
<i class="fa-regular fa-face-frown"></i>
</div>
<div class="slice">
<i class="fa-regular fa-face-meh"></i>
</div>
<div class="slice">
<i class="fa-regular fa-face-smile"></i>
</div>
<div class="slice">
<i class="fa-regular fa-face-grin-hearts"></i>
</div>
</div>
<div class="marker"></div>
</div>
<div class="form">
<input type="range" value="0" step="0.1" min="0" max="5" id="range" />
</div>
HTML
格式化
支持Emmet,输入 p 后按 Tab键试试吧!
<head> ... </head>
<body>
</body>
SCSS
格式化
// Graph Code
@use 'sass:list';
$colors: #d72e2c, #ff6259, #f19c4b, #68ca6f, #509d55;
$angle: 180/ list.length($colors);
.graph-container{
--size: 20rem;
--stroke-size: calc(var(--size)/5);
--rating: 0;
position: relative;
display: inline-flex;
box-sizing: border-box;
animation: 1s animateRating linear;
* , *::before, *::after {
box-sizing: border-box;
}
}
.half-donut{
width: var(--size);
height: calc(var(--size)/2);
border-radius: var(--size) var(--size) 0 0;
position: relative;
overflow: hidden;
filter: drop-shadow(0 0 0.3rem #0005);
}
.slice{
--stroke-color: #000;
--rotate: 0deg;
position: absolute;
width: 100%;
height: 100%;
border-radius: var(--size) var(--size) 0 0;
border:var(--stroke-size) solid var(--stroke-color) ;
box-sizing: border-box;
border-bottom: none;
transform-origin: 50% 100%;
background: #0000;
transform: rotate(calc(var(--rotate)));
.fa-regular {
font-size: 2rem;
color: #000;
position: absolute;
left: -2.5rem;
top: 2.5rem;
--emo-rotate: 90deg;
transform: rotate(var(--emo-rotate));
}
&:hover{
opacity: 0.8;
cursor: pointer;
}
@each $color in $colors {
$i: index($colors, $color);
&:nth-child(#{$i}) {
--stroke-color: #{$color};
--rotate: calc(#{$angle}deg * (#{$i} - 1) );
.fa-regular{
--emo-rotate: calc(-#{$angle}deg * (#{$i} - 1));
}
}
}
}
.marker{
position: absolute;
z-index: 1;
transform: translateX(-50%);
--round-size: calc(var(--size) / 10);
--round-o-size: calc(var(--round-size)* 0.32);
width: var(--round-size);
height: var(--round-size);
left: 50%;
bottom: 0;
border: var(--round-o-size) solid #fff;
border-radius: 50%;
--turn: calc(45deg + (#{$angle} * calc(var(--rating)* 1deg)) );
transform: translate(-50%, 50%) rotate(var(--turn));
transform-origin: 50% 50%;
transition: 0.2s linear;
&::before{
content: "";
position: absolute;
border: calc(var(--round-size) / 3) solid transparent;
border-right: calc(var(--size)* 0.4) solid #FFF;
left: 0%;
bottom: 0;
transform: translate(-100%, 50%) rotate(-45deg);
transform-origin: 100% 50%;
filter: drop-shadow(calc(var(--round-size) / -10) 0 0.2rem #0008);
}
}
@keyframes animateRating{
50% { --rating: 5;}
}
// Range style not directly connected with graph
#range {
-webkit-appearance: none;
width: 20rem;
height: 0.5rem;
background: #90CAF9;
outline: none;
opacity: 0.7;
border-radius: 0.5rem;
-webkit-transition: .2s;
transition: opacity .2s;
}
#range:hover {
opacity: 1;
}
#range::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 2rem;
height: 2rem;
border-radius: 50%;
background: #2962FF;
border: 0.5rem solid #FFF;
cursor: pointer;
}
#range::-moz-range-thumb {
width: 2rem;
height: 2rem;
background: #2962FF;
cursor: pointer;
}
// Base Layout style not related with graph
body{
background: #262638;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 0;
height: 100vh;
gap: 5rem;
}
JS
格式化
document.getElementById('range').addEventListener('input', e=>{
document.querySelector('.graph-container').style.setProperty('--rating', e.target.value);
})