不用ECharts!从0到1徒手撸一个Vue3柱状图

0. 前言

柱状图(Bar Chart),也称为条形图,是一种常用的数据可视化图表,用于展示不同类别的数据量。 它通过水平或垂直的条形来表示数据的大小,条形的长度或高度与它们所代表的值成比例。

有许多JavaScript库可以帮助你快速创建柱状图,其中一些流行的包括: Chart.jsD3.jsHighchartsECharts等。

今天,我们将从0开始,基于Vue3,仅使用CSS3动画来实现一个最基础的柱状图。

1. 数据生成

1-1. 类型定义

ts 复制代码
interface BarItem {
    id: string; // ID
    title: string; // 标题
    val: number; // 数值
}

interface BarChartItem extends BarItem {
    percent: string; // 整体占比
}

1-2. 计算占比

ts 复制代码
import { random, maxBy } from 'lodash-es';

// 数据列表
const barItems: Ref<BarItem[]> = ref([])

// 自动计算百分比
const barChartItems = computed<BarChartItem[]>(() => {
    // 最大值
    const maxItem = maxBy(barItems.value, item => item.val)
    if (!maxItem) return []
    return barItems.value.map(item => {
        return {
            percent: (item.val / maxItem?.val * 100).toFixed(1),
            ...item,
        }
    })
})

使用数据项中的最大值作为基准,计算所有项的百分比。此百分比将用于后续展示柱状图的高度。

1-3. 添加、删除数据

ts 复制代码
import { random, maxBy, times } from 'lodash-es';

// 添加一项数据
const addItem = () => {
    barItems.value.push({
        id: useId(),
        title: `${curIdx.value++}-${faker.commerce.department()}`,
        val: random(1, 200)
    })
}

// 删除一项
const delItem = () => {
    const idx = random(0, barItems.value.length - 1)
    barItems.value.splice(idx, 1)
}

// 随机增加数值
const addVal = () => {
    barItems.value.forEach((item) => {
        item.val = Math.max(1, item.val + random(-50, 50))
    })
}

onMounted(() => {
    // 初始化默认添加5项数据
    times(5, addItem)
})
  • addItem:添加一项数据项,并生成1-200的随机值;同时这里我们使用faker来生成一个公司部门名称作为标题。
  • delItem: 随机删除一条数据。
  • addVal:为每个数据项随机增加-50到50的数据值,来模拟数据值变化的效果。
  • 页面初始化:默认添加5项数据

2. 页面结构

2-1. 数据操作

html 复制代码
<n-button-group>
    <n-button @click="addItem">添加一项</n-button>
    <n-button @click="delItem">删除一项</n-button>
    <n-button @click="addVal">添加随机值</n-button>
</n-button-group>

添加操作按钮,手动调整柱状图数据。

2-2. 柱状图

html 复制代码
<TransitionGroup name="list" tag="section" class="flex flex-row h-500px self-center gap-x-5">
    <div v-for="item in barChartItems" :key="item.id" class="flex flex-col h-full w-60px">
        <section class="flex-1 relative flex flex-col-reverse items-center">
            <div class="w-full transition transition-height transition-duration-500 bg-[#5771c0]" :style="{ height: `${item.percent}%` }"></div>
            <span class="text-[#333] font-bold text-base text-center">{{ item.val }}</span>
        </section>
        <span class="mt-3 text-[#333] font-bold text-center text-base">{{ item.title }}</span>
    </div>
</TransitionGroup>

使用v-for循环生成柱状图数据项,并制定柱状图颜色; 这里使用了Unocsstransition transition-height transition-duration-500来设置柱状图高度变化时的transition动效。

2-3. transition

css 复制代码
.list-move, /* 对移动中的元素应用的过渡 */
.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}

.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}

.list-leave-active {
  position: absolute;
}

使用Vue自带的组件TransitionGroup组件为柱状图元素在增加或删除时,添加过度动效。

3. 最终效果

最后我们运行一下,查看最终效果:


以上全部代码已经分享到Gitee上,如有所需,欢迎自取。

相关推荐
郑州光合科技余经理30 分钟前
国际版外卖系统:税率字段怎么和订单主流程解耦
android·java·开发语言·前端·后端·php·ai编程
梦想平凡1 小时前
百游棋牌源代码开发搭建教程(十):隔离部署、备份恢复与双端验收
java·前端·javascript·数据库·源代码管理
yume_sibai2 小时前
06-Rust Web 开发实战(Axum 框架 + 数据库 + JWT 认证 + 中间件 + 部署)
前端·数据库·rust
计算机魔术师4 小时前
特朗普上台打给黄仁勋:AI末日论是骗局,我们绝不让它发生
前端
troy1284 小时前
Python 基础语法(八):Web 后端开发、数据分析与可视化、网络爬虫、人工智能 / 大模型应用
前端·python·数据分析
计算机魔术师4 小时前
CEO说要慢下来,黑客说别做梦了——同一篇论文,两种命运
前端
kyriewen4 小时前
我花3天抓了一个幽灵bug,凶手藏在第4层
前端·javascript·程序员
IT_陈寒5 小时前
Java里用Stream.parallel()翻车实录,这性能还不如单线程
前端·人工智能·后端
Bs_MoneyMagnet5 小时前
基于springboot+vue的生态果园采摘预约系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·毕业设计·计算机毕业设计
wangchunyu1145 小时前
JavaScript 零基础入门教程
前端