【大屏可视化】系统(Vue3 + ECharts5)
- Vue
- 2025-06-26
- 21热度
01:前言
资源地址:https://gitee.com/wangming956514476/imooc-visualization.git
这一小节,我们将要来实现一个地图可视化的项目,项目最终的实现效果如下:

整个可视化项目,一共分为 8 部分。
这八部分我们会按照,难易的顺序来进行绘制,尽量帮助大家可以以 逐步深入 的方式掌握大屏可视化的内容。
- 横向柱形图
- 竖向柱形图
- 雷达图
- 环形图
- 关系图
- 数据云图
- 数据展示图
- 地图可视化
那么明确好了,本章的内容之后,下面这一章的项目开发吧~~
02:基于 vite 与 tailwindcss 创建大屏可视化项目
那么这一小节,咱们就基于 vite+tailwindcss
构建大屏可视化项目 imooc-visualization
。
- 基于
vite
创建项目,使用:
npm create vite@latest
Code language: CSS (css)
- 选择脚手架配置,使用
vue3
:
✔ Project name: … imooc-visualization
✔ Select a framework: › Vue
✔ Select a variant: › JavaScript
接下来 导入 tailwindcss ,按照文档给出的步骤即可。
因为咱们的大屏可视化项目仅包含一个页面,所以可以直接在 APP.vue
中进行布局。
- 导入课程资源
imooc-visualization/src/assets
,包含fonts
、imgs
和MapData
- 在
imooc-visualization/src/App.vue
中进行布局,整体的布局应该分为 左、中、右 三部分,并创建对应组件:
<template>
<div
class="bg-[url("assets/imgs/bg.jpg")] bg-cover bg-center h-screen text-white p-5 flex overflow-hidden"
>
<div class="flex-1 mr-5 bg-opacity-50 bg-slate-800 p-3 flex flex-col">
<em><!-- 横向柱状图 --></em>
<HorizontalBar class="h-1/3 box-border pb-4" />
<em><!-- 雷达图 --></em>
<RadarBar class="h-1/3 box-border pb-4" />
<em><!-- 数据传递关系图 --></em>
<Relation class="h-1/3" />
</div>
<div class="w-1/2 mr-5 flex flex-col">
<em><!-- 数据展示图 --></em>
<TotalData class="bg-opacity-50 bg-slate-800 p-3" />
<em><!-- 地图可视化 --></em>
<MapChart class="bg-opacity-50 bg-slate-800 p-3 mt-4 flex-1" />
</div>
<div class="flex-1 bg-opacity-50 bg-slate-800 p-3 flex flex-col">
<em><!-- 竖向柱状图 --></em>
<VerticalBar class="h-1/3 box-border pb-4" />
<em><!-- 环形资源站比图 --></em>
<RadiueBar class="h-1/3 box-border pb-4" />
<em><!-- 文档云图 --></em>
<WordCloud class="h-1/3 box-border" />
</div>
</div>
</template>
<script setup>
import HorizontalBar from './components/HorizontalBar.vue'
import RadarBar from './components/RadarBar.vue'
import Relation from './components/Relation.vue'
import TotalData from './components/TotalData.vue'
import MapChart from './components/MapChart.vue'
import VerticalBar from './components/VerticalBar.vue'
import RadiueBar from './components/RadiueBar.vue'
import WordCloud from './components/WordCloud.vue'
</script>
Code language: HTML, XML (xml)
此时,展示的内容如下:

03:导入 echarts 与 axios ,获取大屏动态数据
在大屏可视化中,数据通常是动态进行展示的,所以我们需要依赖 axios
获取服务端数据,依赖 echarts
进行展示,同时需要 定时获取数据,以保证数据的实时性。
- 安装
echarts
与axios
:
npm i --save echarts@5.4.2 axios@1.4.0
Code language: CSS (css)
- 创建
imooc-visualization/src/utils/request.js
文件:
import axios from 'axios'
const service = axios.create({
baseURL: 'https://api.imooc-web.lgdsunday.club/api',
timeout: 5000
})
<em>// 请求拦截器</em>
service.interceptors.request.use(
(config) => {
config.headers.icode = 'input you icode'
return config <em>// 必须返回配置</em>
},
(error) => {
return Promise.reject(error)
}
)
<em>// 响应拦截器</em>
service.interceptors.response.use((response) => {
const { success, message, data } = response.data
<em>// 要根据success的成功与否决定下面的操作</em>
if (success) {
return data
} else {
return Promise.reject(new Error(message))
}
})
export default service
Code language: JavaScript (javascript)
- 创建
imooc-visualization/src/api/visualization.js
文件:
import request from '@/utils/request.js'
<em>/**
* 数据可视化
*/</em>
export const getVisualization = () => {
return request({
url: '/visualization'
})
}
Code language: PHP (php)
- 注意:
**vite**
中默认并不支持**@**
符号,所以需要在vite.config.js
中进行配置:
<em>// https://vitejs.dev/config/</em>
export default defineConfig({
plugins: [vue()],
<em>// 为 ./src 提供别名 @</em>
resolve: {
alias: {
'@': './src'
}
},
<em>// 主动开启热更新</em>
server: {
hmr: true
}
})
Code language: JavaScript (javascript)
- 在
imooc-visualization/src/App.vue
中发起数据请求,并通过定时器定时获取数据:
import { ref } from 'vue'
import { getVisualization } from '@/api/visualization.js'
const data = ref(null)
const loadData = async () => {
data.value = await getVisualization()
console.log(data.value)
}
loadData()
setInterval(() => {
loadData()
}, 3000)
Code language: JavaScript (javascript)
那么此时,我们就已经拿到了大屏的动态数据。下一小节,我们就根据这个数据,绘制横向的柱形图。
04:绘制大区横向柱形图
在上一小节中,我们拿到了大屏数据,数据中的 regionData
即为 大区横向柱形图 数据。
所以,我们就可以依赖该数据,进行图形绘制:
- 在
App.vue
中,数据获取成功之后,在进行渲染:
<div
class="bg-[url("assets/imgs/bg.jpg")] bg-cover bg-center h-screen text-white p-2 flex overflow-hidden"
v-if="data"
>
Code language: JavaScript (javascript)
- 在
App.vue
中,传递指定数据到HorizontalBar
:
<em><!-- 横向柱状图 --></em>
<HorizontalBar class="h-1/3 box-border pb-4" :data="data.regionData" />
Code language: HTML, XML (xml)
- 在
imooc-visualization/src/components/HorizontalBar.vue
中,通过defineProps
接收数据:
const props = defineProps({
data: {
type: Object,
required: true
}
})
Code language: JavaScript (javascript)
此时,数据已经得到。
接下来我们根据数据绘制 echarts
图表。
echarts
图表的绘制,大体分为三步:
- 根据
DOM
实例,通过echarts.init
方法,生成echarts
实例 - 构建
options
配置对象,整个echarts
的样式,皆有该对象决定 - 最后通过
实例.setOption
方法,设置配置对象
配置对象是 echarts
中最复杂的部分,也就是 核心。
所有的配置项内容,都可以通过 这里 进行查阅
如果你之前 从未 使用过 echarts
,那么特别建议你先看一下 快速入门 。
那么根据刚才所描述的三步,我们可以根据数据,构建出如下代码:
<template>
<div>
<div>【大区数据信息】</div>
<div ref="target" class="w-full h-full"></div>
</div>
</template>
Code language: HTML, XML (xml)
<em>// 获取 dom 实例</em>
const target = ref(null)
<em>// echarts 实例变量</em>
let mChart = null
<em>// 在 mounted 生命周期之后,实例化 echarts</em>
onMounted(() => {
mChart = echarts.init(target.value)
<em>// 渲染 echarts</em>
renderChart()
})
<em>// 渲染图表</em>
const renderChart = () => {
const options = {
<em>// X 轴展示数据</em>
xAxis: {
<em>// 数据展示</em>
type: 'value',
<em>// 不显示轴</em>
show: false,
<em>// 最大值(防止触顶)</em>
max: function (value) {
<em>// 取整</em>
return parseInt(value.max * 1.2)
}
},
<em>// Y 轴展示选项</em>
yAxis: {
type: 'category',
<em>// 根据根据服务端数据筛选</em>
data: props.data.regions.map((item) => item.name),
<em>// 反向展示</em>
inverse: true,
<em>// 不展示轴线</em>
axisLine: {
show: false
},
<em>// 不展示刻度</em>
axisTick: {
show: false <em>// 取消 Y 轴刻度</em>
},
<em>// 文字色值</em>
axisLabel: {
color: '#9EB1C8'
}
},
<em>// echarts 网格绘制的位置,对应 上、右、下、左</em>
grid: {
top: 0,
right: 0,
bottom: 0,
left: 0,
<em>// 计算边距时,包含标签</em>
containLabel: true
},
<em>// 柱形图核心配置</em>
series: [
{
<em>// 图表类型</em>
type: 'bar',
<em>// 数据筛选</em>
data: props.data.regions.map((item) => ({
name: item.name,
value: item.value
})),
<em>// 显示背景</em>
showBackground: true,
<em>// 背景色</em>
backgroundStyle: {
color: 'rgba(180, 180, 180, 0.2)'
},
<em>// 每个轴的样式</em>
itemStyle: {
color: '#479AD3', <em>// 设置柱子的颜色</em>
barBorderRadius: 5, <em>// 设置柱子的圆角</em>
shadowColor: 'rgba(0, 0, 0, 0.3)', <em>// 设置柱子的阴影颜色</em>
shadowBlur: 5 <em>// 设置柱子的阴影模糊大小</em>
},
<em>// 轴宽度</em>
barWidth: 12,
<em>// 轴上的字体</em>
label: {
show: true,
<em>// 设置标签位置为右侧</em>
position: 'right',
textStyle: {
<em>// 设置标签文本颜色</em>
color: '#fff'
}
}
}
]
}
mChart.setOption(options)
}
Code language: JavaScript (javascript)
那么此时,一个基础的横向图表绘制完成。
同时,因为我们需要 动态更新图表,所以我们需要通过 watch
监听数据变化的行为,重新渲染视图:
<em>// 监听数据的变化,重新渲染图表</em>
watch(
() => props.data,
() => {
renderChart()
}
)
Code language: JavaScript (javascript)
至此,横向柱形图渲染完成。
05:绘制服务竖向柱形图
上一小节,我们简单的利用 echarts
的特性,绘制了横向的柱形图,那么接下来我们就趁热打铁,再来绘制一个 竖向柱形图。
还是使用 visualization
接口,数据属性为 serverData
。
整体的流程还是分为三步:
- 把数据传递到
VerticalBar
组件 - 构建
echarts
容器 - 利用
option
绘制图表
最终代码如下:
<template>
<div>
<div>【服务资源占用比】</div>
<div ref="target" class="w-full h-full"></div>
</div>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import * as echarts from 'echarts'
<em>// 不要忘记从父组件传递数据</em>
const props = defineProps({
data: {
type: Object,
required: true
}
})
const target = ref(null)
let mChart = null
onMounted(() => {
mChart = echarts.init(target.value)
renderChart()
})
const renderChart = () => {
const options = {
<em>// X 轴展示选项</em>
xAxis: {
type: 'category',
<em>// 根据根据服务端数据筛选</em>
data: props.data.servers.map((item) => item.name),
<em>// 文字色值</em>
axisLabel: {
color: '#9EB1C8'
}
},
<em>// Y 轴展示数据</em>
yAxis: {
<em>// 数据展示</em>
type: 'value',
<em>// 不显示轴</em>
show: false,
<em>// 最大值(防止触顶)</em>
max: function (value) {
<em>// 取整</em>
return parseInt(value.max * 1.2)
}
},
<em>// echarts 网格绘制的位置,对应 上、右、下、左</em>
grid: {
top: 16,
right: 0,
bottom: 26,
left: -26,
<em>// 计算边距时,包含标签</em>
containLabel: true
},
<em>// 柱形图核心配置</em>
series: {
<em>// 柱形图</em>
type: 'bar',
<em>// 数据筛选</em>
data: props.data.servers.map((item) => ({
name: item.name,
value: item.value
})),
<em>// 每个轴的样式</em>
itemStyle: {
color: '#479AD3', <em>// 设置柱子的颜色</em>
barBorderRadius: 5, <em>// 设置柱子的圆角</em>
shadowColor: 'rgba(0, 0, 0, 0.3)', <em>// 设置柱子的阴影颜色</em>
shadowBlur: 5 <em>// 设置柱子的阴影模糊大小</em>
},
<em>// 柱子宽度</em>
barWidth: 12,
<em>// 文本</em>
label: {
show: true,
<em>// 设置标签位置为右侧</em>
position: 'top',
textStyle: {
<em>// 设置标签文本颜色</em>
color: '#fff'
},
formatter: '{c}%'
}
}
}
mChart.setOption(options)
}
<em>// 监听数据的变化,重新渲染图表</em>
watch(
() => props.data,
() => {
renderChart()
}
)
</script>
Code language: HTML, XML (xml)
06:绘制报警风险雷达图
前面两个小节,咱们创建了基本的柱形图。
通过柱形图,咱们大致应该了解了 echarts
基本的运行方式。
所以说,接下来,咱们就来构建一个稍微复杂一些的图表 雷达图。
雷达图,使用 riskData
字段数据。
整个雷达图的绘制,包含 5
个重要的属性:
radar
:雷达图坐标系配置polar
:坐标居中angleAxis
:坐标角度radiusAxis
:径向轴series
:图表核心配置
最终渲染的代码如下:
<template>
<div>
<div>【云端报警风险】</div>
<div ref="target" class="w-full h-full"></div>
</div>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import * as echarts from 'echarts'
<em>// 不要忘记从父组件传递数据</em>
const props = defineProps({
data: {
type: Object,
required: true
}
})
const target = ref(null)
let mChart = null
onMounted(() => {
mChart = echarts.init(target.value)
renderChart()
})
const renderChart = () => {
const options = {
<em>// 雷达图坐标系配置</em>
radar: {
<em>// 坐标系名</em>
name: {
textStyle: {
color: '#05D5FF',
fontSize: 14
}
},
<em>// 雷达绘制类型。polygon 多边形</em>
shape: 'polygon',
<em>// 居中</em>
center: ['50%', '50%'],
<em>// 边境</em>
radius: '80%',
<em>// 开始的角度(可以避免绘制到边框之外)</em>
startAngle: 120,
<em>// 轴线配置</em>
axisLine: {
lineStyle: {
color: 'rgba(5, 213, 255, .8)'
}
},
<em>// 网格线配置</em>
splitLine: {
show: true,
lineStyle: {
width: 1,
color: 'rgba(5, 213, 255, .8)' <em>// 设置网格的颜色</em>
}
},
<em>// 指示器文字</em>
indicator: props.data.risks.map((item) => ({
name: item.name,
max: 100
})),
<em>// 不展示拆分区域</em>
splitArea: {
show: false
}
},
<em>// 坐标居中</em>
polar: {
center: ['50%', '50%'], <em>// 默认全局居中</em>
radius: '0%'
},
<em>// 坐标角度</em>
angleAxis: {
<em>// 坐标轴刻度最小值</em>
min: 0,
<em>// 坐标轴分割间隔</em>
interval: 5,
<em>// 刻度增长逆时针</em>
clockwise: false
},
<em>// 径向轴</em>
radiusAxis: {
<em>// 最小值</em>
min: 0,
<em>// 间隔</em>
interval: 20,
<em>// 不显示分割线</em>
splitLine: {
show: true
}
},
<em>// 图表核心配置</em>
series: [
{
<em>// 雷达图</em>
type: 'radar',
<em>// 拐点的样式,还可以取值'rect','angle'等</em>
symbol: 'circle',
<em>// 拐点的大小</em>
symbolSize: 10,
<em>// 折线拐点标志的样式</em>
itemStyle: {
normal: {
color: '#05D5FF'
}
},
<em>// 区域填充样式</em>
areaStyle: {
normal: {
color: '#05D5FF',
opacity: 0.5
}
},
<em>// 线条样式</em>
lineStyle: {
width: 2,
color: '#05D5FF'
},
<em>// 图形上的文本标签</em>
label: {
normal: {
show: true,
formatter: (params) => {
return params.value
},
color: '#fff'
}
},
<em>// 数据</em>
data: [
{
value: props.data.risks.map((item) => item.value)
}
]
}
]
}
mChart.setOption(options)
}
<em>// 监听数据的变化,重新渲染图表</em>
watch(
() => props.data,
() => {
renderChart()
}
)
</script>
Code language: HTML, XML (xml)
07:绘制异常处理双环形图
在前面的 echarts
图表绘制中,整体的绘制还是比较简单的。那么接下来咱们就来绘制一个稍微复杂一些的图形 双环形图。

首选我们现在分析一下双环形图的构图原理:
- 在
echarts
中,是没有提供环形图图表的。所以这里的环形图本质上是通过 饼图 来进行绘制的(只需要把饼图的内边距调大,外边距调小,就可以实现环形)。 - 每个环都是都是有两个饼图组成。其中一个饼图表示上层展示,一个饼图作为底层的背景。只需要让它们位置一致就可以得到对应的图形
- 动态变化每一对环形的位置,从而得到一个逐层向内的环形展示
那么,咱们分析完成双环形的原理之后,接下来咱们就根据数据 abnormalData
来实现这个双环形:
<template>
<div>
<div>【大区异常处理】</div>
<div ref="target" class="w-full h-full"></div>
</div>
</template>
<script setup></script>
Code language: HTML, XML (xml)
08:绘制数据传递关系图
在前面,我们绘制了很多基本的 echarts
图表。
但是在实际的企业开发中,可能会存在一些比较特殊的图表类型,比如 信息传递图 :

想要完成这样的图表,咱们需要借助两个 series
中的图表类型:
- graph:它表示 关系图,主要用于展现节点以及节点之间的关系数据。
- lines:它表示 路径图,主要用来绘制两个节点 从起点到终点 的路径。
两者之间进行结合,就可以得到咱们上面的数据关系图了。
具体代码如下:
<template>
<div>
<div>【数据传递信息】</div>
<div ref="target" class="w-full h-full"></div>
</div>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import * as echarts from 'echarts'
const props = defineProps({
data: {
type: Object,
required: true
}
})
<em>// 获取 dom 实例</em>
const target = ref(null)
<em>// echarts 实例变量</em>
let mChart = null
<em>// 在 mounted 生命周期之后,实例化 echarts</em>
onMounted(() => {
mChart = echarts.init(target.value)
<em>// 渲染 echarts</em>
renderChart()
})
<em>// 渲染图表</em>
const renderChart = () => {
const options = {
<em>// X 轴不需要展示</em>
xAxis: {
show: false,
type: 'value'
},
<em>// X 轴不需要展示</em>
yAxis: {
show: false,
type: 'value'
},
<em>// 核心数据配置</em>
series: [
{
<em>// 用于展现节点以及节点之间的关系数据</em>
type: 'graph',
<em>// 不采用任何布局</em>
layout: 'none',
<em>// 使用二维的直角坐标系</em>
coordinateSystem: 'cartesian2d',
<em>// 节点标记的大小</em>
symbolSize: 26,
<em>// z-index</em>
z: 3,
<em>// 边界标签(线条文字)</em>
edgeLabel: {
normal: {
show: true,
color: '#fff',
textStyle: {
fontSize: 14
},
formatter: function (params) {
let txt = ''
if (params.data.speed !== undefined) {
txt = params.data.speed
}
return txt
}
}
},
<em>// 圆饼下文字</em>
label: {
normal: {
show: true,
position: 'bottom',
color: '#5e5e5e'
}
},
<em>// 边两端的标记类型</em>
edgeSymbol: ['none', 'arrow'],
<em>// 边两端的标记大小</em>
edgeSymbolSize: 8,
<em>// 圆数据</em>
data: props.data.relations.map((item) => {
<em>// id 为 0 ,表示数据中心,数据中心单独设置</em>
if (item.id !== 0) {
return {
name: item.name,
category: 0,
active: true,
<em>// 位置</em>
value: item.value
}
} else {
return {
name: item.name,
<em>// 位置</em>
value: item.value,
<em>// 数据中心圆的大小</em>
symbolSize: 100,
<em>// 圆的样式</em>
itemStyle: {
normal: {
<em>// 渐变色</em>
color: {
colorStops: [
{ offset: 0, color: '#157eff' },
{ offset: 1, color: '#35c2ff' }
]
}
}
},
<em>// 字体</em>
label: { normal: { fontSize: '14' } }
}
}
}),
<em>// 线</em>
links: props.data.relations.map((item, index) => ({
<em>// 方向</em>
source: item.source,
target: item.target,
<em>// 线上的文字</em>
speed: `${item.speed}kb/s`,
<em>// 线的样式</em>
lineStyle: { normal: { color: '#12b5d0', curveness: 0.2 } },
<em>// 文字位置</em>
label: {
show: true,
position: 'middle',
offset: [10, 0]
}
}))
},
{
<em>// 用于带有起点和终点信息的线数据的绘制</em>
type: 'lines',
<em>// 使用二维的直角坐标系</em>
coordinateSystem: 'cartesian2d',
<em>// z-index</em>
z: 1,
<em>// 线特效的配置</em>
effect: {
show: true,
smooth: false,
trailLength: 0,
symbol: 'arrow',
color: 'rgba(55,155,255,0.5)',
symbolSize: 12
},
<em>// 线的样式</em>
lineStyle: {
normal: {
curveness: 0.2
}
},
<em>// 线的数据级,前后线需要重合。数据固定</em>
data: [
[{ coord: [0, 300] }, { coord: [50, 200] }],
[{ coord: [0, 100] }, { coord: [50, 200] }],
[{ coord: [50, 200] }, { coord: [100, 100] }],
[{ coord: [50, 200] }, { coord: [100, 300] }]
]
}
]
}
mChart.setOption(options)
}
<em>// 监听数据的变化,重新渲染图表</em>
watch(
() => props.data,
() => {
renderChart()
}
)
</script>
Code language: HTML, XML (xml)
09:绘制关键词条文档云图
在前面的图表中,我们都是基于 echarts
的原生图表支持进行的绘制。但是有些情况下,某些图表我们需要依赖插件才可以完成对应的绘制,比如:文档云图

想要绘制这样的文档云图,那么我们首先必须先安装 echarts-wordcloud,执行:
cnpm i --save echarts-wordcloud@2.1.0
Code language: CSS (css)
安装完成之后,需要在使用 wordcloud
的组件上,导入 import 'echarts-wordcloud'
。
那么这样,我们就可以基于 wordCloudData
数据渲染文档云图了:
<template>
<div>
<div>【关键词条】</div>
<div ref="target" class="w-full h-full"></div>
</div>
</template>
<script setup></script>
Code language: HTML, XML (xml)
10:绘制数据总览图
通常在大屏可视化项目中,除了包含基本的图表之外,还会存在一些数据概览的内容。这就是我们这一小节主要讲解的东西。
咱们这里所实现的数据概览,主要包含两块功能:
- 数值自增
- 数值渐变 + 特殊字体
首先针对于数值自增而言,主要可以通过 countup.js
进行实现:
- 安装
countup.js
:
cnpm i --save countup.js@2.6.2
Code language: CSS (css)
- 实现如下布局代码:
<template>
<div class="p-6">
<div class="text-slate-300 text-center">
数据总量:
<span
ref="totalCountTarget"
class="text-7xl ml-2 mr-2 font-bold"
>
679,473,929
</span>
条记录
</div>
<div class="mt-3 flex flex-wrap">
<div class="w-1/3 text-center text-slate-400 text-sm">
华北:
<span ref="city1" class="text-[#5DC5EF] text-3xl"> 8,778,988 </span>
</div>
<div class="w-1/3 text-center text-slate-400 text-sm">
东北:<span ref="city2" class="text-[#5DC5EF] text-3xl">8,778,988</span>
</div>
<div class="w-1/3 text-center text-slate-400 text-sm">
华东:<span ref="city3" class="text-[#5DC5EF] text-3xl">8,778,988</span>
</div>
<div class="w-1/3 text-center text-slate-400 text-sm">
中南:<span ref="city4" class="text-[#5DC5EF] text-3xl">8,778,988</span>
</div>
<div class="w-1/3 text-center text-slate-400 text-sm">
西南:<span ref="city5" class="text-[#5DC5EF] text-3xl">8,778,988</span>
</div>
<div class="w-1/3 text-center text-slate-400 text-sm">
西北:<span ref="city6" class="text-[#5DC5EF] text-3xl">8,778,988</span>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import { CountUp } from 'countup.js'
const props = defineProps({
data: {
type: Object,
required: true
}
})
const totalCountTarget = ref(null)
const city1 = ref(null)
const city2 = ref(null)
const city3 = ref(null)
const city4 = ref(null)
const city5 = ref(null)
const city6 = ref(null)
onMounted(() => {
new CountUp(totalCountTarget.value, props.data.total).start()
new CountUp(city1.value, props.data.hb).start()
new CountUp(city2.value, props.data.db).start()
new CountUp(city3.value, props.data.hd).start()
new CountUp(city4.value, props.data.zn).start()
new CountUp(city5.value, props.data.xn).start()
new CountUp(city6.value, props.data.xb).start()
})
</script>
Code language: HTML, XML (xml)
那么此时,我们就实现了数据自增的功能。
接下来第二块是实现数值渐变 + 特殊字体。
数值渐变可以直接通过 css
进行实现,本质上是通过 背景渐变 + 字体镂空 进行实现。
而特殊字体需要导入资料中 07:图表与大屏可视化 -> assets -> fonts
中的字体
- 导入电子表字体到
src/assets/fonts/FX-LED.ttf
中 - 在
src/style.css
中写入如下css
:
@font-face {
font-family: 'Electronic';
src: url('./assets/fonts/FX-LED.ttf') format('truetype');
}
.text-gradient {
<em>/* 背景渐变 */</em>
background-image: linear-gradient(to bottom, #e5e4ea, #5EA8F2);
<em>/* 元素背景延伸到文本 */</em>
-webkit-background-clip: text;
<em>/* 文本字符填充颜色透明 */</em>
-webkit-text-fill-color: transparent;
}
Code language: PHP (php)
- 在
src/components/TotalData.vue
中,为每个span
添加font-[Electronic]
类名 - 单独为数据总量添加
text-gradient
类名
11:地图可视化分析与时间轴图表绘制
那么到目前,我们就只剩下最后一块,也是最复杂的一块功能需要进行实现了。
这一块图表,可以被分为四个部分:
- 时间轴
- 横向柱形图
- 地图
- 绘制地图散点图
所以针对这样的功能,咱们将分成四个小节分步进行绘制。
那么这一小节,咱们就先就来实现 时间轴 绘制。
时间轴绘制,需要使用到 echarts
中的 timeline
属性,具体代码如下:
<template>
<div>
<div ref="target" class="w-full h-full"></div>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import * as echarts from 'echarts'
const props = defineProps({
data: {
type: Object,
required: true
}
})
const target = ref(null)
let mChart = null
onMounted(() => {
mChart = echarts.init(target.value)
renderChart()
})
const renderChart = () => {
let options = {
<em>// 时间线,提供了在多个 ECharts option 间进行切换</em>
timeline: {
<em>// 数据</em>
data: props.data.voltageLevel,
<em>// 类目轴</em>
axisType: 'category',
<em>// 自动切换</em>
autoPlay: true,
<em>// 间隔时间</em>
playInterval: 3000,
<em>// 位置</em>
left: '10%',
right: '10%',
bottom: '0%',
width: '80%',
<em>// 轴的文本标签</em>
label: {
<em>// 默认状态</em>
normal: {
textStyle: {
color: '#ddd'
}
},
<em>// 高亮状态</em>
emphasis: {
textStyle: {
color: '#fff'
}
}
},
<em>// 文字大小</em>
symbolSize: 10,
<em>// 线的样式</em>
lineStyle: {
color: '#555'
},
<em>// 选中点的样式</em>
checkpointStyle: {
borderColor: '#888',
borderWidth: 2
},
<em>// 控件样式</em>
controlStyle: {
<em>// 上一步按钮</em>
showNextBtn: true,
<em>// 下一步按钮</em>
showPrevBtn: true,
<em>// 默认样式</em>
normal: {
color: '#666',
borderColor: '#666'
},
<em>// 高亮样式</em>
emphasis: {
color: '#aaa',
borderColor: '#aaa'
}
}
}
}
mChart.setOption(options)
}
</script>
Code language: HTML, XML (xml)
12:地图可视化绘制动态柱形图
这一小节,咱们来绘制地图可视化中的动态柱形图。
柱形图的绘制,对咱们现在而言,应该是有一些熟悉的了,同时因为有时间轴的存在,所以我们可以直接添加 options
属性,来为时间轴动态绑定多个图表。
对应的绘制代码如下:
const renderChart = () => {
let options = {
<em>// 时间线,提供了在多个 ECharts option 间进行切换</em>
timeline: {...},
<em>// 柱形图右侧展示</em>
baseOption: {
grid: {
right: '2%',
top: '15%',
bottom: '10%',
width: '20%'
}
},
<em>// 绑定时间轴的多个图表</em>
options: []
}
<em>// 为每一年度的图表添加数据</em>
props.data.voltageLevel.forEach((item, index) => {
options.options.push({
<em>// 背景色</em>
backgroundColor: '#142037',
title: [
<em>// 主标题,对应地图</em>
{
text: '2019-2023 年度数据统计',
left: '0%',
top: '0',
textStyle: {
color: '#ccc',
fontSize: 30
}
},
<em>// 副标题,对应柱形图</em>
{
id: 'statistic',
text: item + '年数据统计情况',
right: '0%',
top: '4%',
textStyle: {
color: '#ccc',
fontSize: 20
}
}
],
<em>// X 轴配置</em>
xAxis: {
<em>// 数据轴</em>
type: 'value',
<em>// 脱离 0 值比例</em>
scale: true,
<em>// 位置</em>
position: 'top',
<em>// 不显示分割线</em>
splitLine: {
show: false
},
<em>// 不显示轴线</em>
axisLine: {
show: false
},
<em>// 不显示刻度尺</em>
axisTick: {
show: false
},
<em>// 类别文字</em>
axisLabel: {
margin: 2,
textStyle: {
color: '#aaa'
}
}
},
<em>// Y 轴</em>
yAxis: {
<em>// 选项轴</em>
type: 'category',
<em>// 轴线</em>
axisLine: {
show: true,
lineStyle: {
color: '#ddd'
}
},
<em>// 轴刻度</em>
axisTick: {
show: false,
lineStyle: {
color: '#ddd'
}
},
<em>// 轴标签</em>
axisLabel: {
interval: 0,
textStyle: {
color: '#ddd'
}
},
<em>// 根据年份,获取对应数据</em>
data: props.data.categoryData[item].map((item) => item.name)
},
<em>// 核心配置</em>
series: [
{
zlevel: 1.5,
<em>// 柱形图</em>
type: 'bar',
<em>// 每个柱子的色值</em>
itemStyle: {
normal: {
color: props.data.colors[index]
}
},
<em>// 根据年份,获取对应数据</em>
data: props.data.categoryData[item].map((item) => item.value)
}
]
})
})
mChart.setOption(options)
}
Code language: JavaScript (javascript)
13:地图可视化,绘制地图
最后,我们来绘制地图。
想要绘制地图,那么需要首先 导入地图的**json**
文件:
import mapJson from '@/assets/MapData/china.json'
echarts.registerMap('china', mapJson)
Code language: JavaScript (javascript)
然后在 baseOption
中,添加 geo
作为地图配置:
baseOption: {
...
<em>// 中国地图</em>
geo: {
<em>// 展示</em>
show: true,
<em>// 中国地图</em>
map: 'china',
<em>// 开启缩放</em>
roam: true,
<em>// 初始缩放</em>
zoom: 0.8,
<em>// 中心点</em>
center: [113.83531246, 34.0267395887],
<em>// 默认状态的省份样式</em>
itemStyle: {
normal: {
<em>// 边框色值</em>
borderColor: 'rgba(147, 235, 248, 1)',
<em>// 边框宽度</em>
borderWidth: 1,
<em>// 区域颜色</em>
areaColor: {
<em>// 经向色值</em>
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.5,
colorStops: [
<em>// 0% 处的颜色</em>
{
offset: 0,
color: 'rgba(147, 235, 248, 0)'
},
<em>// 100% 处的颜色</em>
{
offset: 1,
color: 'rgba(147, 235, 248, .2)'
}
],
<em>// 缺省为 false</em>
globalCoord: false
}
},
<em>// 鼠标移入的色值</em>
emphasis: {
areaColor: '#389BB7',
borderWidth: 0
}
}
}
}
Code language: HTML, XML (xml)
14:地图可视化散点图绘制
最后只需要在 series
中绘制散点图即可:
<em>// 散点图</em>
{
<em>// 散点(气泡)图</em>
type: 'effectScatter',
<em>// 使用地理坐标系</em>
coordinateSystem: 'geo',
<em>// 数据</em>
data: props.data.topData[item],
<em>// 标记大小</em>
symbolSize: function (val) {
return val[2] / 4
},
<em>// 绘制完成后显示特效</em>
showEffectOn: 'render',
<em>// 展示涟漪特效</em>
rippleEffect: {
brushType: 'stroke'
},
<em>// 文字</em>
label: {
normal: {
formatter: '{b}',
position: 'right',
show: true
}
},
<em>// 每一项的配置</em>
itemStyle: {
normal: {
color: props.data.colors[index],
<em>// 阴影配置</em>
shadowBlur: 5,
shadowColor: props.data.colors[index]
}
},
zlevel: 1
}
Code language: JavaScript (javascript)
15:AntV 概述与 G2 开发柱形图
那么到现在为止,咱们就已经利用利用 echarts
完成了一个大屏可视化项目的开发。
但是大家需要知道的是,除了 ehcarts
之外,还有一些其他的框架,也可以实现可视化图表开发,比如 antv。
AntV:由蚂蚁集团数据可视化团队发布,内部进行了库的细分:
- G2:类似于
Echarts
,提供了各种常见的图表。课程中的 大屏可视化项目 ,也可以基于此实现 - S2:表格数据图形化
- G6:数据关系可视化。比如脑图实现
- X6:图形编辑引擎。比如流程图、
ER
图构建 - L7:地理空间数据可视化。与地图相关
- F2:移动端数据可视化。可以理解为
G2
的移动端版本 - AVA:可视化生成框架。可以理解为可视化的低代码框架
Antv
从使用中和 echarts
会有一些不同,我们可以通过这个 案例 来查看 G2
的基本使用:
- 通过
vite
创建新的项目antv-g2
:
npm create vite@latest
Code language: CSS (css)
- 在
App.vue
中写入如下代码:
<template>
<div>
<div id="container"></div>
</div>
</template>
<script setup>
import { Chart } from '@antv/g2'
import { onMounted } from 'vue'
<em>// 准备数据</em>
const data = [
{ genre: 'Sports', sold: 275 },
{ genre: 'Strategy', sold: 115 },
{ genre: 'Action', sold: 120 },
{ genre: 'Shooter', sold: 350 },
{ genre: 'Other', sold: 150 }
]
onMounted(() => {
<em>// 初始化图表实例</em>
const chart = new Chart({
container: 'container',
theme: 'classic'
})
<em>// 声明可视化</em>
chart
.interval() <em>// 创建一个 Interval 标记</em>
.data(data) <em>// 绑定数据</em>
.encode('x', 'genre') <em>// 编码 x 通道</em>
.encode('y', 'sold') <em>// 编码 y 通道</em>
<em>// 渲染可视化</em>
chart.render()
})
</script>
Code language: HTML, XML (xml)
这样,咱们可以利用 G2
构建一个基本的柱形图
16:大屏数据展示组件库 DataV
在本章的最后,我为大家介绍最后一个东西 DataV。
DataV
是一个 大屏数据展示组件库,同时提供了 vue
版本和 react
版本。
它的使用和其他的组件库一样,都是安装之后全局导入组件和局部导入组件。只不过它的组件会更加偏向于 大屏可视化的场景。
它内部提供的组件并不多,大家可以通过视频查看对应的演示。在文档中,咱们就不过多赘述了。
17:总结
那么到这里,咱们本章的主要内容就已经全部完成了。
在本章中,我们首先利用 vite + tailwindcss
构建了一个大屏可视化的项目。
然后通过 echarts
完成了大屏可视化的功能。在项目中,每一个图表都是一个单独的组件。
在本章的最后,我们有学习了一下 antv
并且利用 G2 库
实现了简单的柱形图。