D3.js的V5版本-Vue框架中使用(第九章) ---力導向圖
阿新 • • 發佈:2019-02-13
一. Api使用
- d3.forceSimulation() ,新建一個力導向圖,
- d3.forceSimulation().force(),新增或者移除一個力
- d3.forceSimulation().nodes(),輸入是一個數組,然後將這個輸入的陣列進行一定的資料轉換
- d3.forceLink.links(),這裡輸入的也是一個數組(邊集),然後對輸入的邊集進行轉換
- tick函式,這個函式對於力導向圖來說非常重要,因為力導向圖是不斷運動的,每一時刻都在發生更新,所以需要不斷更新節點和連線的位置
- d3.drag(),是力導向圖可以被拖動
二. vue使用
<template lang='pug'> div.force-pane(:id="id") svg </template> <script> /** * 力導向圖 */ import * as d3 from 'd3' let gs = '', forceSimulation = '', links = '', linksText = '' let nodes = [{ name: '湖南' }, { name: '毛澤東' }, { name: '主席' }] let edges = [ { source: 0, target: 1, relation: '籍貫', value: 1.3 }, { source: 1, target: 2, relation: '職責', value: 1 } ] export default { name: 'Scale', data() { return { id: '' } }, methods: { uuid() { function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1) } return ( s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4() ) }, ticked() { links .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 }) linksText .attr('x', function(d) { return (d.source.x + d.target.x) / 2 }) .attr('y', function(d) { return (d.source.y + d.target.y) / 2 }) gs.attr('transform', d => { return 'translate(' + d.x + ',' + d.y + ')' }) }, dragStart(d) { if (!d3.event.active) { //設定衰減係數,對節點位置移動過程的模擬,數值越高移動越快,數值範圍[0,1] forceSimulation.alphaTarget(0.8).restart() } d.fx = d.x d.fy = d.y }, dragEnd(d) { d.fx = d3.event.x d.fy = d3.event.y }, drag(d) { if (!d3.event.active) { forceSimulation.alphaTarget(0) } d.fx = null d.fy = null } }, created() { this.id = this.uuid() }, mounted() { //1.建立svg畫布 let marge = { top: 160, bottom: 60, left: 160, right: 60 } let width = document.getElementById(this.id).clientWidth let height = document.getElementById(this.id).clientHeight const svg = d3 .select(this.$el) .select('svg') .attr('width', width) .attr('height', height) let g = svg .append('g') .attr( 'transform', 'translate(' + marge.top + ',' + marge.left + ')' ) //2.設定一個color的顏色比例尺,為了讓不同的扇形呈現不同的顏色 var colorScale = d3 .scaleOrdinal() .domain(d3.range(nodes.length)) .range(d3.schemeCategory10) //3.新建一個力導向圖 forceSimulation = d3 .forceSimulation() .force('link', d3.forceLink()) .force('charge', d3.forceManyBody()) .force('center', d3.forceCenter()) //4. 初始化力導向圖 //生成節點資料 forceSimulation.nodes(nodes).on('tick', this.ticked) //生成邊資料 forceSimulation .force('link') .links(edges) .distance(function(d) { //每一邊的長度 return d.value * 100 }) //設定圖形的中心位置 forceSimulation .force('center') .x(width / 4) .y(height / 4) //5. 繪製邊(有了節點和邊的資料後) links = g .append('g') .selectAll('line') .data(edges) .enter() .append('line') .attr('stroke', function(d, i) { return colorScale(i) }) .attr('stroke-width', 1) linksText = g .append('g') .selectAll('text') .data(edges) .enter() .append('text') .text(function(d) { return d.relation }) //6. 繪製節點, 先為節點和節點上的文字分組 gs = g .selectAll('.circleText') .data(nodes) .enter() .append('g') .attr('transform', function(d, i) { var cirX = d.x var cirY = d.y return 'translate(' + cirX + ',' + cirY + ')' }) .call( d3 .drag() .on('start', this.dragStart) .on('drag', this.drag) .on('end', this.dragEnd) ) //繪製節點 gs.append('circle') .attr('r', 10) .attr('fill', function(d, i) { return colorScale(i) }) //文字 gs.append('text') .attr('x', -10) .attr('y', -20) .attr('dy', 10) .text(function(d) { return d.name }) } } </script> <style lang='scss' scoped> .force-pane { width: 100%; height: 1000px; } </style>