2017-04-25 58 views
1

上午試圖與從API接收到的數據的圖形,並把這個圖形上(https://bl.ocks.org/mbostock/4062045) - 力指向圖如何使上VueJS一個圖形

但是我在這是怎麼完成的不確定VueJs還是有更簡單的工具來做到這一點?

D3力定向圖似乎有點複雜,也許有一個圖書館已經開箱即用?

+0

先生你去https://www.npmjs.com/package/vue-d3 –

+0

看看https://github.com/johnnynotsolucky/samples/tree/master/vuejs-d3你可以看更多的演示在https://github.com/vuejs/awesome-vue – Ethaan

回答

2

從評論中提到的vue-d3包只是將D3添加到Vue原型,因此可以通過this.$d3訪問。

我已經測試過這個軟件包,但它不能與我的D3版本一起工作。看起來像一個套管問題(D3而不是D3)。所以我手動添加了原型。

我不知道是否有更容易創建力圖的庫,但請看下面的演示或此fiddle

我修改了鏈接中的示例以創建一個強制有向圖。演示正在工作,但正如你所提到的,它非常複雜。 也可以從SVG綁定到Vue.js模型。但我找不到一個更好的方法來做到這一點。

例如,點擊添加一個新節點並不適用於只向數組中添加新節點,但這應該是Vue.js組件的目標。一旦數據改變,SVG圖應該自動更新。

目前,組件中沒有使用Vue.js中的節點和鏈接,因爲我不知道如何添加圖形的更新。

如果您想出瞭如何使用模型數據添加更新,請讓我知道。通過刪除SVG並重新創建它,刷新整個圖表非常容易。 (見重新加載按鈕)

// https://unpkg.com/[email protected] --> 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" 
 
    \t @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() { 
 
    \t \t 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

我通過提供d3 force graph with vue.js的一例回答上VUE + D3另一個問題。

d3.js現在拆分成小模塊,具體計算被隔離在小組件中,如d3-force。 SVG可以像任何其他HTML結構一樣在組件模板中繪製。