Увеличение и уменьшение изображения на HTML5 Canvas: Zoom к курсору
Быстрый ответ
Для того чтобы реализовать масштабирование холста с фокусом в точке, которую обозначает положение курсора, требуется изменить масштаб и «сдвинуть» контекст холста. Весь процесс можно разбить на следующие этапы:
- Смещаем контекст к месту, где расположен курсор.
- Применяем масштабирование с установленным коэффициентом.
- Совершаем обратное смещение контекста, учитывая масштабирование.
Ниже представлен пример кода на JavaScript, позволяющего выполнить описанный процесс:
function zoomAtCursor(canvas, ctx, zoomFactor, cursorX, cursorY) {
// Рассчитываем размеры холста
var rect = canvas.getBoundingClientRect();
// Вычисляем смещение точки масштабирования
var offsetX = (cursorX – rect.left) * (1 – zoomFactor);
var offsetY = (cursorY – rect.top) * (1 – zoomFactor);
// Применяем комбинацию функций смещения и масштабирования
ctx.translate(offsetX, offsetY);
ctx.scale(zoomFactor, zoomFactor);
ctx.translate(-offsetX, -offsetY);
// Контекст подготовлен для рисования.
}
Для того чтобы осуществляла масштабирование с фокусом на курсоре, следует вызвать функцию zoomAtCursor
и передать ей коэффициент масштабирования и координаты курсора.
Важные нюансы
Обработка событий мыши и касаний
При реализации масштабирования наперёд учтём различные варианты взаимодействия пользователей с системой:
- Клик мыши для увеличения относительного размера.
- Shift + Клик для уменьшения относительного размера.
- Перемещение мыши с зажатой кнопкой для плавного перемещения изображения.
- Одновременное касание двумя пальцами для масштабирования на touch-устройствах.
Матричные преобразования и вопрос производительности
В процессе масштабирования рекомендуется использовать функцию ctx.setTransform
, которая поможет избежать накопления трансформаций, повысив тем самым производительность. После каждого масштабирования следует сбросить трансформации:
ctx.setTransform(1, 0, 0, 1, 0, 0); // Сброс к исходному состоянию
Очистка холста
Необходимо очищать холст перед каждым процессом отрисовки, чтобы старые кадры не воздействовали на новые:
ctx.clearRect(0, 0, canvas.width, canvas.height); // Стереть все содержимое
Использование сторонних библиотек и внешних функций
Библиотеки, такие как Loupe, CanvasZoom или Scroller, могут существенно облегчить вашу работу, выполняя сложные вычисления за вас, в частности, инверсию матриц.
Плавное масштабирование
Для реализации плавного масштабирования используем функцию requestAnimationFrame
. Это особенно актуально для устройств с ограниченной производительностью:
function animateZoom(canvas, ctx, targetZoom, cursorX, cursorY, steps) {
var currentStep = 0;
(function step() {
if (currentStep < steps) {
var zoomFactor = 1 + (targetZoom – 1) * currentStep / steps;
zoomAtCursor(canvas, ctx, zoomFactor, cursorX, cursorY);
currentStep++;
requestAnimationFrame(step); // Повторяем действие
}
})();
}
Визуализация
Представьте себя астронавтом в поисках новых планет. Ваш телескоп фокусирует изображение одной из планет, которая постепенно монополизирует ваше поле зрения, оказываясь в его центре.
До масштабирования: [👨🚀🔭🌌🪐] (Вы обнаружили некую планету)
После масштабирования: [👨🚀🔭🪐🌌] (Теперь планета в центре вашего внимания)
Процесс масштабирования холста можно сравнить с работой телескопа, где курсор мыши выступает в роли точки сведения.
Перед масштабированием: [🖼️🐁🌌🌠] (Курсор указывает на звезду)
После масштабирования: [🌌🌠🐁🌌] (Звезда остаётся под курсором независимо от масштаба)
Такой подход позволяет сохранить концентрацию внимания на определённом объекте в процессе масштабирования.
Полезные материалы
- API HTML-холста – Веб-API | MDN — подробное руководство MDN по API холста.
- Получение точного положения мыши на холсте – Stack Overflow — обсуждение подходов к определению положения курсора на холсте.
- Coding Dude: Ресурс о веб-разработке, JavaScript, HTML, CSS, SEO — собрание информации о матрицах аффинных преобразований, актуальных для масштабирования.
- GitHub – anvaka/panzoom: Библиотека панорамирования и масштабирования – библиотека, эффективная для задач масштабирования веб-элементов.
- Пример на CodePen – демонстрация масштабирования холста с учетом положения курсора.