前言

这次要做的 Web 前端实战是一个 Gitee 个人主页下的贡献图(在线 Demo),偶尔做一两个,熟悉熟悉 JS 以及 jQ。整体来说这个案例并不难,主要是控制第一个节点以及最后一个节点处于星期几;且必须保持365个节点。

开始

布局设计

整体的布局是上下,顶部一个 div、下面一个 div。下面的 div 是左右布局,左边是星期、右边是贡献节点。一列贡献节点一共有7个(不一定每一列都是7个)。星期要与每一行贡献节点保持平行。左右布局的高度保持一致,因此,每一个贡献节点的宽和高就取自布局的高/7

<div id="cb-chart">
<div class="top-bar">
<div class="occupation"></div>
<div class="months"></div>
</div>
<div class="bottom">
<div class="left-side">
<div class="week">周一</div>
<div class="week">周四</div>
<div class="week">周日</div>
</div>
<div class="right-side"></div>
</div>
</div>

CSS 样式

div#cb-chart

div.top-bardiv.bottom两个容器内的元素都是水平方向排列。div.top-bar的高度占整个div#cb-chart的 20%;div.bottom自然就是 80%。

#cb-chart {
width: 940px;
height: 140px;
} #cb-chart .top-bar {
display: flex;
height: 20%;
width: 100%;
} #cb-chart .bottom {
display: flex;
height: 80%;
width: 100%;
}

div.bottom

星期与贡献节点是左右排列在整个容器的,且星期占整个容器的 8%:

#cb-chart .bottom .left-side {
width: 8%;
height: 100%;
} #cb-chart .bottom .right-side {
width: 92%;
height: 100%;
}

星期下的所有元素要均匀分配整个div.left-side的纵向空间:

#cb-chart .bottom .left-side {
/* ...... */
display: flex;
flex-direction: column;
justify-content: space-between;
}

div.right-side中的所有元素(贡献节点)都是从上到下排列,若超出容器的空间时自动换行,左右之间的元素要保持垂直水平对齐:

#cb-chart .bottom .right-side {
/* ...... */
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
flex-direction: column;
align-content: center;
align-items: center;
}

div.top-bar

下面两张图显示了顶部容器最左边有一个不显示的且占了空间的元素,主要目的是用来隔开星期剩余的空间,使顶部容器的每一个月份能够完美对齐下面的贡献节点。


因此在div.top-bar中加了一个空元素<div class="occupation"></div>

#cb-chart .top-bar .occupation {
width: 8%;
}

div.left-side的宽度 8%,所以它也是 8%;而div.months自然就占整个容器的 92%。

#cb-chart .top-bar .months {
font-size: 12px;
height: 100%;
width: 92%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: space-between;
align-items: center;
}

div.point

这个就是每一个贡献节点元素的样式,宽高必须要经过计算之后才可以给出来,节点的宽和高取自div.bottom 的高/7。使用 CSS var() 函数代替固定的值:

#cb-chart .bottom .right-side .point {
width: var(--point-size);
height: var(--point-size);
border: 1px solid #FFF;
box-sizing: border-box;
background-color: white;
}

JS 部分

绘制节点图

在开始之前要给div.right-side处添加大于365个的贡献节点的 div 元素:

function drawChartGrid() {
let $el = $("#cb-chart .bottom .right-side");
$el.css("--point-size", `${ $el.height() / 7 }px`);
for ( let h = 0; h < 54; h++ ) {
for ( let v = 0; v < 7; v++ ) {
$el.append(`<div class="point"></div>`);
}
}
}

定位起始节点和结束节点

这些贡献度节点的数量是大于365个的,并且每一天的星期数都是有变化的,所以要计算今天是星期几,以及去年的今天是星期几,这样才可以定位起始节点和结束节点。

从起始节点开始,循环到结束节点,这之间就是准确的节点数量,一共365个。使用 $().slice(start, end)函数循环,循环对象是div.right-side下的所有div.point

函数需要两个变量来控制循环,起始和结束。起始就是去年的今天的星期是几?在 JS Date() 对象中,索引值 1 代表星期一;索引值 0 代表星期日。由于贡献节点的索引值是从 0 开始的,所以,索引值 0 代表星期一,6 代表星期日。所以,要进行计算:

星期 Date 中的索引值 贡献节点索引值
星期一 1 0
星期二 2 1
星期三 3 2
星期四 4 3
星期五 5 4
星期六 6 5
星期日 0 6

查找规律,除星期日以外,Date 中的索引值与贡献节点的索引值总是相差 1。所以,只需要 Date 中的索引值(weekIndex)减去 1 就知道slice()函数从哪里开始。

特殊情况星期日:当weekIndex - 1 < 0时,说明是星期日,函数要从索引值 6 开始。

function drawPoints() {
let nowDate = new Date();
let oldDate = new Date(`${ nowDate.getFullYear() - 1 }-${ nowDate.getMonth() + 1 }-${ nowDate.getDate() }`); let weekIndex = oldDate.getDay(); let start = weekIndex - 1 < 0 ? 6 : weekIndex - 1;
let end = start === 6 ? 372 : 365 + weekIndex; $(`#cb-chart .bottom .right-side .point`).slice(start, end).each((i, el) => {
// ......
});
}

绘制节点颜色

节点的颜色根据贡献的数量来设置:

function setPointColor(el, number) {
if ( number > 0 && number <= 5 ) {
$(el).addClass("a-type-point");
} else if ( number > 5 && number <= 10 ) {
$(el).addClass("b-type-point");
} else if ( number > 10 && number <= 15 ) {
$(el).addClass("c-type-point");
} else if ( number > 15 ) {
$(el).addClass("d-type-point");
} else {
$(el).addClass("e-type-point");
}
}

函数要获取当前循环的贡献节点的 DOM 对象,以及这个节点对应的贡献数量。函数在下面进行调用:

function drawPoints() {
// ......
let data = getPointsData(oldDate);
$(`#cb-chart .bottom .right-side .point`).slice(start, end).each((i, el) => {
setPointColor(el, data[i].number);
});
}

这里出现了一个 getPointsData 函数,暂时不用管,它是随机生成数据的函数。

目前为止的效果如上图所示。

Gitee 仓库

https://gitee.com/shiramashiro/web-learning/tree/main/src/03.案例

Web 前端实战:Gitee 贡献图的更多相关文章

  1. Web 前端实战:雷达图

    前言 在Canvas 线性图形(五):多边形实现了绘制多边形的函数.本篇文章将记录如何绘制雷达图.最终实现的效果是这样的: 绘制雷达图 雷达图里外层 如动图中所示,雷达图从里到外一共有 6 层,所以, ...

  2. Web 前端实战:JQ 实现树形控件

    前言 这是一篇个人练习 Web 前端各种常见的控件.组件的实战系列文章.本篇文章将介绍个人通过 JQuery + 无序列表 + CSS 动画完成一个简易的树形控件. 最终实现的效果是: 这样结构比较复 ...

  3. web前端开发学习路径图

    第一阶段 WEB前端工程师课程 HTML语句,HTML页面结构.css语法.style属性.link和style标签.id属性.等HTML语句中的相关属性: 通过Dreamweaver制作出跨越平台限 ...

  4. WEB前端知识体系脑图

    说在开始的话: 我上大学那会,虽说主要是学Java语言,但是web前端也稍微学了一些,那时候对前端也没多在意,因为涉入的不深,可以搞一个差不多可以看的界面就可以了,其他也没过多在意. 因为稍微了解一点 ...

  5. Web 前端实战(三):雷达图

    前言 在<Canvas 线性图形(五):多边形>实现了绘制多边形的函数.本篇文章将记录如何绘制雷达图.最终实现的效果是这样的: 绘制雷达图 雷达图里外层 如动图中所示,雷达图从里到外一共有 ...

  6. 【h5+c3】web前端实战项目、快装webapp手机案例源码

    快装WebApp项目(Web移动端开发案例)webapp移动端项目源码.html5+css3实战案例分享.微信端H5实例开发 简介快装WebApp是一个面向移动端的快速装修app,此项目为手机端:使用 ...

  7. Web 前端实战:JQ 实现下拉菜单

    实现过程 实现一个简易的鼠标悬停菜单项显示其子项的下拉框控件.将用到 CSS 绝对定位.流式布局.动画等:JQuery 鼠标移入和移出事件.DOM 查找.效果图如下: HTML 结构: <div ...

  8. web前端职业规划(转)

    关于一个WEB前端的职业规划,其实是有各种的答案,没有哪种答案是完全正确的,全凭自己的选择,只要是自己选定了, 坚持去认真走,就好.在这里,我只是简要说一下自己对于这块儿内容的理解.有一个观点想要分享 ...

  9. 一张图告诉你移动Web前端所有技术(工程化、预编译、自动化)

    你要的移动web前端都在这里! 大前端方向:移动Web前端.Native客户端.Node.js. 大前端框架:React.Vue.js.Koa 跨终端技术:HTML5.CSS 3.JavaScript ...

随机推荐

  1. 当运行npm install 命令的时候带上ignore-scripts,会发生什么?

    摘要:运行npm install 命令的时候带上ignore-scripts, 可以避免一个恶意包里的病毒. 本文分享自华为云社区<运行npm install 命令的时候带上--ignore-s ...

  2. easy-captcha生成验证码

    通常一些网页登陆时,都需要通过验证码去登录: 生成验证码的方法有很多,这次分享一个验证码即能是汉字的 又能是算术的. 首先maven坐标: <dependency> <groupId ...

  3. 聊聊 C++ 和 C# 中的 lambda 玩法

    这几天在看 C++ 的 lambda 表达式,挺有意思,这个标准是在 C11标准 加进去的,也就是 2011 年,相比 C# 2007 还晚了个 4 年, Lambda 这东西非常好用,会上瘾,今天我 ...

  4. 菜鸟学git的基本命令及常见错误

    Git init //在当前项目工程下履行这个号令相当于把当前项目git化,变身!\ git config --global user.name "xxx" # 配置用户名 git ...

  5. kruskal 及其应用

    kruskal 最小生成树 kruskal 是一种常见且好理解的最小生成树(MST)算法. 前置知识 并查集和路径压缩 生成树 在有 n 的顶点的无向图中,取其中 n-1 条边相连,所得到的树即为生成 ...

  6. 【Spring】AOP实现原理(三):创建代理

    AbstractAutoProxyCreator 在AbstractAutoProxyCreator的wrapIfNecessary方法中,调用getAdvicesAndAdvisorsForBean ...

  7. Nodejs实现图片的上传、压缩预览、定时删除

    前言 我们程序员日常都会用到图片压缩,面对这么常用的功能,肯定要尝试实现一番.第一步,node基本配置 这里我们用到的是koa框架,它可是继express框架之后又一个更富有表现力.更健壮的web框架 ...

  8. 老掉牙的 synchronized 锁优化,一次给你讲清楚!

    我们都知道 synchronized 关键字能实现线程安全,但是你知道这背后的原理是什么吗?今天我们就来讲一讲 synchronized 实现线程同步背后的原因,以及相关的锁优化策略吧. synchr ...

  9. HTML知识点概括——一篇文章带你完全掌握HTML

    HTML知识点概括 前端三件套分别是HTML3,CSS5,JavaScript 稍微介绍一下W3C标准: 结构化标准语言(HTML) 表现标准语言(CSS) 行为标准(DOM,JavaScript) ...

  10. Tapdata 实时数据融合平台解决方案(三):数据中台的技术需求

    作者介绍:TJ,唐建法,Tapdata 钛铂数据 CTO,MongoDB中文社区主席,原MongoDB大中华区  首席架构师,极客时间MongoDB视频课程讲师. 我们讲完了这个中台的一个架构和它的逻 ...