- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已经构建了一个力导向图,但是,就我而言,我还有一个带有 80px*80px 框的网格。我希望图中的每个节点不仅根据现有的重力和力定位,而且还位于最近的网格框的中间(没有固定)。
可以在 d3js 中做到这一点吗?
最佳答案
Moritz Stefaner 想出了一种方法来做到这一点
代码:https://github.com/moritzstefaner/gridexperiments/
演示:http://moritzstefaner.github.io/gridexperiments/
编辑:
正如@altocumulus 所提到的,这没有代码的副本。通常我只从个人网站复制代码,因为它们比 github 上的东西更容易消失。或者当它很短(小于 50 loc?)时我会复制它。无论如何,由于代码的内容可能会被拉出,我复制了下面的 mortiz 的 index.html 文件。其他引用的 js 文件可以很容易地在其他地方找到。 (请注意,您可能应该提取截至 2011 年 12 月 9 日的每个库的版本)
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<meta charset="utf-8">
<title>Forces and grids</title>
<script type="text/javascript" src="d3.min.js"></script>
<script type="text/javascript" src="d3.layout.min.js"></script>
<script type="text/javascript" src="d3.geom.min.js"></script>
<script type="text/javascript" src="underscore-min.js"></script>
<script src="jquery-1.7.2.min.js" charset="utf-8"></script>
<style type="text/css" media="screen">
.menu { position:absolute; top :20px; right:20px; }
</style>
</head>
<body>
<script type="text/javascript" charset="utf-8">
var w = 700, h = 700;
var vis = d3.select("body").append("svg:svg").attr("width", w).attr("height", h);
var background = vis.append("g");
var nodes = [];
var links = [];
var USE_GRID = true;
var GRID_SIZE = 60;
var GRID_TYPE = "HEXA";
// set up event handlers
$(document).ready(function(){
$("#USE_GRID").click(
function(){
USE_GRID = $(this).is(":checked");
$(this).blur();
force.start();
}
);
//$("#CELL_SIZE").rangeinput();
$("#CELL_SIZE").bind("change",
function(){
console.log($(this).attr("value"));
GRID_SIZE = $(this).attr("value");
grid.init();
force.start();
}
);
$("[name=GRID_TYPE]").click(
function(){
GRID_TYPE = $(this).attr("value");
grid.init();
force.start();
}
);
});
for(var i = 0; i < 30; i++) {
var node = {
label : "node " + i
};
nodes.push(node);
};
for(var i = 0; i < nodes.length; i++) {
for(var j = 0; j < i; j++) {
if(Math.random() > .99-Math.sqrt(i)*.02)
links.push({
source : i,
target : j,
weight :1
});
}
};
var force = d3.layout.force().size([w, h]).nodes(nodes).links(links).gravity(1).linkDistance(function(d){return (1-d.weight)*100}).charge(-3000).linkStrength(function(x) {
return x.weight * 5
});
force.start();
var link = vis.selectAll("line.link").data(links).enter().append("svg:line").attr("class", "link").style("stroke-width", 1.5).style("stroke", "#555").style("opacity", function(d){return d.weight*.7});
var node = vis.selectAll("g.node").data(force.nodes()).enter().append("svg:g").attr("class", "node");
node.append("svg:circle").attr("r", 6).style("fill", "#555").style("stroke", "#FFF").style("stroke-width", "4px");
node.call(force.drag);
var updateLink = function() {
this.attr("x1", function(d) {
return d.source.screenX;
}).attr("y1", function(d) {
return d.source.screenY;
}).attr("x2", function(d) {
return d.target.screenX;
}).attr("y2", function(d) {
return d.target.screenY;
});
}
var updateNode = function() {
this.attr("transform", function(d) {
if(USE_GRID) {
var gridpoint = grid.occupyNearest(d);
if(gridpoint) {
d.screenX = d.screenX || gridpoint.x;
d.screenY = d.screenY || gridpoint.y;
d.screenX += (gridpoint.x - d.screenX) * .2;
d.screenY += (gridpoint.y - d.screenY) * .2;
d.x += (gridpoint.x - d.x) * .05;
d.y += (gridpoint.y - d.y) * .05;
}
} else {
d.screenX = d.x;
d.screenY = d.y;
}
return "translate(" + d.screenX + "," + d.screenY + ")";
});
};
var grid = function(width, height) {
return {
cells : [],
init : function() {
this.cells = [];
for(var i = 0; i < width / GRID_SIZE; i++) {
for(var j = 0; j < height / GRID_SIZE; j++) {
// HACK: ^should be a better way to determine number of rows and cols
var cell;
switch (GRID_TYPE) {
case "PLAIN":
cell = {
x : i * GRID_SIZE,
y : j * GRID_SIZE
};
break;
case "SHIFT_ODD_ROWS":
cell = {
x : i * GRID_SIZE,
y : 1.5 * (j * GRID_SIZE + (i % 2) * GRID_SIZE * .5)
};
break;
case "HEXA":
cell = {
x : i * GRID_SIZE + (j % 2) * GRID_SIZE * .5,
y : j * GRID_SIZE * .85
};
break;
}
this.cells.push(cell);
};
};
},
sqdist : function(a, b) {
return Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2);
},
occupyNearest : function(p) {
var minDist = 1000000;
var d;
var candidate = null;
for(var i = 0; i < this.cells.length; i++) {
if(!this.cells[i].occupied && ( d = this.sqdist(p, this.cells[i])) < minDist) {
minDist = d;
candidate = this.cells[i];
}
}
if(candidate)
candidate.occupied = true;
return candidate;
}
}
}(w, h);
force.on("tick", function() {
vis.select("g.gridcanvas").remove();
if(USE_GRID) {
grid.init();
var gridCanvas = vis.append("svg:g").attr("class", "gridcanvas");
_.each(grid.cells, function(c) {
gridCanvas.append("svg:circle").attr("cx", c.x).attr("cy", c.y).attr("r", 2).style("fill", "#555").style("opacity", .3);
});
}
node.call(updateNode);
link.call(updateLink);
});
</script>
<div class="menu">
<div>
<input type="checkbox" id="USE_GRID" checked>use grid</input>
</div>
<div>
<input type="range" min="30" step="10" max="150" id="CELL_SIZE" value="60"></input>
</div>
<div>
<input type="radio" name="GRID_TYPE" value="PLAIN">plain</input>
<input type="radio" name="GRID_TYPE" value="SHIFT_ODD_ROWS">Shift odd rows</input>
<input type="radio" name="GRID_TYPE" value="HEXA" checked>Hexa</input>
</div>
</div>
</body>
关于d3.js - D3 力布局图,节点位于网格中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25642769/
我正在尝试编写一个程序,以表格的形式计算我的结果。我有一个液压升降机,可以显示作用在直径 (D1) 的活塞上的小力(我称之为 F1)可以乘以作用在直径 (D2) 的活塞上的大力 (F2) ,电梯的运行
我有一个 fiddle :https://jsfiddle.net/mvLf579a/284/ 此 fiddle 允许您使用 D3 径向布局来布置力网络,并将布局重置为默认力布局。但是,重置时链接强度
我想实现表格 View 单元格重叠,因为我想实现这种效果: 所以基本上细胞会一个接一个地堆叠。我的目标是 iOS7+(目前正在测试 iOS8)。 我目前正在做一个 CAGradientLayer,它被
尽管在 box2d 前花了几个小时,但我仍然不明白 applyforce 和 applyimpulse 是如何工作的。我尝试使用一些视觉效果来更好地理解正在发生的事情(通过在 body 位置和应用点之
首先,我是 D3 的新手。我正在尝试使用这些示例在单个 D3 图中实现不同的行为: Drag + Zoom 力导向图 但我的图表在几秒钟后卡住,我不明白为什么... 这是我的代码:http://jsf
所以,我在 Xcode 上用 Swift 玩了这个游戏,我有一个跳跃的 SKShapeNode。不过,我希望这种跳跃与玩家的触感相称。因此,小水龙头会跳得小,而轻快的水龙头会跳得更高。怎么可能做到这一
在 ARKit/SceneKit 中,当用户点击按钮时,我想对我的节点施加一个脉冲。我希望冲动来自当前用户的角度。这意味着节点将远离用户的视角。多亏了这段代码,我能够获得当前的方向/方向: func
我正在使用 Angular2 并拥有父子组件。我的子组件正在使用 DatePipe 提供程序,因为父单元测试失败并给出以下错误, 错误:非法状态:无法加载管道 DatePipe 的摘要。 如何解决这个
我是一名优秀的程序员,十分优秀!