Подтвердить что ты не робот

D3.js и document.onReady

Я только начинаю с d3.js, и есть одна деталь, которая полностью ускользает от меня: как мне выполнить мой код только после того, как DOM готов принять вход?

Я мог бы, конечно, использовать что-то вроде jQuery, но это кажется чрезмерным.

В каждый пример d3.js Я столкнулся, похоже, нет специального типа document.onReady(), но все примеры работают безотказно. Тем не менее, при тестировании кода на моем конце код полностью терпит неудачу, если он выполняется до того, как DOM готов (запрос моего кода на window.onload подтверждает это).

Что дает?

4b9b3361

Ответ 1

В своих примерах вы заметите, что их javascript находится ниже любого из элементов html, которые используются так, чтобы часть dom была загружена до того, как она начнет выполнение javascript.

Просто размещение вашего javascript в нижней части тела обычно достаточно хорошо.

Ответ 2

Иногда вы не можете полагаться на размещение DIV/HTML, например, когда вам нужно динамически вставлять элемент, управляемый D3, в документ. В таких ситуациях одно решение - отслеживать документ для событий DOMNodeInserted и вставлять код D3 в обратный вызов (я считаю, что это исключает версии IE до 9, хотя). Вот пример с jQuery:

$(document).bind('DOMNodeInserted', function(event)
{
    if (event.target.id == "viz")
    {
        var sampleSVG = d3.select("#viz")
                 .append("svg:svg")
                 .attr("width", 100)
                 .attr("height", 100);    

        sampleSVG.append("svg:circle")
                 .style("stroke", "gray")
                 .style("fill", "white")
                 .attr("r", 40)
                 .attr("cx", 50)
                 .attr("cy", 50)
                 .on("mouseover", function() {
                      d3.select(this).style("fill", "aliceblue");
                 })
                 .on("mouseout", function() {
                      d3.select(this).style("fill", "white");}
                 );
    }
});

Ответ 3

Ответ, помеченный как правильный, не работал у меня, и на самом деле он ошибочен. Это своего рода хак и не следует рассматривать как правильный ответ. Точно так же вы можете просто выполнить свой код внутри setTimeout (function() {..}, 1000). Это еще более надежно, поскольку вы можете установить задержку: -/

В моем случае мне нужно было подождать, пока все элементы будут обработаны, чтобы узнать их фактические размеры. Когда они не построены, обработаны и не выполнены, цифры были неверными.

ОБНОВЛЕНО. Вот правильный ответ:

Скорее всего, вы получаете свои данные для построения DOM, используя какой-то асинхронный вызов типа d3.json(), и поэтому это занимает некоторое время. Поскольку асинхронный вызов не блокируется, ваш последующий код вызывается еще до завершения асинхронного вызова, что вызывает проблемы, и именно по этой причине вы разместили этот вопрос.

Итак, вы пытаетесь решить это, ища что-то в D3 или где-либо еще, что скажет вам, что асинхронный вызов D3 закончен, и теперь вы можете сделать следующее. Некоторые люди предлагают сделать синхронный вызов ajax. Это ужасно НЕПРАВИЛЬНО. Асинхронные вызовы создаются для async.

Что вам действительно нужно сделать, так это изменить свою парадигму. Просто передайте обратный вызов этому асинхронному вызову и его! Что-то вроде этого:

function thingsToDoWhenDOMisBuilt() {
    ...
}

function buildDOM(rootNode, error, thingsToDoWhenDOMisBuilt) {
    ...
    // everything is built, so we can do our post-build thing against DOM
    if (thingsToDoWhenDOMisBuilt)
        thingsToDoWhenDOMisBuilt()
}

d3.json(urlToData, buildDOM) {
    if (error)
        console.log("oops")
    buildDOM(rootNode, thingsToDoWhenDOMisBuilt)
}

Кроме того, посмотрите async.js

События привязки, как было предложено выше, также являются ужасной идеей. Вместо этого вы должны использовать .enter().exit(). D3 управляется данными, если вам нужен поток, управляемый событиями, тогда просто используйте jQuery или vanilla JS!

Ответ 4

Вы можете поместить событие onload в тело и поместить весь код d3js в функцию. Например:

<body onload="yourFunctionName()">

И в вашем javascript вставьте это:

function yourFunctionName() {
    //Your d3js code goes here
}

Просто вставьте полный код примера d3 внутри этой функции. Событие onload произойдет после готовности DOM.