Javascript D3.js中强制定向wordcloud的自动碰撞检测和纠正
我一直在尝试使用D3.js创建一个力导向布局。在下面的代码中,我填充了一系列对象,这些对象随后被渲染为文本元素。我希望避免单词之间的冲突,并相应地调整它们在网格上的表示 我在这里使用了Eric Dobbs编写的代码 但这对我来说仍然不起作用。这些物体最终会在屏幕上飞来飞去。我已经花了很多时间对此感到困惑,我将非常感谢任何可以提供的帮助 这是我的密码Javascript D3.js中强制定向wordcloud的自动碰撞检测和纠正,javascript,d3.js,collision-detection,force-layout,word-cloud,Javascript,D3.js,Collision Detection,Force Layout,Word Cloud,我一直在尝试使用D3.js创建一个力导向布局。在下面的代码中,我填充了一系列对象,这些对象随后被渲染为文本元素。我希望避免单词之间的冲突,并相应地调整它们在网格上的表示 我在这里使用了Eric Dobbs编写的代码 但这对我来说仍然不起作用。这些物体最终会在屏幕上飞来飞去。我已经花了很多时间对此感到困惑,我将非常感谢任何可以提供的帮助 这是我的密码 <!DOCTYPE html> <html> <head> <script src="https://d3
<!DOCTYPE html>
<html>
<head>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<script>
//arguments passed in when this class is modularised
var metaDataObject = {"type":"wordcloud","label":"data1","data":"data2","color":"color"};
var dataObject = {"data1":["apple","orange","pear","grapes","mango","papaya","kiwi","banana", "watermelon","strawberry","honeydew","dragonfruit","durian","pineapple","jackfruit","lychee","mangosteen","passionfruit","raspberry","blueberry","rockmelon","coconut","lemon","lime","pomelo","rambutan","aguave","longan","mandarin","calamansi","sugarcane","avocado","bittergourd","wintermelon","dates"],"data2":[100,50,150,40,70,60,30,35,95,120,60,70,80,15,30,140,100,170,200,40,90,20,180,99,66,55,130,20,50,55,100,120,30,20,90],"color":["#23af50"]};
//transform raw data
var frequency_list = transformData(metaDataObject, dataObject);
frequency_list.sort(function(a, b) {
return b.size-a.size;
});
//set cloud container variables
var cloudWidth = 600;
var cloudHeight = 400;
var cloudContainer = d3.select("body").append("svg")
.attr("width", cloudWidth)
.attr("height", cloudHeight);
//set approximate scaling
var largestQty = d3.max(dataObject[metaDataObject.data]);
var rangeCap = cloudWidth*cloudHeight/7500;
var scale = d3.scale.linear()
.domain([0, largestQty])
.range([5, rangeCap]);
var color = d3.scale.linear()
.domain([0,1,2,3,4,5,6,10,15,20,30,largestQty])
.range(["#ddd", "#ccc", "#bbb", "#aaa", "#999", "#888", "#777", "#666", "#555", "#444", "#333", "#222"]);
var words = createText(frequency_list);
var rendered = cloudContainer.selectAll("node")
.data(words)
.enter()
.append("text")
.attr("id", function(d, i) {
return "t"+i;
})
.text(function(d) {
return d.text;
})
.attr("font-family", "sans-serif")
.attr("fill", function(d, i) {
return color(i);
})
.attr("font-size", function(d) {
return scale(d.size)+"px";
})
.on("mouseover", handleMouseOver)
.on("mouseout", handleMouseOut);
var force = d3.layout.force()
.nodes(words)
.size([cloudWidth, cloudHeight])
.charge(-50)
.gravity(0.1)
.on("tick", tick)
.start();
rendered.call(force.drag);
function tick(e) {
var q = d3.geom.quadtree(words);
for(var i=0; i<words.length; i++) {
var word = words[i];
q.visit(collide(word));
}
// console.log(d.x2);
rendered
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; });
}
function collide(node) {
var nx1, nx2, ny1, ny2, padding;
padding = 32;
nx1 = node.x - padding;
nx2 = node.x2 + padding;
ny1 = node.y - padding;
ny2 = node.y2 + padding;
return function(quad, x1, y1, x2, y2) {
var dx, dy;
console.log(node.x2);
if (quad.point && (quad.point !== node)) {
if (overlap(node, quad.point)) {
dx = Math.min(node.x2 - quad.point.x, quad.point.x2 - node.x) / 2;
node.x -= dx;
quad.point.x += dx;
dy = Math.min(node.y2 - quad.point.y, quad.point.y2 - node.y) / 2;
node.y -= dy;
quad.point.y += dy;
}
}
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
};
};
function overlap(a, b) {
return !(a.x2 < b.x ||
a.x > b.x2 ||
a.y2 < b.y ||
a.y > b.y2);
}
function createText(frequency_list) {
var words = [];
for(var wordIndex=0; wordIndex<frequency_list.length; wordIndex++) {
var word = {
x: Math.random() * (cloudHeight - 40) +20,
y: Math.random() * (cloudWidth -40) +20,
text: frequency_list[wordIndex].text,
size: frequency_list[wordIndex].size,
// x2: word.x + word.text.length * word.size /1.5,
// y2: word.y + scale(word.size) * 1.1
};
word.x2 = word.x + word.text.length * word.size /1.5;
word.y2 = word.y + scale(word.size) * 1.1;
words.push(word);
}
return words;
}
function transformData(metaDataObject, dataObject) {
//To transform data to this format:
// var frequency_list = [{"text":"apple","size":100}, {"text":"orange","size":100}, {"text":"pear","size":25}, {"text":"grapes","size":301}, {"text":"mango","size":56}];
var frequency_list = [];
var wordFieldName = metaDataObject.label;
var valuesFieldName = metaDataObject.data;
var wordList = dataObject[wordFieldName];
var valuesList = dataObject[valuesFieldName];
for(var itemIndex=0; itemIndex<wordList.length; itemIndex++) {
var item = {
text: wordList[itemIndex].toUpperCase(),
size: valuesList[itemIndex]
}
frequency_list.push(item);
}
return frequency_list;
}
function handleMouseOver(d, i) {
d3.select(this).transition().attr({
fill: "black",
"font-size": scale(d.size) + 5 + "px"
});
cloudContainer.append("text").attr({
id: "t" + d.text + "-" + d.size,
x: 10,
y:20
})
.text(function() {
return ["weight: " + d.size];
// return [""+occupiedSpaces[1].top];
})
}
function handleMouseOut(d, i) {
d3.select(this).transition().attr({
fill: color(i),
"font-size": scale(d.size) + "px"
});
d3.select("#t" + d.text + "-" + d.size).remove();
}
</script>
</body>
</html>
//将此类模块化时传入的参数
var metaDataObject={“type”:“wordcloud”,“label”:“data1”,“data”:“data2”,“color”:“color”};
var dataObject={“data1”:[“苹果”、“橙子”、“梨”、“葡萄”、“芒果”、“木瓜”、“猕猴桃”、“香蕉”、“西瓜”、“草莓”、“蜜露”、“龙须果”、“榴莲”、“菠萝”、“菠萝”、“菠萝”、“菠萝”、“荔枝”、“山竹”、“西番莲”、“覆盆子”、“蓝莓”、“甜瓜”、“椰子”、“柠檬”、“酸橙”、“柚子”、“红毛丹”、“阿加维”、“龙眼”、“柑橘”、“卡拉曼西”、“甘蔗”,“鳄梨”、“苦瓜”、“冬瓜”、“枣”]、“数据2”:[100,50150,40,70,60,30,35,95120,60,70,80,15,301401001170200,40,90,20180,99,66,55130,20,50,55100120,30,20,90]、“颜色”:[“23af50”];
//转换原始数据
var frequency_list=transformData(metaDataObject,dataObject);
频率列表排序(功能(a、b){
返回b.size-a.size;
});
//设置云容器变量
云宽=600;
云高=400;
var cloudContainer=d3.select(“body”).append(“svg”)
.attr(“宽度”,云宽)
.attr(“高度”,云高);
//设置近似比例
var largestQty=d3.max(dataObject[metaDataObject.data]);
var rangeCap=云宽*云高/7500;
var scale=d3.scale.linear()
.domain([0,最大数量])
.范围([5,范围上限]);
var color=d3.scale.linear()
.域([0,1,2,3,4,5,6,10,15,20,30,最大数量])
.范围([“ddd”、“ccc”、“bbb”、“aaa”、“999”、“888”、“777”、“666”、“555”、“444”、“333”、“222”);
var words=createText(频率列表);
var rendered=cloudContainer.selectAll(“节点”)
.数据(字)
.输入()
.append(“文本”)
.attr(“id”,函数(d,i){
返回“t”+i;
})
.文本(功能(d){
返回d.text;
})
.attr(“字体系列”、“无衬线”)
.attr(“填充”,函数(d,i){
返回颜色(i);
})
.attr(“字体大小”,函数(d){
返回刻度(d.size)+“px”;
})
.on(“鼠标悬停”,把手放在手上)
.on(“mouseout”,handleMouseOut);
var-force=d3.layout.force()
.节点(字)
.size([cloudWidth,cloudHeight])
。收费(-50)
.重力(0.1)
.on(“滴答”,滴答)
.start();
调用(强制拖动);
功能勾号(e){
var q=d3.geom.quadtree(字);
对于(var i=0;i nx2 | x2ny2 | y2b.x2 | |
a、 y2b.y2);
}
函数createText(频率列表){
var-words=[];
对于(var wordIndex=0;wordIndex