Vue+D3实现直方图与力导向图

本文档详细介绍了如何在Vue3环境下结合D3.js库,创建直方图和力导向图。首先,介绍了Node.js、Vue和Vite的基础知识及安装步骤。接着,通过配置环境,利用npm安装必要的依赖。然后,展示了如何在Vue组件中编写代码,分别绘制随机数据的直方图和基于《爱情公寓》人物关系的力导向图,并提供了完整的代码示例。最后,通过app.vue组件展示了直方图和力导向图的整合效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、基础知识

Node.js :是运行在服务端的 JavaScript,Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。

Vue: The Progressive JavaScript Framework 目前最为流行的前端框架之一,不可否认的是它相比 React 的学习曲线要更为平缓。

VITE:Native-ESM powered web dev build tool. ⾯向未来的前端构建⼯具。

D3:D3.js是一个用于网页作图、生成互动图形的JavaScript函数库。它提供一个d3对象,所有方法都通过这个对象调用。

二、环境配置

1.node.js安装

下载链接:https://nodejs.org/en/download/
认准LTS版本,下载安装即可。

2.Vue安装

在nodejs根目录下执行以下命令:

npm install vue

npm:包管理⼯具,已随 Node.js 默认安装。

结果如下:

3.安装vite:

npm install vite  安装Vite 包
npm init vite-app hellovue   创建工程
npm run dev     运行

结果如下:
在这里插入图片描述

三、Vue+D3绘制直方图和力导向图

1.直方图

hist.vue: 数据为随机数

<template>
    <h2><a href="https://d3js.org" target="_blank" >D3直方图@VUE3</a></h2>
    <div id="hist-container"></div>
</template>

<script>
import { defineComponent } from 'vue';
//import axios from "axios";
import * as d3 from "d3";

var data=new Array(20);
for (var i=0;i<20;i++)
{
    data[i]=Math.floor(Math.random()*255);           
    console.log(data[i]);
}
var color=d3.schemeCategory10;

export default defineComponent({
    mounted() {      
        this.drawBarChart(data);      
    },
    methods:{
        drawBarChart(data){
            var w=window.innerWidth|| document.documentElement.clientWidth|| document.body.clientWidth;
			var h=window.innerHeight|| document.documentElement.clientHeight|| document.body.clientHeight;
			w=w*0.98;
			h=h*0.5;
            var svg=d3.select("#hist-container")
                        .append("svg")
                        .attr("width",w)
                        .attr("height",h);

            svg.selectAll("rect")
               .data(data)
               .enter()
               .append("rect")
               .attr("fill",(d,i)=>color[i%10])
               .attr("x",function(d,i){
                   return w*i/20;
               })
               .attr("y",d=>(h-d))
               .attr("height",d=>d)
               .attr("width",w*0.9/20);
        }
    }
})
</script>

2.力导向图(可拖拽)

force.vue: 数据采用电视剧《爱情公寓》人物关系网络

<template>
    <h2><a href="https://d3js.org" target="_blank" >D3力导向图@VUE3</a></h2>
    <div id="force-container"></div>
</template>

<script>
import { defineComponent } from 'vue';
//import axios from "axios";
import * as d3 from "d3";

var color=d3.schemeCategory10;

var nodes = [
				{"name":"爱情公寓"},
				{"name":"曾小贤"},
				{"name":"胡一菲"},
				{"name":"吕子乔"},
				{"name":"陈美嘉"},
				{"name":"关谷神奇"},
				{"name":"唐悠悠"},
				{"name":"陆展博"},
				{"name":"林宛瑜"},
				{"name":"张伟"},
				{"name":"诸葛大力"},
				{"name":"秦羽墨"},
				{"name":"诺澜"},
				{"name":"Lisa榕"},
				{"name":"杜俊"},
				{"name":"赵海棠"},
				{"name":"咖喱酱"}
			];
var links = [
				{"source":1,"target":0,"relation":"租户"},
				{"source":2,"target":0,"relation":"租户"},
				{"source":3,"target":0,"relation":"租户"},
				{"source":4,"target":0,"relation":"租户"},
				{"source":5,"target":0,"relation":"租户"},
				{"source":6,"target":0,"relation":"租户"},
				{"source":7,"target":0,"relation":"租户"},
				{"source":8,"target":0,"relation":"租户"},
				{"source":9,"target":0,"relation":"租户"},
				{"source":10,"target":0,"relation":"租户"},
				{"source":11,"target":0,"relation":"租户"},
				{"source":15,"target":0,"relation":"租户"},
				{"source":16,"target":0,"relation":"租户"},
				{"source":1,"target":2,"relation":"夫妻"},
				{"source":1,"target":13,"relation":"上下级"},
				{"source":1,"target":12,"relation":"同事&喜欢"},
				{"source":2,"target":7,"relation":"姐弟"},
				{"source":2,"target":11,"relation":"同学"},
				{"source":2,"target":12,"relation":"情敌"},
				{"source":3,"target":4,"relation":"夫妻"},
				{"source":3,"target":6,"relation":"小姨妈/大外甥"},
				{"source":3,"target":13,"relation":"暗恋"},
				{"source":4,"target":6,"relation":"闺蜜"},
				{"source":5,"target":6,"relation":"夫妻"},
				{"source":5,"target":14,"relation":"师兄弟"},
				{"source":7,"target":8,"relation":"情侣"},
				{"source":9,"target":10,"relation":"情侣"},
				{"source":9,"target":15,"relation":"情敌"},
				{"source":9,"target":16,"relation":"助理"},
				{"source":10,"target":15,"relation":"同学"},
				{"source":10,"target":2,"relation":"师生"},
				{"source":15,"target":10,"relation":"追求"},
				{"source":15,"target":2,"relation":"师生"},
				{"source":13,"target":12,"relation":"同学"}
			];

export default defineComponent({
    mounted() {      
        this.drawBarChart(nodes,links);      
    },
    methods:{
        drawBarChart(nodes,links){
            var w=window.innerWidth|| document.documentElement.clientWidth|| document.body.clientWidth;
			var h=window.innerHeight|| document.documentElement.clientHeight|| document.body.clientHeight;
			w=w*0.98;
			h=h*0.9;
            var svg=d3.select("#force-container")
                        .append("svg")
                        .attr("width",w)
                        .attr("height",h*1.2);
            var forceSimulation = d3.forceSimulation()
                                    .force("link",d3.forceLink())
                                    .force("charge",d3.forceManyBody().strength(-800))
                                    .force("center",d3.forceCenter(w/2,h/2));
            forceSimulation.nodes(nodes)
                           .on("tick");
            forceSimulation.force("link")
                           .links(links)
                           .distance(180);
            var link=svg.selectAll(".link")
                        .data(links)
                        .enter()
                        .append("line")
                        .attr("class","link")
                        .style("stroke-width",1)
                        .style("stroke",(d,i)=>color[i%10])
					    .style("opacity",0.6);
            var node=svg.selectAll(".node")
                        .data(nodes)
                        .enter()
                        .append("circle")
                        .attr("r",16)
                        .style("fill",(d,i)=>color[i%10])
                        .call(drag()); 
            forceSimulation.on("tick",()=>{
                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);
                node.attr("cx",d=>d.x)
                    .attr("cy",d=>d.y);
                edges_text.attr("x",d=>(d.source.x + d.target.x) / 2 )
					.attr("y",d=>(d.source.y + d.target.y) / 2 );
                texts.attr("x",d=>d.x)
					 .attr("y",d=>d.y);
            });
            function drag()
            {
                function dragstarted(event,d){
                    if(!event.active)   forceSimulation.alphaTarget(0.3).restart();
                    d.fx=d.x;
                    d.fy=d.y;
                }
                function dragged(event,d){
                    d.fx=event.x;
                    d.fy=event.y;
                }
                function dragended(event,d){
                    if(!event.active)   forceSimulation.alphaTarget(0);
                    d.fx=null;
                    d.fy=null;
                }
                return d3.drag()
                         .on("start",dragstarted)
                         .on("drag",dragged)
                         .on("end",dragended);
            };
            var edges_text = svg.selectAll(".linetext")
							.data(links)
							.enter()
							.append("text")
							.attr("class","linetext")
							.text(d=> d.relation)
							.style("stroke",(d,i)=>color[i%10])
							.style("font-size",10);	                
            var texts=svg.selectAll(".forceText")
			 .data(nodes)
			 .enter()
			 .append("text")
			 .attr("class","forceText")
			 .style("stroke",(d,i)=>color[i%10])
			 .style("font-size","12px")
			 .attr("text-anchor","middle")
			 .attr("dy",30)
			 .text(d=>d.name);
            
        }
    }
})
</script>

3.结果展示

app.vue:

<template>
  <BarChart />
  <Hist />
</template>

<script>
import BarChart from './components/force.vue';
import Hist from './components/hist.vue';

export default {
  name: 'App',
  components: {
    BarChart,
    Hist
}
}
</script>

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值