Годовой круг со стрелкой на JavaScript
Мне кажется симпатичной идея визуализировать не примитивно отдельную неделю, а целый год как круг времени, по которому движется стрелка, показывающая текущий день.
В этом скрипте мне нужно было сделать следующее:
- создать элемент
div
, у которого фоном наложена картинка с годовым кругом. Центрировать картинку можно с помощью стилевого указания, её фон вне круга прозрачен; - при первом вызове функции
yearCycle
создать канву и разместить её вdiv
; - написать функцию (
img.onload
) для вывода рисунка.png
(или.gif
) с прозрачным фоном, размещённого в центре канвы и повёрнутого относительно этого центра на нужный угол (желательно, чтобы расчёт не зависел от размеров рисунка); также есть код для проведения линии из центра канвы под нужным углом (закомментирован в листинге); - рассчитать угол поворота рисунка со стрелкой, исходя из номера текущего дня в году и общего количества дней в нём;
- вывести немного ниже центра канвы текущую дату в текстовом виде;
- обеспечить вызов основной функции один раз в час для обновления информации.
Углы считаются как на циферблате аналоговых часов со стрелками - то есть, по часовой стрелке и угол, равный нулю градусов (и 360 градусам) находится вверху в положении цифры "12".
Ниже показан скрипт в работе и полный исходник на момент написания.
Возможно, вам придётся поменять пути к картинкам url(back.gif)
и img.src = 'arrow.png';
(см. в исходнике).
Предполагается, что исходник будет добавлен к файлу типа .html
в кодировке Юникода utf-8, но это не обязательно.
Скрипт в работе:

фоновая картинка скрипта back.gif для указания в стиле раздела div

стрелка с прозрачным фоном arrow.png для указания в операторе img.src = '...'
<div id="clockDiv" style="margin: 0 auto; text-align: center; background: url(back.gif) center no-repeat;"> </div> <script> function yearCycle (id,createCanvas) { let container = document.getElementById (id); let canvas; if (createCanvas) { //В первый раз создать канву canvas = document.createElement('canvas'); canvas.id = id + '_canvas'; container.appendChild (canvas); } else canvas = document.getElementById (id + '_canvas'); //Затем получать id готовой let ctx = canvas.getContext('2d'); let w = canvas.width = 450; let h = canvas.height = 450; //Размеры канвы - по фоновой картинке контейнера let cx = w/2, cy=h/2; //Центр канвы //Нарисовать белую окружность по центру канвы: let radius = 74; ctx.beginPath(); ctx.fillStyle='#fff'; ctx.arc(cx, cy, radius, 0, Math.PI * 2, true); ctx.fill(); let toRadians = function (degree,addition) { return (degree + addition) * Math.PI / 180.0; } //Рассчитать угол поворота стрелки: function numberOfDay() { //Номер дня в текущем году let now = new Date(); let start = new Date(now.getFullYear(), 0, 0); let diff = now - start; let oneDay = 1000 * 60 * 60 * 24; let day = Math.floor(diff / oneDay); return day; } function numberOfDays() { //Количество дней в текущем году let now = new Date(); let year = now.getFullYear(); return (year%4==0) && (year%100!=0) || (year%400==0) ? 366 : 365; } let num = numberOfDay(); let nums = numberOfDays(); let degree = num * 360 / nums; //Угол пока задан в градусах /* //Так можно нарисовать линию с тем же углом (блок закомментирован): ctx.beginPath(); ctx.moveTo (cx, cy); ctx.strokeStyle = '#07f'; let radians = toRadians(degree,-90); let x1 = cx + radius * Math.cos(radians); let y1 = cy + radius * Math.sin(radians); ctx.lineTo(x1,y1); ctx.stroke(); */ //Вместо этого нарисуем "прицел" ctx.strokeStyle = '#ccc'; ctx.setLineDash([2,5]); ctx.beginPath(); for (let deg=0; deg<=360; deg+=90) { let rad = toRadians(deg,-90); let x1 = cx + radius * Math.cos(rad); let y1 = cy + radius * Math.sin(rad); ctx.moveTo (cx,cy); ctx.lineTo (x1,y1); } ctx.stroke(); //Вывести рисунок-стрелку с поворотом на угол degree градусов относительно центра канвы: let img = new Image(); img.src = 'arrow.png'; img.onload = function() { let cache = this; //кэшируем копию рисунка let iw = cache.width; let ih = cache.height; //не будем зависеть от размеров рисунка при расчёте координат ctx.save(); ctx.translate(cx ,cy); ctx.rotate(toRadians(degree,0)); ctx.translate(-(w/2), -(h/2)); ctx.drawImage(img, w/2 - iw/2, h/2 - ih/2, iw, ih); ctx.restore(); } //Вывести дату: function strDate() { //дата в формате "Четверг, 31 декабря 2020, день 366" let dt = new Date(); let monthes = [ 'января','февраля','марта','апреля','мая','июня', 'июля','августа','сентября','октября','ноября','декабря' ]; let weekdays = ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота']; return weekdays[dt.getDay()]+', '+dt.getDate()+' '+ monthes[dt.getMonth()]+' '+dt.getFullYear()+', день '+numberOfDay(); } ctx.fillStyle='#111'; let fontSize = 14; //размер шрифта в пикселях ctx.font = fontSize+"px sans-serif"; ctx.textAlign = "center"; ctx.textBaseline="middle"; ctx.fillText(strDate(),cx,cy+fontSize); } window.addEventListener ('load', function (e) { yearCycle ('clockDiv',true); setInterval (yearCycle, 1000*60*60, 'clockDiv', false); //Вызываем раз в час }); </script> <noscript> <div style="margin: 0 auto; text-align: center;"> Включите в браузере JavaScript для работы приложения! </div> </noscript>
26.02.2020, 22:31 [1988 просмотров]