美文网首页
Canvas基础及动态时钟的实现

Canvas基础及动态时钟的实现

作者: 我小时候很可爱 | 来源:发表于2020-06-10 00:17 被阅读0次

Canvas基础以及动态时钟的实现

写在前面

HTML5 <canvas> 元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成,<canvas> 标签只是图形容器,和别的标签不同,我们不在<canvas>标签里面写内容,必须使用脚本来绘制图形。Canvas是一个行内块元素。

Canvas基础

  1. 画布的创建,在绘图之前我们首先是需要一张“纸”,默认情况下 <canvas> 元素没有边框和内容。

    • <canvas id="myCanvas" width="200" height="100"></canvas>
      
    • 标签通常需要指定一个id属性 (脚本中经常引用), width 和 height 属性定义的画布的大小

  2. 在<canvas>上绘制

    • 首先要获取到canvas元素

    • 创建context对象 (这里我们可以利用判断是否有上下文对象来判断浏览器是否支持)

    • var c=document.getElementById("myCanvas");
      var ctx=c.getContext("2d");
      
  3. 2D上下文

    • 使用2d绘图上下文提供的方法,可以绘制简单的2D图形,比如矩形、弧形和路径等。2D上下文的起始位置是<canvas>画布的左上角,原点坐标为(0,0)。所有的坐标值都是基于这个点计算的,x越大表示越靠右,y越大表示越靠下。大家在绘图时候可以在脑海中构建一个坐标系。width和height表示在这两个方向上可用的像素数目。
  4. 线条和填充、路径

    • 路径
方法 描述 属性值
stroke() 绘制已定义的路径
beginPath() 起始一条路径,或重置当前路径
closePath() 创建从当前点回到起始点的路径
lineTo() 添加一个新点,然后在画布中创建从该点到最后指定点的线条 坐标
arc() 创建弧/曲线(用于创建圆形或部分圆) (x,y,r,sAngle,eAngle,counterclockwise)
moveTo() 把路径起始位置移动到画布中的指定点,不创建线条 坐标
  • 线条
方法 描述 属性值
lineCap() 设置或返回线条的结束端点样式 butt:向线条的每个末端添加平直的边缘。round:向线条的每个末端添加圆形线帽。square:向线条的每个末端添加正方形线帽。
lineWidth() 设置或返回当前的线条宽度 number:当前线条的宽度,以像素计。
  • 填充
方法 描述 属性值
fillStyle() 设置或返回用于填充绘画的颜色、渐变或模式 color:指示绘图填充色的CSS颜色值;gradient:用于填充绘图的渐变对象
fill() 填充当前绘图(路径)

实例:

<body>
    <canvas id="canvas" width="200" height="200"></canvas>
</body>
<script>
    var convas = document.getElementById('canvas');
    var ctx = convas.getContext('2d');
    ctx.moveTo(100, 100);
    ctx.lineTo(150, 150);
    ctx.lineTo(80, 150);
    ctx.lineWidth = 5;
    ctx.strokeStyle = "#ccc";
    ctx.stroke()
    ctx.fill()
</script>
  1. 文本、转化和保存

    • 文本
    方法 描述 属性值
    font 设置或返回文本内容的当前字体属性 font-style、font-variant、font-weight
    textAlign 设置或返回文本内容的当前对齐方式 center、left、right、start、end
    textBaseline 设置或返回在绘制文本时使用的当前文本基线 middle、top、buttom
    • 转化
    方法 描述 属性值
    scale() 缩放当前绘图至更大或更小 scalewidth:缩放当前绘图的宽度(1=100%);scaleheight:缩放当前绘图的高度
    rotate() 旋转当前绘图 angle:角度
    transalte() 重新映射画布上的 (0,0) 位置 坐标(x,y)
    • 保存
    方法 描述 属性值
    save() 保存当前环境的状态
    restore() 返回之前保存过的路径状态和属性
  2. 绘制弧线的方法(利用arc()方法)

    arc(x,y,r,sAngle,eAngle,counterclockwise)

    x,y就是画这个弧线的圆心坐标;r为半径值;sAngle,eAngle就是起始角和结束角;counterclockwise是表示画的方向,false为顺时针,true为逆时针。

    sAngle,eAngle的具体可见下图(记住起始位置不是在上面而是在右边

Tip:当我们使用顺时针画和逆时针画是不同的,要注意区分,请看下面例子,只是画的方向不同,图形也不同

var convas = document.getElementById('canvas');
var ctx = convas.getContext('2d');
ctx.beginPath()
ctx.arc(100, 100, 50, 0, 1.5 * Math.PI, false) //顺时针画法
ctx.stroke()
ctx.closePath()
ctx.beginPath()
ctx.arc(200, 100, 50, 0, 1.5 * Math.PI, true)//逆时针画法
ctx.stroke()
ctx.closePath()  

动态时钟案例

原理:通过canvas绘制时钟的每一个线段,在把当前时间写入到绘图函数中,每一秒钟调用一次绘图函数,就可以实现时钟动态化

源码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动态时钟</title>
    <style>
        #clock {
            border: 1px solid #ccc;
        }
        
        div {
            text-align: center;
        }
    </style>
</head>
<body>
    <div>
        <canvas id="clock" width="200px" height="200px"></canvas>
    </div>
    <script>
        var clo = document.getElementById('clock');
        var ctx = clo.getContext('2d');
        var width = ctx.canvas.width;
        var height = ctx.canvas.height;
        var r = width / 2; //半径

        function drawBackground() {
            ctx.save(); //为了保存清除之前时钟的环境
            ctx.translate(r, r); //切换中心点,此时(0,0)就在最中心了,不再是在左上角
            ctx.beginPath();
            ctx.lineWidth = 8;//线条的宽度
            ctx.arc(0, 0, r - 4, 0, 2 * Math.PI, false)//绘制最外圆
            ctx.stroke();
            //画小时数
            var hourNumber = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
            ctx.font = '18px Arial'; //设置文本大小
            ctx.textAlign = 'center'; //文本居中
            ctx.textBaseline = 'middle';
            hourNumber.forEach(function(number, i) {
                //求出每一个对应的弧度
                var rad = 2 * Math.PI / 12 * i;
                var x = Math.cos(rad) * (r - 30);//算出每个数字对应的坐标
                var y = Math.sin(rad) * (r - 30);
                ctx.fillText(number, x, y) //填充文本
            });
            //画每分钟对应的小点点
            for (var i = 0; i < 60; i++) {
                var rad = 2 * Math.PI / 60 * i;
                var x = Math.cos(rad) * (r - 10);
                var y = Math.sin(rad) * (r - 10);
                ctx.beginPath();
                if (i % 5 === 0) { //被5整除也就是小时数
                    ctx.fillStyle = "#000"; //要加上,否则由于canvas是基于状态的,所以会把                                                 这里的颜色也改成#ccc
                    ctx.arc(x, y, 2.5, 0, 2 * Math.PI, true)
                } else {
                    ctx.fillStyle = "#ccc"
                    ctx.arc(x, y, 1.5, 0, 2 * Math.PI, true)
                }
                ctx.fill()
            }

        }

        function drawHour(hour, minute) {//画时针函数
            ctx.save(); //保存画小时之前的环境
            ctx.beginPath();
            var rad = 2 * Math.PI / 12 * hour; //每一个小时要旋转的弧度
            var mrad = 2 * Math.PI / 12 / 60 * minute; //分钟数移动的弧度
            ctx.rotate(rad + mrad); //画布的旋转
            ctx.lineWidth = 5;
            ctx.moveTo(0, 10); //移动原点到原点的下面一点,作为画时针的起始位置
            ctx.lineTo(0, -r / 2); //原点的位置在中心所以往上画要是负数
            ctx.lineCap = 'round'; //设置线条的结尾形状
            ctx.stroke();
            ctx.restore(); //返回画小时之前的画布的保存过的路径和属性状态
        }

        function drawMinute(minute) {//画分针函数
            //为了区分开画布环境
            ctx.save();
            ctx.beginPath();
            var rad = 2 * Math.PI / 60 * minute; //每一个小时要旋转的弧度
            ctx.rotate(rad); //画布的旋转
            ctx.lineWidth = 3;
            ctx.moveTo(0, 10); //移动原点到原点的下面一点,作为画时针的起始位置
            ctx.lineTo(0, -r + 20); //原点的位置在中心所以往上画要是负数,值越大画的越短
            ctx.lineCap = 'round'; //设置线条的结尾形状
            ctx.stroke();
            ctx.restore();

        }

        function drawSecond(second) {//画秒针函数
            ctx.save();
            ctx.beginPath();
            var rad = 2 * Math.PI / 60 * second; //每一个小时要旋转的弧度
            ctx.rotate(rad); //画布的旋转
            ctx.lineWidth = 2;
            ctx.strokeStyle = "red"
            ctx.moveTo(0, 10); //移动原点到原点的下面一点,作为画时针的起始位置
            ctx.lineTo(0, -r + 20); //原点的位置在中心所以往上画要是负数,值越大画的越短
            ctx.lineCap = 'round'; //设置线条的结尾形状
            ctx.stroke();
            ctx.restore();
        }

        function drawDot() {//画中心点
            ctx.beginPath();
            ctx.fillStyle = "#fff"
            ctx.arc(0, 0, 3, 0, 2 * Math.PI, false)
            ctx.fill()
        }

        function draw() {//绘图函数
            ctx.clearRect(0, 0, width, height); //每秒清除一次canvas再画出时分秒
            var date = new Date();
            var hour = date.getHours();
            var minute = date.getMinutes();
            var second = date.getSeconds();
            drawBackground()
            drawHour(hour, minute);
            drawMinute(minute);
            drawSecond(second);
            drawDot()
            ctx.restore(); //画完之后
        }

        draw(); //避免第一秒无效果
        setInterval(draw, 1000);//定时器函数每秒调用一次
    </script>
</body>

</html>

实现结果:

时钟特效

相关文章

网友评论

      本文标题:Canvas基础及动态时钟的实现

      本文链接:https://www.haomeiwen.com/subject/friytktx.html