用JS和echarts实现了自动数羊的钟表。
内含逻辑:
- 实现圆形刻度表盘的钟表,带有分针、时针、秒针
- 每过一秒,秒针走一格
- 每过一秒,数一只羊 效果如下:
在线预览: 注意需要适当调整页面高度以保证正常显示
技术栈:html
+ css
+ js
+ echarts
下面是阿拉伯数字转汉字的算法
function numberToChinese(num) {
var units = '个十百千万@#%亿^&~';
var chars = '零一二三四五六七八九';
var a = (num + '').split(''), s = [];
if (a.length > 12) {
throw new Error('数字太大,无法解析');
}
for (var i = 0, j = a.length - 1; i <= j; i++) {
if (j == 1 || j == 5 || j == 9) { //两位数 处理特殊的 1*
if (i == 0) {
if (a[i] != '1') s.push(chars.charAt(a[i]));
} else {
s.push(chars.charAt(a[i]));
}
} else {
s.push(chars.charAt(a[i]));
}
if (i != j) {
s.push(units.charAt(j - i));
}
}
//return s;
return s.join('').replace(/零([十百千万亿@#%^&~])/g, function (m, d, b) { //优先处理 零百 零千 等
b = units.indexOf(d);
if (b != -1) {
if (d == '亿') return d;
if (d == '万') return d;
if (a[j - b] == '0') return '零'
}
return '';
}).replace(/零+/g, '零').replace(/零([万亿])/g, function (m, b) { //处理 零万 零亿
return b;
}).replace(/亿[万千百十]/g, '亿').replace(/[零]$/, '').replace(/[@#%^&~]/g, function (m) {
return { '@': '十', '#': '百', '%': '千', '^': '十', '&': '百', '~': '千' }[m];
}).replace(/([亿万])([一-九])/g, function (m, d, b, c) {
c = units.indexOf(d);
if (c != -1) {
if (a[j - c] == '0') return d + '零' + b
}
return m;
});
}
console.log(numberToChinese(1234567));
下面直接贴最终实现效果的完整代码,是一份完整的html,复制到本地,liverserver打开
即可预览。
<!DOCTYPE html>
<html lang="en" style="height: 100%">
<head>
<meta charset="utf-8">
</head>
<body style="height: 100%; margin: 0">
<div id="container" style="height: 80%"></div>
<div id="sheep-box"></div>
<!-- <script type="text/javascript" src="./echarts.min.js"></script> -->
<script type="text/javascript" src="https://registry.npmmirror.com/echarts/5.5.1/files/dist/echarts.min.js"></script>
<script type="text/javascript">
var dom = document.getElementById('container');
var myChart = echarts.init(dom, null, {
renderer: 'canvas',
useDirtyRect: false
});
var app = {};
var option;
option = {
series: [
{
name: 'hour',
type: 'gauge',
startAngle: 90,
endAngle: -270,
min: 0,
max: 12,
splitNumber: 12,
clockwise: true,
axisLine: {
lineStyle: {
width: 15,
color: [[1, 'rgba(0,0,0,0.7)']],
shadowColor: 'rgba(0, 0, 0, 0.5)',
shadowBlur: 15
}
},
splitLine: {
lineStyle: {
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 3,
shadowOffsetX: 1,
shadowOffsetY: 2
}
},
axisLabel: {
fontSize: 50,
distance: 25,
formatter: function (value) {
if (value === 0) {
return '';
}
return value + '';
}
},
anchor: {
show: false,
icon: 'path://M532.8,70.8C532.8,70.8,532.8,70.8,532.8,70.8L532.8,70.8C532.7,70.8,532.8,70.8,532.8,70.8z M456.1,49.6c-2.2-6.2-8.1-10.6-15-10.6h-37.5v10.6h37.5l0,0c2.9,0,5.3,2.4,5.3,5.3c0,2.9-2.4,5.3-5.3,5.3v0h-22.5c-1.5,0.1-3,0.4-4.3,0.9c-4.5,1.6-8.1,5.2-9.7,9.8c-0.6,1.7-0.9,3.4-0.9,5.3v16h10.6v-16l0,0l0,0c0-2.7,2.1-5,4.7-5.3h10.3l10.4,21.2h11.8l-10.4-21.2h0c6.9,0,12.8-4.4,15-10.6c0.6-1.7,0.9-3.5,0.9-5.3C457,53,456.7,51.2,456.1,49.6z M388.9,92.1h11.3L381,39h-3.6h-11.3L346.8,92v0h11.3l3.9-10.7h7.3h7.7l3.9-10.6h-7.7h-7.3l7.7-21.2v0L388.9,92.1z M301,38.9h-10.6v53.1H301V70.8h28.4l3.7-10.6H301V38.9zM333.2,38.9v10.6v10.7v31.9h10.6V38.9H333.2z M249.5,81.4L249.5,81.4L249.5,81.4c-2.9,0-5.3-2.4-5.3-5.3h0V54.9h0l0,0c0-2.9,2.4-5.3,5.3-5.3l0,0l0,0h33.6l3.9-10.6h-37.5c-1.9,0-3.6,0.3-5.3,0.9c-4.5,1.6-8.1,5.2-9.7,9.7c-0.6,1.7-0.9,3.5-0.9,5.3l0,0v21.3c0,1.9,0.3,3.6,0.9,5.3c1.6,4.5,5.2,8.1,9.7,9.7c1.7,0.6,3.5,0.9,5.3,0.9h33.6l3.9-10.6H249.5z M176.8,38.9v10.6h49.6l3.9-10.6H176.8z M192.7,81.4L192.7,81.4L192.7,81.4c-2.9,0-5.3-2.4-5.3-5.3l0,0v-5.3h38.9l3.9-10.6h-53.4v10.6v5.3l0,0c0,1.9,0.3,3.6,0.9,5.3c1.6,4.5,5.2,8.1,9.7,9.7c1.7,0.6,3.4,0.9,5.3,0.9h23.4h10.2l3.9-10.6l0,0H192.7z M460.1,38.9v10.6h21.4v42.5h10.6V49.6h17.5l3.8-10.6H460.1z M541.6,68.2c-0.2,0.1-0.4,0.3-0.7,0.4C541.1,68.4,541.4,68.3,541.6,68.2L541.6,68.2z M554.3,60.2h-21.6v0l0,0c-2.9,0-5.3-2.4-5.3-5.3c0-2.9,2.4-5.3,5.3-5.3l0,0l0,0h33.6l3.8-10.6h-37.5l0,0c-6.9,0-12.8,4.4-15,10.6c-0.6,1.7-0.9,3.5-0.9,5.3c0,1.9,0.3,3.7,0.9,5.3c2.2,6.2,8.1,10.6,15,10.6h21.6l0,0c2.9,0,5.3,2.4,5.3,5.3c0,2.9-2.4,5.3-5.3,5.3l0,0h-37.5v10.6h37.5c6.9,0,12.8-4.4,15-10.6c0.6-1.7,0.9-3.5,0.9-5.3c0-1.9-0.3-3.7-0.9-5.3C567.2,64.6,561.3,60.2,554.3,60.2z',
showAbove: false,
offsetCenter: [0, '-35%'],
size: 120,
keepAspect: true,
itemStyle: {
color: '#707177'
}
},
pointer: {
icon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z',
width: 12,
length: '55%',
offsetCenter: [0, '8%'],
itemStyle: {
color: '#C0911F',
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 8,
shadowOffsetX: 2,
shadowOffsetY: 4
}
},
detail: {
show: false
},
title: {
offsetCenter: [0, '30%']
},
data: [
{
value: 0,
}
]
},
{
name: 'minute',
type: 'gauge',
startAngle: 90,
endAngle: -270,
min: 0,
max: 60,
clockwise: true,
axisLine: {
show: false
},
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
},
pointer: {
icon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z',
width: 8,
length: '70%',
offsetCenter: [0, '8%'],
itemStyle: {
color: '#C0911F',
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 8,
shadowOffsetX: 2,
shadowOffsetY: 4
}
},
anchor: {
show: true,
size: 20,
showAbove: false,
itemStyle: {
borderWidth: 15,
borderColor: '#C0911F',
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 8,
shadowOffsetX: 2,
shadowOffsetY: 4
}
},
detail: {
show: false
},
title: {
offsetCenter: ['0%', '-40%']
},
data: [
{
value: 0,
}
]
},
{
name: 'second',
type: 'gauge',
startAngle: 90,
endAngle: -270,
min: 0,
max: 60,
animationEasingUpdate: 'bounceOut',
clockwise: true,
axisLine: {
show: false
},
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
},
pointer: {
icon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z',
width: 4,
length: '85%',
offsetCenter: [0, '8%'],
itemStyle: {
color: '#C0911F',
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 8,
shadowOffsetX: 2,
shadowOffsetY: 4
}
},
anchor: {
show: true,
size: 15,
showAbove: true,
itemStyle: {
color: '#C0911F',
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 8,
shadowOffsetX: 2,
shadowOffsetY: 4
}
},
detail: {
show: false
},
title: {
offsetCenter: ['0%', '-40%']
},
data: [
{
value: 0
}
]
}
]
};
function numberToChinese(num) {
var units = '个十百千万@#%亿^&~';
var chars = '零一二三四五六七八九';
var a = (num + '').split(''), s = [];
if (a.length > 12) {
throw new Error('数字太大,无法解析');
}
for (var i = 0, j = a.length - 1; i <= j; i++) {
if (j == 1 || j == 5 || j == 9) { //两位数 处理特殊的 1*
if (i == 0) {
if (a[i] != '1') s.push(chars.charAt(a[i]));
} else {
s.push(chars.charAt(a[i]));
}
} else {
s.push(chars.charAt(a[i]));
}
if (i != j) {
s.push(units.charAt(j - i));
}
}
//return s;
return s.join('').replace(/零([十百千万亿@#%^&~])/g, function (m, d, b) { //优先处理 零百 零千 等
b = units.indexOf(d);
if (b != -1) {
if (d == '亿') return d;
if (d == '万') return d;
if (a[j - b] == '0') return '零'
}
return '';
}).replace(/零+/g, '零').replace(/零([万亿])/g, function (m, b) { //处理 零万 零亿
return b;
}).replace(/亿[万千百十]/g, '亿').replace(/[零]$/, '').replace(/[@#%^&~]/g, function (m) {
return { '@': '十', '#': '百', '%': '千', '^': '十', '&': '百', '~': '千' }[m];
}).replace(/([亿万])([一-九])/g, function (m, d, b, c) {
c = units.indexOf(d);
if (c != -1) {
if (a[j - c] == '0') return d + '零' + b
}
return m;
});
}
console.log(numberToChinese(1234567)); // "一百二十三万四千五百六十七"
let numm = 0
setInterval(function () {
var date = new Date();
var second = date.getSeconds();
var minute = date.getMinutes() + second / 60;
var hour = (date.getHours() % 12) + minute / 60;
option.animationDurationUpdate = 300;
numm += 1
document.getElementById('sheep-box').innerText += '🐏'
myChart.setOption({
series: [
{
name: 'hour',
animation: false,
// data: [{ value: hour}],
title: {
textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE
fontWeight: 'bolder', //控制表盘title字体是否加粗
},
"show": true, //控制表盘title字体是否显示
"fontSize": 16, //控制表盘title字体大小
"color": "black", //控制表盘title字体颜色
"offsetCenter": [0, "-30%"], //设置表盘title位置
},
data: [{ value: hour, name: numberToChinese(numm)+'只羊🐏' }]
},
{
name: 'minute',
animation: minute !== 0,
data: [{ value: minute }]
},
{
animation: second !== 0,
name: 'second',
data: [{ value: second,}]
}
]
});
}, 1000);
if (option && typeof option === 'object') {
myChart.setOption(option);
}
window.addEventListener('resize', myChart.resize);
</script>
</body>
</html>