使用css和svg实现周历时间线

我是一个手账爱好者,使用ob以来,一直希望将自己的纸质手账迁移过来。其中最有难度的一部分是周记录的时间轴。例如这样(图片来源于网络)

最开始的想法是做个插件,类似mermaid.js一样规定好特定语法规则,使用js插件生成svg图片(例如生成每日、每周的时间线、时间饼图)。
甚至更进一步,将特定的代码块数据收集到某一个csv文件中,使用特定的语法动态生成统计图表(例如一月起床记录、睡眠时长条形图、投入时间,就像爱今天app一样)

可是苦于不知如何入门制作插件,从头学习js成本又太大,此项工作一度陷入停滞。
现在我是用css和svg初步实现了绘制时间线的功能
一、先看效果(演示使用默认主题+css片段)
周历页面


日记页面


二、实现方法
简单来说就是在日记页面直接写svg代码,将日记页的某一节标题嵌入到周历页面的表格中。并针对这种嵌入和svg定制了css片段
三、使用方法

四、文件及代码

  1. 启用以下css代码
diary.css
/* .diary-draw绘图 ————————————————————————*/

/* 设置svg颜色、字体、大小 */
/* 时间分类 */
:root{
   --ta:#56cc6688;
   --tb:#d3c65088;
   --tc:#6597d888;
   --td:#ff7d7d88;
}
.theme-dark{
   --svg-color: #33333394;    /*绘制的svg背景色*/
   --svg-font:#eeeeee;
   --svg-line:#888;        
   --embed-bg:#202020dc;  /*嵌入表格的背景色*/

}
.theme-light{
   --svg-color:#00000011;
   --svg-font:#000;
   --svg-line:#000;
   --embed-bg:#e9e8e8d7;
}

.diary svg rect{
   /* 设定变换的容器 */
   transform-box: fill-box;
   /* 设定变换中心 */
   transform-origin: 0% 0%; /* 或者 100% 100% */
   /* 变换顺序从后往前 */
   transform:scale(1, 0.01667);
   /* transform:scale(1, 0.0165); */
   width:265px
} 






/* 紧凑的嵌入———————————————————— */

/* 缩减不必要的边距 */

.markdown-preview-view .markdown-preview-sizer
.markdown-embed{
   margin-top: 0px !important;
   margin-bottom: 3px !important;
   padding-top: 0px;
   padding-bottom: 0px;

}
.markdown-preview-sizer .markdown-preview-section{
   margin: 0px !important;
   /* padding: 0px 0px !important; */
   padding-left: 5px !important;
   padding-right: 5px !important;
   padding-top: 0px !important;
   padding-bottom: 0px !important;
}
/* ———————————————— */
.markdown-preview-view{
   padding: 50px;
}

.markdown-embed .markdown-preview-sizer{
   padding-left: 10px;
}
  

/* 隐藏嵌入的标题 */
.markdown-embed-title,
.markdown-embed h1,
.markdown-embed h2,
.markdown-embed h3,
.markdown-embed h4,
.markdown-embed h5,
.markdown-embed h6{
   display: none !important;
}



td,
.markdown-preview-view .markdown-embed-content > .markdown-preview-view{
   /* max-height: 120% !important; */
   max-height: max-content !important;
   /* min-height: 100px; */
   background-color: var(--embed-bg);
   vertical-align: top !important;
   overflow: hidden;
}
/* 在嵌入的文件前显示来源  显示宽度为5em 根据实际情况可采用40px之类的值 超出部分隐藏*/
.internal-embed:not([src*="."])::before{
   content: attr(alt) " ";
   display:block;
   /* width: 5em !important; */
   white-space: nowrap;
   overflow: hidden;
   text-overflow: clip;
}
td .internal-embed:not([src*="."])::before{
   content: none;
}

/* 在嵌入的文件上方画一条上边框线 */

.markdown-embed:not([src*="."]){
   /* border-top: solid 1px #ff3c00; */
   border: #888 solid 1px;
   border-radius: 0px;
}


/* 嵌入文件的右上方打开链接按钮 */
.markdown-embed-link{
   top: -25px !important;
   right: 0;
   text-align: right;
   width: 20px !important;
   height: 20px;
   border-radius: 5px;
   /*指定链接按钮背后的背景色(现在为透明色)*/
   background-color: #4097df00;
   /*指定链接的图标颜色*/
   color: #888 !important;
}
td .markdown-embed-link{
   display: none !important;
}
/* td .markdown-embed .markdown-preview-view .markdown-preview-section, */
td .markdown-embed .markdown-preview-view {
   padding: 0px 0px 0px 0px !important;
}
td{
   padding: 2px 1px 2px 1px !important;
}

.workspace .markdown-preview-view .markdown-embed-content,
td .markdown-preview-view .markdown-embed-content {
   max-height: min-content !important;
   /* background-color: #f51313; */
   /* background-color: #534d4d; */

}

  1. 创建日记页面
  • 写下如下yaml
---
cssclass: diary
---
  • 在某一标题后写下如下svg(此处标题为timeline),直接写源码,不要放进代码块里
svg代码
<svg 	viewBox="0 0 3 18" 			width="120" >	
	<path d="M0 0L3 0 L3 18L0 18z"fill=var(--svg-color)></path>
	<!--这里是svg注释-->
	<!-- 本日记录方框-->
	<g transform=' scale(1, 1) translate(0.3,-6)'>
		<rect  y="6"  		height="60" 	fill=var(--tb)	/>
		<rect  y="9" 	  		height="30" 	fill=var(--tb)	/>
		<rect  y="9.5" 	  	height="30" 	fill=var(--tc)	/>
		<rect  y="11" 	  		height="60" 	fill=var(--td)	/>
		<rect  y="12" 	  		height="60" 	fill=var(--ta)	/>
		<rect  y="14" 	  		height="60" 	fill=var(--tb)	/>
		<rect  y="15.5" 	  	height="60" 	fill=var(--tc)	/>
		<rect  y="18" 	  		height="60" 	fill=var(--ta)	/>
		<rect  y="11" 	  		height="60" 	fill=var(--td)	/>
	</g>
	<!-- 本日记录文字-->
	<g transform-origin='cener' transform='translate(0.6,-5.93)' fill=var(--svg-font) font-size='0.4'>
		<text    y="6.5"  >洗漱吃饭</text>
		<text    y="12"  >上课</text>
		<text    y="24"  >英语单词</text>
	</g>
	<!-- 以下为背景,无需改动-->
	
	
	
	
	
	
	
	
	
	
	
	
	<g transform='translate(0,0)' id="一周模板"    >	
		<line  y1='0' x2='3' y2='0' stroke='red'  stroke-width='0.02'/>
		<line  y1='1' x2='3' y2='1' stroke='#55b'  stroke-width='0.01'/>
		<line  y1='2' x2='3' y2='2' stroke='#55b'  stroke-width='0.01'/>
		<line  y1='3' x2='3' y2='3' stroke=var(--svg-line)  stroke-width='0.02'/>
		<line  y1='4' x2='3' y2='4' stroke='#55b'  stroke-width='0.01'/>
		<line  y1='5' x2='3' y2='5' stroke='#55b'  stroke-width='0.01'/>
		<line  y1='6' x2='3' y2='6' stroke='red'  stroke-width='0.02'/>
		<line x1='0' y1='7' x2='3' y2='7' stroke='#55b'  stroke-width='0.01'/>
		<line x1='0' y1='8' x2='3' y2='8' stroke='#55b'  stroke-width='0.01'/>
		<line x1='0' y1='9' x2='3' y2='9' stroke=var(--svg-line)  stroke-width='0.02'/>
		<line x1='0' y1='10' x2='3' y2='10' stroke='#55b'  stroke-width='0.01'/>
		<line x1='0' y1='11' x2='3' y2='11' stroke='#55b'  stroke-width='0.01'/>
		<line x1='0' y1='12' x2='3' y2='12' stroke='red'  stroke-width='0.02'/>
		<line x1='0' y1='13' x2='3' y2='13' stroke='#55b'  stroke-width='0.01'/>
		<line x1='0' y1='14' x2='3' y2='14' stroke='#55b'  stroke-width='0.01'/>
		<line x1='0' y1='15' x2='3' y2='15' stroke=var(--svg-line)  stroke-width='0.02'/>
		<line x1='0' y1='16' x2='3' y2='16' stroke='#55b'  stroke-width='0.01'/>
		<line x1='0' y1='17' x2='3' y2='17' stroke='#55b'  stroke-width='0.01'/>
		<line x1='0' y1='18' x2='3' y2='18' stroke='red'  stroke-width='0.02'/>
	</g>
	<g transform='translate(0,-6)' fill=var(--svg-font)>
		<text  y="6.2" font-size='0.25' >06</text>
		<text  y="7"  font-size='0.25' >07</text>
		<text  y="8"  font-size='0.25' >08</text>
		<text  y="9"  font-size='0.25' >09</text>
		<text  y="10"  font-size='0.25' >10</text>
		<text  y="11"  font-size='0.25' >11</text>
		<text  y="12"  font-size='0.25' >12</text>
		<text  y="13"  font-size='0.25' >13</text>
		<text  y="14"  font-size='0.25' >14</text>
		<text  y="15"  font-size='0.25' >15</text>
		<text  y="16"  font-size='0.25' >16</text>
		<text  y="17"  font-size='0.25' >17</text>
		<text  y="18"  font-size='0.25' >18</text>
		<text  y="19"  font-size='0.25' >19</text>
		<text  y="20"  font-size='0.25' >20</text>
		<text  y="21"  font-size='0.25' >21</text>
		<text  y="22"  font-size='0.25' >22</text>
		<text  y="23"  font-size='0.25' >23</text>
		<text  y="24"  font-size='0.25' >24</text>
	</g>
</svg> 
  1. 在周历页面引用,例如
---
cssclass: diary
---

| [[日记]]           | [[日记]]           | [[日记]]           | [[日记]]           | [[日记]]           | [[日记]]           | [[日记]]           |
| ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ |
| ![[日记#todo]]     | ![[日记#todo]]      | ![[日记#todo]]     | ![[日记#todo]]     | ![[日记#todo]]     | ![[日记#todo]]     | ![[日记#todo]]     |
| ![[日记#timeline]] | ![[日记#timeline]] | ![[日记#timeline]] | ![[日记#timeline]] | ![[日记#timeline]] | ![[日记#timeline]] | ![[日记#timeline]] |

完成!
每次日记后手动将相关的数值填入相应位置,即可生成时间线

3 个赞

我喜欢你的手帐! 个人感觉哦,要电子化时间使用记录的话,时间块应用更方便&合适。不过虽然我自己不喜欢电子化,但这个idea很好哎! Bon 在做大日历插件,有周视图,以后可能会弄这种时间块的形式,你可以和他交流下

1 个赞

感谢提议,这种方法也只是权宜之计,现在还在学js基础,等以后有能力开发插件希望有机会进行深入交流。

1 个赞

插件实现方法看这里: