尝试使用从API接收的数据创建图表并将其放在图表上(https://bl.ocks.org/mbostock/4062045) - 强制导向图
但是我不确定如何在VueJ上完成这项工作,或者是否有更简单的工具来执行此操作?
D3 Force-Directed Graph似乎有点复杂,也许有一个库可以开箱即用吗?
答案 0 :(得分:2)
评论中提到的vue-d3
软件包只是将D3添加到Vue原型中,因此可以使用this.$d3
访问它。
我已经测试过该软件包,但它不适用于我的D3版本。看起来像套管问题(D3而不是d3)。所以我手动添加了原型。
我不知道是否有更容易创建力图的库,但请查看下面的演示或fiddle。
我已经修改了链接中的示例以创建力导向图。该演示正在运行,但正如您所提到的,它非常复杂。 还可以改进从SVG到Vue.js模型的绑定。但我找不到更好的方法来做到这一点。
例如,在单击时添加新节点不能仅仅向阵列添加新节点,但这应该是Vue.js组件的目标。一旦数据发生变化,SVG图表就会自动更新。
目前,Vue.js中的节点和链接未在组件中使用,因为我不知道如何添加图表的更新。
如果您想出如何使用模型数据添加更新,请告诉我们。通过删除SVG并重新创建它,刷新整个图表非常容易。 (见重新加载按钮)
// https://unpkg.com/vue-d3@0.1.0 --> only adds d3 to Vue.prototype but it wasn't working as expected (d3 is lower case)
Vue.prototype.$d3 = d3;
const URL = 'https://demo5147591.mockable.io/miserables'; // data copied from below link because of jsonp support
//'https://bl.ocks.org/mbostock/raw/4062045/5916d145c8c048a6e3086915a6be464467391c62/miserables.json';
//console.log(window.d3);
const d3ForceGraph = {
template: `
<div>
{{mousePosition}}
<button @click="reload">reload</button>
<svg width="600" height="600"
@mousemove="onMouseMove($event)"></svg>
</div>
`,
data() {
return {
nodes: [],
links: [],
simulation: undefined,
mousePosition: {
x: 0,
y: 0
}
}
},
mounted() {
this.loadData(); // initially load json
},
methods: {
// load data
loadData() {
this.$svg = $(this.$el).find('svg');
let svg = this.$d3.select(this.$svg.get(0)), //this.$d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
//console.log($(this.$el).find('svg').get(0));
this.simulation = this.$d3.forceSimulation()
.force("link", this.$d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", this.$d3.forceManyBody())
.force("center", this.$d3.forceCenter(width / 2, height / 2));
let color = this.$d3.scaleOrdinal(this.$d3.schemeCategory20);
$.getJSON(URL, (graph) => {
//d3.json("miserables.json", function(error, graph) { // already loaded
//if (error) throw error; // needs to be implemented differently
let nodes = graph.nodes;
let links = graph.links;
let link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(links) //graph.links)
.enter().append("line")
.attr("stroke-width", function(d) {
return Math.sqrt(d.value);
});
let node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(nodes) //graph.nodes)
.enter().append("circle")
.attr("r", 5)
.attr("fill", function(d) {
return color(d.group);
})
.call(this.$d3.drag()
.on("start", this.dragstarted)
.on("drag", this.dragged)
.on("end", this.dragended));
node.append("title")
.text(function(d) {
return d.id;
});
this.simulation
.nodes(graph.nodes)
.on("tick", ticked);
this.simulation.force("link")
.links(links); //graph.links);
function ticked() {
link
.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
}
})
},
reload() {
//console.log('reloading...');
this.$svg.empty(); // clear svg --> easiest way to re-create the force graph.
this.loadData();
},
// mouse events
onMouseMove(evt) {
//console.log(evt, this)
this.mousePosition = {
x: evt.clientX,
y: evt.clientY
}
},
// drag event handlers
dragstarted(d) {
if (!this.$d3.event.active) this.simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
},
dragged(d) {
d.fx = this.$d3.event.x;
d.fy = this.$d3.event.y;
},
dragended(d) {
if (!this.$d3.event.active) this.simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
}
};
new Vue({
el: '#app',
data() {
return {}
},
components: {
d3ForceGraph
}
});
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: #fff;
stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.8.0/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app">
<d3-force-graph></d3-force-graph>
</div>
答案 1 :(得分:1)
我通过提供一个d3 force graph with vue.js的例子来回答关于vue + d3的另一个问题。
d3.js现在拆分为小模块,特定计算被隔离在像d3-force这样的小组件中。 SVG可以像任何其他HTML结构一样在组件模板中绘制。
答案 2 :(得分:0)
您可以使用vue-d3-network
npm install vue-d3-network
参见this fiddle
html: ```
<head>
<script type="text/javascript" src="https://unpkg.com/vue">
</script>
<link rel="stylesheet" type="text/css" href="https://rawgit.com/emiliorizzo/vue-d3-network/master/dist/vue-d3-network.css">
<script type="text/javascript" src="https://rawgit.com/emiliorizzo/vue-d3-network/master/dist/vue-d3-network.umd.js"></script>
</head>
<body>
<div id="app">
<d3-network :net-nodes="nodes" :net-links="links" :options="options">
</d3-network>
</div>
</body>
```
javascript: ``
var D3Network = window['vue-d3-network']
new Vue({
el: '#app',
components: {
D3Network
},
data () {
return {
nodes: [
{ id: 1, name: 'my node 1' },
{ id: 2, name: 'my node 2' },
{ id: 3, _color:'orange' },
{ id: 4 },
{ id: 5 },
{ id: 6 },
{ id: 7 },
{ id: 8 },
{ id: 9 }
],
links: [
{ sid: 1, tid: 2, _color:'red' },
{ sid: 2, tid: 8, _color:'f0f' },
{ sid: 3, tid: 4,_color:'rebeccapurple' },
{ sid: 4, tid: 5 },
{ sid: 5, tid: 6 },
{ sid: 7, tid: 8 },
{ sid: 5, tid: 8 },
{ sid: 3, tid: 8 },
{ sid: 7, tid: 9 }
],
options:
{
force: 3000,
nodeSize: 20,
nodeLabels: true,
linkWidth:5
}
}
},
})
```