zoukankan      html  css  js  c++  java
  • [JS,Canvas]日历时钟

    [JS,Canvas]日历时钟

    Html:

     1 <!doctype html>
     2 <html>
     3 <head>
     4 <meta charset="UTF-8">
     5 <title>Document</title>
     6 <script src="requestNextAnimationFrame.js"></script>
     7 <script src="calendarWithTime.js"></script>
     8 </head>
     9 <body>
    10 <style>
    11 * {margin:0; padding:0;}
    12 #calendarWithTime{
    13     margin : 0;
    14 }
    15 </style>
    16 <canvas id="calendarWithTime"></canvas>
    17 </body>
    18 </html>

    js:

    ;var calendarWithTime = function(){
        v = navigator.userAgent.toLowerCase().indexOf("android") != -1 || navigator.userAgent.toLowerCase().indexOf("iphone") != -1 || navigator.userAgent.toLowerCase().indexOf("ipad") != -1;
        // 浏览器可见区域
        appWidth =  (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth);
        appHeight =  (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) - 3; // chrome下,高度一样是,会出现下拉滚动条
        // 中心点
        centerPoint = {'x':appWidth*0.5,'y':appHeight*0.5};
        // 动画用
        lastFpsUpdateTime = (+new Date);
        // canvas对象
        caObj = null;
        // canvas context对象
        ctxtObj = null;
        // 现在时间
        timeNow = "";
        // 开始年份
        startY = 1988;
        init = function(){
            window.onload=function(){this.initCanvas();}
        }();
        getDomId = function(id){return document.getElementById(id);}
        initCanvas = function(id){
            this.caObj = this.getDomId("calendarWithTime");
            this.ctxtObj = this.caObj.getContext("2d");
            // 全屏canvas
            this.caObj.style.width = (this.appWidth+'px');
            this.caObj.style.height = (this.appHeight+'px');
            this.caObj.width = this.appWidth;
            this.caObj.height = this.appHeight;
            if (v) {
                caObj.style.border = "none";
            }
            // 开始年份
            startY = Math.floor((new Date()).getFullYear() / 8) * 8;
            // test 
            // startY = Math.floor(2010 / 8) * 8;
            this.lastFpsUpdateTime = (+new Date);
            this.animate();
        }
        doDraw = function(){
            this.ctxtObj.clearRect(0, 0, this.caObj.width, this.caObj.height);
            
            var date = new Date();
            // test
            /*date.setDate(29);
            date.setMonth(3);
            date.setFullYear(2010);*/
            var afterGap = 8 - (date.getFullYear() - startY);
            var allYears = date.getFullYear()-this.startY+afterGap;
            var allDays = this.getCountDays(date.getFullYear(),date.getMonth());
            
            this.doDrawDayPanel(31,allDays);
            this.doDrawMonthPanel();
            this.doDrawYearPanel(this.startY,date.getFullYear(),afterGap);
            
            // 画时间针
            this.doDrawTPanel();
            this.drawYMDHMS(0,0.35,0,0.1,date.getSeconds(),0,30,'s','');
            this.drawYMDHMS(0,0.3,0,0.05,date.getMinutes(),date.getSeconds()/60,30,'m','');
            this.drawYMDHMS(0,0.25,0,0.03,date.getHours() % 12,date.getMinutes()/60,6,'h','');
            
            this.drawYMDHMS(0.4,0.7,0.4,0.66,date.getDate(),date.getHours()/24,Math.ceil(31*0.5),'d',date.getDate());
            this.drawYMDHMS(0.4,0.6,0.4,0.568,(date.getMonth()),date.getDate()/(allDays+1),6,'M',date.getMonth()+1);
            this.drawYMDHMS(0.4,0.55,0.4,0.52,(date.getFullYear() - this.startY),(date.getMonth()+1)/13,Math.ceil(allYears*0.5),'y',date.getFullYear());
            
            // 显示时间
            this.getTimeNow();
            this.ctxtObj.save();
            
            this.ctxtObj.beginPath();
            this.ctxtObj.fillStyle = "#369";
            this.ctxtObj.strokeStyle = "#369";
            this.ctxtObj.font = "30px bold 微软雅黑";
            this.ctxtObj.textAlign="start";
            this.ctxtObj.textBaseline="top";
            this.ctxtObj.fillText(this.timeNow,0,0);
            this.ctxtObj.strokeText(this.timeNow,0,0);
            
            this.ctxtObj.restore();
            /*
            fillText(String text,float x,float y,[float maxwidth]):填充字符串
            strokeText(String text,float x,float y,[float maxwidth]):绘制边框
            font="bold 45px 宋体"
            textAlign:设置绘制字符串的水平对齐方式,start|end|right|center
            textBaseline:垂直对齐方式:top|hanging|middle|alphabetic|bottom
            */
        }
        doChangeToFront = function(i,x){
            // 转换为画面值
            return (i +Math.ceil(x/4)) % 60;
        }
        doChangeToEnd = function(i,x){
            // 转换为后台值
            return (i +Math.ceil(x/4*3)) % 60;
        }
        doDrawTPanel = function(){
            // 画时钟面板
            var minsLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.3;
            var mineLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.32;
            var maxsLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.28;
            var maxeLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.34;
            var gap = Math.PI/30;
            futoNum = 5;
            this.ctxtObj.save();
                this.ctxtObj.fillStyle = "#369";
            this.ctxtObj.strokeStyle = "#369";
            for(var i =0;i<=59;i++){
                if(i % futoNum==0){
                    sLen = maxsLen;
                    eLen = maxeLen;
                }else{
                    sLen = minsLen;
                    eLen = mineLen;
                }
                
                this.ctxtObj.beginPath();
                this.ctxtObj.moveTo(Math.cos(i*gap)*sLen + this.centerPoint.x ,Math.sin(i*gap)*sLen + this.centerPoint.y);
                this.ctxtObj.lineTo(Math.cos(i*gap)*eLen + this.centerPoint.x,Math.sin(i*gap)*eLen + this.centerPoint.y);
                this.ctxtObj.stroke();
                this.ctxtObj.closePath();
                
                /*iDiff = this.doChangeToFront(i); // i => iDiff
                //iDiff2 = this.doChangeToEnd(iDiff,60); // iDiff => i
                this.ctxtObj.font = "2px bold 微软雅黑";
                this.ctxtObj.textAlign="center"
                this.ctxtObj.textBaseline="middle"
                this.ctxtObj.fillText(iDiff,Math.cos(i*gap)*eLen + this.centerPoint.x,Math.sin(i*gap)*eLen + this.centerPoint.y);
                */
                
            }
            this.ctxtObj.beginPath();
            this.ctxtObj.arc(this.centerPoint.x,this.centerPoint.y,Math.min( this.caObj.width, this.caObj.height)*0.5*0.01,0,360,false);
            this.ctxtObj.fillStyle="red";
            this.ctxtObj.fill();
            this.ctxtObj.closePath();
            this.ctxtObj.restore();
        }
        doDrawYearPanel = function(startYear,nowYear,afterGap){
            // 画年份面板
            var sLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.53;
            var eLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.55;
            var labelLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.60;
            var allYears = nowYear-startYear+afterGap;
            var gap = Math.PI/Math.ceil(allYears*0.5);
            this.ctxtObj.save();
            
                this.ctxtObj.fillStyle = "#b4ffff";
            this.ctxtObj.beginPath();
            this.ctxtObj.arc(this.centerPoint.x,this.centerPoint.y,eLen+2,0,360,false);
            this.ctxtObj.closePath();
            this.ctxtObj.fill();
                this.ctxtObj.fillStyle = "white";
            this.ctxtObj.beginPath();
            this.ctxtObj.arc(this.centerPoint.x,this.centerPoint.y,sLen-2,0,360,false);
            this.ctxtObj.closePath();
            this.ctxtObj.fill();
            
            this.ctxtObj.restore();
            
                this.ctxtObj.fillStyle = "#369";
            this.ctxtObj.strokeStyle = "#369";
                for(var i =-2;i<=allYears-3;i++){
                this.ctxtObj.save();
                this.ctxtObj.beginPath();
                this.ctxtObj.moveTo(Math.cos(i*gap)*sLen + this.centerPoint.x ,Math.sin(i*gap)*sLen + this.centerPoint.y);
                this.ctxtObj.lineTo(Math.cos(i*gap)*eLen + this.centerPoint.x,Math.sin(i*gap)*eLen + this.centerPoint.y);
                this.ctxtObj.closePath();
                this.ctxtObj.stroke();
                
                iDiff = this.doChangeToFront(i,allYears) + startYear;
                
                this.ctxtObj.translate(this.centerPoint.x, this.centerPoint.y);
                 this.ctxtObj.rotate(i*gap);
                this.ctxtObj.font = "10px bold 微软雅黑";
                this.ctxtObj.textAlign="start";
                this.ctxtObj.textBaseline="bottom";
                this.ctxtObj.fillText(iDiff,sLen,0);
                
                this.ctxtObj.restore();
            }
        }
        doDrawMonthPanel = function(){
            // 画年份面板
            var sLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.58;
            var eLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.6;
            var labelLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.70;
            var gap = Math.PI/6;
            this.ctxtObj.save();
            
                this.ctxtObj.fillStyle = "#fde08c";
            this.ctxtObj.beginPath();
            this.ctxtObj.arc(this.centerPoint.x,this.centerPoint.y,eLen+2,0,360,false);
            this.ctxtObj.closePath();
            this.ctxtObj.fill();
                this.ctxtObj.fillStyle = "white";
            this.ctxtObj.beginPath();
            this.ctxtObj.arc(this.centerPoint.x,this.centerPoint.y,sLen-2,0,360,false);
            this.ctxtObj.closePath();
            this.ctxtObj.fill();
            this.ctxtObj.restore();
            
            
                this.ctxtObj.fillStyle = "#369";
            this.ctxtObj.strokeStyle = "#369";
                for(var i =-2;i<=9;i++){
                this.ctxtObj.save();
                this.ctxtObj.beginPath();
                this.ctxtObj.moveTo(Math.cos(i*gap)*sLen + this.centerPoint.x ,Math.sin(i*gap)*sLen + this.centerPoint.y);
                this.ctxtObj.lineTo(Math.cos(i*gap)*eLen + this.centerPoint.x,Math.sin(i*gap)*eLen + this.centerPoint.y);
                this.ctxtObj.closePath();
                this.ctxtObj.stroke();
                
                iDiff = (this.doChangeToFront(i,12)) % 12+1;
                
                this.ctxtObj.translate(this.centerPoint.x, this.centerPoint.y);
                 this.ctxtObj.rotate(i*gap);
                this.ctxtObj.font = "20px bold 微软雅黑";
                this.ctxtObj.textAlign="start";
                this.ctxtObj.textBaseline="middle";
                this.ctxtObj.fillText((iDiff+'').PadLeft(2,0),eLen,0);
                this.ctxtObj.restore();
            }
        }
        doDrawDayPanel = function(dayCount,realAllDay){
            // 画年份面板
            var sLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.68;
            var eLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.7;
            var labelLen = Math.min( this.caObj.width, this.caObj.height)*0.5*0.80;
            var gap = Math.PI/Math.ceil(dayCount*0.5);
            this.ctxtObj.save();
            
            this.ctxtObj.fillStyle = "#e587e5";
            this.ctxtObj.beginPath();
            this.ctxtObj.arc(this.centerPoint.x,this.centerPoint.y,eLen+2,0,360,false);
            this.ctxtObj.closePath();
            this.ctxtObj.fill();
            this.ctxtObj.fillStyle = "white";
            this.ctxtObj.beginPath();
            this.ctxtObj.arc(this.centerPoint.x,this.centerPoint.y,sLen-2,0,360,false);
            this.ctxtObj.closePath();
            this.ctxtObj.fill();
            this.ctxtObj.restore();
            
            
            this.ctxtObj.fillStyle = "#369";
            this.ctxtObj.strokeStyle = "#369";
            for(var i =-2;i<=dayCount-2;i++){
                this.ctxtObj.save();
                this.ctxtObj.beginPath();
                this.ctxtObj.moveTo(Math.cos(i*gap)*sLen + this.centerPoint.x ,Math.sin(i*gap)*sLen + this.centerPoint.y);
                this.ctxtObj.lineTo(Math.cos(i*gap)*eLen + this.centerPoint.x,Math.sin(i*gap)*eLen + this.centerPoint.y);
                this.ctxtObj.closePath();
                this.ctxtObj.stroke();
                
                iDiff = (this.doChangeToFront(i,dayCount)) % (dayCount+1);
                if(iDiff<=realAllDay && iDiff!=0){
                    this.ctxtObj.translate(this.centerPoint.x, this.centerPoint.y);
                     this.ctxtObj.rotate(i*gap);
                    this.ctxtObj.font = "20px bold 微软雅黑";
                    this.ctxtObj.textAlign="start";
                    this.ctxtObj.textBaseline="middle";
                    this.ctxtObj.fillText((iDiff+'').PadLeft(2,0),eLen,0);
                }
                this.ctxtObj.restore();
            }
        }
        drawYMDHMS = function(slen,elen,cslen,celen,main,sub,gapM,type,value){
            // 画日期时间针
            var date = new Date();
            var siM = main;
            var siS = sub;
            var gap = Math.PI/gapM;
            var sLen = Math.min( this.caObj.width, this.caObj.height)*0.5*slen;
            var eLen = Math.min( this.caObj.width, this.caObj.height)*0.5*elen;
            var csLen = Math.min( this.caObj.width, this.caObj.height)*0.5*cslen;
            var ceLen = Math.min( this.caObj.width, this.caObj.height)*0.5*celen;
            
            i = this.doChangeToEnd(siM+siS,gapM*2);
            ci = (i+gapM) % (gapM*2);
            this.ctxtObj.save();
            this.ctxtObj.beginPath();
            if(type=='y'){
                this.ctxtObj.strokeStyle="#00cece";
                this.ctxtObj.lineWidth = 6;
            }else if(type=='M'){
                this.ctxtObj.strokeStyle="#ce9b00";
                this.ctxtObj.lineWidth = 5;
            }else if(type=='d'){
                this.ctxtObj.strokeStyle="#bd01bd";
                this.ctxtObj.lineWidth = 4;
            }else if(type=='h'){
                this.ctxtObj.lineWidth = 3;
            }else if(type=='m'){
                this.ctxtObj.lineWidth = 2;
            }else if(type=='s'){
                this.ctxtObj.lineWidth = 1;
            }
            this.ctxtObj.moveTo(Math.cos(i*gap)*sLen + this.centerPoint.x ,Math.sin(i*gap)*sLen + this.centerPoint.y);
            this.ctxtObj.lineTo(Math.cos(i*gap)*eLen + this.centerPoint.x,Math.sin(i*gap)*eLen + this.centerPoint.y);
            this.ctxtObj.moveTo(Math.cos(ci*gap)*csLen + this.centerPoint.x ,Math.sin(ci*gap)*csLen + this.centerPoint.y);
            this.ctxtObj.lineTo(Math.cos(ci*gap)*ceLen + this.centerPoint.x,Math.sin(ci*gap)*ceLen + this.centerPoint.y);
            this.ctxtObj.stroke();
            this.ctxtObj.closePath();
            this.ctxtObj.restore();
            var cpi = ci*gap*360/Math.PI;
            if(type=='y'){
                this.ctxtObj.save();
                
                    this.ctxtObj.fillStyle = "#00cece";
                this.ctxtObj.strokeStyle="#00cece";
                this.ctxtObj.lineWidth = 8;
                this.ctxtObj.beginPath();
                this.ctxtObj.arc(this.centerPoint.x,this.centerPoint.y,ceLen,ci*gap-gap*0.5,ci*gap+gap*0.5,false);
                this.ctxtObj.stroke();
                this.ctxtObj.closePath();
                
                this.ctxtObj.translate(this.centerPoint.x, this.centerPoint.y);
                 this.ctxtObj.rotate(i*gap);
                this.ctxtObj.font = "20px bold 微软雅黑";
                this.ctxtObj.textAlign="start";
                this.ctxtObj.textBaseline="middle";
                this.ctxtObj.lineWidth = 2;
                this.ctxtObj.fillText(value + '年',eLen*1.03,0);
                this.ctxtObj.strokeText(value + '年',eLen*1.03,0);
                this.ctxtObj.restore();
            }else if(type=='M'){
                this.ctxtObj.save();
                
                this.ctxtObj.beginPath();
                    this.ctxtObj.fillStyle = "#ce9b00";
                this.ctxtObj.strokeStyle="#ce9b00";
                this.ctxtObj.lineWidth = 7;
                this.ctxtObj.arc(this.centerPoint.x,this.centerPoint.y,ceLen,ci*gap-gap*0.5,ci*gap+gap*0.5,false);
                this.ctxtObj.stroke();
                this.ctxtObj.closePath();
                
                this.ctxtObj.translate(this.centerPoint.x, this.centerPoint.y);
                 this.ctxtObj.rotate(i*gap);
                this.ctxtObj.font = "20px bold 微软雅黑";
                this.ctxtObj.textAlign="start";
                this.ctxtObj.textBaseline="middle";
                this.ctxtObj.lineWidth = 2;
                this.ctxtObj.fillText(value + '月',eLen*1.03,0);
                this.ctxtObj.strokeText(value + '月',eLen*1.03,0);
                this.ctxtObj.restore();
            }else if(type=='d'){
                this.ctxtObj.save();
                
                this.ctxtObj.beginPath();
                    this.ctxtObj.fillStyle = "#bd01bd";
                this.ctxtObj.strokeStyle="#bd01bd";
                this.ctxtObj.lineWidth = 6;
                this.ctxtObj.arc(this.centerPoint.x,this.centerPoint.y,ceLen,ci*gap-gap*0.5,ci*gap+gap*0.5,false);
                this.ctxtObj.stroke();
                this.ctxtObj.closePath();
                
                this.ctxtObj.translate(this.centerPoint.x, this.centerPoint.y);
                 this.ctxtObj.rotate(i*gap);
                this.ctxtObj.font = "20px bold 微软雅黑";
                this.ctxtObj.textAlign="start";
                this.ctxtObj.textBaseline="middle";
                this.ctxtObj.lineWidth = 2;
                this.ctxtObj.fillText(value + '日',eLen*1.03,0);
                this.ctxtObj.strokeText(value + '日',eLen*1.03,0);
                this.ctxtObj.restore();
            }
            
            this.ctxtObj.restore();
        }
        animate = function(){
            var now = (+new Date);
            if (now - this.lastFpsUpdateTime > 60) {
                this.lastFpsUpdateTime = now;
                this.doDraw();
            }
            window.requestNextAnimationFrame(this.animate);
        }
        getCountDays = function (year,month) {
            var curDate = new Date();
            curDate.setFullYear(year);
            curDate.setMonth(month+1);
            curDate.setDate(0);
            return curDate.getDate();
        }
        getTimeNow = function(){
            var date = new Date();
            var seperator1 = "-";
            var seperator2 = ":";
            this.timeNow = date.getFullYear() 
                    + seperator1 + (date.getMonth()+1+'').PadLeft(2,0)
                    + seperator1 + (date.getDate()+'').PadLeft(2,0)
                + " " + (date.getHours()+'').PadLeft(2,0)
                    + seperator2 + (date.getMinutes()+'').PadLeft(2,0)
                + seperator2 + (date.getSeconds()+'').PadLeft(2,0)
                    + '.' +(date.getMilliseconds()+'').PadLeft(3,0);
        }
        // objects
    }
    
    var cwt = new calendarWithTime();
    //=================================================
    String.prototype.PadLeft = function(totalWidth, paddingChar)
    {
     if ( paddingChar != null )
     {
      return this.PadHelper(totalWidth, paddingChar, false);
     } else {
      return this.PadHelper(totalWidth, ' ', false);
     }
    }
    String.prototype.PadRight = function(totalWidth, paddingChar)
    {
     if ( paddingChar != null )
     {
      return this.PadHelper(totalWidth, paddingChar, true);
     } else {
      return this.PadHelper(totalWidth, ' ', true);
     }
    }
    String.prototype.PadHelper = function(totalWidth, paddingChar, isRightPadded)
    {
    
     if ( this.length < totalWidth)
     {
      var paddingString = new String();
      for (i = 1; i <= (totalWidth - this.length); i++)
      {
       paddingString += paddingChar;
      }
    
      if ( isRightPadded )
      {
       return (this + paddingString);
      } else {
       return (paddingString + this);
      }
     } else {
      return this;
     }
    }

    源码下载地址:

    http://download.csdn.net/download/wangxsh42/9720724

    @wangxinsheng http://www.cnblogs.com/wangxinsheng/

  • 相关阅读:
    说一说前端路由与后端路由的区别
    HTTP 8种请求方式介绍
    JavaScript 运行机制以及Event Loop(事件循环)
    常见的数据结构
    JS中常见的几种继承方法
    JS异步编程
    js中的数据类型,以及如何检测数据类型
    js面试题之手写节流函数和防抖函数
    前端面试题
    (八) SpringBoot起飞之路-整合Shiro详细教程(MyBatis、Thymeleaf)
  • 原文地址:https://www.cnblogs.com/wangxinsheng/p/6219688.html
Copyright © 2011-2022 走看看