Средний
7 уроков
Курс
JS & canvas
В этом курсе, состоящим из 7 статей Роман Спиридонов познакомит вас с canvas.

JS&canvas 4/7 — Огораживаемся от других

Не будем мешать другим — оформляем весь код в подобие плагина, и проводим небольшую оптимизацию работы с canvas.

День 4

Давайте сегодня оптимизируем механику работы наших часов и не будем перерисовывать абсолютно всё каждую секунду. Что на часах у нас никогда не изменяется? Правильно, корпус часов, а также их циферблат, которого у нас пока нет. Соответственно, можно их сохранять перед рисованием стрелок, а потом не очищать холст, а восстанавливать картинку с корпусом и циферблатом, поверх которой уже рисовать стрелки.

Сохранить область canvas позволяет метод контекста рисования getImageData который на вход принимает координаты прямоугольника аналогично методу clearRect. Метод getImageData вернет прямоугольник, который мы должны будем сохранить в переменную, а нарисовать его затем позволит метод putImageData(). Аргументы у этого метода — переменная содержащая картинку для вставки, а также координаты х и у левого верхнего угла нового положения картинки.

Для буфера, хранящего статичные части весов создадим переменную buffer. Делать снимок циферблата и корпуса будем сразу же в инициализации, раз мы больше их изменять не будем:

В функции update мы будем сначала рисовать сохраненный корпус часов а затем стрелки в новом их положении:

Раз уж мы немного взялись за оптимизацию процесса, то давайте уберем из общего доступа весь мусор, который захламляет объект window и спрячем все внутренние переменные внутрь области видимости часов, выведя наружу только метод инициализации, а в дальнейшем и методы для задания параметров отображения часов. Для этого сделаем следущее:
создадим переменную clock, в нее присвоим анонимную функцию, в которой мы и будем работать.

Чтобы сделать метод init() доступным извне и разрешить вызов вида Myclock.init() нужно добавить следующую строку внутрь анонимной функции:

Это говорит нам, что мы в поле init объекта-функции Myclock записываем внутренний метод init, и теперь мы сможем позвать его извне. Определяя таким образом функцию Myclock мы, по сути, создаем класс с приватными и публичными методами. Все методы и переменные, которые мы не выведем изнутри с помощью объекта this остаются приватными.

Чтобы сделать этот класс самостоятельным, зададим параметр canvasId на вход метода init, который будет равен идентификатору холста, на котором мы хотим рисовать часы. Добавим также проверку на передачу такого параметра и существование холста с таким идентификатором. Функция инициализации тогда примет следующий вид:

Опишем также математику получения координат стрелок. В ней нет ничего сложного, что мы делаем? Сначала считаем угол наклона стрелки, как количество единиц времени now.getSeconds (для секунд) умноженное на угол перемещения стрелки за одну такую единицу — Math.PI / 30 (так как Math.PI — в радианах это угол в 180 градусов, или пол-окружности, соответственно в одной половине окружности у нас 30 секунд). Смещение угла на -Math.PI/2; обусловлено тем, что 0 градусов находится в самой правой точке окружности (вспоминаем первую картинку со 2 дня), а у часов ноль находится в самой верхней точке. Поэтому нужно отнять 90 градусов, чтобы ноль на циферблате был там, где и должен быть.

Вычислив угол стрелки, можно считать координаты ее кончика:

которые определяются как фукнция косинус для х координаты, и функция синус для у координаты от текущего ее угла наклона. Полученную проекцию умножаем на нужную нам длину стрелки, в данном случае это R*0.9 и прибавляем к соответствующей координате центра часов.

На сегодня все.

Код страницы day4.html

Рекомендуемые курсы