git日历坐标系? 手动实现github活跃/贡献图

git日历坐标系? 手动实现github活跃/贡献图

前言

在使用github或gitlab时,我们总能发现,我们一年内的活跃度能够通过一张图直观地展现出来,那么你是否好奇它是如何实现的,最近工作中也遇到这样类似的需求,刚开始打算使用echarts的日历坐标系,但demo测试下来结果不尽人意,除了配置麻烦,自定义自由度不够,以及对于业务需求支持度也不够,因此,痛定思痛,决定动手手写一个自由度更高的组件。而且对于后端数据结构要求很低,除了能展示近一年数据,还能自定义时间范围,有需要的小伙伴可以直接查看源码:https://gitee.com/fcli/vue-calendar-map.git

话不多说,先上实现效果图:

布局结构

本组件主要分为三个部分:
(1)最左侧展示周一至周日部分,每周开始时间从周日或周一开始可自定义修改

<div class="weeks"><div class="week">周一</div><div class="week">周二</div><div class="week">周三</div><div class="week">周四</div><div class="week">周五</div><div class="week">周六</div><div class="week">周日</div>
</div>

(2)每一列表示一周的始末时间,使用el-tooltip悬浮展示具体时间,需要的可以自定义修改展示内容和样式

<div class="column" v-for="(columnData, columnIndex) in allDateData" :key="columnIndex"><div class="my-title">{{ columnData.title }}</div><div class="date-wrapper" v-for="(dateItem, dateIndex) in columnData.data" :key="dateIndex":style="{ background: getColor(dateItem.number).color }":class="{ hiddenDate: (columnIndex == 0 && dateIndex < prevTodayWeek - 1), active: getColor(dateItem.number).level == hoverLevel }"><el-tooltip class="box-item" effect="dark" :content="dateItem.date" placement="top"><div class="date"></div></el-tooltip></div>
</div>

(3)贡献图例,可自定义实现点击筛选等功能

 <div class="operation"><div class="legend"><div class="level-desc">少</div><div class="level level-1" @mouseover="hoverLevel = i" @mouseout="hoverLevel = 0" v-for="i in 5" :key="i":class="['level-' + i]"></div><div class="level-desc">多</div></div>
</div>

具体实现

1、首先计算和获取上一年的时间,以及是星期几,我这里采用dayjs来获取。计算上年今日最接近的周一的时间,该时间为起始时间。

 // 上年今日
let prevToday = dayjs().subtract(1, 'year').format('YYYY-MM-DD')
// 上年今日的是星期几,dayjs获取的为0-6,0是星期日
let prevTodayWeekNum = dayjs(prevToday).format('d') || 7;
prevTodayWeek.value = prevTodayWeekNum;
// 初始日期(上年临近的星期一)
let firstMondayDate =
prevTodayWeekNum > 1? dayjs().subtract(1, 'year').subtract(prevTodayWeekNum - 1, 'days').format('YYYY-MM-DD'): prevToday;

2、计算从开始时间到结束时间之间有多少个周,计算列数

 // 初始日期至今日的天数,包括今日
let days = dayjs().diff(dayjs(firstMondayDate), 'days') + 1;
// 每周天数
let columns = 7;
// 最大列数(周数)
let lineNums = Math.ceil(days / columns);

3、绘制图表数据,判断月份需要展示的位置,可往dateData中自定义添加需要的数据字段。第一列直接根据第一天的月份,之后的每列数根据上一周的最后一天减去第一天的月份,如果大于1代表月份发生了改变,下一列的title显示最新的月份。

 // 绘制图表的源数据let dateData: any = [];let monthCN = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];for (let i = 0; i < lineNums; i++) {// 最近一星期不一定满的let weekColumn = i === lineNums - 1 ? (days % columns ? days % columns : columns) : columns;// 开始计算title(月份的图例)let theWeekStartMonth = dayjs(firstMondayDate).add(i * 7, 'days').format('M');let day = dayjs(firstMondayDate).add(i * 7, 'days').format('DD');//防止开始时月份挤在一起if (i == 0 && 30 - day < 15) {theWeekStartMonth = theWeekStartMonth + 1;}let theWeekEndMonth = dayjs(firstMondayDate).add(i * 7 + weekColumn, 'days').format('M');let title = i === 0 ? monthCN[theWeekStartMonth - 1] : '';let isSwitchMonth = false;if (theWeekEndMonth - theWeekStartMonth) {isSwitchMonth = true;}if (i && dateData[i - 1].isSwitchMonth) {title = monthCN[theWeekEndMonth - 1];}// 图表源数据格式:columns:列数,title:列标题,isSwitchMonth:月份是否发生改变,data:每格数据dateData.push({columns: weekColumn,title: title,isSwitchMonth: isSwitchMonth,data: []});for (let j = 0; j < dateData[i].columns; j++) {let date = dayjs(firstMondayDate).add(i * 7 + j, 'days').format('YYYY-MM-DD');// 提交次数在slider范围内再进行次数赋值let number = submissionRecord.value[date];// number:提交次数,date:提交日期dateData[i].data.push({number: number,date: date});}}

(4)根据活跃度或数据量,展示不同节点的背景颜色

const getColor = (number: number) => {let num = number / props.maxData;let level = 1;if (num == 0) {num = 0.1;level = 1} else if (num > 0 && num < 0.3) {num = 0.3;level = 2} else if (num > 0.3 && num < 0.6) {num = 0.6;level = 3} else if (num < 0.9) {num = 0.8;level = 4} else {num = 1;level = 5}if (props.maxData == 0) {num = 0.1;level = 1}return { color: 'rgba(55,126,259,' + num + ')', level };
}

(5)监听数据的变化,动态响应,更新组件数据

    watch(() => props.timeData, (newValue) => {submissionRecord.value = newValue;init();}, { immediate: true, deep: true })

使用示例

已经打包上传npm,有需要的小伙伴可以直接安装使用,如果需要自定义修改组件内容,可访问git源码自行修改。git地址:https://gitee.com/fcli/vue-calendar-map.git

npm install @fcli/vue-calendar-map --save-dev 来安装在项目中使用
import VueCalendarMap from '@fcli/vue-calendar-map';
const app=createApp(App)
app.use(VueCalendarMap);
测试demo
<template><div class="content"><vue-calendar-map :timeData="timeData" :maxData="maxData"></vue-calendar-map></div>
</template><script setup lang="ts">
import dayjs from 'dayjs';
import VueCalendarMap from './plugin/index.vue';
import {ref} from 'vue';
components:{VueCalendarMap
}
const maxData=ref(190);
const timeData=ref<any>({})
let tempDate:any={}
for(let i=0;i<366;i++){let date=dayjs().subtract(1, 'year').add(i, 'days').format('YYYY-MM-DD')tempDate[date]=(Math.random() * 200).toFixed(0);
}
timeData.value=tempDate;
</script>
参数说明
属性属性名称类型可选值
timeData日期和数量对应对象Object{}
maxData最大值Number0

最后

本人长期分享一些实用干货和学习总结之类的开源技术文章,欢迎有需要的小伙伴点赞收藏和点个关注🙏。

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

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

相关文章

区块链介绍

区块链提供了比特币的公共账本&#xff0c;这是一个有序的、带有时间戳的交易记录。这个系统用于防止重复消费和修改之前的交易记录。 Introduction 比特币网络中的每个完全节点都独立存储只包含该节点验证的块的区块链。当多个节点在他们的区块链中都有相同的块时&#xff0…

uboot环境变量配置

uboot默认环境变量配置启动 进入uboot/include/configs目录下面 打开 xxxxconfig.h&#xff08;自定义uboot头文件名&#xff09;&#xff0c;配置文件中有很多的定义&#xff0c;根据具体的情况定义 根据配置&#xff0c;编译uboot uboot的自定义配置 在uboot下面的board.c…

00TDI 这件红色大衣也太适合过年穿了

分享女儿的时尚穿搭—红色大衣 这款大衣非常厚实 摸起来很软糯的触感 复合了660-700g绵羊绒 厚实度堪比一件厚实的羽绒服 门禁处做了立体的爱心装饰 精致又可爱&#xff01;&#xff01;&#xff01;

C++ String 字符串系列转换

// 宽字符转UTF8 ,处理字符乱码 std::string EncodeUtf8(std::wstring in) { std::string s(in.length() * 3 1, ); size_t len ::WideCharToMultiByte(CP_UTF8, 0, in.c_str(), in.length(), &s[0], s.length(), NULL, NULL); s.resize(len); return s; } /…

java--单继承、Object

java是单继承的&#xff0c;java中的类不支持多继承&#xff0c;但是支持多层继承。 反证法&#xff1a; 如果一个类同时继承两个类&#xff0c;然后两个类中都有同样的一个方法&#xff0c;哪当我创建这个类里的方法&#xff0c;是调用哪父类的方法 所以java中的类不支持多继…

Spring的@Feign源码分析

首先是开启Feign的注解EnableFeignClientsFeignClient EnableFeignClients会导入FeignClientsRegistrar类&#xff0c; FeignClientsRegistrar里面会解析EnableFeignClients注解&#xff0c;把里面配置的路径解析&#xff0c; 找到带有FeignClient注解的接口&#xff0c;注意是…

【Linux】:信号的产生

信号 一.前台进程和后台进程1.前台进程2。后台进程3.总结 二.自定义信号动作接口三.信号的产生1.键盘组合键2.kill信号进程pid3.系统调用1.kill函数2.raise函数3.abort函数 四.异常五.软件条件六.通过终端按键产生信号 一.前台进程和后台进程 1.前台进程 一个简单的代码演示 …

提高SQL语句执行效率的8个方法

提高SQL语句执行效率的8个方法 在日常的数据库操作中&#xff0c;如何提高SQL语句的执行效率是每个程序员都需要关注的问题&#xff0c;SQL语句的执行效率对系统的性能有着重要影响&#xff0c;本文将介绍8种提高SQL语句执行效率的方法。 合理使用索引 索引介绍 索引是数据…

quickapp_快应用_全局数据

全局数据 [1]本地数据存储[2] 数据缓存问题 有时在接口请求的某个数据需要在多个页面使用&#xff0c;此时有2个方法 [1] 将数据存储在本地—> 等价于浏览器的localStorage[2] 将数据存储在数据缓存中 -> 等价于vue中的vuex [1]本地数据存储 官方文档&#xff1a;官方…

【云备份】数据管理模块

文章目录 1. 数据管理模块要管理什么数据&#xff1f;2. 数据管理模块如何管理数据&#xff1f;3. 数据管理模块的具体实现BackupInfo 数据信息类NewBackupInfo —— 获取各项属性信息 DataManager 数据管理类构造函数析构函数insert —— 新增update —— 修改GetOneByURL——…

数据结构之时间复杂度与空间复杂度

1.算法效率 1.1 如何衡量一个算法的好坏&#xff1f; 比方说我们非常熟悉的斐波拉契数列&#xff1a; long long Fib(int N) {if(N < 3)return 1;return Fib(N-1) Fib(N-2); } 递归实现方式非常简洁&#xff0c;但一定好吗&#xff1f;如何衡量其好与坏&#xff1f; 1…

一文打尽相机单目标定(远心,沙姆镜头)

文章目录 普通镜头标定远心镜头标定沙姆镜头标定远心沙姆镜头标定实战 普通镜头标定 远心镜头标定 沙姆镜头标定 远心沙姆镜头标定 实战

JVM——垃圾回收器(Serial,SerialOld,ParNew,CMS,Parallel Scavenge,Parallel Old)

目录 1.垃圾回收器的组合关系1.年轻代-Serial垃圾回收器2.老年代-SerialOld垃圾回收器3.年轻代-ParNew垃圾回收器4.老年代- CMS(Concurrent Mark Sweep)垃圾回收器CMS执行步骤&#xff1a;CMS垃圾回收器存在的问题缺点&#xff1a;CMS垃圾回收器存在的问题 – 线程资源争抢问题…

Android 应用中Deep Link 和 App Link的区别

Android 应用中Deep Link 和 App Link的区别以及使用场景如下表格&#xff0c;希望给大家讲清楚了&#xff1a; 方式安全性跳转过程适配情况备注使用DeepLink接收无需校验&#xff0c;支持任意scheme需要浏览器中转支持所有Android版本由于支持所有版本的系统&#xff0c;可以…

目录 / 学习笔记快速链接

1.c语言 c语言 / 指针错误的几种情况-CSDN博客 c语言 / typedef和define之间的区别-CSDN博客 c语言 / 存储类型-CSDN博客 C语言 / 自定义函数实现strcat-CSDN博客 C语言 / 冒泡排序法-CSDN博客 C语言 / 指针相关内容总结-CSDN博客 C语言 / 自定义strcmp函数实现字符串排…

机器学习——支持向量机(SVM)

1.线性支持向量机 1.1数学模型 机器学习最终都是求解目标函数的最优问题&#xff1b; 一般都是讲问题转化为最小值来求解。 数学模型获得是一个不等式约束的最小化问题&#xff0c;求解时可通过构建拉格朗日函数求解。 1.2 拉格朗日函数及对偶问题求解 1.3 SMO算法求解 SMO算…

鸿蒙应用开发-初见:ArkTS

作者&#xff1a;HarderCoder ArkTS ArkTS围绕应用开发在 TypeScript &#xff08;简称TS&#xff09;生态基础上做了进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集 ArkTS在TS的基础上扩展了struct和很多的装饰器以达到描述UI和状态管理的目的 基本语法 …

python 常用内置模块之 json

介绍 当处理 JSON 数据时&#xff0c;Python 中的 json 模块提供了四个主要的函数&#xff1a;dump、dumps、load 和 loads。这些函数提供了在 JSON 数据和 Python 对象之间进行转换和序列化的功能。 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数…

ROS 功能包

ROS 功能包是 ROS 的核心组成部分之一&#xff0c;它是一个包含了源代码、配置文件、脚本等元素的一个单独的目录结构&#xff0c;用来实现特定功能。每个 ROS 功能包都有一些共同的文件&#xff0c;如 package.xml 文件&#xff0c;CMakeLists.txt 文件等&#xff0c;用于描述…

Redis Lua沙盒绕过 命令执行(CVE-2022-0543)漏洞复现

Redis Lua沙盒绕过 命令执行(CVE-2022-0543)漏洞复现 Redis如果在没有开启认证的情况下&#xff0c;可以导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据。–那么这也就是redis未授权访问了 Redis的默认端口是6379 可以用空间测绘搜索&#xff…