十二小时制的时钟,时刻度在圆盘上面显示,交叉线顶角为分和秒的刻度。
时分秒:最小的是秒、中等的是分、圈内的蓝点为时。
中心圆:随着秒钟缩小,数字时钟的显示。
秒钟走动的声音,每小时和每3小时的有语音提示。
html
<canvas id="can" width="860px" height="860px">
canvas>
<audio src="./audio/7987.mp3" id="aud" loop="loop" >audio>
css
<style type="text/css">
body{
text-align: center;background-color: black}
style>
js代码配合js功能函数使用
// 获取声音
var aud = document.getElementById('aud');
// 点击开启声音
document.addEventListener('click',startTime)
function startTime(){
aud.play();
document.removeEventListener('click',startTime);// 开启声音后解绑事件
}
// 解决时间晚一秒的问题
window.onload = function(){
clock();
}
// 获取画布
var can = document.getElementById('can');
// 获取画笔
var cx = can.getContext('2d');
cx.translate(420,420);// 设置中心点 默认值
setInterval(clock,1000);// 开始时间
var zgongxinyuan = 246;// 控制中心圆的大小
function clock(){
zgongxinyuan -=1;
// 获取当前时间对象
var today = new Date();
var hour = today.getHours();//时
var min = today.getMinutes();//分
var secd = today.getSeconds();//秒
if(secd==0){
zgongxinyuan = 246;// 中心圆的半径
}
// 清除绘画区
cx.clearRect(-420,-420,860,860);
cx.beginPath();
cx.arc(0,0,395,0,Math.PI*2,true);
cx.strokeStyle = 'rgba(0,100,100,.4)';
cx.lineWidth = '10';
cx.stroke();
cx.closePath();
// 分刻度
for(var i=0;i<60;i++){
calibration(60,6,-388);// 网格线
}
// 时刻度
for(var i=0;i<12;i++){
calibration(12,30,-396)
}
// 时间绘制
hour = hour+min/60;// 小时数里面包含的分钟的小数数
hour>12 ?hour =hour-12:hour;// 将24小时制转为12小时制
// 每小时提醒一次
console.log(secd,min)
if(min==0 && secd==0 && hour% 3!=0 ){
playAudio('audio/2341.mp3',1000)
}
// 整点提示3、6、9、12提示
// console.log(secd,min)
if( (hour%3==0)&& min==0 && secd==0){
playAudio('audio/7120.mp3',2000)
}
// 时针
hand(hour,30,-260,12)
// 分钟
hand(min,6,-356,8)
// 秒针
// hand(secd,6,-300,'red')
cx.save();// 保存之前的
cx.beginPath();
cx.rotate(secd*6*Math.PI/180);
// line(0,0,0,-300,'red','1','round')
cx.closePath();
// 中心圆
circle(0,zgongxinyuan,'rgba(0,100,100,.2)');
// 秒针圆
if(secd%5==0){
circle(-396,18,'#999');
}else{
circle(-384,4,'#ccc');
}
cx.restore();// 恢复
// 小时文字填充
cx.beginPath();// 开始路径
cx.fillStyle = '#fff';
cx.font = '20px 宋体'
cx.fillText('12',-10,-390)
cx.fillText('1',194,-336)
cx.fillText('2',339,-190)
cx.fillText('3',392,8)
cx.fillText('4',338,204)
cx.fillText('5',193,352)
cx.fillText('6',-4,404)
cx.fillText('7',-202,350)
cx.fillText('8',-348,204)
cx.fillText('9',-401,6)
cx.fillText('10',-353,-190)
cx.fillText('11',-208,-336)
cx.closePath()
// 绘制作者
cx.beginPath();
cx.strokeStyle = 'white';
cx.font = '28px 宋体';
cx.lineWidth = '1'
cx.fillStyle = 'rgba(0,100,100,1)';
cx.strokeText('xxxxx Made',-140,90);
cx.fillText('xxxxx Made',-140,90)
cx.closePath();
// 绘制数字时钟
cx.beginPath();
// cx.strokeStyle = 'white';
cx.font = '38px 宋体';
cx.lineWidth = '1'
var bgr = cx.createLinearGradient(-20,-100,-10,-10);//设置颜色渐变
bgr.addColorStop(0.1,'rgba(0,100,100,1)');
bgr.addColorStop(0.5,'rgba(0,100,100,.2)');
bgr.addColorStop(1,'rgba(0,100,100,1)');
cx.fillStyle = bgr;
var numTime = `${
zero(today.getHours())}:${
zero(min)}:${
zero(secd)}`
cx.strokeText(numTime,-80,-20);
cx.fillText(numTime,-80,-20)
cx.closePath();
}
js功能函数:绘制形状比较频繁的函数封装
// 切换语音提示
// srcValue 文件路径
// srcValue 播放时间
function playAudio(srcValue,time){
aud.src = srcValue;
// $('#aud').attr('src',srcValue);// 新的音乐播放
aud.play();
setTimeout(function(){
// 'audio/7987.mp3'为本地存储的秒钟时间声音-----可以自定义
aud.src = 'audio/7987.mp3';// time 秒后回到原来的音乐
aud.play();
},time)
}
// 5.封装一个直线的函数
// x1,y1开始坐标
// x2,y2;结束坐标
// color线条颜色
// width线条大小
// shape线条样式
function line(x1,y1,x2,y2,color,width,shape){
color = color || '#000';
width = width || 'butt';
shape = shape || 'butt';
cx.save()
cx.beginPath();// 开始路径
cx.moveTo(x1,y1);// 起点
cx.lineTo(x2,y2); // 终点
cx.strokeStyle = color;// 设置颜色
cx.lineWidth = width; // 设置大小
cx.lineCap = shape;// 两端的状态值是 round圆角、butt、square
cx.stroke(); // 绘制
cx.closePath();// 结束路径
cx.restore();
}
// 封装一个绘制刻度的函数
// num 刻度个数 ---数字
// deg 表示旋转的度数
// y1 终点坐标
function calibration(num,deg,y1){
for(var i=num;i>0;i--){
cx.save();//保存
cx.beginPath();
cx.strokeStyle = 'seagreen';
cx.rotate(i*deg*Math.PI/180);
if(num==12){
circle(y1,18,'rgba(10,10,0,.4)',2);
}else{
line(y1,0,0,y1,'rgba(0,100,100,.4)',1);
}
cx.closePath();// 关闭路径
cx.restore();// 恢复
}
}
// 封装时钟分钟的函数
// time表示时间 -- 数据类型-变量
// deg表示度数 -- 数字
// y2 结束位置 -- 数字
// r 半径
function hand(time,deg,y2,r){
cx.save();// 保存之前的
cx.beginPath();
cx.rotate(time*deg*Math.PI/180);
// line(0,0,0,y2,color,'10','round')
if(deg==6){
// 如果时分钟
circle(y2,r,'#84AFD9',4);// 时针和分针的圆
}else{
circle(y2,r,'#39DEFA',4);// 时针和分针的圆
}
cx.closePath();
cx.restore();// 恢复
}
// 圆形绘制函数
// y1 yz坐标位置
// r 半径
// color填充色
// width画笔大小
function circle(y1,r,color,width){
// 秒针圆
cx.beginPath();// 开始路径
cx.strokeStyle = 'rgba(10,100,100,.4)';
cx.lineWidth = '4';
cx.arc(0,y1,r,0,Math.PI*2,true);// 中心点
cx.fillStyle = color;
cx.fill();
cx.stroke(); // 绘制
cx.closePath();// 结束路径
}
// 去0补位
function zero(num){
return num<10? '0'+num : num;
}
audio标签默认是秒钟的声音,可以自己设置。
每小时语音提示代码修改路径和提示时间
// 每小时提醒一次
console.log(secd,min)
if(min==0 && secd==0 && hour% 3!=0 ){
playAudio('audio/2341.mp3',1000)
}
// 整点提示3、6、9、12提示
// console.log(secd,min)
if( (hour%3==0)&& min==0 && secd==0){
playAudio('audio/7120.mp3',2000)
}
需要点击一下任意位置开始或者等小时提示的信息结束后,才能播放,试了好多种方式开启音频,最后点击一下任意位置开启是最稳定的,有更好的方式希望大家多分享分享。
// 点击开启声音
document.addEventListener('click',startTime)
function startTime(){
aud.play();
document.removeEventListener('click',startTime);// 开启声音后解绑事件
}
刚使用canvas的时候,对于我来说找坐标点有点晕,尤其是使用 translate() 重新设置中心点之后更晕了。
找坐标
通过 offsetX,offsetY获取鼠标在元素(canvas)的位置。将值直接输出到页面中就能得到一个大致的值,如果从新设置了中心点,需要把设置中心点的位置也算进去。
// 鼠标在画布上的位置
var x = document.getElementById('x');
var y = document.getElementById('y');
document.onmousemove = function(e){
x.innerHTML ='x坐标:'+ e.offsetX;
y.innerHTML ='y坐标:'+ e.offsetY;
}