2014-01-26 2 views
1

Я новичок в D3, и это выглядит довольно круто. Я думал, что попытаюсь создать что-то, используя макет направленной силы.Заполнение дополнительных данных в D3 Направленная силовая компоновка

То, что я пытаюсь сделать

Я создаю объект JSON с помощью для цикла, чтобы добавить все мои детали, готовые к использованию на force.start(). Это прекрасно работает. Однако я хочу добавить больше данных через другой источник json. Для этого у меня есть еще один цикл внутри первого цикла, чтобы добавить больше данных на основе данных в моем первом цикле (см. Код).

Насколько я получил

Я консоли вошли, и я могу видеть, что элементы вставлены в мой объект JSON, однако они не получают правильные атрибуты для force.nodes(); см.:

group: 2 
name: "Alt-J" 
px: NaN 
py: NaN 
x: NaN 
y: NaN 

Почему это? Мне кажется, что диаграмма построена до того, как цикл закончен, и элементы правильно добавлены.

Heres мой код:

// Get the users top played artists 
d3.json("http://ws.audioscrobbler.com/2.0/?method=user.gettopartists.gettopartists&user="+ username +"&api_key=be4ff3242bdb1d653517df99df39cfe2&format=json", function(error, graph) { 
    // Loops through them and push them in nodes.names[] 
    for (var i = 0; i < graph.topartists.artist.length; i++) { 
    var item = graph.topartists.artist[i]; 
    // Then get for each top artist their respect related artists 
    d3.json("http://ws.audioscrobbler.com/2.0/?method=artist.getsimilar&artist="+ item.name +"&api_key=be4ff3242bdb1d653517df99df39cfe2&format=json", function(error, related) { 
     // Do this just for 5 item to reduce load 
     for (var i2 = 0; i2 < 5; i2++) { 
      var relatedItem = related.similarartists.artist[i2]; 
      console.log(i2); 
      // Add those to our json object like with top artists 
      nodes.names.push({ 
      "name" : relatedItem.name, 
      "group" : 2 
      }); 
      nodes.links.push({ 
      "source" : i + i2 , 
      "target" : 0 
      }); 
     } 
     console.log(nodes.names); 
    }); 

    nodes.names.push({ 
     "name" : item.name, 
     "group" : 1 
    }); 
    nodes.links.push({ 
     "source" : i, 
     "target" : 0 
    }); 
    } 
    force 
     .nodes(nodes.names) 
     .links(nodes.links) 
     .distance(20) 
     .start(); 

ответ

2

Причина этого заключается в том, что d3.json является асинхронным. То есть, обратный вызов не выполняется немедленно, но когда возвращается вызов для получения JSON. Это означает, что блок кода для инициализации и запуска макета силы выполняется до того, как вложенные вызовы d3.json возвратят и добавят данные.

Это не проблема, так как вы можете добавить новые товары в массивы, которые вы даете force.nodes() и force.links(). Проблема в том, что позиции этих новых элементов не инициализируются, и это происходит только на force.start(). Поэтому после добавления новых узлов/ссылок вам нужно снова запустить силовую схему.

Вы можете исправить это в своем коде, объявив force дальше и позвонив force.start() в конце каждого вложенного обратного вызова.

+0

Спасибо, Ларс. Я попробую скорректировать мой код в ближайшее время. Я вижу, что ваши ответы приходят на вопросы D3. Знаете ли вы хорошие онлайн-ресурсы/учебники? Cheers –

+0

Уроки, связанные с веб-сайтом D3, как правило, являются хорошим местом для начала и покрытия большого количества материала. –

Смежные вопросы