Progress
从其名字上就知道<progress>元素就是作为进度条展示。在不指定 value 的情况下,它将来回播放展示:
<progress></progress>
同样的,也可以为其指定 value 和最大值(max)
<progress value="70" max="100"></progress>
通过伪元素给<progress>添加一个进度条滑块
progress::after {
width: 10px;
height: 20px;
border-radius: 5px;
content: '';
background-color: #61c554;
position: absolute;
top: 50%;
translate: -50% -50%;
left: calc(var(--progress) * 1%);
}
监听<progress>标签的鼠标事件
const progressBox = document.querySelector('#progress')
progressBox.addEventListener('mousemove', handleMouseMove)
progressBox.addEventListener('mouseup', handleMouseUp)
progressBox.addEventListener('mousedown', handleMouseDown)
progressBox.addEventListener('mouseout', handleMouseseout)
之后设置css变量去控制伪元素滑块的left值达到滑动效果,
同理球体盒子添加伪元素让它旋转,变量去控制伪元素的top值达到上移动效果
js代码
const progressBox = document.querySelector('#progress')
const textBox = document.querySelector('#text')
const progress = document.getElementById('progress')
const text = document.getElementById('text')
const borderBox = document.querySelector('.border')
function setProgressValue(v) {
progress.value = v
text.innerText = v
borderBox.style.setProperty(
'--boder',
120 - Math.floor(120 * (v / 100))
)
progress.style.setProperty('--progress', v)
}
let dragging = false
function handleMouseDown() {
dragging = true
}
function handleMouseUp() {
dragging = false
}
function handleMouseMove(e) {
if (dragging) {
const { width, left } = progress.getBoundingClientRect()
const mouseX = e.clientX
const percent = (mouseX - left) / width
let value = Math.round(percent * 100)
if (value > 100) value = 100
if (value < 0) value = 0
setProgressValue(value)
}
}
function handleMouseseout(e) {
dragging = false
}
progressBox.addEventListener('mousemove', handleMouseMove)
progressBox.addEventListener('mouseup', handleMouseUp)
progressBox.addEventListener('mousedown', handleMouseDown)
progressBox.addEventListener('mouseout', handleMouseseout)
css代码
:root {
--progress: 0;
--boder: 120;
}
progress {
cursor: grabbing;
width: 200px;
position: relative;
}
progress::after {
width: 10px;
height: 20px;
border-radius: 5px;
content: '';
background-color: #61c554;
position: absolute;
top: 50%;
translate: -50% -50%;
left: calc(var(--progress) * 1%);
}
@keyframes move {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.border {
width: 100px;
height: 100px;
margin-left: 50px;
border: 2px solid #000;
border-radius: 50%;
position: relative;
overflow: hidden;
}
.border::after {
z-index: -1;
content: '';
width: 250px;
height: 250px;
position: absolute;
top: calc(var(--boder) * 1%);
left: -80%;
border-radius: 30%;
background-image: linear-gradient(to top, #0ff7eb 0%, #fa145d 100%);
transform: rotate(45deg);
animation: move 5s linear infinite;
}
html标签
<div style="user-select: none; width: 300px; height: 300px; margin: 0 auto">
<div class="border"></div>
<progress id="progress" value="0" max="100"></progress>
<span id="text" style="user-select: none">0</span>
</div>