我想创建一个力方向直方图(或点/泡直方图),或者是y值沿x轴受到约束的蜂巢式直方图。
也就是说,使用以力为导向的布局,根据某个x值分配x位置,并根据该值的计数分配y位置,其中y值必须保持在某些较低的边界之上。。
我已经创建了一个力定向蜂温地块,这几乎是我想要的。我只是还没有计算出y轴约束。
谢谢你的帮助/建议!
发布于 2018-08-20 22:10:49
要应用这样的约束,可以直接限制d.y值--只需替换
.attr('cy', d => d.y)例如,
.attr('cy', d => d.y = Math.min(d.y, height / 2))这样,节点就必须位于height / 2之上。不仅要约束cy,还要更新d.y,以便在下一次迭代中考虑到这个新位置。如果您不喜欢在返回语句中赋值,则可以使用d.y操作符单独修改each。
这里的forceCenter会把事情搞砸,我不确定这是否有必要。我也怀疑manyBody力的必要性--为什么圆必须互相吸引(你用正强度=吸引)?最好是用轴线来吸引他们(forceY)。
圆的精确x位置、x轴的吸引力和收敛的速度(在迭代中)之间存在折衷。需要对力的强度进行一些调整。强度的影响描述在d3-force自述:强度。对于大多数力量,建议在0,1范围内使用强度。
const width = 500
const height = 150
const svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
const colorScale = d3.scaleOrdinal()
.range(['#FCFCFC', '#F7567C', '#FFFAE3', '#99E1D9', '#5D576B'])
const radius = 7
const sampleData = d3.range(150).map(() => ({r: radius,
value: width/2 + d3.randomNormal(0,75)()}))
// set params for force layout
//const manyBody = d3.forceManyBody().strength(2)
//const center = d3.forceCenter().x((width/2)).y((height/2))
// define force
let force = d3.forceSimulation()
//.force('charge', manyBody)
//.force('center', center)
.force('collision', d3.forceCollide(d => d.r).strength(1))
.velocityDecay(.48)
.force('x', d3.forceX(d => d.value).strength(3))
.force('y', d3.forceY(height - radius).strength(0.2))
.nodes(sampleData)
.on('tick', changeNetwork)
svg.selectAll('circle')
.data(sampleData)
.enter()
.append('circle')
.style('fill', (d,i) => colorScale(i))
.attr('r', d => d.r)
.attr('stroke', 'black')
.attr('stroke-width', .1)
function changeNetwork() {
d3.selectAll('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y = Math.min(d.y, height - radius - 1))
}<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
https://stackoverflow.com/questions/51936114
复制相似问题