如何解决D3力布局forceY未映射到范围
我试图使用forceY()
属性以D3强制布局垂直排列我的节点,但是我没有限制y轴的上限。我的画布高度为200px,我要订购50个类别并将其投影到高度为1000px的平面上。我最初希望看到顶部的200px,而其余节点在底部看不到。如果需要,我让用户平移那里。
我将let y_scale = d3.scaleLinear().domain([0,50]).range([0,1000]);
与d3.forceSimulation(nodes).force("y",d3.forceY().y(d => y_scale(d.category)))
结合使用,我认为这样可以自然地以0 px及更低的像素绘制节点,但事实并非如此。节点是根据类别进行排序的,但是0类别并不会映射到0px,而是说-400px不在顶部。
有没有办法使forceY
真正映射到[0,1000]
范围?
我知道我可以使用y
之类的东西在svg上限制节点Math.max(0,d.y)
的情况,但这只会使所有从顶部拖尾的节点堆叠在0行。
解决方法
对于分类变量,应改为使用d3.scaleBand()
。那应该是造成奇怪定位的主要原因:
const fruits = ["Apple","Apple","Pear","Orange","Grape"];
const data = fruits.map(d => ({
x: 50,fruit: d
}));
const colours = ["Red","Green","Purple"];
const unique = arr => arr.filter((d,i) => arr.indexOf(d) === i);
const yscale = d3.scaleBand()
.domain(unique(fruits))
.range([50,150]);
const colour = d3.scaleOrdinal()
.domain(unique(fruits))
.range(colours);
const circle = d3.select("body")
.append("svg")
.attr("height",200)
.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("r",4)
.attr("cx",d => d.x)
.attr("cy",d => yscale(d.fruit))
.attr("fill",d => colour(d.fruit));
var graphLayout = d3.forceSimulation(data)
.force("collide",d3.forceCollide().radius(5))
.force("x",d3.forceX(50))
.force("y",d3.forceY().y(d => yscale(d.fruit)))
.on("tick",ticked);
function ticked() {
circle
.attr("cx",d => d.x)
.attr("cy",d => d.y)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。