当前位置: 首页 > news >正文

日历热力图,月度数据可视化图表(日活跃图、格子图)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"/>

相关文章:

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

日历热力图&#xff0c;月度数据可视化图表&#xff0c;vue组件 先看效果&#x1f447; 在线体验https://www.guetzjb.cn/calanderViewGraph/ 日历图简单划分为近一年时间&#xff0c;开始时间是 上一年的今天&#xff0c;例如2024/01/01 —— 2025/01/01&#xff0c;跨度刚…...

Vue 3中导航守卫(Navigation Guard)结合Axios实现token认证机制

在Vue 3中&#xff0c;导航守卫&#xff08;Navigation Guard&#xff09;用于拦截路由的变化&#xff0c;可以在用户访问页面前进行检查。结合Axios进行token认证机制时&#xff0c;我们可以通过导航守卫在路由跳转时&#xff0c;检查用户的认证状态&#xff0c;确保用户有有效…...

【爬虫】使用 Scrapy 框架爬取豆瓣电影 Top 250 数据的完整教程

前言 在大数据和网络爬虫领域&#xff0c;Scrapy 是一个功能强大且广泛使用的开源爬虫框架。它能够帮助我们快速地构建爬虫项目&#xff0c;并高效地从各种网站中提取数据。在本篇文章中&#xff0c;我将带大家从零开始使用 Scrapy 框架&#xff0c;构建一个简单的爬虫项目&am…...

一分钟学习数据安全——白盒加密及安当应用

白盒加密作为一种先进的加密技术&#xff0c;在数据安全、通信安全和信息隐私保护等多个关键领域都有应用。这次的一分钟&#xff0c;让您快速了解一下白盒加密的概念&#xff0c;以及安当产品中的白盒加密应用。 一、什么是白盒加密 简单来说&#xff0c;白盒加密是一种特殊…...

composer安装指定php版本, 忽略平台原因导致的报错

windows下 //composer安装指定php版本, 写出完整的php和composer.phar路径 D:\phpstudy_pro\Extensions\php\php8.1.11nts\php.exe D:\phpstudy_pro\Extensions\composer1.8.5\composer.phar install windows下一些扩展不支持, 如下图, 所以本地composer安装组件时可以忽略 …...

Java 前端详解

Java 前端详解 Java 前端开发主要涉及使用 Java 相关技术和框架来创建用户界面和处理用户交互。虽然 Java 原本是后端开发的主力语言&#xff0c;但它也提供了许多前端开发工具和框架。以下是 Java 前端开发的主要内容和技术栈。 一、Java 前端技术栈 Java Swing 和 AWT AWT (…...

鸿蒙安装HAP时提示“code:9568344 error: install parse profile prop check error” 问题现象

在启动调试或运行应用/服务时&#xff0c;安装HAP出现错误&#xff0c;提示“error: install parse profile prop check error”错误信息。 解决措施 该问题可能是由于应用使用了应用特权&#xff0c;但应用的签名文件发生变化后未将新的签名指纹重新配置到设备的特权管控白名…...

Javaweb之css

css的三种引入方式 1内行式 2.内嵌式 3.外部样式表 内行式和内嵌式 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0&quo…...

实施工程师:面试基础宝典

一.运维工程师和实施工程师的区别&#xff1a;工作内容不同、职能不同、工作形式不同 1.工作内容不同&#xff1a; 运维工程师要对公司硬件和软件进行维护。 硬件包括&#xff1a;机房、机柜、网线光纤、PDU、服 务器、网络设备、安全设备等。 实施工程师包括常用操作系统、应…...

react install

react 安装 React 是一个用于构建用户界面的 JavaScript 库。以下是安装 React 的步骤&#xff1a; 使用 Create React App Create React App 是一个官方支持的命令行工具&#xff0c;用于快速搭建 React 应用。 安装 Node.js 和 npm 确保你的计算机上安装了 Node.js 和 npm…...

ElasticSearch DSL查询之排序和分页

一、排序功能 1. 默认排序 在 Elasticsearch 中&#xff0c;默认情况下&#xff0c;查询结果是根据 相关度 评分&#xff08;score&#xff09;进行排序的。我们之前已经了解过&#xff0c;相关度评分是通过 Elasticsearch 根据查询条件与文档内容的匹配程度自动计算得出的。…...

uniapp封装websocket

WebSocket介绍 后端使用的是springbootnetty做websocket的服务端&#xff0c;参考我其他博文 项目使用场景 开发uniapp项目时&#xff0c;需要进行实时通信&#xff0c;比如聊天等。需要封装一个工具类&#xff0c;统一对socket进行管理。 uniapp websocket官方文档&#xff1…...

【Linux】18.Linux进程控制(2)

文章目录 3. 进程程序替换3.1 单进程版 -- 看看程序替换3.2 替换原理3.3 替换函数函数解释命名理解 3.4 多进程版 -- 验证各种程序替换接口3.5 自定义shell 3. 进程程序替换 3.1 单进程版 – 看看程序替换 makefile mycommand:mycommand.cgcc -o $ $^ -stdc99 .PHONY:clean …...

reactor框架使用时,数据流请求流程

1. 我们在Flux打开时&#xff0c;可以看到 public abstract class Flux<T> implements CorePublisher<T> { 2. public interface CorePublisher<T> extends Publisher<T> {void subscribe(CoreSubscriber<? super T> subscriber); } Publish…...

读西瓜书的数学准备

1&#xff0c;高等数学&#xff1a;会求偏导数就行 2&#xff0c;线性代数&#xff1a;会矩阵运算就行 参考&#xff1a;线性代数--矩阵基本计算&#xff08;加减乘法&#xff09;_矩阵运算-CSDN博客 3&#xff0c;概率论与数理统计&#xff1a;知道啥是随机变量就行...

摄像头模块如何应用在宠物产品领域

一、宠物监控类产品 家庭宠物远程监控摄像头 1.基本功能与原理&#xff1a;这类摄像头可以通过 Wi - Fi 连接到家庭网络&#xff0c;主人可以使用手机应用程序在任何有网络连接的地方查看宠物的实时画面。摄像头模块内置有图像传感器&#xff0c;能够捕捉光线并将其转换为数字…...

c++学习第七天

创作过程中难免有不足&#xff0c;若您发现本文内容有误&#xff0c;恳请不吝赐教。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考。 一、const成员函数 //Date.h#pragma once#include<iostream> using namespace std;class Date { public:Date…...

Ubuntu 24.04 LTS 通过 docker 安装 nextcloud 搭建个人网盘

准备 Ubuntu 24.04 LTSUbuntu 空闲硬盘挂载Ubuntu 安装 Docker DesktopUbuntu 24.04 LTS 安装 tailscale [我的Ubuntu服务器折腾集](https://blog.csdn.net/jh1513/article/details/145222679。 安装 nextcloud 参考 Ubuntu24.04系统Docker安装NextcloudOnlyoffice _。 更…...

RabbitMQ1-消息队列

目录 MQ的相关概念 什么是MQ 为什么要用MQ MQ的分类 MQ的选择 RabbitMQ RabbitMQ的概念 四大核心概念 RabbitMQ的核心部分 各个名词介绍 MQ的相关概念 什么是MQ MQ(message queue)&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO 先入先出&am…...

Open3D计算点云粗糙度(方法一)【2025最新版】

目录 一、Roughness二、代码实现三、结果展示博客长期更新,本文最近更新时间为:2025年1月18日。 一、Roughness 通过菜单栏的Tools > Other > Roughness找到该功能。 这个工具可以估计点云的“粗糙度”。 选择一个或几个点云,然后启动这个工具。 CloudCompare只会询问…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...

基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究

摘要&#xff1a;在消费市场竞争日益激烈的当下&#xff0c;传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序&#xff0c;探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式&#xff0c;分析沉浸式体验的优势与价值…...

Python异步编程:深入理解协程的原理与实践指南

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 持续学习&#xff0c;不断…...

十二、【ESP32全栈开发指南: IDF开发环境下cJSON使用】

一、JSON简介 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;具有以下核心特性&#xff1a; 完全独立于编程语言的文本格式易于人阅读和编写易于机器解析和生成基于ECMAScript标准子集 1.1 JSON语法规则 {"name"…...

LTR-381RGB-01RGB+环境光检测应用场景及客户类型主要有哪些?

RGB环境光检测 功能&#xff0c;在应用场景及客户类型&#xff1a; 1. 可应用的儿童玩具类型 (1) 智能互动玩具 功能&#xff1a;通过检测环境光或物体颜色触发互动&#xff08;如颜色识别积木、光感音乐盒&#xff09;。 客户参考&#xff1a; LEGO&#xff08;乐高&#x…...

运动控制--BLDC电机

一、电机的分类 按照供电电源 1.直流电机 1.1 有刷直流电机(BDC) 通过电刷与换向器实现电流方向切换&#xff0c;典型应用于电动工具、玩具等 1.2 无刷直流电机&#xff08;BLDC&#xff09; 电子换向替代机械电刷&#xff0c;具有高可靠性&#xff0c;常用于无人机、高端家电…...