Arhn - архитектура программирования

Как сделать график на VueJS

Пытаюсь построить график с данными, полученными от API, и нанести его на график (https://bl.ocks.org/mbostock/4062045) — принудительно направленный график

Однако я не уверен, как это делается на VueJs или есть ли для этого более простой инструмент?

D3 Force-Directed Graph кажется немного сложным, может быть, уже есть библиотека, которая делает это из коробки?

25.04.2017


Ответы:


1

Упомянутый пакет vue-d3 из комментария просто добавляет D3 к прототипу Vue, поэтому он доступен с this.$d3.

Я протестировал этот пакет, но он не работал с моей версией D3. Похоже на проблему с корпусом (D3 вместо d3). Поэтому я добавил прототип вручную.

Я не знаю, есть ли более простая библиотека для создания графика силы, но, пожалуйста, взгляните на демонстрацию ниже или на этот скрипка.

Я изменил пример из вашей ссылки, чтобы создать граф, ориентированный на силу. Демо работает, но, как вы упомянули, оно довольно сложное. Также может быть улучшена привязка 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" 
    	@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>

26.04.2017

2

Я ответил на другой вопрос о vue + d3, предоставив пример графа силы d3 с vue.js.

d3.js теперь разделен на небольшие модули, а определенные вычисления изолированы в небольших компонентах, таких как d3-force. SVG можно нарисовать в шаблоне компонента, как и любую другую структуру HTML.

28.04.2017

3

Вы можете использовать vue-d3-сеть

npm install vue-d3-network см. эту скрипку

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
      }
    }
  },
})

```

10.10.2018
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..