网站首页 > 技术文章 正文
上节中我们做了绘画类,这次做时钟类。
大致逻辑:
- 处理传过来的参数
- 绘制表盘
- 根据获取的表针角度,绘制表针
- 使用动画方法重复绘制表盘和表针逻辑
/**
* 时钟类
*/
class Clock {
el = '';
w = window;
$ = function (id) {
return document.getElementById(id);
};
/**
* 时钟类的构造函数 new 的时候执行
* @param {object} options new 的时候传入的参数
* @return {this}
*/
constructor(options) {
for (let i in options){
if(!options.hasOwnProperty(i)) continue;
this[i] = options[i];
}
// 执行初始化方法
this.init && this.init();
}
/**
* 初始化方法 用于实例化完成后处理一些属性
* @return {[type]} [description]
*/
init() {
// 判断必须的参数
if(!this.el){
throw new Error('el 参数必须有');
}
// 处理DOM对象
this.obj = this.$(this.el);
// 宽度设置 默认500
this.obj.width = this.width || 500;
// 高度设置 默认500
this.obj.height = this.height || 500;
// 将宽高放置到自身
this.width = this.obj.width;
this.height = this.obj.height;
// 处理时钟的半径 高度的百分之八十 除以 2
this.r = this.height * .8 / 2;
// 处理时钟的中心坐标点
this.x = this.width / 2;
this.y = this.width == this.height ?
this.x :
this.height / 2;
// 实例化绘画对象 方便画圆、线、字
this.drawer = new Drawer(this.obj);
// 是否显示 分钟对应的文字
this.min = this.showMin || false;
// 执行画方法
this.draw();
// 开始动起来
this.start();
}
/**
* clock 类的画方法
* @return
*/
draw() {
// 清除上次画的页面
this.drawer.clearRect(
0,
0,
this.width,
this.height
);
// 画表盘
this.drawClockDial();
// 画表针
this.drawWatchHand();
}
/**
* 画表盘
*/
drawClockDial() {
var r = this.r;
var x = this.x;
var y = this.y;
var drawer = this.drawer;
// 设置填充样式 红色
drawer.setFillStyle('red');
// 设置画的样式为填充
drawer.setDrawStyle('fill');
// 画一个实心圆(上面设置为填充)
drawer.drawArc(this.x, this.y, 8);
// 设置线条样式 不是填充
drawer.setStrokeStyle('black');
// 设置画的样式为线条样式(非填充)
drawer.setDrawStyle('stroke');
// 画一个空心圆(上面设置为非填充)
drawer.drawArc(this.x, this.y, 12);
// 设置线条宽度 5 下面的多有线条变粗
drawer.setLineWidth(5);
// 画一个空心圆(上面设置线条宽度,这个圆线条粗)
drawer.drawArc(x, y, r);
// 设置线条宽度为 1 下面画的线条变细
drawer.setLineWidth(1);
// 保持当前绘画环境
drawer.save();
// 重新设置坐标原点,便于接下来的绘画
drawer.translate(x, y);
// 表盘有 60个刻度 循环60次
for (var i = 0; i < 60; i++) {
// 下面是循环体内 i 依次为1,2,3 ……,59
// i为60 退出循环 因为 i为60 的时候 不小于60
var h = i / 5;
var m = i;
if(i == 0) {
h = 12;
}
if(i == 0){
drawer.rotate(-180);
}
if(!(i%5)) {
// 当 i除以5 余数为0 的时候执行这里的代码
// 小时相关操作
// 设置线条宽度
drawer.setLineWidth(4);
// 画线 小时对应的 刻度
drawer.drawLine(0, r-20, 0, r);
// 设置线条宽度
drawer.setLineWidth(1);
// 设置字体
drawer.setFont('28px Arial');
// 设置绘画样式为填充
drawer.setDrawStyle('fill');
// 保存绘画环境
drawer.save();
// 设置绘画坐标原点
drawer.translate(0, r-38);
// 旋转角度
drawer.rotate(-i*6 + 180);
// 画字 小时对应的文字
drawer.drawerFont(
h,
0,
0,
'center',
'middle'
);
// 恢复绘画环境为上次保存前 方便下面操作
drawer.restore();
}
// 分钟相关操作
// 设置线条宽度
drawer.setLineWidth(1);
// 画分钟对应的刻度
drawer.drawLine(0, r-10, 0, r);
// 设置字体及大小
drawer.setFont('12px Arial');
// 设置绘画样式为填充
drawer.setDrawStyle('fill');
if (this.min) {
// 如果需要画分钟刻度对应的分钟文字
// 执行这里,有个参数可以设置 showMin
// 保存绘画环境
drawer.save();
// 重新设置坐标原点
drawer.translate(0, r+15);
// 旋转角度
drawer.rotate(-i*6 + 180);
// 设置填充颜色
drawer.setFillStyle('green');
// 画字
drawer.drawerFont(
this.fillZero(m),
0,
0,
'center',
'middle'
);
// 恢复保存之前的绘画环境
drawer.restore();
}
// 旋转 6度 每个分钟刻度之间夹角是6度
drawer.rotate(6);
}
// 恢复上次保存的绘画环境
drawer.restore();
}
/**
* 画表针
* @return {[type]} [description]
*/
drawWatchHand() {
var r = this.r;
var x = this.x;
var y = this.y;
var drawer = this.drawer;
// 获取当前日期对象
var now = new Date;
// 获取当前时间对应的刻度
var angle = now.getAngle();
var time = now.getTimes();
// 指针对应的样式
var angleStyle = {
h:{
width:7,
strokeStyle:'red',
line:{
s:-12,
e:.6,
}
},
m:{
width:5,
strokeStyle:'green',
line:{
s:-22,
e:.7,
}
},
s:{
width:2,
strokeStyle:'yellowgreen',
line:{
s:-28,
e:.9,
}
},
};
// 保存绘画环境
drawer.save();
// 重新设置绘画坐标原点
drawer.translate(x, y);
// 又一个循环 只有三次 h小时 m分钟 s秒
for (let i in angle) {
// 保存绘画环境
drawer.save();
// 获取对应的指针样式
let style = angleStyle[i];
// 旋转角度
drawer.rotate(angle[i] - 90);
// 设置样式中指针的宽度
drawer.setLineWidth(style.width);
// 设置样式中 线条样式
drawer.setStrokeStyle(style.strokeStyle);
// 画线(画指针)
drawer.drawLine(
style.line.s,
0,
style.line.e * this.r,
0
);
// 恢复绘画环境
drawer.restore();
}
// 恢复绘画环境
drawer.restore();
}
// 时钟开始动起来
start() {
this.draw();
this._stop = window.requestAnimationFrame(
this.start.bind(this)
);
}
// 时钟停止
stop() {
// clearInterval(this._stop);
window.cancelAnnimationFrame(this._stop);
}
fillZero (n) {
if( n > 9 ) return n;
return '0' + n;
}
}
- 上一篇: 根据年月计算当月有哪几个周,及每周的起止日期
- 下一篇: 前端学习需要多久时间呢 前端一般需要学多久
猜你喜欢
- 2025-07-06 为什么前端大佬都推荐用 performance.now() 而非 Date.now()?
- 2025-07-06 实战分享:邀请有礼产品怎么做?(邀请有礼活动)
- 2025-07-06 揭秘:视频播放网站如何精准记录用户观看进度
- 2025-07-06 第七篇 前端基础十问,看看你是否真的掌握扎实?
- 2025-07-06 下单预约送货时间功能设计及思路(预约送货怎么说)
- 2025-07-06 每天一个 Python 库:datetime 模块全攻略,时间操作太丝滑!
- 2025-07-06 前端代码更新,如何优雅地通知用户刷新页面?
- 2024-10-09 JS Date对象的妙用:如何更优雅的计算时间差?
- 2024-10-09 从零开始的前端请求之旅 从零开始学前端开发
- 2024-10-09 如何在上班时间利用终端控制台摸鱼??????
你 发表评论:
欢迎- 593℃几个Oracle空值处理函数 oracle处理null值的函数
- 586℃Oracle分析函数之Lag和Lead()使用
- 574℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 571℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 567℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 559℃【数据统计分析】详解Oracle分组函数之CUBE
- 546℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 540℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端懒加载 (49)
- 前端获取当前时间 (50)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)