Create a gist now

Instantly share code, notes, and snippets.

Embed
На основании идеи с http://www.artlebedev.ru/everything/brain/2014/03/20/
<html lang="ru">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
#canv {
border: 2px solid #eee;
margin: 20px auto;
display: block;
color: #7a93b4;
}
</style>
<script>
"use strict";
var app = {
conf: {
idCanv: 'canv', // ID Canvas
R: 240, // Радиус циферблата
hourL: 70, // Длина часовой
minL: 100, // Длина минутной
secL: 110, // Дина секундной
hourW: 4, // Толщина часовой
minW: 3, // Толщина минутной
secW: 2, // Толщина секундной
armClr: '#000', // Цвет стрелок
vectorClr: '#999', // Цвет векторов
clockClr: '#5E7490',// Цвет циферблата
numberClr: '#777', // Цвет чисел
intervalMs: 30 // Интервал отрисовки в миллисекундах
},
centerX: 0, // Центр по X
centerY: 0, // Центр по Y
canv: {}, // DOM элемент канвы
ctx: {}, // Контекст канвы
tau: 2 * Math.PI, // Константа для упрощения расчетов
/**
* Исходная точка приложения
*/
start: function () {
this.setCanvas();
this.startClock()
},
/**
* Настройка канвы для отрисовки
*/
setCanvas: function () {
this.canv = document.getElementById(this.conf.idCanv);
this.ctx = this.canv.getContext('2d');
this.centerX = this.canv.width / 2;
this.centerY = this.canv.height / 2;
},
/**
* Запуск основного цикла
*/
startClock: function () {
var self = this;
setInterval(function () {
// Очистка
self.ctx.clearRect(0, 0, self.canv.width, self.canv.height);
// Получение времени
var date = new Date(),
h = date.getHours(),
m = date.getMinutes(),
s = date.getSeconds(),
ms = date.getMilliseconds();
// Корректировка движения стрелок
s += ms / 1000;
m += s / 60;
h += m / 60;
self.drawClockface();
self.drawArms(h, m, s);
}, this.intervalMs);
},
/**
* Отрисовка циферблата
*/
drawClockface: function () {
// Окружность
this.ctx.beginPath();
this.ctx.arc(this.centerX, this.centerY, this.conf.R, 0, Math.PI * 2, true);
this.ctx.lineWidth = 4;
this.ctx.strokeStyle = this.conf.clockClr;
this.ctx.stroke();
this.ctx.closePath();
// Цифры
this.ctx.beginPath();
this.ctx.fillStyle = this.conf.numberClr;
this.ctx.font = "30pt Arial";
this.ctx.textAlign = "center";
this.ctx.textBaseline = "middle";
this.ctx.fillText("12", this.centerX, this.centerY - this.conf.R * 0.9);
this.ctx.fillText("3", this.centerX + this.conf.R * 0.9, this.centerY);
this.ctx.fillText("6", this.centerX, this.centerY + this.conf.R * 0.9);
this.ctx.fillText("9", this.centerX - this.conf.R * 0.9, this.centerY);
this.ctx.closePath();
},
/**
* Отрисовка стрелок
* @param h часы
* @param m минуты
* @param s секунды
*/
drawArms: function (h, m, s) {
/* Отрисовка стрелок */
// Часы
var hArmRadians = (this.tau * h / 12) - (this.tau / 4),
hTargetX = this.centerX + Math.cos(hArmRadians) * this.conf.hourL,
hTargetY = this.centerY + Math.sin(hArmRadians) * this.conf.hourL;
drawArm.apply(this, [hTargetX, hTargetY, this.conf.hourW]);
// Минуты
var mArmRadians = (this.tau * m / 60) - (this.tau / 4),
mTargetX = this.centerX + Math.cos(mArmRadians) * this.conf.minL,
mTargetY = this.centerY + Math.sin(mArmRadians) * this.conf.minL;
drawArm.apply(this, [mTargetX, mTargetY, this.conf.minW]);
// Секунды
var sArmRadians = (this.tau * s / 60) - (this.tau / 4),
sTargetX = this.centerX + Math.cos(sArmRadians) * this.conf.secL,
sTargetY = this.centerY + Math.sin(sArmRadians) * this.conf.secL;
drawArm.apply(this, [sTargetX, sTargetY, this.conf.secW]);
/* Отрисовка векторов */
// Вектор между часами и минутами
var hmVectorX = (hTargetX + mTargetX) - this.centerX,
hmVectorY = (hTargetY + mTargetY) - this.centerY;
drawVector.apply(this, [hTargetX, hTargetY, hmVectorX, hmVectorY, mTargetX, mTargetY]);
// Вектор между минутыми и секундами
var msVectorX = (mTargetX + sTargetX) - this.centerX,
msVectorY = (mTargetY + sTargetY) - this.centerY;
drawVector.apply(this, [mTargetX, mTargetY, msVectorX, msVectorY, sTargetX, sTargetY]);
// Вектор между часами и секундами
var hsVectorX = (hTargetX + sTargetX) - this.centerX,
hsVectorY = (hTargetY + sTargetY) - this.centerY;
drawVector.apply(this, [hTargetX, hTargetY, hsVectorX, hsVectorY, sTargetX, sTargetY]);
// Результирующий вектор
this.ctx.beginPath();
var hmsVectorX = (hTargetX + mTargetX + sTargetX) - this.centerX * 2,
hmsVectorY = (hTargetY + mTargetY + sTargetY) - this.centerY * 2;
this.ctx.moveTo(hsVectorX, hsVectorY);
this.ctx.lineTo(hmsVectorX, hmsVectorY);
this.ctx.moveTo(hmVectorX, hmVectorY);
this.ctx.lineTo(hmsVectorX, hmsVectorY);
this.ctx.moveTo(msVectorX, msVectorY);
this.ctx.lineTo(hmsVectorX, hmsVectorY);
this.ctx.lineWidth = 1;
this.ctx.strokeStyle = this.conf.vectorClr;
this.ctx.stroke();
this.ctx.closePath();
/**
* Отрисовка самой стрелки-палки.
* Использовать в контексте.
* @param x Координата X
* @param y Координата Y
* @param w Толщина линии
*/
function drawArm(x, y, w) {
this.ctx.beginPath();
this.ctx.moveTo(this.centerX, this.centerY);
this.ctx.lineTo(x, y);
this.ctx.lineWidth = w;
this.ctx.strokeStyle = this.conf.armClr;
this.ctx.stroke();
this.ctx.closePath();
}
/**
* Отрисовка векторов.
* Рисует ломаную, состоящую из 2-х векторов.
* Использовать в контексте.
* @param startX X-координата начала
* @param startY Y-координата начала
* @param line1X X-координата конца 1-го вектора, начало 2-го
* @param line1Y Y-координата конца 1-го вектора, начало 2-го
* @param line2X X-координата конца 2-го вектора
* @param line2Y Y-координата конца 2-го вектора
*/
function drawVector(startX, startY, line1X, line1Y, line2X, line2Y) {
this.ctx.beginPath();
this.ctx.moveTo(startX, startY);
this.ctx.lineTo(line1X, line1Y);
this.ctx.lineTo(line2X, line2Y);
this.ctx.lineWidth = 1;
this.ctx.strokeStyle = this.conf.vectorClr;
this.ctx.stroke();
this.ctx.closePath();
}
}
};
// Запуск приложения при загрузке страницы
window.onload = function () {
app.start();
};
</script>
</head>
<body>
<canvas width="900" height="800" id='canv'></canvas>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment