Выразительный JavaScript (Хавербеке) - страница 209

Но здесь мы опять сталкиваемся с деталями реализации песочницы в браузере. Когда картинка грузится с URL с другого домена, если ответ сервера не содержит заголовок, разрешающий использование ресурса с других доменов (см. главу 17), холст будет содержать информацию, которая будет видна пользователю, но не видна скрипту.

Мы могли запросить картинку с приватной информацией (график изменений банковского счёта). Если бы скрипт мог получить к ней доступ, он мог бы шпионить за пользователем.

Для предотвращения таких утечек информации, когда картинка, невидимая скрипту, будет загружена на холст, браузеры пометят его как «испорчен». Пиксельные данные, включая URL с данными, нельзя будет получить с «испорченного» холста. На него можно писать, но с него нельзя читать.

Поэтому нам нужна обработка >try/catch в функции >update для ссылки сохранения. Когда холст «портится», вызов >toDataURL выбросит исключение, являющееся экземпляром >SecurityError. В этом случае мы перенаправляем ссылку на ещё один вид URL с протоколом javascript:. Такие ссылки просто выполняют скрипт, стоящий после двоеточия, и наша ссылка покажет предупреждение, сообщающее о проблеме.

Загрузка картинок

Последние два элемента управления используются для загрузки картинок с локального диска и с URL. Нам потребуется вспомогательная функция, которая пробует загрузить картинку с URL и заменить ею содержимое холста.

>function loadImageURL(cx, url) {

>  var image = document.createElement("img");

>  image.addEventListener("load", function() {

>    var color = cx.fillStyle, size = cx.lineWidth;

>    cx.canvas.width = image.width;

>    cx.canvas.height = image.height;

>    cx.drawImage(image, 0, 0);

>    cx.fillStyle = color;

>    cx.strokeStyle = color;

>    cx.lineWidth = size;

>  });

>  image.src = url;

>}

Нам надо поменять размер холста, чтобы он соответствовал картинке. Почему-то при смене размера холста его контекст забывает все настройки (>fillStyle и >lineWidth), в связи с чем функция сохраняет их и загружает обратно после обновления размера холста.

Элемент управления для загрузки локального файла использует технику >FileReader из главы 18. Кроме используемого здесь метода >readAsText у таких объектов есть метод под названием >readAsDataURL – а это то, что нам нужно. Мы загружаем файл, который пользователь выбирает, как URL с данными, и передаём его в >loadImageURL для вывода на холст.

>controls.openFile = function(cx) {

>  var input = elt("input", {type: "file"});

>  input.addEventListener("change", function() {

>    if (input.files.length == 0) return;