zoukankan      html  css  js  c++  java
  • 使用canvas绘制一个时钟

      周末学习canvas的一些基础功能,顺带写了一个基础的时钟。现在加工一下,做的更好看一点,先放上效果图:

        

      谈一些自己的理解:

        (1)、要绘制一个新的样式(不想被其他样式影响,或者影响到其他样式),那么一定记得先用beginPath(),beginPath()可以新建一个子路径,接下来的绘制,都是针对该子路径进行的。如果不适用该方法,那么默认和之前路径为同一路径设置,在接下来的绘制中,前面设置的路径会被重复绘制(打个比方,如果不用beginPath(),上面我绘制了一个长方形,边框宽度为1,下面我又绘制了一个长方形,边框宽度为5,那么上面的长方形会被重新绘制,且边框宽度也变为5)。相对的还有一个closePath()方法,如果前面设置的路径是开放的,该方法会自动用直线连接终点和起点。

        (2)、因为时、分、秒针都是通过循环并且旋转来做出移动效果,所以需要在每次旋转前,通过save()方法保存下当前状态,并在旋转后restore()恢复到之前状态,否则每次旋转都会在上一次旋转的基础上进行。

        (3)、仔细看的话可以发现秒针的尾端是一个弧线,canvas里有很多曲线的绘制方法,且大多与切线(切点)有关,具体可以搜索下,网上有很多详解文章了。

        (4)、lineTo()、arc()、arcTo()这些都仅仅是绘制路径,最后要通过fill()或者stroke()来完成绘制。

      下面给出完整代码,补上了注释:

    <!doctype html>
    <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <style>
    </style>
    </head>
    <body>
    <canvas id="my_clock" width="1200" height="900">不支持canvas</canvas>
    <script>
    	var myClock = document.getElementById('my_clock');
    	var ctx = myClock.getContext('2d');
    	var clockImg = new Image();
    	clockImg.src = 'clock.png';
    	ctx.translate(600, 400);
    
    	var startTime = new Date().getTime(),
    		count = 0;
    
    	function clock() {
    		ctx.clearRect(-600, -400, 1200, 900);
    
    		// 裁剪钟面图,只留下圆的钟面
    		ctx.beginPath();
    		ctx.arc(0, 0, 250, 0, 2 * Math.PI);
    		ctx.clip();
    
    		// 钟面图有点歪,需要差不多顺时针旋转1/3度
    		ctx.save()
    		ctx.rotate(1 / 3 * 2 * Math.PI / 60);
    		ctx.drawImage(clockImg, - 250, -250, 500, 500);
    		ctx.restore();
    		
    		// 这里注释的部分的是绘制的一个简单的钟面,如果不用图片可以打开下面的注释
    		// ctx.beginPath();
    		// ctx.arc(0, 0, 200, 0, 2 * Math.PI, false);
    
    		// ctx.moveTo(195, 0);
    		// ctx.arc(0, 0, 195, 0, 2 * Math.PI, false);
    		// ctx.stroke();
    		// ctx.closePath();
    
    		// ctx.font = '16px Arial';
    		// ctx.textAlign = 'center';
    		// ctx.textBaseline = 'middle';
    
    		// ctx.fillText('12', 0, -180);
    		// ctx.fillText('3', 180, 0);
    		// ctx.fillText('6', 0, 180);
    		// ctx.fillText('9', -180, 0);
    
    	
    		var nowTime = new Date(),
    			sec = nowTime.getSeconds(),
    			min  = nowTime.getMinutes() + sec / 60,
    			hour12 = nowTime.getHours() >= 12 ? nowTime.getHours() - 12 : nowTime.getHours(),
    			hour = hour12 + min / 60;
    		
    		// 实时时间转换成角度,一圈是360度,也就是2PI,一圈有60小格,一小格就是(2 * Math.PI / 60)
    		var angle = 2 * Math.PI / 60,
    			secHandAngle = sec * angle,
    			minHandAngle = min * angle,
    			hourHandAngle = hour * 5 * angle;
    
    		// 秒针
    		ctx.save();
    		ctx.beginPath();
    		ctx.rotate(secHandAngle)
    		ctx.moveTo(-2, 10);   
    		ctx.lineTo(0, -240);	
    		ctx.lineTo(2, 10);
    		ctx.moveTo(-2, 10);
    		ctx.arcTo(0, -240, 2, 10, 2);
    		ctx.stroke();
    		ctx.restore();
    		
    		// 分针
    		ctx.save();
    		ctx.beginPath();
    		ctx.rotate(minHandAngle)
    		ctx.moveTo(0, 0);   
    		ctx.lineTo(0, -170);
    		ctx.lineWidth = 2;
    		ctx.stroke();
    		ctx.restore();
    
    		// 时针
    		ctx.save();
    		ctx.beginPath();
    		ctx.rotate(hourHandAngle)
    		ctx.moveTo(-5, 0);   
    		ctx.lineTo(0, -120);	
    		ctx.lineTo(5, 0);
    		ctx.strokeStyle = '#fff'
    		ctx.fillStyle = 'rgba(0, 0, 0, .3)';
    		ctx.lineWidth = 1;
    		ctx.stroke();
    		ctx.fill();
    		ctx.restore();
    
    		// 减少setTimeout误差
    		count++;
    		var diff = new Date().getTime() - (startTime + count * 1000);
    		var nextStart = (1000 - diff) < 0 ? 0 : 1000 - diff;
    		setTimeout(clock, nextStart);
    	}
    
    	// 占用线程
    	// setInterval(function(){ 
    	//  	var j = 0; 
    	//  	while (j++ < 100000000); 
    	// }, 0); 
    	// setInterval(function(){ 
    	//  	var j = 0; 
    	//  	while (j++ < 100000000); 
    	// }, 0); 
    	// setInterval(function(){ 
    	//  	var j = 0; 
    	//  	while (j++ < 100000000); 
    	// }, 0); 
    
    	setTimeout(clock, 1000);
    	// setInterval(clock, 1000)
    
    	
    </script>
    </body>
    </html>
    

      然后给上我用的钟面图:

        

  • 相关阅读:
    1.3.9、通过权重 Weight匹配
    1.3.8、通过RemoteAddr匹配
    1.3.7、通过QueryParam匹配
    1.3.6、通过Path匹配
    1.3.5、通过Method匹配
    1.3.4、通过Host匹配
    css选择器优先级如何计算
    pm2常用命令
    前端微服务 二
    前端微服务
  • 原文地址:https://www.cnblogs.com/youyouluo/p/6109438.html
Copyright © 2011-2022 走看看