Это более или менее значок на странице, который при нажатии делает что-то, но значок на странице в настоящее время является якорем. Я могу изменить это на div (все остальные значки в моем пользовательском интерфейсе являются div), но по какой-то причине следующее не работает.

Почему первый щелчок ничего не регистрирует?

$('#a').click(save);

function save(ev) {
  $('#canvas')[0].toBlob((blob) => {
    let URLObj = window.URL || window.webkitURL;
    ev.target.href = URLObj.createObjectURL(blob)
    ev.target.download = "untitled.png";
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id='canvas'></canvas>
<a id='a'>click me to save</a>

Скрипка, чтобы увидеть поведение: https://jsfiddle.net/udbq3fb7/

3
simon 2 Янв 2018 в 04:52

2 ответа

Лучший ответ

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

$('#a').click(save);

function save(ev) {
   $('#canvas')[0].toBlob((blob) => {
        let URLObj = window.URL || window.webkitURL;
        let a = document.createElement("a");  
        a.href = URLObj.createObjectURL(blob);
        a.download = "untitled.png";
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
   });
}

Скрипка: https://jsfiddle.net/rkqkr47w/

5
simon 2 Янв 2018 в 10:25

Вот краткое описание текущей ситуации:

  1. Пользователь нажимает.
  2. Событие отправляется в документе.
  3. Обработчики событий запускаются [если есть].
  4. по умолчанию происходит щелчок [если не предотвращено в 3.].

Теперь то, что ваш код пытается сделать, - это перезаписать поведение действия click (4.) по умолчанию, изменив href вашего <a> в обработчиках событий (3.).

Этот трюк обычно работает, потому что 3. происходит до 4., но в вашем случае вы вызываете асинхронный метод в 3., и href изменяется только после того, как ваш асинхронный обратный вызов получает называется.

Итак, у вас есть
...
3. Canvas.toBlob (обратный вызов)
4. По умолчанию происходит щелчок
...
п. срабатывает обратный вызов (изменить поведение по умолчанию)

Когда вызывается ваш обратный вызов, событие клика давно не действует, и изменение его href будет иметь место только при следующем клике.


Вы можете напрямую вызвать метод <a> click внутри этого обратного вызова, но это приведет к бесконечному циклу, за исключением случаев, когда вы удалите обработчик событий и переназначите его снова, но, вероятно, было бы проще полностью создать новый элемент <a>, который вы удалите позже, и еще проще использовать библиотеку, например FileSaver.js, который делает именно это вместе с устранением некоторых причуд в старых браузерах.

$('#a').click(save);

function save(ev) {
  $('#canvas')[0].toBlob((blob) => {
    saveAs(blob, "untitled.png");
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.js"></script>
<canvas id='canvas'></canvas>
<a id='a'>click me to save</a>
1
Kaiido 2 Янв 2018 в 07:21