日历热力图,月度数据可视化图表(日活跃图、格子图)vue组件

日历热力图,月度数据可视化图表,vue组件

先看效果👇
在这里插入图片描述
在这里插入图片描述
在线体验https://www.guetzjb.cn/calanderViewGraph/

日历图简单划分为近一年时间,开始时间是 上一年的今天,例如2024/01/01 —— 2025/01/01,跨度刚好一年,依次从上到下看一排真好七个小方格,分别对应着 周日、周一、周二、周三、周四、周五、周六。

PC端、移动端支持良好

方法颜色支持自定义,可根据数据大小规定颜色深度。

实现方式简单易懂~用到element plus和moment,用前请安装到项目

yarn add element-plus moment
# or
npm i element-plus moment

show code

calanderViewGraph.vue

<script setup lang='ts'>
import moment from 'moment'
import 'moment/dist/locale/zh-cn'moment.locale('zh-cn')const props = withDefaults(defineProps<{size: number
}>(), {size: 10
})const ansRes: any = []
const date = new Date()
const today = {year: date.getFullYear(),month: date.getMonth(),day: date.getDate()
}
let endTime = moment(date, 'YYYY/MM/DD').format('L')
let startTime = moment((today.year - 1) + '/' + (today.month + 1) + '/' + today.day, 'YYYY/MM/DD').format('L')
const visibleList = ref<Record<string, boolean>>({})
let days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]function isLeapYear(year: number) {return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}function init() {//上一年开始遍历//下标从0开始for (let month = today.month; month <= 12 + today.month; month++) {let year = Math.floor(month / 12); //0->前一年 1->今年let m = month % 12;let remainDaylet weekif (month != today.month && month != 12 + today.month) {remainDay = days[m] + (isLeapYear(today.year - (year == 0 ? 1 : 0)) && m == 1 ? 1 : 0) // 闰年补1week = new Date(today.year - (year == 0 ? 1 : 0) + '/' + (m + 1) + '/1').getDay()} else {if (month == today.month) {remainDay = days[m] - today.day + 1 + (isLeapYear(today.year - (year == 0 ? 1 : 0)) && m == 1 ? 1 : 0) // 例如 1/1 ~ 1/2 日期相差2天,相减+1week = new Date(today.year - (year == 0 ? 1 : 0) + '/' + (m + 1) + '/' + today.day).getDay()} else {remainDay = today.day + (isLeapYear(today.year - (year == 0 ? 1 : 0)) && m == 1 ? 1 : 0)week = new Date(today.year - (year == 0 ? 1 : 0) + '/' + (m + 1) + '/1').getDay()}}ansRes.push({year,month: m,remainDay,week,rev: month == today.month // 第一个日期必须反转 例如2024/1/20 剩余11天,应该显示2024/1/20 ~ 2024/1/31})}
}const viewsList = ref<any>({totalCnt: 0,views: {// '2025/01/20': 10 //格式 —— (key:日期,value:数量)},colors: {// '2025/01/20': '#fff000' //格式 —— (key:日期,value:色值)}
})// 自定义颜色
const colorArr = ["#E0F8E0", "#C6E0C6", "#AEE6AE", "#96EA96", "#7EF07E", "#66F566", "#4EF94E", "#36FD36", "#1EFF1E", "#00CC00"]
function getColorFunc(value: number): string {let i = 0while (value > 10 && i < colorArr.length) {value -= 10i += 1}return colorArr[i]
}function generateData() {let startTimeStamp = new Date(startTime).getTime()let endTimeStamp = new Date(endTime).getTime()// 随机生成365个数据for (let i = 0; i < 365; i++) {let randomTimeStamp: number = (endTimeStamp - Math.random() * (endTimeStamp - startTimeStamp)) //  随机减一个随机时间戳,相当于在今天的时间戳基础上减let dateStr: string = moment(randomTimeStamp).format('YYYY/MM/DD')if (!viewsList.value.views[dateStr]) {viewsList.value.views[dateStr] = 0}let curCnt = Math.random() * 100 | 0 // |0去除小数点 viewsList.value.views[dateStr] += curCntviewsList.value.totalCnt += curCntviewsList.value.colors[dateStr] = getColorFunc(viewsList.value.views[dateStr])}
}const formatDate = (year: number, month: number, day: number) => {return moment(today.year + (year == 0 ? -1 : 0) + '/' + (month + 1) + '/' + (day + 1), 'YYYY/MM/DD').format('L')
}init()
onMounted(() => {generateData()
})</script><template><div class="calander_box"><p class="view_title">近一年共浏览<span style="font-weight: bold;padding: 0 5px;">{{ viewsList?.totalCnt != null ?viewsList?.totalCnt : '...' }}</span></p><el-scrollbar><div class="mobile_wrap"><div class="calander_view_g_wrap"><div class="views_wrap" v-for="month in ansRes" v-show="month.remainDay > 0"><!-- 一排 7个 加边距(20px) --><div class="views_month" :style="{ height: props.size * 7 + 20 + 'px' }"><!-- 伪装的格子 --><div class="views_day" :style="{width: props.size + 'px',height: props.size + 'px'}" v-for="_offset in month.week" style="background: transparent;cursor: auto;"></div><!-- 真正显示的格子 --><div v-for="(_day, index) in month.remainDay"><el-tooltip effect="dark" :visible="visibleList[formatDate(month.year, month.month, index)]":content="`${formatDate(month.year, month.month, !month.rev ? index : (days[month.month] - (month.remainDay - index)))}  ${viewsList?.views[formatDate(month.year, month.month, index)] || 0}次浏览`"placement="top-start"><div class="views_day" @mouseenter="visibleList[formatDate(month.year, month.month, index)] = true"@mouseleave="visibleList[formatDate(month.year, month.month, index)] = false" :style="{background: viewsList?.colors[formatDate(month.year, month.month, index)],width: props.size + 'px',height: props.size + 'px'}"></div></el-tooltip></div></div><p style="color: #a2a2a2;">{{ month.month + 1 + '月' }}</p></div></div></div></el-scrollbar></div>
</template><style lang='scss' scoped>
.calander_box {width: 100%;padding: 20px;.view_title {font-size: 18px;padding-left: 10px;margin-bottom: 20px;}.mobile_wrap {width: fit-content;@media screen and (max-width:480px) {width: 800px;white-space: nowrap;overflow-anchor: auto;}.calander_view_g_wrap {display: flex;justify-content: space-between;.views_wrap {width: 100%;margin-right: 8px;margin-left: 8px;p {text-align: center;margin-top: 10px;}.views_month {width: calc(100% / 12);height: 90px;display: flex;flex-direction: column;flex-wrap: wrap;@media screen and (max-width:1200px) {height: 50px;}.views_day {margin: 0 2px 2px 0;border-radius: 2px;background: #F7F7F8;cursor: pointer;@media screen and (max-width:1200px) {width: 5px;height: 5px;}}}}}}}
</style>

使用方法:

传入size表示方格的宽度和高度,

如果不想要方形,可以自己改样式实现(注意调整外部div高度,必须一排七个,否则周(日、一……六)的顺序会错乱)

<calanderViewGraph :size="10"/>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/68896.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年第十五届蓝桥杯青少组国赛(c++)真题—快速分解质因数

快速分解质因数 完整题目和在线测评可点击下方链接前往&#xff1a; 快速分解质因数_C_少儿编程题库学习中心-嗨信奥https://www.hixinao.com/tiku/cpp/show-3781.htmlhttps://www.hixinao.com/tiku/cpp/show-3781.html 若如其他赛事真题可自行前往题库中心查找&#xff0c;题…

[Computer Vision]实验三:图像拼接

目录 一、实验内容 二、实验过程及结果 2.1 单应性变换 2.2 RANSAC算法 三、实验小结 一、实验内容 理解单应性变换中各种变换的原理&#xff08;自由度&#xff09;&#xff0c;并实现图像平移、旋转、仿射变换等操作&#xff0c;输出对应的单应性矩阵。利用RANSAC算法优…

FPGA自分频产生的时钟如何使用?

对于频率比较小的时钟&#xff0c;使用clocking wizard IP往往不能产生&#xff0c;此时就需要我们使用代码进行自分频&#xff0c;自分频产生的时钟首先应该经过BUFG处理&#xff0c;然后还需要进行时钟约束&#xff0c;处理之后才能使用。

【喜讯】海云安荣获“数字安全产业贡献奖”

近日&#xff0c;国内领先的数字化领域独立第三方调研咨询机构数世咨询主办的“2025数字安全市场年度大会”在北京成功举办。在此次大会上&#xff0c;海云安的高敏捷信创白盒产品凭借其在AI大模型技术方面的卓越贡献和突出的技术创新能力&#xff0c;荣获了“数字安全产业贡献…

ceph基本概念,架构,部署(一)

一、分布式存储概述 1.存储分类 存储分为封闭系统的存储和开放系统的存储&#xff0c;而对于开放系统的存储又被分为内置存储和外挂存储。 外挂存储又被细分为直连式存储(DAS)和网络存储(FAS)&#xff0c;而网络存储又被细分网络接入存储(NAS)和存储区域网络(SAN)等。 DAS(D…

Markdown Viewer 浏览器, vscode

使用VS Code插件打造完美的MarkDown编辑器&#xff08;插件安装、插件配置、markdown语法&#xff09;_vscode markdown-CSDN博客 右键 .md 文件&#xff0c;选择打开 方式 &#xff08;安装一些markdown的插件) vscode如何预览markdown文件 | Fromidea GitCode - 全球开发者…

wx036基于springboot+vue+uniapp的校园快递平台小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

AIGC的企业级解决方案架构及成本效益分析

AIGC的企业级解决方案架构及成本效益分析 一,企业级解决方案架构 AIGC(人工智能生成内容)的企业级解决方案架构是一个多层次、多维度的复杂系统,旨在帮助企业实现智能化转型和业务创新。以下是总结的企业级AIGC解决方案架构的主要组成部分: 1. 技术架构 企业级AIGC解决方…

LeetCode 热题 100_全排列(55_46_中等_C++)(递归(回溯))

LeetCode 热题 100_两数之和&#xff08;55_46&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;思路一&#xff08;递归&#xff08;回溯&#xff09;&#xff09;&#xff1a; 代码实现代码实现&#xff08;思路一&#xff08…

2025发文新方向:AI+量化 人工智能与金融完美融合!

2025深度学习发论文&模型涨点之——AI量化 人工智能的融入&#xff0c;使量化交易实现了质的突破。借助机器学习、深度学习等先进技术&#xff0c;人工智能可高效处理并剖析海量市场数据&#xff0c;挖掘出数据背后错综复杂的模式与趋势&#xff0c;从而不仅提升了数据分析…

3.CSS的背景

通过CSS背景属性&#xff0c;可以给页面元素添加背景样式。 背景属性可以设置背景颜色、背景图片、背景平铺、背景图片位置、背景图像固定等。 3.1 背景颜色 background-color属性定义了元素的背景颜色 background-color:颜色值&#xff1b; 一般情况下元素背景颜色默认值…

AIGC视频生成模型:Stability AI的SVD(Stable Video Diffusion)模型

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍Stability AI的视频生成模型SVD(Stable Video Diffusion)模型&#xff0c;这家公司在图像生成领域富有盛名&#xff0c;开发并维护了知名开源项目SD系列…

【若依】添加数据字典

接下来&#xff0c;在生成代码的页面将“学科”字段改为下拉框&#xff0c;然后选择数据字典 然后&#xff0c;将生成的代码中的index文件复制到vue3的index中&#xff0c;替换掉之前的index文件 修改数据库中的subject的值&#xff0c;这样就可以通过数据字典来查询 以上操作成…

基于quartz,刷新定时器的cron表达式

文章目录 前言基于quartz&#xff0c;刷新定时器的cron表达式1. 先看一下测试效果2. 实现代码 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&…

MySQL中的关联查询:方式、区别及示例

MySQL中的关联查询&#xff1a;方式、区别及示例 在数据库操作中&#xff0c;我们常常需要从多个相关的表中获取数据&#xff0c;这就用到了关联查询。MySQL提供了多种关联查询方式&#xff0c;每种方式都有其特点和适用场景。下面我们就来详细探讨这些关联查询的使用方式、它…

软件卸载不干净?用“它”一键卸载!

前言&#xff1a; 今天我要向大家推荐一款适用于Windows系统的卸载工具&#xff0c;它是一款完全免费且开源的软件&#xff0c;使用体验极佳&#xff0c;绝对值得大家一试。 Bulk Crap Uninstalle 这款名为Bulk Crap Uninstaller的软件&#xff0c;相较于系统自带的卸载工具…

使用AI生成金融时间序列数据:解决股市场的数据稀缺问题并提升信噪比

“GENERATIVE MODELS FOR FINANCIAL TIME SERIES DATA: ENHANCING SIGNAL-TO-NOISE RATIO AND ADDRESSING DATA SCARCITY IN A-SHARE MARKET” 论文地址&#xff1a;https://arxiv.org/pdf/2501.00063 摘要 金融领域面临的数据稀缺与低信噪比问题&#xff0c;限制了深度学习在…

吴恩达深度学习——如何实现神经网络

来自吴恩达深度学习&#xff0c;仅为本人学习所用。 文章目录 神经网络的表示计算神经网络的输出激活函数tanh选择激活函数为什么需要非激活函数双层神经网络的梯度下降法 随机初始化 神经网络的表示 对于简单的Logistic回归&#xff0c;使用如下的计算图。 如果是多个神经元…

MATLAB 如何避免复杂shp文件对inpolygon的影响

**任务描述&#xff1a;**当我想用inpolygon函数将属于非洲的pixel选出来时&#xff0c;发现因为周边小岛的影响&#xff0c;pixel选取有问题&#xff0c;如下图。 第一种解决办法&#xff1a; 首先将复杂shp文件查分成简单的shp文件&#xff0c;即将不相交的元素分离开 [QGIS…

【机器学习】嘿马机器学习(科学计算库)第11篇:Pandas,学习目标【附代码文档】

本教程的知识点为&#xff1a;机器学习&#xff08;常用科学计算库的使用&#xff09;基础定位 机器学习概述 机器学习概述 1.5 机器学习算法分类 1 监督学习 机器学习概述 1.7 Azure机器学习模型搭建实验 Azure平台简介 Matplotlib 3.2 基础绘图功能 — 以折线图为例 1 完善原…