我試圖在拖動特定節點時模糊/降低非相關鏈接的不透明度。所以它只需要在拖動時突出顯示相關的鏈接和節點,并模糊那些與被拖動節點無關的鏈接和節點。如果它在拖動功能之外,它就可以作業,但是當我把它放在里面時它并不一致。它只是隨機閃爍。它是否需要在拖動中發生?
const link = vis.selectAll("line")
.data(data.links)
.join("line")
.attr("stroke", 'grey')
.attr("fill", "red")
.attr("opacity", 0.2)
const drag = (simulation) => {
const dragstarted = (event) => {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}
const dragged = (event) => {
event.subject.fx = event.x;
event.subject.fy = event.y;
node.on("mouseover", function(d) {
let thisNode = this.id;
console.log("?? ~ file: index.html ~ line 99 ~ node.on ~ thisNode", thisNode)
console.log("?? ~ file: index.html ~ line 106 ~ node.on ~ d", d)
link.attr("opacity", function(d) {
return (d.source.id == thisNode || d.target.id == thisNode) ? 1 : 0.2
});
});
// Set the stroke width back to normal when mouse leaves the node.
node.on('mouseout', function(d) {
link.attr('opacity', 0.2);
});
}
const dragended = (event) => {
if (!event.active) {simulation.alphaTarget(0)};
event.subject.fx = null;
event.subject.fy = null;
}
return d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
}
const node = vis.selectAll(".node")
.data(data.nodes)
.join("path")
.attr("class", "node")
.attr("d", d3.symbol().type(d3.symbolPlus).size(300))
.attr("id", d => d.id)
.attr("r", 10)
.attr("stroke", 'red')
.style("fill", "none")
.call(drag(simulation));
simulation.on("tick", () => {
text.attr("transform", (d) => {
return "translate(" (d.x 20) "," (d.y 5) ")";
});
node.attr("transform", (d) => {
return "translate(" d.x "," d.y ")";
});
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y)
})
let data ={"nodes":[{"id":"piquetures hp","group":"big"},{"id":"postcards hp","group":"big"},{"id":"instagram hp","group":"big"},{"id":"tumblr hp","group":"big"},{"id":"soundcloud","group":"big"},{"id":"pq about","group":"mid"},{"id":"pq playlists","group":"mid"},{"id":"pq videos","group":"mid"},{"id":"pq channels","group":"mid"},{"id":"pc about","group":"mid"},{"id":"pc videos","group":"mid"},{"id":"pc playlists","group":"mid"},{"id":"pc channels","group":"mid"},{"id":"tb about","group":"mid"},{"id":"passion project playlist","group":"less mid"},{"id":"other playlists","group":"less mid"},{"id":"old videos","group":"less mid"},{"id":"nz snacks","group":"low"},{"id":"macbook pro","group":"low"},{"id":"asia trip","group":"low"},{"id":"AoT","group":"low"},{"id":"names.","group":"low"},{"id":"vade","group":"low"},{"id":"nyc","group":"low"},{"id":"meet me","group":"low"},{"id":"doubleD","group":"low"},{"id":"nice day!","group":"low"},{"id":"k-pop","group":"low"},{"id":"4 lives","group":"low"},{"id":"adventure awaits","group":"low"},{"id":"jill vid","group":"low"},{"id":"chatty cny","group":"low"},{"id":"fan art","group":"low"},{"id":"bts","group":"low"},{"id":"ig xposts","group":"low"},{"id":"reblogged content","group":"low"},{"id":"fitness stories","group":"low"},{"id":"campaigns","group":"low"},{"id":"other channels","group":"less mid"},{"id":"online art portfolio","group":"less mid"},{"id":"angela","group":"low"}],"links":[{"source":"piquetures hp","target":"instagram hp","do I have to click to see":"","context":""},{"source":"instagram hp","target":"piquetures hp","do I have to click to see":"","context":""},{"source":"tumblr hp","target":"tb about","do I have to click to see":1,"context":"sidebar"},{"source":"tb about","target":"tumblr hp","do I have to click to see":"","context":""},{"source":"postcards hp","target":"piquetures hp","do I have to click to see":"","context":"we put it there"},{"source":"piquetures hp","target":"passion project playlist","do I have to click to see":"","context":"we put it there"},{"source":"passion project playlist","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"piquetures hp","target":"pq about","do I have to click to see":"","context":"youtube given"},{"source":"pq about","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"piquetures hp","target":"pq playlists","do I have to click to see":"","context":"youtube given"},{"source":"pq playlists","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"piquetures hp","target":"pq videos","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"piquetures hp","target":"pq channels","do I have to click to see":"","context":"youtube given"},{"source":"pq channels","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"piquetures hp","target":"AoT","do I have to click to see":"","context":"we put it there"},{"source":"piquetures hp","target":"names.","do I have to click to see":"","context":"we put it there"},{"source":"piquetures hp","target":"doubleD","do I have to click to see":"","context":"we put it there"},{"source":"piquetures hp","target":"meet me","do I have to click to see":"","context":"we put it there"},{"source":"piquetures hp","target":"other channels","do I have to click to see":"","context":"we put it there"},{"source":"piquetures hp","target":"asia trip","do I have to click to see":"","context":"we put it there"},{"source":"piquetures hp","target":"other playlists","do I have to click to see":"","context":"we put it there"},{"source":"AoT","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"AoT","target":"vade","do I have to click to see":1,"context":"within text"},{"source":"AoT","target":"names.","do I have to click to see":1,"context":"within text"},{"source":"AoT","target":"passion project playlist","do I have to click to see":1,"context":"within text"},{"source":"AoT","target":"bts","do I have to click to see":1,"context":"within text"},{"source":"AoT","target":"soundcloud","do I have to click to see":1,"context":"within text"},{"source":"AoT","target":"instagram hp","do I have to click to see":1,"context":"within text"},{"source":"AoT","target":"postcards hp","do I have to click to see":1,"context":"within text"},{"source":"AoT","target":"tumblr hp","do I have to click to see":1,"context":"within text"},{"source":"names.","target":"postcards hp","do I have to click to see":1,"context":"within text"},{"source":"names.","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"names.","target":"passion project playlist","do I have to click to see":1,"context":"within text"},{"source":"names.","target":"soundcloud","do I have to click to see":1,"context":"within text"},{"source":"names.","target":"instagram hp","do I have to click to see":1,"context":"within text"},{"source":"names.","target":"tumblr hp","do I have to click to see":1,"context":"within text"},{"source":"doubleD","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"doubleD","target":"meet me","do I have to click to see":1,"context":"within text"},{"source":"doubleD","target":"soundcloud","do I have to click to see":1,"context":"within text"},{"source":"doubleD","target":"instagram hp","do I have to click to see":1,"context":"within text"},{"source":"doubleD","target":"tumblr hp","do I have to click to see":1,"context":"within text"},{"source":"doubleD","target":"passion project playlist","do I have to click to see":1,"context":"within text"},{"source":"doubleD","target":"k-pop","do I have to click to see":2,"context":"end of video"},{"source":"doubleD","target":"piquetures hp","do I have to click to see":2,"context":"end of video"},{"source":"meet me","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"meet me","target":"instagram hp","do I have to click to see":1,"context":"within text"},{"source":"meet me","target":"soundcloud","do I have to click to see":1,"context":"within text"},{"source":"meet me","target":"AoT","do I have to click to see":2,"context":"end of video"},{"source":"meet me","target":"piquetures hp","do I have to click to see":2,"context":"end of video"},{"source":"4 lives","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"4 lives","target":"other channels","do I have to click to see":1,"context":"within text"},{"source":"4 lives","target":"instagram hp","do I have to click to see":1,"context":"within text"},{"source":"4 lives","target":"soundcloud","do I have to click to see":1,"context":"within text"},{"source":"4 lives","target":"online art portfolio","do I have to click to see":1,"context":"within text"},{"source":"4 lives","target":"old videos","do I have to click to see":1,"context":"within text"},{"source":"4 lives","target":"asia trip","do I have to click to see":1,"context":"within text"},{"source":"vade","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"vade","target":"angela","do I have to click to see":1,"context":"within text"},{"source":"vade","target":"instagram hp","do I have to click to see":1,"context":"within text"},{"source":"vade","target":"online art portfolio","do I have to click to see":1,"context":"within text"},{"source":"nyc","target":"other channels","do I have to click to see":1,"context":"within text"},{"source":"nyc","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"nyc","target":"instagram hp","do I have to click to see":1,"context":"within text"},{"source":"nyc","target":"soundcloud","do I have to click to see":1,"context":"within text"},{"source":"nice day!","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"nice day!","target":"other channels","do I have to click to see":1,"context":"within text"},{"source":"k-pop","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"adventure awaits","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"adventure awaits","target":"other channels","do I have to click to see":1,"context":"within text"},{"source":"piquetures hp","target":"4 lives","do I have to click to see":1,"context":"within embedded playlist"},{"source":"piquetures hp","target":"vade","do I have to click to see":1,"context":"within embedded playlist"},{"source":"piquetures hp","target":"nyc","do I have to click to see":1,"context":"within embedded playlist"},{"source":"piquetures hp","target":"nice day!","do I have to click to see":1,"context":"within embedded playlist"},{"source":"piquetures hp","target":"k-pop","do I have to click to see":1,"context":"within embedded playlist"},{"source":"piquetures hp","target":"adventure awaits","do I have to click to see":1,"context":"within embedded playlist"},{"source":"pq videos","target":"old videos","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"nz snacks","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"macbook pro","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"asia trip","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"AoT","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"names.","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"vade","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"nyc","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"meet me","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"doubleD","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"nice day!","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"k-pop","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"4 lives","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"adventure awaits","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"instagram hp","do I have to click to see":"","context":"at top"},{"source":"pq videos","target":"pq playlists","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"pq channels","do I have to click to see":"","context":"youtube given"},{"source":"pq videos","target":"pq about","do I have to click to see":"","context":"youtube given"},{"source":"pq playlists","target":"other playlists","do I have to click to see":"","context":"we put it there"},{"source":"pq playlists","target":"passion project playlist","do I have to click to see":"","context":"we put it there"},{"source":"pq playlists","target":"pq videos","do I have to click to see":"","context":"youtube given"},{"source":"pq playlists","target":"pq channels","do I have to click to see":"","context":"youtube given"},{"source":"pq playlists","target":"pq about","do I have to click to see":"","context":"youtube given"},{"source":"pq playlists","target":"asia trip","do I have to click to see":"","context":"we put it there"},{"source":"pq channels","target":"pq videos","do I have to click to see":"","context":"youtube given"},{"source":"pq channels","target":"pq playlists","do I have to click to see":"","context":"youtube given"},{"source":"pq channels","target":"pq about","do I have to click to see":"","context":"youtube given"},{"source":"pq channels","target":"other channels","do I have to click to see":"","context":"we put it there"},{"source":"pq about","target":"pq videos","do I have to click to see":"","context":"youtube given"},{"source":"pq about","target":"pq playlists","do I have to click to see":"","context":"youtube given"},{"source":"pq about","target":"pq channels","do I have to click to see":"","context":"youtube given"},{"source":"pq about","target":"instagram hp","do I have to click to see":"","context":"we put it there"},{"source":"pq about","target":"postcards hp","do I have to click to see":"","context":"we put it there"},{"source":"pq about","target":"instagram hp","do I have to click to see":"","context":"at top"},{"source":"pq channels","target":"instagram hp","do I have to click to see":"","context":"at top"},{"source":"pq playlists","target":"instagram hp","do I have to click to see":"","context":"at top"},{"source":"postcards hp","target":"jill vid","do I have to click to see":"","context":"we put it there"},{"source":"postcards hp","target":"chatty cny","do I have to click to see":"","context":"we put it there"},{"source":"postcards hp","target":"pc about","do I have to click to see":"","context":"youtube given"},{"source":"postcards hp","target":"pc videos","do I have to click to see":"","context":"youtube given"},{"source":"postcards hp","target":"pc playlists","do I have to click to see":"","context":"youtube given"},{"source":"postcards hp","target":"pc channels","do I have to click to see":"","context":"youtube given"},{"source":"pc videos","target":"pc about","do I have to click to see":"","context":"youtube given"},{"source":"pc videos","target":"pc playlists","do I have to click to see":"","context":"youtube given"},{"source":"pc videos","target":"pc channels","do I have to click to see":"","context":"youtube given"},{"source":"pc videos","target":"jill vid","do I have to click to see":"","context":"youtube given"},{"source":"pc videos","target":"chatty cny","do I have to click to see":"","context":"youtube given"},{"source":"pc videos","target":"piquetures hp","do I have to click to see":"","context":"at top"},{"source":"pc playlists","target":"pc about","do I have to click to see":"","context":"youtube given"},{"source":"pc playlists","target":"pc videos","do I have to click to see":"","context":"youtube given"},{"source":"pc playlists","target":"pc channels","do I have to click to see":"","context":"youtube given"},{"source":"pc playlists","target":"piquetures hp","do I have to click to see":"","context":"at top"},{"source":"pc channels","target":"piquetures hp","do I have to click to see":"","context":"we put it there"},{"source":"pc channels","target":"pc about","do I have to click to see":"","context":"youtube given"},{"source":"pc channels","target":"pc videos","do I have to click to see":"","context":"youtube given"},{"source":"pc channels","target":"pc playlists","do I have to click to see":"","context":"youtube given"},{"source":"pc channels","target":"piquetures hp","do I have to click to see":"","context":"at top"},{"source":"pc about","target":"pc channels","do I have to click to see":"","context":"youtube given"},{"source":"pc about","target":"pc videos","do I have to click to see":"","context":"youtube given"},{"source":"pc about","target":"pc playlists","do I have to click to see":"","context":"youtube given"},{"source":"pc about","target":"piquetures hp","do I have to click to see":"","context":"at top"},{"source":"pc about","target":"piquetures hp","do I have to click to see":"","context":"we put it there"},{"source":"pc about","target":"instagram hp","do I have to click to see":"","context":"we put it there"},{"source":"pc about","target":"piquetures hp","do I have to click to see":"","context":"we put it there"},{"source":"jill vid","target":"piquetures hp","do I have to click to see":1,"context":"within text"},{"source":"jill vid","target":"instagram hp","do I have to click to see":1,"context":"within text"},{"source":"jill vid","target":"tumblr hp","do I have to click to see":1,"context":"within text"},{"source":"jill vid","target":"soundcloud","do I have to click to see":1,"context":"within text"},{"source":"chatty cny","target":"piquetures hp","do I have to click to see":1,"context":"within text"},{"source":"chatty cny","target":"instagram hp","do I have to click to see":1,"context":"within text"},{"source":"chatty cny","target":"soundcloud","do I have to click to see":1,"context":"within text"},{"source":"chatty cny","target":"names.","do I have to click to see":2,"context":"end of video"},{"source":"chatty cny","target":"piquetures hp","do I have to click to see":2,"context":"end of video"},{"source":"passion project playlist","target":"AoT","do I have to click to see":"","context":"youtube given"},{"source":"passion project playlist","target":"names.","do I have to click to see":"","context":"youtube given"},{"source":"passion project playlist","target":"doubleD","do I have to click to see":"","context":"youtube given"},{"source":"passion project playlist","target":"meet me","do I have to click to see":"","context":"youtube given"},{"source":"passion project playlist","target":"4 lives","do I have to click to see":"","context":"youtube given"},{"source":"passion project playlist","target":"vade","do I have to click to see":"","context":"youtube given"},{"source":"passion project playlist","target":"nyc","do I have to click to see":"","context":"youtube given"},{"source":"passion project playlist","target":"nice day!","do I have to click to see":"","context":"youtube given"},{"source":"passion project playlist","target":"k-pop","do I have to click to see":"","context":"youtube given"},{"source":"passion project playlist","target":"adventure awaits","do I have to click to see":"","context":"youtube given"},{"source":"passion project playlist","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"asia trip","target":"piquetures hp","do I have to click to see":"","context":"youtube given"},{"source":"instagram hp","target":"piquetures hp","do I have to click to see":"","context":"we put it there"},{"source":"campaigns","target":"instagram hp","do I have to click to see":"","context":"instagram given"},{"source":"tumblr hp","target":"fan art","do I have to click to see":"","context":"we put it there"},{"source":"tumblr hp","target":"bts","do I have to click to see":"","context":"we put it there"},{"source":"tumblr hp","target":"ig xposts","do I have to click to see":"","context":"we put it there"},{"source":"tumblr hp","target":"reblogged content","do I have to click to see":"","context":"we put it there"},{"source":"bts","target":"jill vid","do I have to click to see":"","context":"within text"},{"source":"reblogged content","target":"tumblr hp","do I have to click to see":"","context":"we put it there"},{"source":"bts","target":"tumblr hp","do I have to click to see":"","context":"we put it there"},{"source":"ig xposts","target":"tumblr hp","do I have to click to see":"","context":"we put it there"},{"source":"fan art","target":"tumblr hp","do I have to click to see":"","context":"we put it there"},{"source":"tb about","target":"instagram hp","do I have to click to see":"","context":"we put it there"},{"source":"tb about","target":"piquetures hp","do I have to click to see":"","context":"we put it there"},{"source":"tb about","target":"postcards hp","do I have to click to see":"","context":"we put it there"},{"source":"tb about","target":"soundcloud","do I have to click to see":"","context":"we put it there"},{"source":"ig xposts","target":"AoT","do I have to click to see":"","context":"within text"},{"source":"instagram hp","target":"campaigns","do I have to click to see":"","context":"instagram given"},{"source":"instagram hp","target":"fitness stories","do I have to click to see":"","context":"instagram given"},{"source":"fitness stories","target":"instagram hp","do I have to click to see":"","context":"instagram given"}]}
// SVG dimensions set to full width and height of the screen
const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
const height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
const drawChart = (data) => {
// Create detached <svg> element.
const vis = d3.select('.main_container')
.append("svg")
.attr("width", width)
.attr("height", height);
const g = vis.append("g")
const simulation = d3.forceSimulation(data.nodes).force("charge", d3.forceManyBody().strength(-300)).force("link", d3.forceLink(data.links)
.id(d => d.id)
.distance(300)).force("center", d3.forceCenter(width / 2, height / 2)).force("collide", d3.forceCollide().strength(10))
const link = vis.selectAll("line")
.data(data.links)
.join("line")
.attr("stroke", 'grey')
.attr("fill", "red")
.attr("opacity", 0.2)
const drag = (simulation) => {
const dragstarted = (event) => {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}
const dragged = (event) => {
event.subject.fx = event.x;
event.subject.fy = event.y;
node.on("mouseover", function(d) {
let thisNode = this.id;
console.log("?? ~ file: index.html ~ line 99 ~ node.on ~ thisNode", thisNode)
console.log("?? ~ file: index.html ~ line 106 ~ node.on ~ d", d)
link.attr("opacity", function(d) {
return (d.source.id == thisNode || d.target.id == thisNode) ? 1 : 0.2
});
});
// Set the stroke width back to normal when mouse leaves the node.
node.on('mouseout', function(d) {
link.attr('opacity', 0.2);
});
}
const dragended = (event) => {
if (!event.active) {simulation.alphaTarget(0)};
event.subject.fx = null;
event.subject.fy = null;
}
return d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
}
const node = vis.selectAll(".node")
.data(data.nodes)
.join("path")
.attr("class", "node")
.attr("d", d3.symbol().type(d3.symbolPlus).size(300))
.attr("id", d => d.id)
.attr("r", 10)
.attr("stroke", 'red')
.style("fill", "none")
.call(drag(simulation));
const text = vis.append("g")
.attr("class", "labels")
.selectAll("text")
.data(data.nodes)
.join("text")
.text(d => d.id);
simulation.on("tick", () => {
text.attr("transform", (d) => {
return "translate(" (d.x 20) "," (d.y 5) ")";
});
node.attr("transform", (d) => {
return "translate(" d.x "," d.y ")";
});
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y)
})
// zoom block
const handleZoom = (e) => {
d3.select('svg g')
.attr('transform', e.transform);
}
const zoom = d3.zoom()
.scaleExtent([0.1, 3.5]) //[k0, k1] where k0 is the minimum allowed scale factor and k1 is the maximum allowed scale factor, and returns this zoom behavior. If extent is not specified, returns the current scale extent, which defaults to [0, ∞]. The scale extent restricts zooming in and out.
// .translateExtent([
// [0, 0],
// [width, height]
// ]) // constrain the zoom and pan so that the it can only zoom and pan within specified bounds
.on('zoom', handleZoom);
d3.select('.main_container')
.call(zoom);
}
drawChart(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/d3.min.js"></script>
<div class="main_container"></div>
uj5u.com熱心網友回復:
dragged在整個拖動程序中被呼叫,因此更新鏈接不透明度是有意義的dragstarted,dragend即最少次數。
例如,在dragstarted運行測驗鏈接是否已連接并適當地更新不透明度(例如,1 表示已連接的鏈接,0.1 表示未連接的鏈接):
const dragstarted = (event) => {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
// update link opacity to 0.1 for non-connected nodes
link.each(function(d) {
const test = d.source.id === event.subject.id || d.target.id === event.subject.id;
d3.select(this).attr("opacity", test ? 1 : 0.1);
});
}
然后,dragended您可以將鏈接恢復為其初始不透明狀態:
const dragended = (event) => {
if (!event.active) {
simulation.alphaTarget(0)
};
event.subject.fx = null;
event.subject.fy = null;
// reset link opacity to 1
link.attr("opacity", 1);
}
我更新了您的代碼中的幾個專案:data為簡潔起見,出于演示目的的鏈接長度,將不透明度從 1 減少到 0.1(根據您的問題)并使用圓圈而不是節點作為交叉點,因為交叉點似乎很難操作。否則,作業示例是根據您的問題:
// SVG dimensions set to full width and height of the screen
const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
const height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
const drawChart = (data) => {
// Create detached <svg> element.
const vis = d3.select('.main_container')
.append("svg")
.attr("width", width)
.attr("height", height);
const g = vis.append("g");
const simulation = d3.forceSimulation(data.nodes)
.force("charge", d3.forceManyBody().strength(-300))
.force("link", d3.forceLink(data.links).id(d => d.id).distance(100)) // reduced from 300 for demo purpose
.force("center", d3.forceCenter(width / 2, height / 2))
.force("collide", d3.forceCollide().strength(10))
const link = vis.selectAll("line")
.data(data.links)
.join("line")
.attr("stroke", 'grey')
.attr("fill", "red")
.attr("opacity", 1) // changed to 1 so we can lower opacity
const drag = (simulation) => {
const dragstarted = (event) => {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
// update link opacity to 0.1 for non-connected nodes
link.each(function(d) {
const test = d.source.id === event.subject.id || d.target.id === event.subject.id;
d3.select(this).attr("opacity", test ? 1 : 0.1);
});
}
const dragged = (event) => {
event.subject.fx = event.x;
event.subject.fy = event.y;
}
const dragended = (event) => {
if (!event.active) {
simulation.alphaTarget(0)
};
event.subject.fx = null;
event.subject.fy = null;
// reset link opacity to 1
link.attr("opacity", 1);
}
return d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
}
// for demo purpose replaced cross with circle
// as the crosses are difficult to drag
const node = vis.selectAll(".node")
.data(data.nodes)
//.join("path")
//.attr("class", "node")
//.attr("d", d3.symbol().type(d3.symbolPlus).size(300))
//.attr("id", d => d.id)
//.attr("r", 10)
//.attr("stroke", 'red')
//.style("fill", "none")
.join("circle")
.attr("class", "node")
.attr("id", d => d.id)
.attr("r", 8)
.style("fill", "red")
.call(drag(simulation));
const text = vis.append("g")
.attr("class", "labels")
.selectAll("text")
.data(data.nodes)
.join("text")
.text(d => d.id);
simulation.on("tick", () => {
text.attr("transform", (d) => {
return "translate(" (d.x 20) "," (d.y 5) ")";
});
node.attr("transform", (d) => {
return "translate(" d.x "," d.y ")";
});
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y)
})
// zoom block
const handleZoom = (e) => {
d3.select('svg g')
.attr('transform', e.transform);
}
const zoom = d3.zoom()
.scaleExtent([0.1, 3.5]) //[k0, k1] where k0 is the minimum allowed scale factor and k1 is the maximum allowed scale factor, and returns this zoom behavior. If extent is not specified, returns the current scale extent, which defaults to [0, ∞]. The scale extent restricts zooming in and out.
// .translateExtent([
// [0, 0],
// [width, height]
// ]) // constrain the zoom and pan so that the it can only zoom and pan within specified bounds
.on('zoom', handleZoom);
d3.select('.main_container')
.call(zoom);
}
drawChart(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/d3.min.js"></script>
<div class="main_container"></div>
<script>
const data = {
"nodes": [
{ "id": "A", "group": "big" },
{ "id": "B", "group": "big" },
{ "id": "C", "group": "big" },
{ "id": "D", "group": "big" },
{ "id": "E", "group": "big" }
],
"links": [
{ "source": "A", "target": "B" },
{ "source": "A", "target": "C" },
{ "source": "B", "target": "D" },
{ "source": "B", "target": "E" }
]
}
</script>
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/462640.html
