问题描述
我正在创建一个具有鱼眼效果的图形,用户在其光标下有一个永久缩放,并且可以四处移动图形节点。
Here's what I have: (ObservableHQ)
以片段形式:
d3.json("https://gist.githubusercontent.com/mbostock/4062045/raw/5916d145c8c048a6e3086915a6be464467391c62/miserables.json").then(draw);
function draw(data) {
const fisheye = fisheyeO.circular()
.radius(100)
.distortion(5);
const height = 400;
const width = 500;
data.nodes.forEach(d=>{d.fisheye={x:0,y:0,z:0}})
const simulation = d3.forceSimulation(data.nodes)
.alphaDecay(0.0125)
.alphaMin(0.01)
.force("link",d3.forceLink(data.links).id(d => d.id))
.force("charge",d3.forceManyBody())
.force("x",d3.forceX(width/2))
.force("y",d3.forceY(height/2));
const svg = d3.select("body").append("svg")
.attr("viewBox",[0,width,height])
const link = svg.append("g")
.attr("stroke","#999")
.attr("stroke-opacity",0.6)
.selectAll("line")
.data(data.links)
.join("line")
.attr("stroke-width",2);
const node = svg.append("g")
.attr("stroke","#fff")
.attr("stroke-width",1.5)
.selectAll("circle")
.data(data.nodes)
.join("circle")
.attr("r",5)
.attr("fill","black")
svg.on("mousemove",function() {
fisheye.focus(d3.mouse(this));
node.each(function(d) { d.fisheye = fisheye(d); })
.attr("cx",function(d) { return d.fisheye.x; })
.attr("cy",function(d) { return d.fisheye.y; })
.attr("r",function(d) { return d.fisheye.z * 4.5; });
link.attr("x1",function(d) { return d.source.fisheye.x; })
.attr("y1",function(d) { return d.source.fisheye.y; })
.attr("x2",function(d) { return d.target.fisheye.x; })
.attr("y2",function(d) { return d.target.fisheye.y; });
})
simulation.on("tick",() => {
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);
node
.attr("cx",d => d.x)
.attr("cy",d => d.y);
});
}
const fisheye0 = fisheyeO = {
circular: () => {
var radius = 200,distortion = 2,k0,k1,focus = [0,0];
function fisheye(d) {
var dx = d.x - focus[0],dy = d.y - focus[1],dd = Math.sqrt(dx * dx + dy * dy);
if (!dd || dd >= radius) return {x: d.x,y: d.y,z: dd >= radius ? 1 : 10};
var k = k0 * (1 - Math.exp(-dd * k1)) / dd * .75 + .25;
return {x: focus[0] + dx * k,y: focus[1] + dy * k,z: Math.min(k,10)};
}
function rescale() {
k0 = Math.exp(distortion);
k0 = k0 / (k0 - 1) * radius;
k1 = distortion / radius;
return fisheye;
}
fisheye.radius = function(_) {
if (!arguments.length) return radius;
radius = +_;
return rescale();
};
fisheye.distortion = function(_) {
if (!arguments.length) return distortion;
distortion = +_;
return rescale();
};
fisheye.focus = function(_) {
if (!arguments.length) return focus;
focus = _;
return fisheye;
};
return rescale();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.min.js"></script>
我使用了 Bostock 的鱼眼效果,只要图形是静态的,它就可以正常工作。但是,如果力模拟正在运行,则不起作用,从而产生以下效果:
我尝试将鱼眼效果重构为一种力,并直接在力模拟中使用它,如下所示:
function forceFisheye(fisheye) {
let nodes;
function force() {
let i;
let n = nodes.length;
let node;
for (i = 0; i < n; ++i) {
node = nodes[i];
let { x,y,z } = fisheye(node);
node.x = x;
node.y = y;
node.z = z;
}
}
force.initialize = function (_) {
nodes = _;
};
return force;
}
let fisheye = fisheye();
// ...
d3.forceSimulation()
.force("fisheye",forceFisheye(fisheye));
但是这会产生奇怪的结果,反而让节点从我的光标处跑开。
如何使用具有鱼眼效果的力导向图?
感谢您的宝贵时间!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)