Рисование изображений на холст с помощью img.crossOrigin = "Анонимный" не работает

В автономном JS-приложении на стороне клиента я пытаюсь сделать так, чтобы я мог вызвать toDataURL() на холсте, на котором я нарисовал несколько изображений, указанных URL. Т.е. я могу ввести в текстовое поле url на любое изображение (размещенное, скажем, imgur), которое я хочу нарисовать на холсте, нажмите кнопку "нарисовать", и он будет рисовать на холсте. Конечный пользователь должен иметь возможность сохранять окончательный рендер как одно изображение, для этого я использую toDataURL().

В любом случае, пока они на самом деле не исправят эту досадную ошибку "операция небезопасна" (да, вы собираетесь рассказать конечному пользователю, что они могут и не могут сделать со своими собственными данными?) Я последовал обходному пути, который сказал добавьте изображение в DOM и установите для свойства crossOrigin значение "Anonmyous", а затем нарисуйте его на холсте.

Здесь полная работающая упрощенная версия моего кода (но на самом деле будет много других возможностей):

<!DOCTYPE html5>
<html>
<head>
<style>
#canvas {border:10px solid green;background-color:black;}
#imgbox {border:2px solid black;}
</style>
</head>
<body>
<canvas id="canvas" width=336 height=336></canvas>
<br><br>
<input size=60 id="imgbox">
<input type="submit" value="Draw" onclick=draw()>
<script>
function draw() {
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    var img = new Image();
    img.src = document.getElementById("imgbox").value;
    img.crossOrigin = "Anonymous";
    context.drawImage(img, 40, 40);
}
</script>
</body>
</html>

Без строки img.crossOrigin = "Anonymous"; я мог бы ввести http://i.imgur.com/c2wRzfD.jpg в текстовое поле и щелкнуть мышью, и это сработает. Однако, как только я добавил эту строку, все это сломалось, и ее вообще не будет тянуть к холсту.

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

Ответ 1

Вы должны установить запрос CORS перед src - просто поменяйте строки на:

img.crossOrigin = "Anonymous";
img.src = document.getElementById("imgbox").value;

Вам также нужно будет добавить обработчик onload к изображению, так как загрузка будет асинхронной:

img.onload = function() {
    context.drawImage(this, 40, 40);
    // call next step in your code here, f.ex: nextStep();
};
img.crossOrigin = "Anonymous";
img.src = document.getElementById("imgbox").value;

Ответ 2

Когда серверу требуется авторизация для доступа к изображениям, значение должно быть:

img.crossOrigin = "Use-Credentials";

В противном случае браузер откажется после приема HTTP 401.