使用 JavaScript 方法创建图形可视化数据

2025-05-24

使用 JavaScript 创建图表

方法

可视化数据

图是由一系列带有边的节点组成的数据结构。图可以是有向的,也可以是无向的。

有向包含的边的功能类似于单行道。边从一个节点流向另一个节点。

例如,您可能有一个人物和电影的图表,其中每个人可以有几部喜欢的电影,但电影没有喜欢的人。

有向图

无向图包含双向流动的边,类似于双向通行的双车道道路。

例如,你可能有一张宠物图,其中每只宠物都有一个主人,每个主人也拥有一只宠物。注意:双向箭头代表一条边,但为了清晰起见,我画了两条箭头。

无向图

图表中没有清晰的信息层次。

方法

我们将构建一个关于人和冰淇淋口味的图。它将是一个有向图,因为人们可能喜欢某些口味,但口味并不喜欢人。

我们将创建三个类:

  • PersonNode
  • IceCreamFlavorNode
  • Graph

人员节点

该类PersonNode将接受一个参数:一个人的名字。这将作为其标识符。

构造函数PersonNode将包含两个属性:

  • name:唯一标识符
  • favoriteFlavors:IceCreamFlavorNodes 数组

此外,该类PersonNode将包含一个方法:addFlavor。它将接受一个参数,IceCreamFlavorNode并将其添加到favoriteFlavors数组中。

类定义如下:



class PersonNode {
  constructor(name) {
    this.name = name;
    this.favoriteFlavors = [];
  }

  addFlavor(flavor) {
    this.favoriteFlavors.push(flavor);
  }
}


Enter fullscreen mode Exit fullscreen mode

冰淇淋口味节点

该类IceCreamFlavorNode将接受一个参数:冰淇淋口味。这将作为其标识符。

这个类不需要包含任何方法,因为这是一个无向图,数据从人流向口味,但不能向后流。

类定义如下:



class IceCreamFlavorNode {
  constructor(flavor) {
    this.flavor = flavor;
  }
}


Enter fullscreen mode Exit fullscreen mode

图形

该类Graph不会接受任何参数,但其构造函数将包含三个属性:

  • peopleNodes:PersonNode 数组。
  • iceCreamFlavorNodes:IceCreamFlavorNodes 数组
  • edges:包含 PersonNodes 和 IceCreamFlavorNodes 之间的边的数组。

Graph 类包含六种方法:

  • addPersonNode(name):接受一个参数,即一个人的名字,PersonNode用这个名字创建一个新名字,然后将其推送到peopleNodes数组中。
  • addIceCreamFlavorNode(flavor):接受一个参数,一种冰淇淋口味,创建一个IceCreamFlavorNode具有这种口味的新冰淇淋,并将其推送到iceCreamFlavorNodes数组中。
  • getPerson(name):接受一个参数,即一个人的名字,并返回该人的节点。
  • getFlavor(flavor):接受一个参数,一种冰淇淋口味,并返回该口味的节点。
  • addEdge(personName, flavorName):接受两个参数,一个人的名字和冰淇淋口味,检索两个节点,将口味添加到人的favoriteFlavors数组中,并将边推送到边缘数组。
  • print():只需打印出数组中的每个人peopleNodes及其最喜欢的冰淇淋口味。

类定义如下:



class Graph {
  constructor() {
    this.peopleNodes = [];
    this.iceCreamFlavorNodes = [];
    this.edges = [];
  }

  addPersonNode(name) {
    this.peopleNodes.push(new PersonNode(name));
  }

  addIceCreamFlavorNode(flavor) {
    this.iceCreamFlavorNodes.push(new IceCreamFlavorNode(flavor));
  }

  getPerson(name) {
    return this.peopleNodes.find(person => person.name === name);
  }

  getFlavor(flavor) {
    return this.iceCreamFlavorNodes.find(flavor => flavor === flavor);
  }

  addEdge(personName, flavorName) {
    const person = this.getPerson(personName);
    const flavor = this.getFlavor(flavorName);
    person.addFlavor(flavor);
    this.edges.push(`${personName} - ${flavorName}`);
  }

  print() {
    return this.peopleNodes.map(({ name, favoriteFlavors }) => {
      return `${name} => ${favoriteFlavors.map(flavor => `${flavor.flavor},`).join(' ')}`;
    }).join('\n')
  }
}


Enter fullscreen mode Exit fullscreen mode

可视化数据

现在我们有了三个类,我们可以添加一些数据并进行测试:



const graph = new Graph(true);
graph.addPersonNode('Emma');
graph.addPersonNode('Kai');
graph.addPersonNode('Sarah');
graph.addPersonNode('Maranda');
graph.addIceCreamFlavorNode('Chocolate Chip');
graph.addIceCreamFlavorNode('Strawberry');
graph.addIceCreamFlavorNode('Cookie Dough');
graph.addIceCreamFlavorNode('Vanilla');
graph.addIceCreamFlavorNode('Pistachio');

graph.addEdge('Emma', 'Chocolate Chip');
graph.addEdge('Emma', 'Cookie Dough');
graph.addEdge('Emma', 'Vanilla');
graph.addEdge('Kai', 'Vanilla');
graph.addEdge('Kai', 'Strawberry');
graph.addEdge('Kai', 'Cookie Dough');
graph.addEdge('Kai', 'Chocolate Chip');
graph.addEdge('Kai', 'Pistachio');
graph.addEdge('Maranda', 'Vanilla');
graph.addEdge('Maranda', 'Cookie Dough');
graph.addEdge('Sarah', 'Strawberry');

console.log(graph.print());


Enter fullscreen mode Exit fullscreen mode

我们的有向图如下所示:

有向图


如果您想查看完整的代码,请查看我的CodePen

文章来源:https://dev.to/emmabostian/creating-graphs-with-javascript-4efm
PREV
使用 JavaScript 创建链表 什么是链表? 节点 NodeList
NEXT
滚动条 CSS 用 24 行 CSS 创建自定义滚动条 HTML。CSS。JavaScript。结论。