学者玩玩Canvas-写个简单的模拟时钟

最近在看HTML5,随便玩玩Canvas,因而想着写个简单的模拟时钟,不过想象力不够丰富,没啥好创意,作的比较丑~~ 哈哈javascript

Demon点这儿你懂得 哈哈html

代码:java

/************************************************************************
*************************************************************************
case Name :           clock - jQuery Plugin
case Revison :        1.0
case Date :         2014-4-02
case Author:        zy_ding@ctrip.com
case Support:        FF, IE9, IE10, Chrome, Others(unknown)
case License :        N/A
*************************************************************************/
(function ($) {
    $.fn.clock = function (opt) {
        var defaults = {
            radius: 200,
            ctX: 500,
            ctY: 300,
            speed: 1000 / 60,
            plummetLength: 160
        }
        var options = $.extend(defaults, opt);
        var colors = ['#000', '#104070', '#184F73', '#285F83', '#306090', '#386F93', '#4070A0', '#487FA3', '#5080B0', '#588FB3', '#6090C0', '#689FC3', '#70A0D0', '#78AFD3'];
        var $this = this;
        var time = new Date();
        var milSeconds = time.getMilliseconds();
        var second = time.getSeconds();
        var minute = time.getMinutes();
        var hour = time.getHours() % 12;
        var increase = 1;
        var lastPosition = 30;
        var lastAngle = 155;
        var c = $this[0];
        var cxt = c.getContext("2d");
        var initDraw = function () {
            setInterval(beginDraw, options.speed);
        }
        var beginDraw = function () {
            time = new Date();
            milSeconds = time.getMilliseconds();
            second = time.getSeconds();
            minute = time.getMinutes();
            hour = time.getHours() % 12;
            //清理画布
            cxt.clearRect(0, 0, $this.attr("width"), $this.attr("height"));
            //画表盘
            drawPanel();
            drawMonth();
            //画耳朵
            drawEars();
            //画秒针
            drawSecondPoint();
            //画分针
            drawMinutePoint();
            //画时针
            drawHourPoint();
            //画眼睛
            drawEyes(cxt);
            //画钟摆
            drawPlummet();
        }
        var drawPanel = function () {
            //外盘面
            cxt.beginPath();
            cxt.strokeStyleStyle = colors[3];
            cxt.fillStyle = "#fff";
            cxt.lineWidth = 10;
            cxt.arc(options.ctX, options.ctY, options.radius, 0, Math.PI * 2, true);
            cxt.fill();
            cxt.stroke();
            //中间盘面
            cxt.beginPath();
            cxt.lineWidth = 1;
            cxt.arc(options.ctX, options.ctY, options.radius - 20, 0, Math.PI * 2, true);
            cxt.fillStyle = colors[13];
            cxt.fill();
            cxt.stroke();
            //圆点
            cxt.beginPath();
            cxt.arc(options.ctX, options.ctY, 20, 0, Math.PI * 2, true);
            cxt.fillStyle = colors[3];
            cxt.fill();
            cxt.stroke();
            //刻度
            cxt.beginPath();
            cxt.strokeStyle = colors[3];
            cxt.stroke();
            for (var i = 0; i < 60; i++) {
                cxt.beginPath();
                var x1 = options.ctX + (options.radius * Math.sin((i * 6 / 180) * Math.PI));
                var y1 = options.ctY - (options.radius * Math.cos((i * 6 / 180) * Math.PI));
                var x2;
                var y2;
                if (i % 5 != 0) {
                    x2 = options.ctX + ((options.radius - 10) * Math.sin((i * 6 / 180) * Math.PI));
                    y2 = options.ctY - ((options.radius - 10) * Math.cos((i * 6 / 180) * Math.PI));
                }
                else {
                    x2 = options.ctX + ((options.radius - 30) * Math.sin((i * 6 / 180) * Math.PI));
                    y2 = options.ctY - ((options.radius - 30) * Math.cos((i * 6 / 180) * Math.PI));
                }
                if (i % 15 == 0) {
                    cxt.beginPath();
                    cxt.fillStyle = colors[11];
                    cxt.arc(x1, y1, 8, 0, Math.PI * 2, true);
                    cxt.fill();
                }
                else {
                    cxt.moveTo(x1, y1);
                    cxt.lineTo(x2, y2);
                    cxt.stroke();
                }
            }
        }
        var drawEars = function () {
            cxt.strokeStyle = colors[11];
            cxt.fillStyle = colors[11];
            var r = 30;
            cxt.beginPath();
            cxt.arc(options.ctX + options.radius * (Math.sin(45 / 180 * Math.PI)) + r, options.ctY - options.radius * (Math.cos(45 / 180 * Math.PI)) - r, r, 0, Math.PI * 2, true);
            cxt.fill();
            cxt.stroke();
            cxt.beginPath();
            cxt.arc(options.ctX - options.radius * (Math.sin(45 / 180 * Math.PI)) - r, options.ctY - options.radius * (Math.cos(45 / 180 * Math.PI)) - r, r, 0, Math.PI * 2, true);
            cxt.fill();
            cxt.stroke();

        }
        var drawMonth = function () {
            cxt.strokeStyle = colors[3];
            cxt.fillStyle = colors[6];
            var r = 80;
            cxt.beginPath();
            cxt.arc(options.ctX, options.ctY + r / 2, r, Math.PI / 4, Math.PI * 3 / 4, false);
            cxt.fill();
            cxt.stroke();
        }
        var drawSecondPoint = function () {

            for (var i = 0; i < 14; i++) {
                cxt.beginPath();
                cxt.strokeStyle = colors[i];
                var x = options.ctX + ((options.radius - 40) * Math.sin((second * 6 / 180 - i / 360 + milSeconds * 6 / 180000) * Math.PI));
                var y = options.ctY - ((options.radius - 40) * Math.cos((second * 6 / 180 - i / 360 + milSeconds * 6 / 180000) * Math.PI));
                cxt.moveTo(options.ctX, options.ctY);
                cxt.lineTo(x, y);
                cxt.stroke();
            }
        }
        var drawMinutePoint = function () {
            for (var i = 0; i < 10; i++) {
                cxt.beginPath();
                cxt.strokeStyle = colors[i];
                var x = options.ctX + ((options.radius - 80) * Math.sin((minute * 6 / 180 - i / 360 + (second / 1800)) * Math.PI));
                var y = options.ctY - ((options.radius - 80) * Math.cos((minute * 6 / 180 - i / 360 + (second / 1800)) * Math.PI));
                cxt.moveTo(options.ctX, options.ctY);
                cxt.lineTo(x, y);
                cxt.stroke();
            }
        }
        var drawHourPoint = function () {
            for (var i = 0; i < 6; i++) {
                cxt.beginPath();
                cxt.strokeStyle = colors[i];
                var x = options.ctX + ((options.radius - 120) * Math.sin((hour * 30 / 180 - i / 360 + minute / 360) * Math.PI));
                var y = options.ctY - ((options.radius - 120) * Math.cos((hour * 30 / 180 - i / 360 + minute / 360) * Math.PI));
                cxt.moveTo(options.ctX, options.ctY);
                cxt.lineTo(x, y);
                cxt.stroke();
            }
        }
        var drawEyes = function () {
            cxt.beginPath();
            if (lastPosition + increase > 80) {
                increase = -1;
            } else if (lastPosition + increase < 30) {
                increase = 1;
            }
            lastPosition += increase;
            cxt.arc(options.ctX - lastPosition, options.ctY - 80, 20, 0, Math.PI * 2, true);
            cxt.arc(options.ctX + lastPosition, options.ctY - 80, 20, 0, Math.PI * 2, true);
            cxt.fillStyle = colors[11];
            cxt.fill();
        }
        var drawPlummet = function () {
            if (lastAngle + increase > 205) {
                increase = -1;
            } else if (lastAngle + increase < 155) {
                increase = 1;
            }
            lastAngle += increase;
            cxt.beginPath();
            cxt.strokeStyle = colors[11];
            cxt.fillStyle = colors[11];
            cxt.moveTo(options.ctX, options.ctY + options.radius);
            cxt.lineTo(options.ctX + Math.sin(lastAngle / 180 * Math.PI) * options.plummetLength, options.ctY + options.radius - Math.cos(lastAngle / 180 * Math.PI) * options.plummetLength);
            cxt.stroke();
            cxt.beginPath();
            cxt.arc(options.ctX + Math.sin(lastAngle / 180 * Math.PI) * options.plummetLength, options.ctY + options.radius - Math.cos(lastAngle / 180 * Math.PI) * options.plummetLength, 30, 0, Math.PI * 2, true);
            cxt.fill();
            cxt.stroke();
        }
        return this.each(function () {
            initDraw();
        });
    };
}
)(jQuery);
View Code

使用:jquery

<!DOCTYPE html">
<html>
<head>
    <title></title>
    <style> #myCanvas { border: 1px solid #c3c3c3; background-color:#ddd;
    }
    </style>
</head>
<body>
    <canvas width="1400" height="800" id="myCanvas">
Your browser does not support the canvas element.
</canvas>
<script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
<script src="jquery.clock.js" type="text/javascript"></script>
<script type="text/javascript"> $(document).ready(function() { $('#myCanvas').clock(); }); </script>
</body>
</html>
View Code

 

超简单,因此思路就很少写了~~canvas

每次刷新都是全幅重画的,本人比较懒~app

有些固定位置的部位(如耳朵,嘴巴)为了不每次重绘都要从新计算位置,用circular对象保存ide

//用于保存各个部位信息,不用每次重绘都从新计算
    var circular = function (x, y, r, sAngle, eAngle, counterclockwise) {
        this.x = x;
        this.y = y;
        this.r = r;
        this.sAngle = sAngle;
        this.eAngle = eAngle;
        this.counterclockwise = counterclockwise;
    }
View Code

为CanvasRenderingContext2D添加方法arc2 使其支持本身建的circular对象,这样在每次画圆的时候就不用写那么一大串了~this

//为CanvasRenderingContext2D添加方法arc2 使其支持circular对象
    CanvasRenderingContext2D.prototype.arc2 = function (circular) {
        this.arc(circular.x, circular.y, circular.r, circular.sAngle, circular.eAngle, circular.counterclockwise);
    }
View Code

添加拖拽(耳朵,嘴巴)spa

var circulars = [];
        var activePart;
        var isActive = false;
        var xDistance;
        var yDistance;
        //鼠标按下位置
        $this.mousedown(function (e) {
            var x = e.clientX;
            var y = e.clientY;
            cxt.beginPath();
            $.each(circulars, function (index, circular) {
                if (circular) {
                    cxt.arc2(circular)
                    if (cxt.isPointInPath(x, y)) {
                        activePart = circular;
                        xDistance = x - circular.x;
                        yDistance = y - circular.y;
                        isActive = true;
                        return false;
                    }
                }
            })

        });
        //鼠标弹起位置
        $this.mouseup(function (e) {
            var x = e.clientX;
            var y = e.clientY;
            if (activePart && isActive) {
                activePart.x = x - xDistance;
                activePart.y = y - yDistance;
                isActive = false;
            }
        });
View Code

应该有许多不合理的地方,好比指针想实现那种“幻影”的效果,可是没找到好的方法,就一个循环画了14条渐变线条~~ 比较挫~prototype

for (var i = 0; i < 14; i++) {
                cxt.beginPath();
                cxt.strokeStyle = colors[i];
                var x = options.ctX + ((options.radius - 40) * Math.sin((second * 6 / 180 - i / 360 + milSeconds * 6 / 180000) * Math.PI));
                var y = options.ctY - ((options.radius - 40) * Math.cos((second * 6 / 180 - i / 360 + milSeconds * 6 / 180000) * Math.PI));
                cxt.moveTo(options.ctX, options.ctY);
                cxt.lineTo(x, y);
                cxt.stroke();
            }
View Code

嘴巴就是一个小半圆~~

var drawMonth = function () {
            cxt.strokeStyle = colors[3];
            cxt.fillStyle = colors[6];
            var r = 80;
            cxt.beginPath();
            if (!circulars[2]) {
                circulars[2] = new circular(options.ctX, options.ctY + r / 2, r, Math.PI / 4, Math.PI * 3 / 4, false);
            }
            cxt.arc2(circulars[2]);
            cxt.fill();
            cxt.stroke();
        }
View Code

 

耳朵,鼻子,钟摆。。。都是圆形 o(╯□╰)o~

var drawEars = function () {
            cxt.strokeStyle = colors[11];
            cxt.fillStyle = colors[11];
            var r = 30;
            cxt.beginPath();
            if (!circulars[1]) {
                circulars[1] = new circular(options.ctX + options.radius * (Math.sin(45 / 180 * Math.PI)) + r, options.ctY - options.radius * (Math.cos(45 / 180 * Math.PI)) - r, r, 0, Math.PI * 2, true);
            }
            cxt.arc2(circulars[1]);
            cxt.fill();
            cxt.stroke();
            cxt.beginPath();
            if (!circulars[0]) {
                circulars[0] = new circular(options.ctX - options.radius * (Math.sin(45 / 180 * Math.PI)) - r, options.ctY - options.radius * (Math.cos(45 / 180 * Math.PI)) - r, r, 0, Math.PI * 2, true);
            }
            cxt.arc2(circulars[0]);
            cxt.fill();
            cxt.stroke();
        }
View Code

 

钟摆和眼睛是随刷新平率作往返运动的,位置和时间无关~~  这个大概不合适 不过懒得改~

var drawPlummet = function () {
            if (lastAngle + increase > 205) {
                increase = -1;
            } else if (lastAngle + increase < 155) {
                increase = 1;
            }
            lastAngle += increase;
            cxt.beginPath();
            cxt.strokeStyle = colors[11];
            cxt.fillStyle = colors[11];
            cxt.moveTo(options.ctX, options.ctY + options.radius);
            cxt.lineTo(options.ctX + Math.sin(lastAngle / 180 * Math.PI) * options.plummetLength, options.ctY + options.radius - Math.cos(lastAngle / 180 * Math.PI) * options.plummetLength);
            cxt.stroke();
            cxt.beginPath();
            cxt.arc(options.ctX + Math.sin(lastAngle / 180 * Math.PI) * options.plummetLength, options.ctY + options.radius - Math.cos(lastAngle / 180 * Math.PI) * options.plummetLength, 30, 0, Math.PI * 2, true);
            cxt.fill();
            cxt.stroke();
        }
View Code

 

求喷 求教育 求鄙视 就是无聊~