Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Можно ли загрузить в img.src содержимое JS переменной синхронно? (https://javascript.ru/forum/dom-window/82649-mozhno-li-zagruzit-v-img-src-soderzhimoe-js-peremennojj-sinkhronno.html)

Was-Ja 06.06.2021 16:01

Можно ли загрузить в img.src содержимое JS переменной синхронно?
 
Добрый день,

имею конструкцию, в которой мне надобно загрузить одну и ту же картинку в несколько канвасов (все скрыты display:none;), потом с ними сделать некоторые преобразования, а потом показывать по одному в зависимости от обстоятельств.

Важный момент, сама картинка лежит в переменной JS.

Сейчас я делаю так:
function ID(id) { return document.getElementById(id); }

// ...

  let ctx_0 = ID("MainInitFrame_0").getContext("2d");
  let img_0 = new Image();

  img_0.src=MainInitFrame_Data;
  ctx_0.drawImage(img_0, 0, 0);

  let ip_0 = ctx_0.getImageData(0, 0, X_Size, Y_Size).data;


но, содержимое ip_0 не всегда содержит картинку.

Попробовал через onload - тоже не получилось...

Полный пример лежит по адресу https://www.elegant-nmr.com/tst/l.html

Скажите, пожалуйста, есть ли способ синхронной загрузки картинки из переменной

img_0.src=MainInitFrame_Data;

Спасибо!

Aetae 06.06.2021 18:10

Есть один deprecated способ, но я вам его не скажу.)
Потому что он подвесит страницу на всё время загрузки картинки, что может занять от секунды до минут и более на медленном соединении.

Изучайте асинхронность в javascript, без этого вы всё равно никуда не уедите.

Was-Ja 06.06.2021 18:32

Спасибо большое, Aetae, что помогаете!

Переписал через onload, все равно не помогает. По ссылке выше уже обновленная версия.

То есть сейчас я делаю:

var MainInitFrame_Img;

...


MainInitFrame_Img = new Image();
MainInitFrame_Img.onload=MainInitFrame_Init2();
MainInitFrame_Img.src=MainInitFrame_Data;


а в MainInitFrame_Init2 уже пытаюсь использовать MainInitFrame_Img:

let ctx_0 = ID("MainInitFrame_0").getContext("2d");
ctx_0.drawImage(MainInitFrame_Img, 0, 0);

let ip_0 = ctx_0.getImageData(0, 0, X_Size, Y_Size).data;


и все равно не стабильно работает... Если вызвать два раза

MainInitFrame_Img.src=MainInitFrame_Data;

один перед onload, другой раз внутри onload то более-менее всегда работает, но ведь так не должно быть!!!

Этот пример по ссылке выше, там добавление-удаление второго копирования в 95-ой строчке.

Цитата:

Потому что он подвесит страницу на всё время загрузки картинки, что может занять от секунды до минут и более на медленном соединении.
У меня же нет соединения! На момент, когда мне это нужно, сама картинка уже находится в локальной переменной в JS!!!

Was-Ja 06.06.2021 18:34

То есть резюмируя, я предполагаю, что мне надо onload на какую-то другую опцию перевести, когда картинка уже отрисовалась, но я не знаю как такая опция называется и вопрошаю, посоветуйте, мне ее, пожалуйста!

Aetae 06.06.2021 19:21

MainInitFrame_Img.onload=MainInitFrame_Init2(); -> MainInitFrame_Img.onload=MainInitFrame_Init2;

() - это вызов функции вот прям тут. Вы хотите не вызвать функцию, а передать её, чтоб при событии load она была вызвана.

Was-Ja 06.06.2021 21:05

Спасибо большое, Aetae,

ой, как же я лажанулся... Все выходные с этой проблемой разбирался и такой тривиальный баг не заметил, а все от того, что в С/С++ это была бы ошибка приведения типа, а тут в синтаксисе языка разрешено и я на это не обратил внимания. А из-за того, что картинка была локально сохранена в JS переменной я долго был уверен, что с onload и без вести себя программа должна одинаково, поэтому всячески искал проблему на не асинхронном варианте.

Все заработало! Спасибо большое, что помогли найти мою глупейшую ошибку!!!

Alexandroppolus 10.06.2021 10:14

Цитата:

Сообщение от Was-Ja
а тут в синтаксисе языка разрешено и я на это не обратил внимания.

используй TS (лучше всего - строгий), все ошибки будут на лету подсвечиваться в IDE

Was-Ja 10.06.2021 10:42

Спасибо, Alexandroppolus за совет!

Цитата:

Сообщение от Alexandroppolus (Сообщение 537861)
используй TS (лучше всего - строгий), все ошибки будут на лету подсвечиваться в IDE

интересно, а в Vim это можно как-то сделать? У меня просто веб интерфейс сильно завязан на backend на С++ и я все это одновременно разрабатываю, а в Vim по крайней мере легко подсвечивать синтаксис JSON структур, которые я между фронт и бек эндами гоняю. То есть у меня есть такие самописные headers, которые в зависимости от того, куда я их вставляю, или в С++ ставляются, или парсятся и в JS вставляются. Бекенд на g++ со вставками на CUDA и строго под линукс.


Часовой пояс GMT +3, время: 07:49.