前言:
现时兄弟们对“d3 力导向图”可能比较注意,各位老铁们都需要剖析一些“d3 力导向图”的相关资讯。那么小编在网摘上网罗了一些关于“d3 力导向图””的相关内容,希望朋友们能喜欢,同学们快快来了解一下吧!D3是一个数据可视化的JavaScript函数库,允许用户绑定任意数据到DOM,然后根据数据来操作文档,创建可交互式的图表。Vue是一个响应式的前端框架,能够将数据渲染到DOM并抽象出复杂的逻辑。看起来两个库都能完成数据到DOM的渲染,结合起来可能会出现使用逻辑上的冲突,故尝试D3做数据处理,Vue做数据响应式处理来解决此冲突。
现在完成如下示例:
首先不使用Vue的模板操作,直接使用常规D3.js的Dom操作,包括数据处理、数据显示。
<script>import * as d3 from 'd3'export default { name: 'demo', template: '<div></div>', data () { return { width: 600, height: 400, nodes: [], links: [] } }, mounted () { const nodes = [ {id: 1, name: '福州'}, {id: 2, name: '宁德'}, {id: 3, name: '莆田'}, {id: 4, name: '泉州'}, {id: 5, name: '厦门'}, {id: 6, name: '漳州'}, ]; const links = [ {source: 1, target: 2}, {source: 1, target: 3}, {source: 1, target: 4}, {source: 3, target: 4}, {source: 4, target: 5}, {source: 4, target: 6}, {source: 5, target: 6}, ]; const svg = d3.select(this.$el) .append('svg') .attr('width', this.width) .attr('height', this.height) const link = svg.selectAll('line') .data(links) .enter() .append('line') .attr('stroke', 'red') const node = svg.selectAll('circle') .data(nodes) .enter() .append('circle') .attr('fill', 'blue') .attr('r', '20') const text = svg.selectAll('text') .data(nodes) .enter() .append('text') .attr('dx', 0) .attr('dy', 5) .attr('fill', 'white') .attr('text-anchor', 'middle') .text(d => d.name) const simulation = d3.forceSimulation(nodes) .force('charge', d3.forceManyBody().strength(-100)) .force("link", d3.forceLink(links).id(d => d.id).distance(50)) .force("center", d3.forceCenter(this.width / 2, this.height / 2)) .on('tick', () => { node.attr('cx', d => d.x).attr('cy', d => d.y) text.attr('x', d => d.x).attr('y', d => d.y) link.attr('x1', d => d.source.x).attr('y1', d => d.source.y) .attr('x2', d => d.target.x).attr('y2', d => d.target.y) }) }}</script>
从代码中可以看出,在不使用模板操作情况下,视图显示操作和逻辑处理其实是混在一起的,现在优化下代码:
<template> <div class="container" style="cursor: pointer"> <svg ref="svg" :width="width" :height="height"> <g> <line v-for="(link, i) in links" :key="i" :x1="link.x1" :x2="link.x2" :y1="link.y1" :y2="link.y2" style="stroke: red" ></line> </g> <g class="node" style="fill: blue; cursor: pointer;" :key="node.id" v-for="node in nodes"> <circle :cx="node.x" :cy="node.y" r="20" > </circle> <text :x="node.x" :y="node.y" dx="0" dy="5" fill="white" text-anchor="middle"> {{node.name}} </text> </g> </svg> </div></template><script>import * as d3 from 'd3'export default { name: 'demo', data () { return { width: 600, height: 400, nodes: [ {id: 1, name: '福州'}, {id: 2, name: '宁德'}, {id: 3, name: '莆田'}, {id: 4, name: '泉州'}, {id: 5, name: '厦门'}, {id: 6, name: '漳州'}, ], links: [ {source: 1, target: 2}, {source: 1, target: 3}, {source: 1, target: 4}, {source: 3, target: 4}, {source: 4, target: 5}, {source: 4, target: 6}, {source: 5, target: 6}, ], simulation: '' } }, mounted () { this.simulation = d3.forceSimulation(this.nodes) .force('charge', d3.forceManyBody().strength(-100)) .force("link", d3.forceLink(this.links).id(d => d.id).distance(50)) .force("center", d3.forceCenter(this.width / 2, this.height / 2)) .on('tick', () => { this.nodes = this.nodes.map(v => v) this.links = this.links.map(v => ({ ...v, x1: v.source.x, y1: v.source.y, x2: v.target.x, y2: v.target.y })) }) }}</script>
把对视图操作部分移植到Vue的模板中,很好的利用的Vue的数据响应特性,同时用户交互很容易就能运用到Vue的事件流:
<g class="node" style="fill: blue; cursor: pointer;" :key="node.id" @click="show(node)" v-for="node in nodes"> ....</g>....methods: { show(node) { alert(node.name) }}....
同时D3内部也提供了方便灵活并且抽象的拖拽交互模块 d3-drag
const node = d3.select(this.$refs.svg).selectAll('.node').data(this.nodes)const drag = d3.drag().on('start', d => { if (!d3.event.active) { this.simulation.alphaTarget(0.4).restart(); } d.fx = d3.event.x; d.fy = d3.event.y; }).on('drag', d => { d.fx = d3.event.x; d.fy = d3.event.y; }).on('end', d => { if (!d3.event.active) { this.simulation.alphaTarget(0); } d.fx = null d.fy = null }) node.call(drag)
标签: #d3 力导向图