专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

WEB前端手写时钟-时钟类 前端手写代码大全

ins518 2024-10-09 16:24:58 技术文章 10 ℃ 0 评论

上节中我们做了绘画类,这次做时钟类。

大致逻辑:

  1. 处理传过来的参数
  2. 绘制表盘
  3. 根据获取的表针角度,绘制表针
  4. 使用动画方法重复绘制表盘和表针逻辑


/**
 * 时钟类
 */
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;
    }
}

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表