Javascript, создающий элемент SVG с помощью createElementNS, иногда возвращает значение null

Следующий код имеет странную особенность:

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 каким-то образом зависает, прежде чем доходит до добавления результата, но почему-то этого не происходит при вызове из консоли.

Когда запускается этот код? Он запускается до того, как svgarea существует?

evolutionxbox 17.12.2020 13:02

Возможно, вы вызываете let svgarea = document.getElementById("svgarea"); перед визуализацией HTML DOM. Не могли бы вы воспроизвести эту проблему на скрипке?

Nikhil Patil 17.12.2020 13:06

Я не знаю, что такое fiddle, но svgarea является частью html-файла, в котором запускается скрипт, и я вызываю его через window.onload, поэтому, по крайней мере, теоретически он должен работать. Я также пробовал использовать setTimeout с одной секундой (после загрузки окна), и все та же проблема.

Nyxeria 17.12.2020 13:27

Собственно, setTimeout сработал, просто я его неправильно назвал. Теперь после window.onload есть функция, которая устанавливает таймаут на 10мс, и теперь svg создает как надо

Nyxeria 17.12.2020 13:34
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
4
158
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это означает, что элемент 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.

Другие вопросы по теме