canvas自适应圆形时钟绘制
前面的话
前面介绍过canvas粒子时钟的绘制,本文将详细介绍canvas自适应圆形时钟绘制
效果演示
最终自适应圆形时钟的效果如下所示
功能分析
下面来分析一下该圆形时钟的功能
【1】静态背景
对于时钟来说,背景是不变的,包括外层钟框、内层圆点及数字、以及中心点的固定按扣
【2】动态时钟
时态的动态,表现在秒针、分针、时针随着当前时间的变化的变化。开启一个每秒变化1次定时器,秒针与当前的时间的秒数保持一致,分针的变化与当前的秒数和分钟数都有关,时针的变化与当前的分钟数和小时数都有关
【3】自适应
要做到时钟自适应,需要将时钟内部的尺寸绘制与时钟整体的宽高相关联,而不能设置为固定值
下面是一张时钟的简易分析图
静态时钟
下面来实现静态的时钟背景,包括外层钟框、内层圆点及数字、以及中心点的固定按扣,以时钟尺寸为200*200为基准,则半径为100,通过translate()将圆心点调整为(0,0)点
【初始设置】
由于外面经常要用到R和cxt.lineWidth,所以将其保存为变量
var cxt = drawing.getContext('2d');
var W = drawing.width = 400;
var H = drawing.height = 400;
var R = W / 2;
var cw = cxt.lineWidth = 0.1*R;
【外层钟框】
为了将外层钟框不超出canvas区域,则其半径设置为R-cw/2,线条宽度与半径成比例
cxt.translate(R,R);
cxt.beginPath();
cxt.arc(0,0,R-cw/2,0,2*Math.PI,false);
cxt.stroke();
【内层数字】
在距离圆心点0.8R-cw/2处,绘制12个数字,表示当前的分钟数,数字的字体大小与半径成比例
cxt.beginPath();
cxt.font = 0.2 * R + 'px 宋体';
cxt.textAlign = 'center';
cxt.textBaseline = 'middle';
var r1 = 0.8*R - cw/2;
for(var i = 12; i > 0; i--){
var radius = 2*Math.PI/12 * i + 1.5*Math.PI;
var x = Math.cos(radius) * r1;
var y = Math.sin(radius) * r1;
cxt.fillText(i,x,y);
}
【内层原点】
在距离圆心点0.9R-cw/2处,绘制60个圆点,表示当前的秒数,当前秒数与分钟数处于同一角度时,表示为大圆点(半径为cx/5),否则为小圆点(半径为cx/8)
cxt.beginPath();
var r2 = 0.9*R - cw/2;
for(var i = 0; i < 60; i++){
var radius = 2*Math.PI/60*i + 1.5*Math.PI;
var x = Math.cos(radius) * r2;
var y = Math.sin(radius) * r2;
cxt.beginPath();
if(i%5 === 0){
cxt.arc(x,y,cw/5,0,2*Math.PI,false);
}else{
cxt.arc(x,y,cw/8,0,2*Math.PI,false);
}
cxt.fill();
}
【绘制中心点的固定按扣】
cxt.beginPath();
cxt.arc(0,0,cw/3,0,2*Math.PI,false);
cxt.fill();
最终,静态背景封装为函数drawStatics(),代码如下
<canvas id="drawing" style="border:1px solid black"></canvas>
<script>
var drawing = document.getElementById('drawing');
if(drawing.getContext){
var cxt = drawing.getContext('2d');
var W = drawing.width = 200;
var H = drawing.height = 200;
var R = W / 2;
var cw = cxt.lineWidth = 0.1*R;
function drawStatics(){
cxt.translate(R,R);
cxt.beginPath();
cxt.lineWidth = 0.1*R;
cxt.arc(0,0,R-cw/2,0,2*Math.PI,false);
cxt.stroke(); cxt.beginPath();
cxt.font = 0.2 * R + 'px 宋体';
cxt.textAlign = 'center';
cxt.textBaseline = 'middle';
var r1 = 0.8*R - cw/2;
for(var i = 12; i > 0; i--){
var radius = 2*Math.PI/12 * i + 1.5*Math.PI;
var x = Math.cos(radius) * r1;
var y = Math.sin(radius) * r1;
cxt.fillText(i,x,y);
} cxt.beginPath();
var r2 = 0.9*R - cw/2;
for(var i = 0; i < 60; i++){
var radius = 2*Math.PI/60*i + 1.5*Math.PI;
var x = Math.cos(radius) * r2;
var y = Math.sin(radius) * r2;
cxt.beginPath();
if(i%5 === 0){
cxt.arc(x,y,cw/5,0,2*Math.PI,false);
}else{
cxt.arc(x,y,cw/8,0,2*Math.PI,false);
}
cxt.fill();
} cxt.beginPath();
cxt.arc(0,0,cw/3,0,2*Math.PI,false);
cxt.fill();
}
function draw(){
cxt.clearRect(0,0,W,H);
drawStatics();
}
draw();
}
</script>
静态效果如下
动态效果
下面来分为时针、分针、秒针来进行动态效果
【秒针】
开启一个每秒变化1次定时器,秒针与当前的时间的秒数保持一致
function drawSecond(second){
cxt.save();
cxt.translate(R,R);
cxt.beginPath();
var radius = 2*Math.PI/60 * second;
cxt.rotate(radius);
cxt.lineWidth = 2;
cxt.moveTo(0,cw*2);
cxt.lineTo(0,-0.8*R);
cxt.strokeStyle = 'red';
cxt.stroke();
cxt.restore();
}
【分针】
分针的变化与当前的秒数和分钟数都有关
function drawMinute(minute,second){
cxt.save();
cxt.translate(R,R);
cxt.beginPath();
var radius = 2*Math.PI/60 * minute;
var sRaiuds = 2*Math.PI/60/60 * second;
cxt.rotate(radius + sRaiuds);
cxt.lineWidth = 4;
cxt.lineCap = 'round';
cxt.moveTo(0,cw);
cxt.lineTo(0,-(0.8*R - cw/2));
cxt.stroke();
cxt.restore();
}
【时针】
时针的变化与当前的分钟数和小时数都有关
function drawHour(hour,minute){
cxt.save();
cxt.translate(R,R);
cxt.beginPath();
var radius = 2*Math.PI/12 * hour;
var mRaiuds = 2*Math.PI/12/60 * minute;
cxt.rotate(radius + mRaiuds);
cxt.lineWidth = 6;
cxt.lineCap = 'round';
cxt.moveTo(0,cw/2);
cxt.lineTo(0,-(0.8*R - cw*2));
cxt.stroke();
cxt.restore();
}
完整代码
现在,需要对代码进行调整,因为canvas是按照代码顺序进行绘制的,所以代码顺序应该是,静态背景(时钟外框、圆点及数字) -> 动态效果(秒针、分针、时针) -> 中心按扣
因此,需要将中心按扣的代码从静态背景函数drawStatics()中分离出来,并重新安排代码顺序
由于浏览器的定时器存在误差,因此设置为1000ms并不合适,由于系统卡顿等原因,可能会跳过某次效果,因此,设置为500ms
最终完整代码如下所示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<canvas id="drawing"></canvas>
<script>
var drawing = document.getElementById('drawing');
if(drawing.getContext){
var cxt = drawing.getContext('2d');
var W = drawing.width = 200;
var H = drawing.height = 200;
var R = W / 2;
var cw = cxt.lineWidth = 0.1*R;
function drawStatics(){
cxt.save();
cxt.translate(R,R);
cxt.beginPath();
cxt.lineWidth = 0.1*R;
cxt.arc(0,0,R-cw/2,0,2*Math.PI,false);
cxt.stroke(); cxt.beginPath();
cxt.font = 0.2 * R + 'px 宋体';
cxt.textAlign = 'center';
cxt.textBaseline = 'middle';
var r1 = 0.8*R - cw/2;
for(var i = 12; i > 0; i--){
var radius = 2*Math.PI/12 * i + 1.5*Math.PI;
var x = Math.cos(radius) * r1;
var y = Math.sin(radius) * r1;
cxt.fillText(i,x,y);
} cxt.beginPath();
var r2 = 0.9*R - cw/2;
for(var i = 0; i < 60; i++){
var radius = 2*Math.PI/60*i + 1.5*Math.PI;
var x = Math.cos(radius) * r2;
var y = Math.sin(radius) * r2;
cxt.beginPath();
if(i%5 === 0){
cxt.arc(x,y,cw/5,0,2*Math.PI,false);
}else{
cxt.arc(x,y,cw/8,0,2*Math.PI,false);
}
cxt.fill();
}
cxt.restore();
}
function drawDot(){
cxt.save();
cxt.translate(R,R);
cxt.beginPath();
cxt.arc(0,0,cw/3,0,2*Math.PI,false);
cxt.fillStyle = '#fff';
cxt.fill();
cxt.restore();
}
function drawSecond(second){
cxt.save();
cxt.translate(R,R);
cxt.beginPath();
var radius = 2*Math.PI/60 * second;
cxt.rotate(radius);
cxt.lineWidth = 2;
cxt.moveTo(0,cw*2);
cxt.lineTo(0,-0.8*R);
cxt.strokeStyle = 'red';
cxt.stroke();
cxt.restore();
}
function drawMinute(minute,second){
cxt.save();
cxt.translate(R,R);
cxt.beginPath();
var radius = 2*Math.PI/60 * minute;
var sRaiuds = 2*Math.PI/60/60 * second;
cxt.rotate(radius + sRaiuds);
cxt.lineWidth = 4;
cxt.lineCap = 'round';
cxt.moveTo(0,cw);
cxt.lineTo(0,-(0.8*R - cw/2));
cxt.stroke();
cxt.restore();
}
function drawHour(hour,minute){
cxt.save();
cxt.translate(R,R);
cxt.beginPath();
var radius = 2*Math.PI/12 * hour;
var mRaiuds = 2*Math.PI/12/60 * minute;
cxt.rotate(radius + mRaiuds);
cxt.lineWidth = 6;
cxt.lineCap = 'round';
cxt.moveTo(0,cw/2);
cxt.lineTo(0,-(0.8*R - cw*2));
cxt.stroke();
cxt.restore();
}
function draw(){
cxt.clearRect(0,0,W,H);
drawStatics();
var now = new Date();
drawHour(now.getHours(),now.getMinutes());
drawMinute(now.getMinutes(),now.getSeconds());
drawSecond(now.getSeconds());
drawDot();
}
draw();
setInterval(draw,500);
}
</script>
</body>
</html>
canvas自适应圆形时钟绘制的更多相关文章
- 环形进度条的实现方法总结和动态时钟绘制(CSS3、SVG、Canvas)
缘由: 在某一个游戏公司的笔试中,最后一道大题是,“用CSS3实现根据动态显示时间和环形进度[效果如下图所示],且每个圆环的颜色不一样,不需要考虑IE6~8的兼容性”.当时第一想法是用SVG,因为SV ...
- js绘制圆形时钟
纯js制作圆形时钟 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- 深夜,用canvas画一个时钟
深夜,用canvas画一个时钟 查看demo 这几天准备阿里巴巴的笔试,可以说已经是心力交瘁,自从阿里和蘑菇街的内推被刷掉之后,开始越来越怀疑起自己的能力来,虽然这点打击应该是微不足道的.毕竟校招在刚 ...
- canvas做的时钟,学习下
canvas标签只是图形容器,您必须使用脚本来绘制图形. getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性.——获取上下文对象. getContext(" ...
- circle_clock 简单canvas实现圆弧时钟
渣渣成品图:http://codepen.io/thewindswor... 最近对于圆形有种特别的感情呢...因为写了个cricle_process_bar就像到了用来做时钟大概会比较有趣吧,所以就 ...
- HTML5之Canvas画圆形
HTML5之Canvas画圆形 1.设计源码 <!DOCTYPE html> <head> <meta charset="utf-8" /> & ...
- canvas动画—圆形扩散、运动轨迹
介绍 在ECharts中看到过这种圆形扩散效果,类似css3,刚好项目中想把它用上,but我又不想引入整个echart.js文件,更重要的是想弄明白它的原理,所以自己动手.在这篇文章中我们就来分析实现 ...
- jQuery ClockPicker 圆形时钟
ClockPicker.js是一款时钟插件,其实还可以改进,里面的分可以改成短横线. 在线实例 实例预览 jQuery ClockPicker 圆形时钟 使用方法 <div class=&qu ...
- Canvas:橡皮筋线条绘制
Canvas:橡皮筋线条绘制 效果演示 实现要点 事件监听 [说明]: 在Canvas中检测鼠标事件是非常简单的,可以在canvas中添加一个事件监听器,当事件发生时,浏览器就会调用这个监听器. 我们 ...
随机推荐
- Docker 部署DropWizard
FROM index.alauda.cn/alauda/ubuntu MAINTAINER hongxiao.shou "shouhongxiao@163.com" COPY jd ...
- Python运维开发基础-概述-简介
Python基础知识分为以下几块 1.Python概述 2.基础语法 3.数据结构 4.Python进阶 5.实训案例 一.Python概述 1.Python简介 2.Hello World 3.搭建 ...
- Ubuntu14.04_x64_Caffe_GPU环境配置
为了让Caffe支持GPU模式,需要安装GPU和CUDA Toolkit,依据NVIDIA官方教程以ubuntu14.04_X64安装cuda8.0,配置Gpu为例如下所示: 1.检查安装环境,是否具 ...
- Mongoose基础入门
前面的话 Mongoose是在node.js异步环境下对mongodb进行便捷操作的对象模型工具.本文将详细介绍如何使用Mongoose来操作MongoDB NodeJS驱动 在介绍Mongoose之 ...
- 原生JSdom节点相关(非原创)
节点属性 Node.nodeName //返回节点名称,只读 Node.nodeType //返回节点类型的常数值,只读 Node.nodeValue //返回Text或Comment节点的文本值,只 ...
- (转)Java多线程之Lock的使用 (待整理)
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util ...
- 解决kindeditor编辑器中使用百度地图时不能拖动坐标的问题
覆盖\plugins\baidumap文件夹下的map.html代码即可 <!doctype html><html><head> <meta http- ...
- HDU1036 Average is not Fast Enough!
Problem Description A relay is a race for two or more teams of runners. Each member of a team runs o ...
- win7下从ruby源代码编译安装
工作中需要在c++代码中嵌入ruby c api,然而在vs工程中编译失败,所以现在通过手动从源代码编译ruby寻找原因(之前使用rubyinstaller安装). 先从官网下载ruby 2.4. ...
- Word2016“此功能看似已中断 并需要修复”问题解决办法
Word2016"此功能看似已中断 并需要修复"问题解决办法 修复步骤: 1. 按Windows 键+R键,输入"regedit"打开注册表. 2.找到以下键值 ...