使用 D3.js 和 Vue 可视化 RDF 三元组

问题描述 投票:0回答:1

我在网上找到了一个非常好的示例,介绍了如何使用 D3 可视化 RDF 三元组。输出如下所示:

我正在尝试在 Vue 中重新创建示例,但我没有成功生成正确的可视化,也没有使我的节点可拖动。我确信我错过了

mounted
方法中的几个重要步骤(我有基本的 Vue 知识)。我的整个代码可以在 GitHub 上找到,但我还在下面添加了最重要的代码。任何帮助将非常感激。当前输出如下所示:

这是我的主要代码:

<template>
  <div>
    <svg></svg>
  </div>
</template>
<script>
import * as d3 from "d3";
import {triplesToGraph} from "@/components/functions/triplesToGraph";

export default {
  mounted() {
    const width = 800;
    const height = 500;
    const triples = [
      {subject:"ex:ThaiLand",   predicate:"ex:hasFood",     object:"ex:TomYumKung"},
      {subject:"ex:TomYumKung",     predicate:"rdf:type",       object:"ex:SpicyFood"},
      {subject:"ex:TomYumKung",     predicate:"ex:includes",    object:"ex:shrimp"},
      {subject:"ex:TomYumKung",     predicate:"ex:includes",    object:"ex:chilly"},
      {subject:"ex:TomYumKung",     predicate:"ex:includes",    object:"ex:lemon"},
      {subject:"ex:lemon",      predicate:"ex:hasTaste",    object:"ex:sour"},
      {subject:"ex:chilly",         predicate:"ex:hasTaste",    object:"ex:spicy"}
    ];

    var graph = triplesToGraph(triples);
    const svg = d3.select("svg").attr("width", width).attr("height", height);

    function ticked() {
      var links = svg.selectAll(".link")
          .data(graph.links)
          .enter()
          .append("line")
          .attr("marker-end", "url(#end)")
          .attr("class", "link")
          .attr("stroke-width",1)
      ;//links


      // ==================== Add Link Names =====================
      var linkTexts = svg.selectAll(".link-text")
          .data(graph.links)
          .enter()
          .append("text")
          .attr("class", "link-text")
          .text( function (d) { return d.predicate; })
      ;
      // ==================== Add Link Names =====================
      var nodeTexts = svg.selectAll(".node-text")
          .data(graph.nodes)
          .enter()
          .append("text")
          .attr("class", "node-text")
          .text( function (d) { return d.label; })
      ;

      // ==================== Add Node =====================
      var nodes = svg.selectAll(".node")
          .data(graph.nodes)
          .enter()
          .append("circle")
          .attr("class", "node")
          .attr("r",8)
          // .call(force.drag)

      nodes
          .attr("cx", function(d){ return d.x; })
          .attr("cy", function(d){ return d.y; })
      ;

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

      nodeTexts
          .attr("x", function(d) { return d.x + 12 ; })
          .attr("y", function(d) { return d.y + 3; })
      ;


      linkTexts
          .attr("x", function(d) { return 4 + (d.source.x + d.target.x)/2  ; })
          .attr("y", function(d) { return 4 + (d.source.y + d.target.y)/2 ; })
      ;
    }

    var force = d3.forceSimulation(graph.nodes)
        .force("link", d3.forceLink(graph.links).id(d => d.id))
        .force("charge", d3.forceManyBody())
        .force("center", d3.forceCenter(width / 2, height / 2))
        .on("tick", ticked);
  },
};
</script>

我发现这也是一个非常有用的链接:https://observablehq.com/@d3/force-directed-graph/2?intent=fork

html vue.js d3.js visualization rdf
1个回答
0
投票

这里发生了一些事情。主要问题是存储库使用的 d3 版本是 d3 v3,而您在存储库中导入的版本是 d3 v7,因此语法非常不同。然后

links
linkTexts
nodeTexts
等应在
ticked
功能之前启动。然后,您确实提到拖动不起作用,那是因为您评论了该行:

// .call(force.drag)

但是取消注释后,

force.drag
仍然是错误,所以我们需要实现我们自己的可拖动(取自这个示例):

    function dragstart() {
      d3.select(this).classed("fixed", true);
    }

    function clamp(x, lo, hi) {
      return x < lo ? lo : x > hi ? hi : x;
    }

    function dragged(event, d) {
      d.fx = clamp(event.x, 0, width);
      d.fy = clamp(event.y, 0, height);
      force.alpha(1).restart();
    }

    const drag = d3.drag().on("start", dragstart).on("drag", dragged);

然后我们可以取消注释我提到的行并传递

drag
变量:

    var nodes = svg
      .selectAll(".node")
      .data(graph.nodes)
      .enter()
      .append("circle")
      .attr("class", "node")
      .attr("r", 8)
      .call(drag);

最后,您还可以从您提供的示例中复制粘贴 CSS。

如果您想现场观看,这是codesandbox 中的完整演示:

Edit dawn-river-cfctxg

© www.soinside.com 2019 - 2024. All rights reserved.