<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="format-detection" content="telephone=no">
<title>翻页时钟</title>
<style>
/* ===== 兼容安卓4.2(WebKit 534 / Chrome 18):
仅使用 ES5 语法;CSS 全部带 -webkit- 前缀;
不使用 flex/grid/css变量/vh/vw ===== */
html, body { height: 100%; margin: 0; padding: 0; }
body {
background: #000000;
color: #ffffff;
font-family: "Helvetica Neue", Helvetica, Arial, "Microsoft YaHei", sans-serif;
display: table;
width: 100%;
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
.center { display: table-cell; vertical-align: middle; text-align: center; }
.clock {
display: inline-block;
position: relative;
-webkit-perspective: 900px;
perspective: 900px;
}
/* ---- 卡片 ---- */
.digits { display: inline-block; }
.flip {
position: relative;
width: 140px; height: 180px;
display: inline-block;
margin: 0 4px;
}
.half {
position: absolute;
left: 0; width: 100%; height: 90px;
overflow: hidden;
background: #161616;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.half span {
position: absolute;
left: 0; width: 100%;
height: 180px; line-height: 180px;
text-align: center;
font-size: 118px; font-weight: 700;
color: #f5f5f5;
}
.half.top { top: 0; border-radius: 10px 10px 0 0; border-bottom: 1px solid #000000; -webkit-box-shadow: inset 0 -2px 4px rgba(0,0,0,0.55); box-shadow: inset 0 -2px 4px rgba(0,0,0,0.55); }
.half.top span { top: 0; }
.half.bottom { bottom: 0; border-radius: 0 0 10px 10px; -webkit-box-shadow: inset 0 2px 4px rgba(255,255,255,0.05); box-shadow: inset 0 2px 4px rgba(255,255,255,0.05); }
.half.bottom span { top: -90px; }
/* 静态层 */
.half.static { z-index: 1; }
/* 动画层:上翻层(新值从顶部翻下) 与 下翻层(旧值向下翻走) */
.anim-top {
z-index: 3;
opacity: 0;
-webkit-transform: rotateX(90deg);
transform: rotateX(90deg);
-webkit-transform-origin: 50% 0%;
transform-origin: 50% 0%;
-webkit-transition: -webkit-transform 0.4s ease-out, opacity 0.3s linear;
transition: transform 0.4s ease-out, opacity 0.3s linear;
}
.anim-top.on {
opacity: 1;
-webkit-transform: rotateX(0deg);
transform: rotateX(0deg);
}
.anim-bottom {
z-index: 2;
-webkit-transform: rotateX(0deg);
transform: rotateX(0deg);
-webkit-transform-origin: 50% 100%;
transform-origin: 50% 100%;
-webkit-transition: -webkit-transform 0.4s ease-in;
transition: transform 0.4s ease-in;
}
.anim-bottom.on {
-webkit-transform: rotateX(-90deg);
transform: rotateX(-90deg);
}
/* ---- 冒号分隔符(闪烁) ---- */
.sep {
display: inline-block;
width: 42px; height: 180px;
line-height: 180px;
font-size: 100px; font-weight: 700;
color: #e0e0e0;
text-align: center;
vertical-align: top;
-webkit-animation: sepblink 1s linear infinite;
animation: sepblink 1s linear infinite;
}
@-webkit-keyframes sepblink { 0%, 100% { opacity: 1; } 50% { opacity: 0.2; } }
@keyframes sepblink { 0%, 100% { opacity: 1; } 50% { opacity: 0.2; } }
/* ---- 日期行 ---- */
.date {
margin-top: 34px;
font-size: 20px;
letter-spacing: 3px;
color: #8a8a8a;
}
/* ---- 一键全屏按钮(兼容安卓4.2) ---- */
.fsbtn {
position: fixed;
right: 14px;
bottom: 14px;
z-index: 999;
background: rgba(255, 255, 255, 0.12);
border: 1px solid rgba(255, 255, 255, 0.35);
border-radius: 22px;
color: #eeeeee;
font-size: 15px;
line-height: 1;
padding: 11px 20px;
cursor: pointer;
-webkit-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.fsbtn:active {
background: rgba(255, 255, 255, 0.28);
}
/* ---- 小屏适配 ---- */
@media (max-width: 600px) {
.flip { width: 84px; height: 108px; margin: 0 2px; }
.half { height: 54px; }
.half span { height: 108px; line-height: 108px; font-size: 68px; }
.half.bottom span { top: -54px; }
.sep { width: 26px; height: 108px; line-height: 108px; font-size: 60px; }
.date { font-size: 15px; margin-top: 22px; letter-spacing: 2px; }
.fsbtn { font-size: 13px; padding: 9px 16px; right: 10px; bottom: 10px; }
}
@media (max-width: 360px) {
.flip { width: 64px; height: 82px; margin: 0 1px; }
.half { height: 41px; }
.half span { height: 82px; line-height: 82px; font-size: 52px; }
.half.bottom span { top: -41px; }
.sep { width: 20px; height: 82px; line-height: 82px; font-size: 46px; }
.date { font-size: 12px; margin-top: 16px; letter-spacing: 1px; }
}
</style>
</head>
<body>
<div class="center">
<div class="clock">
<div class="digits" id="hour">
<div class="flip">
<div class="half top static"><span>0</span></div>
<div class="half bottom static"><span>0</span></div>
<div class="half top anim-top"><span>0</span></div>
<div class="half bottom anim-bottom"><span>0</span></div>
</div>
<div class="flip">
<div class="half top static"><span>0</span></div>
<div class="half bottom static"><span>0</span></div>
<div class="half top anim-top"><span>0</span></div>
<div class="half bottom anim-bottom"><span>0</span></div>
</div>
</div>
<span class="sep">:</span>
<div class="digits" id="min">
<div class="flip">
<div class="half top static"><span>0</span></div>
<div class="half bottom static"><span>0</span></div>
<div class="half top anim-top"><span>0</span></div>
<div class="half bottom anim-bottom"><span>0</span></div>
</div>
<div class="flip">
<div class="half top static"><span>0</span></div>
<div class="half bottom static"><span>0</span></div>
<div class="half top anim-top"><span>0</span></div>
<div class="half bottom anim-bottom"><span>0</span></div>
</div>
</div>
<span class="sep">:</span>
<div class="digits" id="sec">
<div class="flip">
<div class="half top static"><span>0</span></div>
<div class="half bottom static"><span>0</span></div>
<div class="half top anim-top"><span>0</span></div>
<div class="half bottom anim-bottom"><span>0</span></div>
</div>
<div class="flip">
<div class="half top static"><span>0</span></div>
<div class="half bottom static"><span>0</span></div>
<div class="half top anim-top"><span>0</span></div>
<div class="half bottom anim-bottom"><span>0</span></div>
</div>
</div>
<div class="date" id="date"> </div>
</div>
</div>
<button type="button" class="fsbtn" id="fsbtn">⛶ 全屏</button>
<script>
/* ===== 纯 ES5 实现,兼容安卓4.2 WebView ===== */
(function () {
var WEEK = ['日', '一', '二', '三', '四', '五', '六'];
function pad(n) { return n < 10 ? '0' + n : '' + n; }
/* 收集某组(时/分/秒)的两位卡片 */
function buildCells(id) {
var flips = document.getElementById(id).getElementsByClassName('flip');
var cells = [];
var i, f;
for (i = 0; i < flips.length; i++) {
f = flips[i];
cells.push({
staticTop: f.getElementsByClassName('static top')[0].getElementsByTagName('span')[0],
staticBottom: f.getElementsByClassName('static bottom')[0].getElementsByTagName('span')[0],
animTop: f.getElementsByClassName('anim-top')[0],
animBottom: f.getElementsByClassName('anim-bottom')[0],
current: '0'
});
}
return cells;
}
/* 单个数字位翻页 */
function setVal(cell, val) {
var old = cell.current;
if (old === val) { return; }
cell.current = val;
cell.animTop.getElementsByTagName('span')[0].innerHTML = val; /* 新值上半:翻下来 */
cell.animBottom.getElementsByTagName('span')[0].innerHTML = old; /* 旧值下半:翻走 */
/* 重置动画层到起始姿态 */
cell.animTop.className = 'half top anim-top';
cell.animBottom.className = 'half bottom anim-bottom';
void cell.animTop.offsetWidth; /* 强制 reflow,保证过渡生效 */
/* 播放 */
cell.animTop.className = 'half top anim-top on';
cell.animBottom.className = 'half bottom anim-bottom on';
(function (c) {
setTimeout(function () {
/* 动画结束:静态层换成新值,动画层归位待命 */
c.staticTop.innerHTML = val;
c.staticBottom.innerHTML = val;
c.animTop.className = 'half top anim-top';
c.animBottom.className = 'half bottom anim-bottom';
c.animBottom.getElementsByTagName('span')[0].innerHTML = val;
}, 450);
})(cell);
}
var hours = buildCells('hour');
var mins = buildCells('min');
var secs = buildCells('sec');
var dateEl = document.getElementById('date');
function tick() {
var d = new Date();
var h = pad(d.getHours());
var m = pad(d.getMinutes());
var s = pad(d.getSeconds());
var i;
for (i = 0; i < 2; i++) {
setVal(hours[i], h.charAt(i));
setVal(mins[i], m.charAt(i));
setVal(secs[i], s.charAt(i));
}
var str = d.getFullYear() + '年' + (d.getMonth() + 1) + '月' + d.getDate() + '日 星期' + WEEK[d.getDay()];
if (dateEl.innerHTML !== str) { dateEl.innerHTML = str; }
}
tick();
setInterval(tick, 1000);
/* ===== 一键全