svg 实现Github 的每日活跃

355 阅读2分钟

添加宽828px,高128的svg容器

<svg width="828" height="128">

image.png

使用 text 添加月份和日期

问题描述

直接在页面写入SVG,图形正常可以显示

但是使用js动态创建SVG,添加入DOM节点,页面无法显示SVG图形

原因

SVG是基于XML格式定义图像的一种技术,因此创建节点的时候,需要指定命名空间(Namespace),也就是用createElementNS来代替createElement创建节点,使用 setAttributeNS 代替 setAttribute

赋值 text 标签的内容,不能使用innerHtml

SVG nodes don't have a innerHTML property (they're not HTML).

Use textContent instead: `node.textContent='dddd'`

完整例子

const namespaceURI = "http://www.w3.org/2000/svg";
let textDom = document.createElementNS(namespaceURI, "text");
textDom.setAttributeNS(null, "x", "0");
textDom.setAttributeNS(null, "y", "12");
textDom.setAttributeNS(null, "class", "ContributionCalendar-label");
textDom.textContent = "text";
content.appendChild(textDom);

月份坐标,间隔不是固定的,后期再调整,现在固定间隔 60

日期坐标 dy 分别是 25,56,86,使用最小二乘法拟合多项式曲线 得到 F(x) = -0.5*x*x+32.5*x-7

再给 g 标签添加一个位移 <g transform="translate(10, 20)"> 。为什么要加这个,我也不懂,请个大佬解释一下

结果

localhost_3001_ (1).png

渲染小方格

一列7个,一共366天,366/7=52.28,这里渲染53列

localhost_3001_ (2).png

颜色根据 data-level 1-4渲染

Github 每一列使用的 translateX: 16,第 n 列的 rect 偏移x: 16-n。实际效果和我每一列 translateX: 15,第 n 列的 rect 偏移 统一15是一样效果

vite+vue 行内元素没有空格问题

在 vue 中,会被编译成一行,行内元素失去间隔的空格

<p><span>1</span><span>2</span></p>
<p><span>1</span>&nbsp;<span>2</span></p>
<p>
  <span>1</span>
  <span>2</span>
</p>

渲染,最后一组p没有空格

image.png

在普通html中,最后一组p保留空格

渲染

image.png

渲染一年内的数据,月份,星期对应相应位置

localhost_3001_ (5).png

加上随机数据

localhost_3001_ (4).png

添加鼠标事件

使用 Element.matches() 实现类似事件冒泡的功能

使用 getBoundingClientRect() 获取元素的空间位置信息

image.png