一步一步教你用Html5的Canvas绘制钟表

举报
lwq1228 发表于 2021/08/04 17:03:26 2021/08/04
【摘要】 本博文一步一步教你用Html5的Canvas绘制一个钟表

1、表盘绘制

1.1、基础样式代码

定义body背景色为粉色,在body中定义一个800*800的灰色画布,clock.css文件内容如下。

* {
    margin: 0;
    padding: 0;
}

html, body {
    height: 100%;
    overflow: hidden;
    background: pink;
}

#clock {
    background: gray;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate3d(-50%, -50%, 0);
}

1.2、基础Html代码

clock.html代码结构如下。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="clock.css">
</head>
<body>
<canvas id="clock" width="800" height="800"></canvas>
</body>
<script type="text/javascript">
    window.onload = function () {
        // 获取画布元素
        var clock = document.querySelector("#clock");
        // 如果画笔存在
        if (clock.getContext) {
            // 获取画笔
            var ctx = clock.getContext("2d");
        }
    }
</script>
</html>

效果如图:

1.3、定义表盘画笔通用样式

// 保存样式
ctx.save();
// 定义基本样式
// 定义基本线宽为10
ctx.lineWidth = 10;
// 定义线的颜色为黑色
ctx.strokeStyle = "black";
// 定义线段末端以圆形结束
ctx.lineCap = "round";
// 将原点移动到400, 400的位置
ctx.translate(400, 400);
// 逆时针旋转90度
ctx.rotate(-90 * Math.PI / 180);
ctx.beginPath();
ctx.restore();

1.4、绘制外层空心表盘

表盘参数:

  • 圆盘颜色:#325FA2
  • 圆盘宽度:20
  • 圆盘半径:280
// 绘制外层空心表盘
ctx.save();
// 定义外层空心表盘颜色
ctx.strokeStyle = "#325FA2";
// 定义线宽为20
ctx.lineWidth = 20;
// 重置画笔路径
ctx.beginPath();
// 绘制半径为280的圆形表盘
ctx.arc(0, 0, 280, 0, 360 * Math.PI / 180);
ctx.stroke();
ctx.restore();

效果如图:

1.5、绘制时针刻度

时针刻度参数:

  • 长度为30
  • 宽度为10
  • 外层空心圆盘与时针刻度之间的距离也为30
// 绘制时针刻度
ctx.save();
for (var i = 0; i < 12; i++) {
    // 绘制12个时针刻度,每30度一个
    ctx.rotate(30 * Math.PI / 180);
    ctx.beginPath();
    // 每个刻度从220 绘制到 250
    ctx.moveTo(220, 0)
    ctx.lineTo(250, 0);
    ctx.stroke();
}
ctx.restore();

效果如图:

1.5、绘制分针刻度

分针刻度参数:

  • 长度为10
  • 宽度为5
// 绘制分针刻度
ctx.save();
ctx.lineWidth = 5;
for (var i = 0; i < 60; i++) {
    // 绘制48个分针刻度,每6度一个
    ctx.rotate(6 * Math.PI / 180);
    // 如果是时针位置,则不绘制
    if ((i + 1) % 5 !== 0) {
        ctx.beginPath();
        ctx.moveTo(240, 0)
        ctx.lineTo(250, 0);
        ctx.stroke();
    }
}
ctx.restore();

效果如图:

2、表针绘制

2.1、获取系统时间时分秒的值

// 获取系统时间的时分秒的值
var date = new Date();
// 获取系统时间的秒的值
var s = date.getSeconds();
// 获取系统时间的分钟的值
var m = date.getMinutes() + s / 60;
// 获取系统时间的小时的值
var h = date.getHours() + m / 60;
// 如果小时超过12则剪掉12,采用12小时制
h = h > 12 ? h - 12 : h;

2.2、绘制时针

时针参数:

  • 宽度为30
  • 头部离圆心180,尾部离圆心40
// 绘制时针
ctx.save()
// 定义线宽为30
ctx.lineWidth = 30;
// 绘制时针旋转位置
ctx.rotate(h * 30 * Math.PI / 180)
ctx.beginPath()
// 绘制时针线
ctx.moveTo(-40, 0);
ctx.lineTo(180, 0);
ctx.stroke();
ctx.restore()

效果如图:

2.3、绘制分针

分针参数:

  • 宽度为20
  • 头部离圆心220,尾部离圆心60
// 绘制分针
ctx.save()
// 定义线宽为20
ctx.lineWidth = 20;
// 绘制分针旋转位置
ctx.rotate(m * 6 * Math.PI / 180)
ctx.beginPath()
ctx.moveTo(-60, 0);
ctx.lineTo(220, 0);
ctx.stroke();
ctx.restore()

效果如图:

2.4、绘制秒针

秒针参数:

  • 颜色:D40000
  • 宽度为10
  • 头部离圆心200,尾部离圆心70
  • 中心实心圆盘半径为20
  • 秒针头从215开始绘制半径为15、宽度为10的空心圆
// 绘制秒针
ctx.save();
// 定义线宽为10
ctx.lineWidth = 10;
// 定义秒针颜色及填充颜色为D40000
ctx.strokeStyle = "#D40000";
ctx.fillStyle = "#D40000";
// 绘制秒针旋转位置
ctx.rotate(s * 6 * Math.PI / 180);
ctx.beginPath();
ctx.moveTo(-70, 0);
ctx.lineTo(200, 0);
ctx.stroke();
// 绘制表座
ctx.beginPath();
ctx.arc(0, 0, 20, 0, 360 * Math.PI / 180);
ctx.fill();
// 绘制秒头
ctx.beginPath();
ctx.arc(215, 0, 15, 0, 360 * Math.PI / 180);
ctx.stroke();
ctx.restore()

效果如图:

3、让钟表动起来

3.1、将表盘及表针绘制内容封装成一个函数move

function move() {
    // 保存样式
    ctx.save();
    // 定义基本样式
    // 定义基本线宽为10
    ctx.lineWidth = 10;
    // 定义线的颜色为黑色
    ctx.strokeStyle = "black";
    // 定义线段末端以圆形结束
    ctx.lineCap = "round";
    // 将原点移动到400, 400的位置
    ctx.translate(400, 400);
    // 逆时针旋转90度
    ctx.rotate(-90 * Math.PI / 180);
    ctx.beginPath();

    // 绘制外层空心表盘
    ctx.save();
    // 定义外层空心表盘颜色
    ctx.strokeStyle = "#325FA2";
    // 定义线宽为20
    ctx.lineWidth = 20;
    // 重置画笔路径
    ctx.beginPath();
    // 绘制圆形表盘
    ctx.arc(0, 0, 280, 0, 360 * Math.PI / 180);
    ctx.stroke();
    ctx.restore();

    // 绘制时针刻度
    ctx.save();
    for (var i = 0; i < 12; i++) {
        // 绘制12个时针刻度,每30度一个
        ctx.rotate(30 * Math.PI / 180);
        ctx.beginPath();
        // 每个刻度从220 绘制到 250
        ctx.moveTo(220, 0)
        ctx.lineTo(250, 0);
        ctx.stroke();
    }
    ctx.restore();

    // 绘制分针刻度
    ctx.save();
    ctx.lineWidth = 5;
    for (var i = 0; i < 60; i++) {
        // 绘制48个分针刻度,每6度一个
        ctx.rotate(6 * Math.PI / 180);
        // 如果是时针位置,则不绘制
        if ((i + 1) % 5 !== 0) {
            ctx.beginPath();
            ctx.moveTo(240, 0)
            ctx.lineTo(250, 0);
            ctx.stroke();
        }
    }
    ctx.restore();

    // 获取系统时间的时分秒的值
    var date = new Date();
    // 获取系统时间的秒的值
    var s = date.getSeconds();
    // 获取系统时间的分钟的值
    var m = date.getMinutes() + s / 60;
    // 获取系统时间的小时的值
    var h = date.getHours() + m / 60;
    // 如果小时超过12则剪掉12,采用12小时制
    h = h > 12 ? h - 12 : h;

    // 绘制时针
    ctx.save();
    // 定义线宽为30
    ctx.lineWidth = 30;
    // 绘制时针旋转位置
    ctx.rotate(h * 30 * Math.PI / 180);
    ctx.beginPath();
    // 绘制时针线
    ctx.moveTo(-40, 0);
    ctx.lineTo(180, 0);
    ctx.stroke();
    ctx.restore();

    // 绘制分针
    ctx.save();
    // 定义线宽为20
    ctx.lineWidth = 20;
    // 绘制分针旋转位置
    ctx.rotate(m * 6 * Math.PI / 180);
    ctx.beginPath();
    ctx.moveTo(-60, 0);
    ctx.lineTo(220, 0);
    ctx.stroke();
    ctx.restore();

    // 绘制秒针
    ctx.save();
    // 定义线宽为10
    ctx.lineWidth = 10;
    // 定义秒针颜色及填充颜色为D40000
    ctx.strokeStyle = "#D40000";
    ctx.fillStyle = "#D40000";
    // 绘制秒针旋转位置
    ctx.rotate(s * 6 * Math.PI / 180);
    ctx.beginPath();
    ctx.moveTo(-70, 0);
    ctx.lineTo(200, 0);
    ctx.stroke();
    // 绘制表座
    ctx.beginPath();
    ctx.arc(0, 0, 20, 0, 360 * Math.PI / 180);
    ctx.fill();
    // 绘制秒头
    ctx.beginPath();
    ctx.arc(215, 0, 15, 0, 360 * Math.PI / 180);
    ctx.stroke();
    ctx.restore()

    ctx.restore();
}

3.2、使用计时器让钟表动起来

// 开始先执行一次
move();

// 定时执行,每1秒执行一次
setInterval(function () {
    ctx.clearRect(0, 0, clock.width, clock.height);
    move();
}, 1000);

4、Html完整代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="clock.css">
</head>
<body>
<canvas id="clock" width="800" height="800"></canvas>
</body>
<script type="text/javascript">
    window.onload = function () {
        var clock = document.querySelector("#clock");
        if (clock.getContext) {
            var ctx = clock.getContext("2d");

            //move();
            // 定时执行
            setInterval(function () {
                ctx.clearRect(0, 0, clock.width, clock.height);
                move();
            }, 1000);

            function move() {
                // 保存样式
                ctx.save();
                // 定义基本样式
                // 定义基本线宽为10
                ctx.lineWidth = 10;
                // 定义线的颜色为黑色
                ctx.strokeStyle = "black";
                // 定义线段末端以圆形结束
                ctx.lineCap = "round";
                // 将原点移动到400, 400的位置
                ctx.translate(400, 400);
                // 逆时针旋转90度
                ctx.rotate(-90 * Math.PI / 180);
                ctx.beginPath();

                // 绘制外层空心表盘
                ctx.save();
                // 定义外层空心表盘颜色
                ctx.strokeStyle = "#325FA2";
                // 定义线宽为20
                ctx.lineWidth = 20;
                // 重置画笔路径
                ctx.beginPath();
                // 绘制圆形表盘
                ctx.arc(0, 0, 280, 0, 360 * Math.PI / 180);
                ctx.stroke();
                ctx.restore();

                // 绘制时针刻度
                ctx.save();
                for (var i = 0; i < 12; i++) {
                    // 绘制12个时针刻度,每30度一个
                    ctx.rotate(30 * Math.PI / 180);
                    ctx.beginPath();
                    // 每个刻度从220 绘制到 250
                    ctx.moveTo(220, 0)
                    ctx.lineTo(250, 0);
                    ctx.stroke();
                }
                ctx.restore();

                // 绘制分针刻度
                ctx.save();
                ctx.lineWidth = 5;
                for (var i = 0; i < 60; i++) {
                    // 绘制48个分针刻度,每6度一个
                    ctx.rotate(6 * Math.PI / 180);
                    // 如果是时针位置,则不绘制
                    if ((i + 1) % 5 !== 0) {
                        ctx.beginPath();
                        ctx.moveTo(240, 0)
                        ctx.lineTo(250, 0);
                        ctx.stroke();
                    }
                }
                ctx.restore();

                // 获取系统时间的时分秒的值
                var date = new Date();
                // 获取系统时间的秒的值
                var s = date.getSeconds();
                // 获取系统时间的分钟的值
                var m = date.getMinutes() + s / 60;
                // 获取系统时间的小时的值
                var h = date.getHours() + m / 60;
                // 如果小时超过12则剪掉12,采用12小时制
                h = h > 12 ? h - 12 : h;

                // 绘制时针
                ctx.save();
                // 定义线宽为30
                ctx.lineWidth = 30;
                // 绘制时针旋转位置
                ctx.rotate(h * 30 * Math.PI / 180);
                ctx.beginPath();
                // 绘制时针线
                ctx.moveTo(-40, 0);
                ctx.lineTo(180, 0);
                ctx.stroke();
                ctx.restore();

                // 绘制分针
                ctx.save();
                // 定义线宽为20
                ctx.lineWidth = 20;
                // 绘制分针旋转位置
                ctx.rotate(m * 6 * Math.PI / 180);
                ctx.beginPath();
                ctx.moveTo(-60, 0);
                ctx.lineTo(220, 0);
                ctx.stroke();
                ctx.restore();

                // 绘制秒针
                ctx.save();
                // 定义线宽为10
                ctx.lineWidth = 10;
                // 定义秒针颜色及填充颜色为D40000
                ctx.strokeStyle = "#D40000";
                ctx.fillStyle = "#D40000";
                // 绘制秒针旋转位置
                ctx.rotate(s * 6 * Math.PI / 180);
                ctx.beginPath();
                ctx.moveTo(-70, 0);
                ctx.lineTo(200, 0);
                ctx.stroke();
                // 绘制表座
                ctx.beginPath();
                ctx.arc(0, 0, 20, 0, 360 * Math.PI / 180);
                ctx.fill();
                // 绘制秒头
                ctx.beginPath();
                ctx.arc(215, 0, 15, 0, 360 * Math.PI / 180);
                ctx.stroke();
                ctx.restore()

                ctx.restore();
            }
        }
    }
</script>
</html>
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。