Следующий код имеет странную особенность:
function createSVG(){
let svgarea = document.getElementById("svgarea");
let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("id", "my_svg");
svg.setAttribute("width", "100%");
svg.setAttribute("height", "100%");
svgarea.appendChild(svg);
}
Когда я запускаю вызов из скрипта при загрузке страницы или в window.onload, скрипт не работает
"Cannot read property 'appendChild' of null"
в
svgarea.appendChild(svg);
Но он работает нормально, если я вызываю его из консоли. Есть ли обходной путь для этого? Я подозреваю, что createElementNS каким-то образом зависает, прежде чем доходит до добавления результата, но почему-то этого не происходит при вызове из консоли.
Возможно, вы вызываете let svgarea = document.getElementById("svgarea");
перед визуализацией HTML DOM. Не могли бы вы воспроизвести эту проблему на скрипке?
Я не знаю, что такое fiddle, но svgarea является частью html-файла, в котором запускается скрипт, и я вызываю его через window.onload, поэтому, по крайней мере, теоретически он должен работать. Я также пробовал использовать setTimeout с одной секундой (после загрузки окна), и все та же проблема.
Собственно, setTimeout сработал, просто я его неправильно назвал. Теперь после window.onload есть функция, которая устанавливает таймаут на 10мс, и теперь svg создает как надо
Это означает, что элемент DOM #svgarea
еще не существует, когда вы выполняете: let svgarea = document.getElementById("svgarea");
Когда вы выполняете тот же оператор из консоли, DOM уже готов.
Поэтому вы должны отложить выполнение вашей функции createSVG
:
window.addEventListener("DOMContentLoaded", createSVG);
Вы также можете использовать событие load
, но оно срабатывает позже, после загрузки всего контента.
Если вы используете window.onload =
, вы должны быть на 100% уверены, что никакой более поздний код не переопределит его. addEventListener
делает то, что говорит: добавляет дополнительных слушателей
setTimeout(createSVG);
Также помогает в тех случаях, когда События давно прошли, и вы не можете их использовать. Времени не требуется, потому что setTimeout
запустится после завершения цикла событий, поэтому любое создание DOM произойдет.
Если вы хотите создать SVG, вы также можете использовать нотацию HTML:
function createSVG(){
document
.getElementById("svgarea")
.innerHTML=`<svg xmlns='http://www.w3.org/2000/svg' id='my_svg' width='100%' height='100%'></svg>`
}
Или, поскольку innerHTML блокирует рендеринг, немедленно создает узлы DOM:
function createSVG(){
let area = document.getElementById("svgarea");
area.innerHTML=`<svg xmlns='http://www.w3.org/2000/svg' id='my_svg'></svg>`;
let svg = area.querySelector("svg");
svg.setAttribute("width","100%");
svg.setAttribute("height","100%");
}
И не забывайте, что вам, вероятно, понадобится атрибут viewBox
для этих SVG.
Когда запускается этот код? Он запускается до того, как
svgarea
существует?