Использование изображений из другого источника на холсте
HTML предоставляет атрибут crossorigin для изображений, который в сочетании с соответствующим заголовком CORS позволяет использовать изображения, заданные элементом <img> и загруженные из внешних источников, в элементе <canvas> так, как если бы они были загружены с текущего источника.
Подробнее об использовании атрибута crossorigin см. в разделе Атрибуты настроек CORS.
Безопасность и загрязнённые холсты
Поскольку пиксели растрового изображения на холсте могут поступать из самых разных источников, включая изображения и видео, полученные с других хостов, неизбежно могут возникнуть проблемы с безопасностью.
Как только на холст добавляются какие-либо данные, загруженные из другого источника без разрешения CORS, холст становится загрязнённым. Загрязнённый холст больше не считается безопасным, и любая попытка получить из него данные изображения приведёт к возникновению исключения.
Если источником внешнего содержимого является HTML-элемент <img> или SVG-элемент <svg>, попытка получить содержимое холста запрещена.
Если внешнее содержимое поступает из изображения, полученного либо как HTMLCanvasElement, либо как ImageBitMap, и источник изображения не соответствует правилам единого источника, попытки прочитать содержимое холста блокируются.
Вызов любого из следующих методов для загрязнённого холста приведёт к ошибке:
- Вызов
getImageData()у контекста холста - Вызов
toBlob(),toDataURL()илиcaptureStream()непосредственно у элемента<canvas>
Попытка выполнить любое из этих действий с загрязнённым холстом приведёт к возникновению SecurityError. Это защищает пользователей от раскрытия личных данных при использовании изображений для получения информации с удалённых веб-сайтов без разрешения.
Сохранение изображения из внешнего источника
В этом примере мы хотим разрешить получать изображения из внешнего источника и сохранять их в локальном хранилище. Для этого необходимо настроить сервер, а также написать код для самого веб-сайта.
Настройка веб-сервера
Для начала нам понадобится сервер, настроенный для размещения изображений с заголовком Access-Control-Allow-Origin, который разрешает междоменные запросы к файлам изображений.
Предположим, что наш сайт обслуживается с помощью Apache. Рассмотрим файл конфигурации сервера Apache для изображений CORS из HTML5 Boilerplate, доступный по ссылке конфигурация сервера Apache для изображений CORS и приведённый ниже:
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
<FilesMatch "\.(avifs?|bmp|cur|gif|ico|jpe?g|jxl|a?png|svgz?|webp)$">
SetEnvIf Origin ":" IS_CORS
Header set Access-Control-Allow-Origin "*" env=IS_CORS
</FilesMatch>
</IfModule>
</IfModule>
Вкратце, эта конфигурация разрешает получать графические файлы (с расширениями ".bmp", ".cur", ".gif", ".ico", ".jpg", ".jpeg", ".png", ".svg", ".svgz" и ".webp") из любого места в интернете.
Реализация функции сохранения
Теперь, когда сервер настроен для получения изображений из внешних источников, мы можем написать код, который позволит пользователю сохранять их в локальное хранилище, как если бы они обслуживались с того же домена, на котором запущен код.
Главное — использовать атрибут crossorigin, задав crossOrigin для элемента HTMLImageElement, в который будет загружено изображение. Это указывает браузеру запросить доступ из другого источника при загрузке данных изображения.
Начало загрузки
Код, запускающий загрузку (например, при нажатии пользователем кнопки «Загрузить»), выглядит так:
function startDownload() {
let imageURL = "https://mdn.github.io/shared-assets/images/examples/mdn.svg";
let imageDescription = "Logo of a dinosaur in front of a map";
downloadedImg = new Image();
downloadedImg.crossOrigin = "anonymous";
downloadedImg.addEventListener("load", imageReceived);
downloadedImg.alt = imageDescription;
downloadedImg.src = imageURL;
}
Здесь мы используем жёстко заданный URL (imageURL) и связанное с ним описание (imageDescription), но их можно получить откуда угодно. Чтобы начать загрузку изображения, мы создаём новый объект HTMLImageElement с помощью конструктора Image(). Затем для изображения разрешается загрузка из другого источника: атрибуту crossOrigin присваивается значение "anonymous" (то есть разрешается загрузка изображения из другого источника без аутентификации). Для события load, возникающего у элемента изображения, добавляется обработчик. Это событие означает, что данные изображения получены. Также изображению задаётся альтернативный текст; хотя <canvas> не поддерживает атрибут alt, это значение можно использовать для задания aria-label или внутреннего содержимого холста.
Наконец, атрибуту src изображения присваивается URL загружаемого изображения, что запускает загрузку.
Получение и сохранение изображения
Код обработки только что загруженного изображения находится в методе imageReceived():
function imageReceived() {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
canvas.width = downloadedImg.width;
canvas.height = downloadedImg.height;
canvas.innerText = downloadedImg.alt;
context.drawImage(downloadedImg, 0, 0);
imageBox.appendChild(canvas);
try {
localStorage.setItem("saved-image-example", canvas.toDataURL("image/png"));
} catch (err) {
console.error(`Error: ${err}`);
}
}
Для обработки события "load" элемента HTMLImageElement, получающего загруженное изображение, вызывается imageReceived(). Это событие возникает, когда все загруженные данные становятся доступны. Сначала создаётся новый элемент <canvas>, который мы будем использовать для преобразования изображения в URL данных, а также получается доступ к контексту двумерного рисования холста (CanvasRenderingContext2D) в переменной context.
Размер холста подгоняется под полученное изображение, внутренний текст задаётся равным описанию изображения, после чего изображение рисуется на холсте с помощью drawImage(). Затем холст добавляется в документ, чтобы изображение стало видимым.
Теперь можно сохранить изображение локально. Для этого мы используем механизм локального хранилища из Web Storage API, доступный через глобальный объект localStorage. Метод холста toDataURL() преобразует изображение в URL данных формата data://, представляющий изображение PNG. Затем это значение сохраняется в локальном хранилище с помощью setItem().
См. также
- Использование изображений из других доменов в WebGL и Chrome 13
- Спецификация HTML — атрибут
crossorigin - Web Storage API
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/HTML/How_to/CORS_enabled_image