我在使用d3力模拟时遇到错误。在某个点之后(当添加3个主节点时),模拟会出现故障,颤抖和无限排斥。以下是视频(https://youtu.be/XJvQ4v6XPOM)d3 error的链接,以及用于模拟的我(有些混乱)代码。每个链接都有一个'source'和'target'节点对象,其值为。
///////////
d3.select('#canvas').selectAll('svg').remove();
var width = 960,
height = 700
var svg = d3.select("#canvas").append("svg")
.attr("width", width)
.attr("height", height);
var linkDistance = this.props.settings.linkDistance || 200;
var circleSize = this.props.settings.circleSize || 17;
var artistNum = this.props.settings.artistNumber || 7;
var roles = this.props.settings.roles || ['rapper', 'producer'];
var label = this.props.settings.label || 'text';
var nodes = d3.forceSimulation(this.state.allMovies)
.force("charge", d3.forceManyBody().strength(-30))
.force("link", d3.forceLink(this.state.blinks)
.distance((d) => {
return d.value > 0 ? linkDistance/(d.value*1.5) : linkDistance*1.5;
})
// .strength((d) => {
// return d.value > 0 ? d.value*2 : 1;
// })
)
.force("center", d3.forceCenter(400, 300))
// .force("gravity", d3.forceManyBody().strength(-50))
// .force("distance", d3.forceManyBody(100))
// .force('collision', d3.forceCollide().radius(function(d) {
// return 30
// }))
.force("size", d3.forceManyBody([width, height]));
var link = svg.selectAll(".link").data(this.state.blinks).enter()
.append("line")
.attr("class", (d) => `link ${d.source.title.split(' ').join('')} ${d.target.title.split(' ').join('')}`)
.attr("stroke-width", (d) => d.value*3);
$('.link').toggle();
link.on("click", (d) => {
console.log('selected link', d);
// var songsArr = this.state.songsLibrary.filter(song => {
// return d.songList.includes(song.id)
// })
//
// this.setState({
// display: 'link',
// selectedLink: d,
// songs: songsArr
// })
});
var node = svg.selectAll(".node").data(this.state.allMovies).enter()
.append("g").attr("class", "node")
.call(d3.drag()
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended)
);
function dragstarted() {
if (!d3.event.active) nodes.alphaTarget(0.3).restart();
d3.event.subject.fx = d3.event.subject.x;
d3.event.subject.fy = d3.event.subject.y;
}
function dragged() {
d3.event.subject.fx = d3.event.x;
d3.event.subject.fy = d3.event.y;
}
function dragended() {
if (!d3.event.active) nodes.alphaTarget(0);
d3.event.subject.fx = null;
d3.event.subject.fy = null;
}
// append("svg:image")
// .attr('x', -9)
// .attr('y', -12)
// .attr('width', 20)
// .attr('height', 24)
// .attr("xlink:href", "resources/images/check.png")
if (label === 'image') {
node.append("circle")
.attr("r", (d) => d.type === 'primary' ? circleSize*3 : circleSize*2)
.attr("fill", function(d) { return d.type === 'primary' ? '#241587' : '#3f88a3' })
.attr("class", (d) => `${d.title.split(' ').join('')} node`);
node.append("svg:image")
.attr('x', -circleSize*1.5)
.attr('y', -circleSize*1.5)
.attr('width', circleSize*3)
.attr('height', circleSize*3)
.attr("border-radius", '50%')
.attr("xlink:href", (d) => `${d.poster}`)
} else {
node.append("circle")
.attr("r", (d) => d.type === 'primary' ? circleSize*2.5 : circleSize*1.3)
.attr("fill", function(d) { return d.type === 'primary' ? '#241587' : '#3f88a3' })
.attr("class", (d) => `${d.title.split(' ').join('')} node`);
node.append("text")
.attr("dx", -15).attr("dy", ".70em")
.text(function(d) { return d.title })
.style("font-size", "12px")
.style("fill", (d) => d.type === 'primary' ? "#e8eaed" : "#262728")
.attr("class", (d) => `${d.title.split(' ').join('')}`)
}
node.on('click', d => {
console.log('SELECTED', d)
let movie = d.title;
var relatedLinks = this.state.blinks.filter(link => {
return link.source.name === movie || link.target.name === movie;
})
$('.link').css('display', 'none')
$(`.${movie.split(' ').join('')}.link`).toggle();
this.sendRequestForMovies(d.title, 'secondary');
this.setState({
links: relatedLinks
}, () => {
console.log('movie in state', this.state.selectedMovie)
})
});
nodes.on("tick", function() {
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 + ")"; });
});