<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Optimized Auto-updating Flipper Counter</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.container {
text-align: center;
}
.counter {
font-size: 48px;
margin: 20px 0;
perspective: 1000px;
display: inline-block;
}
.flip {
animation: flip 0.1s ease-in-out;
display: inline-block;
transform-style: preserve-3d;
}
@keyframes flip {
0% { transform: rotateX(0); }
50% { transform: rotateX(90deg); }
100% { transform: rotateX(0); }
}
button, input {
font-size: 18px;
padding: 10px 20px;
margin: 5px;
}
button {
cursor: pointer;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
transition: background-color 0.3s;
}
button:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<div class="container">
<div id="counter" class="counter">10</div>
<br>
<input type="number" id="newValue" placeholder="Enter new value">
<button onclick="updateCounter()">Update Counter</button>
</div>
<script>
class FlipperCounter {
constructor(element, initialValue) {
this.element = element;
this._value = initialValue;
this.element.textContent = this._value;
this.minAnimationDuration = 500; // 最小动画时间(毫秒)
this.maxAnimationDuration = 1000; // 最大动画时间(毫秒)
this.frameRate = 30; // 每秒帧数
}
get value() {
return this._value;
}
set value(newValue) {
if (this._value !== newValue) {
this.animateValue(this._value, newValue);
this._value = newValue;
}
}
animateValue(start, end) {
const range = Math.abs(end - start);
const direction = start < end ? 1 : -1;
// 计算动画持续时间,随数值范围增加而增加,但有上限
const duration = Math.min(
this.maxAnimationDuration,
Math.max(this.minAnimationDuration, range * 10)
);
// 计算步进大小,确保动画流畅
const totalSteps = duration / (1000 / this.frameRate);
const stepSize = range / totalSteps;
let current = start;
const startTime = performance.now();
const animate = (currentTime) => {
const elapsedTime = currentTime - startTime;
const progress = Math.min(elapsedTime / duration, 1);
current = start + direction * (progress * range);
const roundedValue = Math.round(current);
if (this.element.textContent != roundedValue) {
this.element.textContent = roundedValue;
this.element.classList.remove('flip');
void this.element.offsetWidth; // Trigger reflow
this.element.classList.add('flip');
}
if (progress < 1) {
requestAnimationFrame(animate);
} else {
this.element.textContent = end;
}
};
requestAnimationFrame(animate);
}
}
// 创建计数器实例
const counter = new FlipperCounter(document.getElementById('counter'), 10);
function updateCounter() {
const newValue = parseInt(document.getElementById('newValue').value);
if (!isNaN(newValue)) {
counter.value = newValue; // 这将触发动画
}
}
</script>
</body>
</html>
如何手写翻牌器效果
于 2024-07-02 15:49:59 首次发布