Пример создания часов на Canvas. Снова я “подсмотрел” пример из зарубежного источника.
И снова мне захотелось его разобрать “по косточкам”. Поэтому на оригинальность не претендую (к моему сожалению).
HTML-разметка
Для HTML-разметки создаем элемент canvas:
Затем в JavaScript-скрипте “достаем” элемент canvas и динамически задаем для него размеры 500 x 500 (мне нравится задавать их динамически):
Время - работа с ним
Создаем новый экземпляр объекта Date для того, чтобы получить текущее время:
Затем из полученного объекта получаем значения времени - часов, минут, секунд и миллисекунд:
В дополнение к этому, получим также текущую дату с учетом local time и locale, в удобном для чтения человеком формате - метод toDateString:
… и точно также - локальное время (метод toLocaleTimeString):
Часы, минуты, секунды
В canvas создаем круговую индикацию часов, минут и секунд.
Делает это будем при помощи canvas-метода arc():
В приведенном выше коде остановимся на некоторых моментах.
Первый момент - метод arc() принимает аргументы для угловых значений в радианах. Для человека этот формат непривычен, так как мы пользуемся градусами.
Поэтому для удобства создадим функцию degreeToRadian, которая преобразовывает градусы в радианы.
Второй момент - начальный угол (точка отсчета) по стандарту canvas (я не ошибся?) - это 0. Это соответствует трем часам (15:00) на часовом циферблате.
Конечно, нас это не устраивает, поэтому смешаем начальную точку на 270 градусов (по часовой стрелке) так, чтобы эта точка находилась в положении 12 часов (12:00) - degreeToRadian(270).
Второй аргумент - конечный угол - будет принимать значение угла динамически, из объекта now:
Из полученного значения нам необходимо вычесть 90 градусов потому, что хоть начальную точку мы и сместили на 270 градусов, отсчет продолжает вестись из начальной точки 0 (которая на 15:00). Почему так происходит, я так и не понял - но код работает.
Результирующее значение умножаем на 15 или 6 для кратности - эти величины взяты чисто эмпирически. В итоге получится красивые и “смотрибельные” окружности\стрелки.
Последний момент - сделаем для всего этого “дела” обертку-функцию renderTime и “запихнем” ее в тайминговую функцию setInterval, с частотой выполнения 40 миллисекунд.
Таким образом мы оформим анимацию отрисовки окружностей\стрелок и наши часы станут настоящими (почти) часами.
Пора взглянуть по получившийся результат, ибо иначе теряется “связь с реальностью”. Готовый код можно посмотреть здесь - JavaScript Canvas Clock - Start.
Небольшое примечание - для большей наглядности примера в код были добавлены толщина линий (lineWidth), цвет линий (strokeStyle), скругление концов линий (lineCap), а также фоновая заливка (fillStyle, fillRect) всего canvas:
И еще один момент - нужно обратить внимание на новую строку:
Что она делает? Она просто получает текущее значение миллисекунд, дробит это значение на еще меньшее значение ( miliSeconds / 1000 ) и прибавляет полученный результат к значению секунд (now.getSeconds).
Зачем это делается? С одной лишь целью - сделать отрисовку секундной окружности более плавной; иначе шаг прибавления будет слишком большим и резким - получится некрасиво.
В результате код для отрисовки секундной окружности будет таким:
Часы - дата и время
Для большей красоты и информативности можно продублировать дату и время, которые можно вывести в виде текста. В этом случае нужно воспользоваться методом fillText, а также воспользоваться методом font для настройки отображения шрифта:
Не забудем спозиционировать текст так, чтобы он нормально смотрелся и посмотрим на полученный результат - JavaScript Canvas Clock - Date and Time.
Добавляем градиент
Пример с часами можно существенно украсить, заменив простую фоновую заливку цветом на градиентную заливку.
В canvas существует два типа градиента - линейный и радиальный. В данном случае будет применяться радиальный градиент.
Градиенты в canvas добавляются совсем не так, как в CSS. Здесь это объект, у которого есть свой метод addColorStop(); создается градиент при помощи функции-конструктора createLinearGradient(x,y,x1,y1) или createRadialGradient(x,y,r,x1,y1,r1).
Изменим код для создания фоновой заливки из предыдущего примера таким образом:
Здесь цвет, идущий (позиция 0) из центра радиального градиента - это:
… а цвет, на котором радиальный градиент останавливается (позиция 1), это:
Не забываем изменить строку clock.fillStyle = ‘#000’; на строку clock.fillStyle = gradient; и посмотрим на готовый результат - JavaScript Canvas Clock - Radial Gradient.
В коде выше были использованы еще два метода canvas для создания тени - shadowBlur (размытие тени) и shadowColor (цвет тени). Так результат смотрится лучше.
canvas в image
Напоследок можно воспользоваться методом canvas под названием toDataURL. Этот метод может брать текущий отрисованный canvas и конвертировать его в картинку (в формате data URI).
Эту картинку можно использовать как угодно, но в том числе - вставлять на HTML-страницу. Этот подход можно применить и заменить картинкой canvas.
В результате canvas будет генерировать картинку с частотой 40 миллисекунд и с такой же частотой вставлять ее на страницу. А canvas убрать. Визуально подмены не будет заметно.
Можно проверить, правда ли на странице картинка, а не canvas. Элементарно - правый клик мыши на изображении и смотрим - в контекстном меню есть пункт “Save image as…”. Будь на этом месте canvas, такого “фокуса” бы не получилось.
Делается это в угоду браузеров, которые не понимают canvas. Правда, такой способ “подвешивает” браузер со страшной силой (по крайней мере, так дело обстоит у меня). Оно и понятно (если я не ошибаюсь) - попробуйте рисовать каждые 40 миллисекунд новую картинку )
Ниже - код:
Тут стоит заметить один важный момент - метод toDataURL() относится к canvas, но не к ‘2d’-контексту canvas’а.
Смотрим окончательный готовый результат (слегка измененный) - JavaScript Canvas Clock - Image.
P.S.
Тут вышла заминка - даже CodePen с трудом справляется с такой задачей (но если подождать, то можно увидеть).
Поэтому продублировал результат простой картинкой на странице, чтобы можно было видеть, как должно получиться:
На этом все.