如何为Vue.js实现D3

Mar*_*ker 7 d3.js vue.js

使用React有各种D3实现.其中一个更有趣的是使用react-faux-dom项目.这种方法的优点是React了解D3创建的DOM元素以及创建同构图的能力.

请参阅以下内容:

在Vue.js中实现D3具有相同的好处需要什么?

是否需要创建类似于react-faux-dom的东西,或者Vue是否已经拥有可用于此的东西?

考虑到Vue的架构,这种方法有意义(或不是)有意义吗?

小智 14

从版本4开始,D3是高度模块化的,并且计算部件在小型库中很好地隔离,例如d3-force.我喜欢的一种方法是让Vue.js处理DOM操作和事件,并使用d3.js进行计算.您的可视化组件与其他组件类似,对于熟悉Vue.js但不熟悉d3.js的人来说更容易理解.

我创建了一个codepen来显示一个强制图实现:

HTML:

<div id="app">
  <svg xmlns="http://www.w3.org/2000/svg" :width="width+'px'" :height="height+'px'" @mousemove="drag($event)" @mouseup="drop()" v-if="bounds.minX">
    <line v-for="link in graph.links" :x1="coords[link.source.index].x" :y1="coords[link.source.index].y" :x2="coords[link.target.index].x" :y2="coords[link.target.index].y" stroke="black" stroke-width="2"/>
    <circle v-for="(node, i) in graph.nodes" :cx="coords[i].x" :cy="coords[i].y" :r="20" :fill="colors[Math.ceil(Math.sqrt(node.index))]" stroke="white" stroke-width="1" @mousedown="currentMove = {x: $event.screenX, y: $event.screenY, node: node}"/>
  </svg>
</div>
Run Code Online (Sandbox Code Playgroud)

使用Javascript:

new Vue({
  el: '#app',
  data: {
    graph: {
      nodes: d3.range(100).map(i => ({ index: i, x: null, y: null })),
      links: d3.range(99).map(i => ({ source: Math.floor(Math.sqrt(i)), target: i + 1 }))
    },
    width: Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
    height: Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - 40,
    padding: 20,
    colors: ['#2196F3', '#E91E63', '#7E57C2', '#009688', '#00BCD4', '#EF6C00', '#4CAF50', '#FF9800', '#F44336', '#CDDC39', '#9C27B0'],
    simulation: null,
    currentMove: null
  },
  computed: {
    bounds() {
      return {
        minX: Math.min(...this.graph.nodes.map(n => n.x)),
        maxX: Math.max(...this.graph.nodes.map(n => n.x)),
        minY: Math.min(...this.graph.nodes.map(n => n.y)),
        maxY: Math.max(...this.graph.nodes.map(n => n.y))
      }
    },
    coords() {
      return this.graph.nodes.map(node => {
        return {
          x: this.padding + (node.x - this.bounds.minX) * (this.width - 2*this.padding) / (this.bounds.maxX - this.bounds.minX),
          y: this.padding + (node.y - this.bounds.minY) * (this.height - 2*this.padding) / (this.bounds.maxY - this.bounds.minY)
        }
      })
    }
  },
  created(){
     this.simulation = d3.forceSimulation(this.graph.nodes)
        .force('charge', d3.forceManyBody().strength(d => -100))
        .force('link', d3.forceLink(this.graph.links))
        .force('x', d3.forceX())
        .force('y', d3.forceY())
  },
  methods: {
    drag(e) {
      if (this.currentMove) {
        this.currentMove.node.fx = this.currentMove.node.x - (this.currentMove.x - e.screenX) * (this.bounds.maxX - this.bounds.minX) / (this.width - 2 * this.padding)
        this.currentMove.node.fy = this.currentMove.node.y -(this.currentMove.y - e.screenY) * (this.bounds.maxY - this.bounds.minY) / (this.height - 2 * this.padding)
        this.currentMove.x = e.screenX
        this.currentMove.y = e.screenY
      }
    },
    drop(){
      delete this.currentMove.node.fx
      delete this.currentMove.node.fy    
      this.currentMove = null
      this.simulation.alpha(1)
      this.simulation.restart()
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

我看到的主要缺点是,如果你有一个大的d3.js代码库,你想在你的Vue.js应用程序中重用,因为你必须重写它.您还将找到许多用纯d3.js语法编写的示例,您必须对它们进行调整.