Как сделать гравитационную компоновку d3.js прямоугольной?

В силовом макете d3.js задание значения силы тяжести делает макет круглым.

введите описание изображения здесь Однако я бы хотел, чтобы силовой макет был прямоугольным, а узлы имели отрицательный заряд и равное расстояние. (как выше)

Есть ли способ сделать макет силы прямоугольным?

Могу ли я добиться этого, изменив функцию тика?

Вот мой код:

var background = d3.select('.background');

var width = background.node().getBoundingClientRect().width,
	height = background.node().getBoundingClientRect().height;

var nodes = d3.range(50).map(function(d, i) {
		return {
      		text: "Hello"
		};
	});

var messages = background.selectAll('.message')
	.data(nodes)
	.enter()
		.append('div')
		.attr('class', 'message')
		.text(d => d.text)
		.each(function(d, i) {
			d.width = this.getBoundingClientRect().width;
			d.height = this.getBoundingClientRect().height;
		});

var force = d3.layout.force()
	.gravity(1/88)
	.charge(-50)
	.nodes(nodes)
	.size([width, height]);

messages.call(force.drag);

force.on('tick', function(e) {
	messages.each(d => {
		d.x = Math.max(0, Math.min(width - d.width, d.x));
		d.y = Math.max(0, Math.min(height - d.height, d.y));
	});
	
	messages.style('left', d => `${d.x}px`)
		.style('top', d => `${d.y}px`);
});

force.start();
body {
  padding: 0;
  margin: 0;
}
.background {
  width: 100%;
  height: 100vh;
  border: 1px solid #007aff;
}
.message {
  display: inline-block;
  font-family: sans-serif;
  border-radius: 100vh;
  color: white;
  padding: 10px;
  background-color: #007aff;
  position: absolute;
}
.boundary {
  display: inline-block;
  width: 10px;
  height: 10px;
  background-color: red;
  position: absolute;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<body>
  <div class="background">
  </div>
</body>


person Stleamist    schedule 20.08.2017    source источник
comment
Да, есть. Да, это связано с изменением функции тика. Однако никто здесь не будет писать код только для того, чтобы показать, как это делается (в смысле, не буду), а ответ без кода в данном случае не имеет смысла. Поэтому опубликуйте свой код для создания силы с функцией тика, так что нам просто нужно его изменить.   -  person Gerardo Furtado    schedule 20.08.2017
comment
@GerardoFurtado О, понятно. Я с тобой согласен. Я обновил свой пост своим кодом! Спасибо.   -  person Stleamist    schedule 20.08.2017


Ответы (1)


Хорошо, отредактируйте 3: в d3v4 forceCollide может может использоваться для установки минимальных расстояний между узлами, если вы затем используете положительную силу, это сближает узлы, помогая установить их на равном расстоянии друг от друга (хотя это выглядит лучше для кругов, чем для прямоугольников):

var force = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-10))
.force("collide", d3.forceCollide(30).strength(1).iterations(1))
.force('x', d3.forceX(width/2).strength(0.5))
.force('y', d3.forceY(height/2).strength(10));

Предполагая, что узлы находятся в прямоугольном SVG, ограничение их в пределах центра SVG может помочь выровнять края:

position.nodes(nodes).on('tick', function ticks() {
        nodes.attr("cx", function(d) {
            return d.x = Math.max(20, Math.min(width + 20, d.x))
        }).attr("cy", function(d) {
            return d.y = Math.max(20, Math.min(height + 20, d.y));
        })
    });

и игра с силой силы может помочь нарисовать их вдоль оси Y:

var position = d3.forceSimulation(nodes).force("charge", d3.forceManyBody())
.force('x', d3.forceX(width/2).strength(1))
.force('y', d3.forceY(height/2).strength(5));

играйте здесь.

Кажется, что в версии 4 силы гораздо более настраиваемые, чем в версии 3, я думаю, что forceCollide интегрировал в библиотеку некоторые обходные пути. Итак, вы можете попытаться найти обходной путь v3 или, возможно, изучить возможность обновления до v4.

В версии 3 я играл с гравитацией, зарядом и ограничением x и y, чтобы немного лучше поддерживать узлы в поле, поиграйте здесь. Но я недостаточно знаю о версии 3, чтобы улучшить ее намного больше.

person Oliver Houston    schedule 20.08.2017
comment
Спасибо! Я должен был проверить d3.js v4. Методы «forceX/Y» очень полезны для меня. - person Stleamist; 22.08.2017