2017-01-25 4 views
4

Я делаю интерактивную диаграмму пузырьков, и я работаю над функциональностью, чтобы разделить данные на две группы, которые перемещаются на противоположные стороны экрана. Я использую центрирующую силу для моделирования, потому что я думаю, что это дает гораздо более приятное и более последовательное отображение данных, чем использование forceX и forceY. Однако у меня возникают проблемы с разбиением моих данных.d3.js: передать анонимную функцию в качестве параметра для центрирования?

У меня возникла мысль, что, поскольку вы можете передать анонимную функцию в качестве параметра forceX, чтобы определить, перемещается ли узел влево или вправо, теоретически вы можете сделать то же самое для значения x в центрирующей силе. Мой центр силы код выглядит следующим образом:

var forceCenterSplit = d3.forceCenter(function(d) { 
      if (d[splitParameter] >= splitVal) 
       return 3*width/4; 
      else 
       return width/4; 
     }, height/2) 

Для сравнения, вот код forceX, который выполняет ту же самую вещь:

var forceXsplit = d3.forceX(function(d) { 
       if (d[splitParameter] >= splitVal) 
        return 3*width/4; 
       else 
        return width/4; 
      }).strength(.05);  

К сожалению, консоль говорит «Неожиданное значение NaN разборе ого атрибут." когда я запускаю центрирующее усилие и нажимаю все данные на cx = 0 (значение по умолчанию).

Я пропустил что-то основное здесь? Можете ли вы передать анонимную функцию в качестве параметра центрирующей силы? Если нет, есть ли лучший способ сделать это?

Спасибо!

Start state

After split

// nicer looking splitting forces that use forceCenter 
     var forceCenterCombine = d3.forceCenter(width/2, height/2); 

     var forceCenterSplit = d3.forceCenter(function(d) { 
      if (d[splitParameter] >= splitVal) 
       return 3*width/4; 
      else 
       return width/4; 
     }, height/2); 

     // simple splitting forces that only use forceX 
     var forceXSplit = d3.forceX(function(d) { 
      if (d[splitParameter] >= splitVal) 
       return 3*width/4; 
      else 
       return width/4; 
     }).strength(.05); 

     var forceXCombine = d3.forceX(width/2).strength(.05); 

     // collision force to stop the bubbles from hitting each other 
     var forceCollide = d3.forceCollide(function(d){ 
      console.log("forceCollide"); 
      return radiusScale(d[radiusParam]) + 1; 
     }).strength(.75) 

     // This code is for the simulation that combines all the forces 
     var simulation = d3.forceSimulation() 
      .force("center", forceCenterCombine) 
      .force("collide", forceCollide) 
      .on('end', function(){console.log("Simulation ended!");}); 

     function ticked() { 
      circles 
       .attr("cx", function(d){ 
        return d.x; 
       }) 
       .attr("cy", function(d){ 
        return d.y; 
       }) 
     } 

var splitFlag = false; 

     // dynamically divide the bubbles into two (or probably more later on) groups 
     $scope.split = function() { 
      // split them apart 
      if (!splitFlag){ 
       console.log("splitForce"); 
       simulation.force("center", forceXSplit) 
        .force("y", d3.forceY(height/2).strength(.05)) 
        .alphaTarget(.25) 
        .restart(); 
       splitFlag = true; 
      } 
      // bring them back together 
      else { 
       console.log("combineForce"); 
       simulation.force("center", forceCenterCombine) 
        .alphaTarget(.25) 
        .restart(); 
       splitFlag = false; 
      } 
     }; 

enter image description here

+1

По самой природе 'd3.forceCenter', это невозможно. API говорит: * «Центрирующая сила переводит узлы равномерно, так что среднее положение ** всех узлов ** (центр массы, если все узлы имеют одинаковый вес) находится в заданной позиции ⟨x, y⟩. * * акцент мой. Таким образом, здесь нет места для функции доступа. 'forceX' и' forceY', с другой стороны, * "установите аксессуар координат на указанное число или ** функцию **" * (снова ударьте мое внимание). –

+0

А, это раздражает.Как я уже упоминал в исходном сообщении, forceX и forceY дают намного более четкое отображение, чем forceCenter - узлы, сталкивающиеся бесконечно, застревают в кластерах других узлов, не перемещаются так далеко, как они предполагают, и т. Д. Я предполагаю единственный способ, которым я мог бы иметь два разных центра масс, - это иметь разные симуляции, работающие на двух разных наборах узлов? Спасибо за ответ кстати –

+1

Но если у вас есть 2 моделирования, как бы вы использовали 'collide', чтобы избежать перекрытия узлов? Если узлы не разделены друг от друга. –

ответ

2

К сожалению, ответ, кажется, нет .

Из-за самой природы d3.forceCenter, что («передать анонимную функцию в качестве параметра«) невозможно. API, говорит:

центрирования сила переводит узлы равномерно таким образом, что среднее положение все узлы (центр масс, если все узлы имеют одинаковый вес) находится в заданном положении ⟨x, y⟩. (выделено мной)

Таким образом, здесь нет места для функции доступа. forceX и forceY, с другой стороны ...

установить координаты аксессор по указанному номеру или функций. (упор мой еще раз)

... и может подойдет вам лучше всего.

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

  • Нет связанных вопросов^_^