Узлы схемы радиальной силы занимают только четверть окружности

Я реализовал изменение макета при нажатии кнопки, чтобы оно перешло от силового макета по умолчанию к радиальному: https://jsfiddle.net/mvLf579a/278/

Кажется, все работает нормально, за исключением того, что узлы занимают только четверть круга.

Вот код обновления:

function radial() {
  simulation
    .force("charge", d3.forceCollide().radius(10))
    .force("r", d3.forceRadial(function(d) { 
      if (d.id < 5) {
        console.info('less than : ', d.id)
        return 100;
      } else {
        console.info('more than : ', d.id)
        return 300;
      } 
    }))
    .force("center", null)
    .on("tick", newTicked);
  simulation.alphaTarget(0.3).restart()

  function newTicked() {
    node
      .attr("transform", function(d) {
        return "translate(" + d.x + ", " + d.y + ")";
      });
  }
}

Вот как это заканчивается: Узлы схемы радиальной силы занимают только четверть окружности

всего через несколько секунд после публикации я обнаружил проблему, но пока не могу ее решить. Это из-за имеющейся у меня «центральной» силы. Я думал, что установка его как null удалит его. Как убрать центральную силу в радиальной функции? Спасибо

thatOneGuy 26.10.2018 09:58
Поведение ключевого слова "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) для оценки ваших знаний,...
1
1
156
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Прежде всего, передача null в форс фактически убирает его. API ясно об этом:

To remove the force with the given name, pass null as the force.

Если я правильно понимаю вашу проблему, вы можете решить ее, просто передав центры x и y радиальной силе, которая их принимает. Нравится:

.force("r", d3.forceRadial(function(d) {
    if (d.id < 5) {
        return 100;
    } else {
        return 300;
    }
}, width / 2, height / 2))

Также для лучшего эффекта установите значение strength(1) или аналогичное высокое. Наконец, используйте alpha для разогрева, а не alphaTarget.

Вот ваш код с этими изменениями (и меньшим размером SVG):

function radial() {
  simulation
    .force("charge", d3.forceCollide().radius(10))
    .force("r", d3.forceRadial(function(d) {
      //console.info(d)
      if (d.id < 5) {
        return 100;
      } else {
        return 300;
      }
      //return d.id < 5 ? 100 : 200;
    }, width / 2, height / 2).strength(1))
    .force("center", null)
    .on("tick", newTicked);
  simulation.alpha(1).restart()

  function newTicked() {
    //node
    //   .attr("cx", function(d) { return d.x; })
    //  .attr("cy", function(d) { return d.y; });
    node
      .attr("transform", function(d) {
        return "translate(" + d.x + ", " + d.y + ")";
      });
  }

}

document.getElementById("radial").addEventListener("click", radial);

var nodes = [{
    "id": 1,
    "name": "server 1"
  },
  {
    "id": 2,
    "name": "server 2"
  },
  {
    "id": 3,
    "name": "server 3"
  },
  {
    "id": 4,
    "name": "server 4"
  },
  {
    "id": 5,
    "name": "server 5"
  },
  {
    "id": 6,
    "name": "server 6"
  },
  {
    "id": 7,
    "name": "server 7"
  },
  {
    "id": 8,
    "name": "server 8"
  },
  {
    "id": 9,
    "name": "server 9"
  },
  {
    "id": 2,
    "name": "server 2"
  },
  {
    "id": 3,
    "name": "server 3"
  },
  {
    "id": 4,
    "name": "server 4"
  },
  {
    "id": 5,
    "name": "server 5"
  },
  {
    "id": 6,
    "name": "server 6"
  },
  {
    "id": 7,
    "name": "server 7"
  },
  {
    "id": 8,
    "name": "server 8"
  },
  {
    "id": 9,
    "name": "server 9"
  },
  {
    "id": 2,
    "name": "server 2"
  },
  {
    "id": 3,
    "name": "server 3"
  },
  {
    "id": 4,
    "name": "server 4"
  },
  {
    "id": 5,
    "name": "server 5"
  },
  {
    "id": 6,
    "name": "server 6"
  },
  {
    "id": 7,
    "name": "server 7"
  },
  {
    "id": 8,
    "name": "server 8"
  },
  {
    "id": 9,
    "name": "server 9"
  },
  {
    "id": 2,
    "name": "server 2"
  },
  {
    "id": 3,
    "name": "server 3"
  },
  {
    "id": 4,
    "name": "server 4"
  },
  {
    "id": 5,
    "name": "server 5"
  },
  {
    "id": 6,
    "name": "server 6"
  },
  {
    "id": 7,
    "name": "server 7"
  },
  {
    "id": 8,
    "name": "server 8"
  },
  {
    "id": 9,
    "name": "server 9"
  },
  {
    "id": 2,
    "name": "server 2"
  },
  {
    "id": 3,
    "name": "server 3"
  },
  {
    "id": 4,
    "name": "server 4"
  },
  {
    "id": 5,
    "name": "server 5"
  },
  {
    "id": 6,
    "name": "server 6"
  },
  {
    "id": 7,
    "name": "server 7"
  },
  {
    "id": 8,
    "name": "server 8"
  },
  {
    "id": 9,
    "name": "server 9"
  },
  {
    "id": 2,
    "name": "server 2"
  },
  {
    "id": 3,
    "name": "server 3"
  },
  {
    "id": 4,
    "name": "server 4"
  },
  {
    "id": 5,
    "name": "server 5"
  },
  {
    "id": 6,
    "name": "server 6"
  },
  {
    "id": 7,
    "name": "server 7"
  },
  {
    "id": 8,
    "name": "server 8"
  },
  {
    "id": 9,
    "name": "server 9"
  },
  {
    "id": 2,
    "name": "server 2"
  },
  {
    "id": 3,
    "name": "server 3"
  },
  {
    "id": 4,
    "name": "server 4"
  },
  {
    "id": 5,
    "name": "server 5"
  },
  {
    "id": 6,
    "name": "server 6"
  },
  {
    "id": 7,
    "name": "server 7"
  },
  {
    "id": 8,
    "name": "server 8"
  },
  {
    "id": 9,
    "name": "server 9"
  },
  {
    "id": 2,
    "name": "server 2"
  },
  {
    "id": 3,
    "name": "server 3"
  },
  {
    "id": 4,
    "name": "server 4"
  },
  {
    "id": 5,
    "name": "server 5"
  },
  {
    "id": 6,
    "name": "server 6"
  },
  {
    "id": 7,
    "name": "server 7"
  },
  {
    "id": 8,
    "name": "server 8"
  },
  {
    "id": 9,
    "name": "server 9"
  }
]

var links = [{
    source: 1,
    target: 2
  },
  {
    source: 1,
    target: 3
  },
  {
    source: 1,
    target: 4
  },
  {
    source: 2,
    target: 5
  },
  {
    source: 2,
    target: 6
  },
  {
    source: 3,
    target: 7
  },
  {
    source: 5,
    target: 8
  },
  {
    source: 6,
    target: 9
  },
]

var index = 10;
var svg = d3.select("svg"),
  width = +svg.attr("width"),
  height = +svg.attr("height"),
  node,
  link;

var simulation = d3.forceSimulation()
  .force("link", d3.forceLink().id(function(d) {
    return d.id;
  }))
  .force("charge", d3.forceManyBody())
  .force("center", d3.forceCenter(width / 2, height / 2));

update();

function update() {
  link = svg.selectAll(".link")
    .data(links, function(d) {
      return d.target.id;
    })

  link = link.enter()
    .append("line")
    .attr("class", "link");

  node = svg.selectAll(".node")
    .data(nodes, function(d) {
      return d.id;
    })

  node = node.enter()
    .append("g")
    .attr("class", "node")
    .on("click", click)
    .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended));

  node.append("circle")
    .attr("r", 5)

  node.append("title")
    .text(function(d) {
      return d.id;
    });


  simulation
    .nodes(nodes)
    .on("tick", ticked);

  simulation.force("link")
    .links(links);
}

function click(d) {
  nodes.push({
    id: index,
    name: "server " + index
  });
  links.push({
    source: d.id,
    target: index
  });
  index++;
  update();
}

function ticked() {
  link
    .attr("x1", function(d) {
      return d.source.x;
    })
    .attr("y1", function(d) {
      return d.source.y;
    })
    .attr("x2", function(d) {
      return d.target.x;
    })
    .attr("y2", function(d) {
      return d.target.y;
    });

  node
    .attr("transform", function(d) {
      return "translate(" + d.x + ", " + d.y + ")";
    });
}

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart()
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = undefined;
  d.fy = undefined;
}



/*
var nodes = [].concat(
  d3.range(80).map(function() { return {type: "a"}; }),
  d3.range(160).map(function() { return {type: "b"}; })
);

var node = d3.select("svg")
  .append("g")
  .selectAll("circle")
  .data(nodes)
  .enter().append("circle")
    .attr("r", 2.5)
    .attr("fill", function(d) { return d.type === "a" ? "brown" : "steelblue"; })

var simulation = d3.forceSimulation(nodes)
    .force("charge", d3.forceCollide().radius(5))
    .force("r", d3.forceRadial(function(d) { return d.type === "a" ? 100 : 200; }))
    .on("tick", ticked);

function ticked() {
  node
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });
}
*/
.link {
  stroke: #aaa;
}

.node {
  pointer-events: all;
  stroke: none;
  stroke-width: 40px;
}
<script src = "https://d3js.org/d3.v5.min.js"></script>
<button id='radial'>
 Radial
</button>
<svg width = "500" height = "400" viewBox = "-240 -125 960 500">

всегда могу положиться на тебя @ Джерардо. Спасибо еще раз

thatOneGuy 26.10.2018 10:50

прежде чем я задам другой вопрос, знаете ли вы, как я могу сделать так, чтобы некоторые узлы не находились в радиальной силе? Скажем, узлы определенного типа, я просто хочу, чтобы на них была физика силы по умолчанию, а не часть радиального вида?

thatOneGuy 26.10.2018 11:00

@thatOneGuy Даже если бы я знал, что предлагаю вам опубликовать новый вопрос: отвечать на вопросы в разделе комментариев довольно громоздко.

Gerardo Furtado 26.10.2018 11:17

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

thatOneGuy 26.10.2018 11:21

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