Я работаю над проектом, в котором мне нужно визуализировать некоторые данные, извлеченные из телешоу. Инструмент показывает данные в виде графика с принудительной ориентацией, и пользователь имеет возможность добавлять или удалять данные из определенного c эпизода.
Моя симуляция силы работает, но не для добавленных данных. Я объясняю: когда я запускаю инструмент, он фильтрует данные из эпизода 1, добавляются узлы и ссылки, но сила на них не действует, поэтому они застревают на x = 0, y = 0. Если я добавлю данные из эпизода 2, сила начнет действовать в эпизоде 1, и оно будет отображаться правильно, но не во 2 эпизоде и так далее. Таким образом, он не работает с последними добавленными данными, но хорошо работает с другими данными.
Вот код функции, которая отображает данные:
module.exports.renderView = (cont = canvas) => {
//get the datas from the correct episodes
let filteredData = getFilteredData(data);
console.log("FilteredData : ");
console.log(filteredData);
//create scales
const xScale = d3.scaleLinear()
.domain([d3.min(filteredData, d => d.Scene),d3.max(filteredData, d => d.Scene)])
.range([0,innerWidth]);
const yScale = d3.scaleBand()
.domain(stories.map(d => d.name))
.range([0,innerHeight])
.paddingInner(0.5);
const colorScale = d3.scaleOrdinal()
.domain(mainPlots)
.range(["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"]);
//show the axis
rightAxis.call(d3.axisBottom(xScale))
.attr('transform', `translate(0,${innerHeight})`);
//extract the links from the dataset
let linkarray = []
for(let i = 0; i<filteredData.length; i++){
filteredData[i].Scene_Links.forEach(e => {
if (e>=0 && filteredData.some(k => {return e==k.Scene})){
linkarray.push({source : filteredData[i].Scene, target : e});
}
});
}
//setup of the force simulation
force = d3.forceSimulation(filteredData)
.force('link', d3.forceLink()
.id(d => {return d.Scene})
.links(linkarray))
.force("charge", d3.forceManyBody());
//circles, or nodes
let circles = circles_g.selectAll('circle').data(filteredData);
circles.join('circle')
.attr('r', yScale.bandwidth)
.attr('id', d => "scene_" + d.Scene)
.attr('fill', "#A8A8A8")
.attr('fill-opacity', 0.7)
.on('mouseover', mouseOverScene)
.on("mouseout", mouseOutScene);
//when hovering a circle
function mouseOverScene(d, i) {
d3.select(this).attr('fill','orange');
evaluationSection.showInfo(d, i);
}
function mouseOutScene(d, i) {
d3.select(this).attr('fill','#A8A8A8');
}
//links
let links = links_g.selectAll('.link').data(linkarray);
links.join('line')
.attr('class', 'link')
.attr("stroke", d => {
let sharedStory;
d.source.Specific_Stories.forEach(e1 => {
sharedStory = d.target.Specific_Stories.find(e2 => e1.split("-")[0]==e2.split("-")[0]);
});
return (sharedStory==undefined) ? "#000000" : colorScale(sharedStory);
})
.attr("stroke-width", "2");
//action of the force simulation
force.on('tick', ticked);
function ticked() {
links.attr('x1',d => xScale(d.source.Scene))
.attr('x2',d => xScale(d.target.Scene))
.attr("y1", function(d) { return d.source.y; })
.attr("y2", function(d) { return d.target.y; });
circles.attr('cx', d => "" + xScale(d.Scene))
.attr('cy', d => {return d.y})
}
//additional infos to make the visualization more clear
let episodeNames = infos_g.selectAll('.name').data(episodeList.filter(d => {return d.show}));
episodeNames.join('text')
.attr('transform', d => `translate(${xScale(d.firstScene)},5)`)
.attr('class', 'name')
.text(d => 'S' + d.season + '-E' + d.episode);
let separators = infos_g.selectAll('.separator').data(episodeList.filter(d => {return d.show}).slice(1));
separators.join('line')
.attr('class', 'separator')
.attr('x1',d => xScale(d.firstScene)-xScale(xScale.domain()[0]+1)/2)
.attr('x2',d => xScale(d.firstScene)-xScale(xScale.domain()[0]+1)/2)
.attr('y1',0)
.attr('y2',innerHeight)
.attr("stroke-dasharray","5, 3")
.attr("style","stroke:rgb(0,0,0);stroke-width:2;");
}
Примечание: я использую d3 v5. Помимо силы, все работает: правильные данные извлекаются с помощью getFilteredData (), ссылки привязываются к нужным узлам, и когда сила применяется, она применяется правильно.