展柜页面搭建记录
进行了一些粗糙愚笨的微小工作……
目录
耗时一下午,总算折腾好我最近惦记起来的展柜。期间各种调试,虽然漫长折磨,但幸好没有出什么很糟心的 bug,基本抽打抽打 GPT 也就解决了,费时但还算顺利!遂来写个作业,万一有人用得上,也防止我以后想修改自己却看不懂代码咋回事……
最终效果这里走!
前期准备 #
看了很多作业,包括这个、这个、这个以及这些作业里提及的其他作业,看得昏过去;也想过要不干脆就当成文章发出来算了,不折腾那些花里胡哨的。后来在 Yelle 的装修记录里看到她做的软件、硬件和相册界面,觉得综合起来还挺符合我的需求的。但我研究一番她参考的作业,看代码看得我又昏过去,实在搞不懂。评论咨询后,Yelle 特别特别好地给我发了邮件,打包了一堆代码和截图,还专门附上了说明文档,真是太感谢了!于是我再度仔细研究,确认了一点,就是我真的搞不懂那么多代码……
其实拿来直接用应该是没问题的,但是我要根据自己的需求做一些整合、一些修改,所以首先要把人家的代码全都搞懂。我觉得我看到脑子裂开应该也是做不到的,遂决定抽打 GPT 试着自己折腾一下。
我的需求是:
- 我想要可以用标签筛选不同类型的作品。
- 我不想要那么 fancy fancy 地通过 JSON 存储作品数据,然后哗啦一下全都导入到网页里。虽然折腾完很轻松,但折腾起来对我而言一点也不简单。所以我打算暂时留在舒适区里,做一个可以用短代码添加作品的
.md
展柜页面就好。 - 作品以海报图片的方式展现,鼠标悬浮其上时会出现详细信息。这个效果是我从别人的类似页面里学来的,虽然很担心一张小小的海报是否放得下我的唠叨感想,但想先这样漂亮地放着。
然后我把这堆需求塞给了 GPT,请看下节分解。
开始折腾 #
要弄好这个展柜,需要四个文件:
- 用于添加展位物品的短代码文件
showcase-item.html
,存放在/layout/shortcodes
里。
具体代码
<div class="showcase-item" data-tags="{{ .Get "tags" }}">
<div class="poster">
<img src="{{ .Get "poster" | safeURL }}" alt="{{ .Get "title" }}" />
<div class="overlay">
<h3>{{ .Get "title" }}</h3>
<p><strong>by </strong>{{ .Get "creator" }}</p>
<p><strong>喜爱程度:</strong>{{ .Get "rating" }}</p>
<p>{{ .Get "description" }}</p>
</div>
</div>
</div>
可以根据自己的需求,增加更多的信息,比如作品年份等等,或者进行删改。<img>
这里我用了{{ .Get "poster" | safeURL }}
,如果要使用本地图片及其相对路径的话,可能要对代码作出修改。
- 用于展柜页面的 template
showcase.html
,存放在/layout/_default
里。
这个 template 相当于应用在.md
文件上的格式,比如所有的博文都会用同一个 template。我自用的展柜 template 是在 Congo 主题的simple.html
上改的,基本就是一个空白页面。
具体代码
<section class="showcase">
<div class="filter-bar">
<button data-filter="all">All</button>
<button data-filter="书籍">书籍</button>
<button data-filter="综艺">综艺</button>
<button data-filter="剧集">剧集</button>
<button data-filter="电影">电影</button>
<button data-filter="音乐">音乐</button>
</div>
{{ .Content | emojify }}
</section>
<script>
document.addEventListener("DOMContentLoaded", function () {
const filterButtons = document.querySelectorAll(".filter-bar button");
const items = document.querySelectorAll(".showcase-item");
filterButtons.forEach((button) => {
button.addEventListener("click", () => {
const filter = button.getAttribute("data-filter");
filterButtons.forEach((btn) => btn.classList.remove("active"));
button.classList.add("active");
items.forEach((item) => {
const itemTag = item.getAttribute("data-tags");
if (filter === "all" || itemTag === filter) {
item.style.display = "block";
} else {
item.style.display = "none";
}
});
});
});
});
</script>
在此进行一些解说。这不是 template 的全部代码,只是展柜相关的部分,只要把它们塞到<header>
和<footer>
中间那里就好啦。
<section class="showcase">
内包含的是整个展柜的内容,<div class="filter-bar">
是标签栏,{{ .Content | emojify }}
是一会儿要提到的.md
文件里的内容,将会渲染在这个位置,<script>
则是让标签筛选起作用的代码。
- 展柜页面本身
showcase.md
,存放在/content
里(一般关于页、友链页之类的都在这个位置)。
具体代码
---
title: "Showcase|展柜"
layout: "showcase"
---
<div class="showcase-grid">
{< showcase-item title="《地海传奇》系列" creator="[美] 厄休拉·勒古恩" poster="https://s2.eslite.com/unsafe/fit-in/x900/s.eslite.com/Upload/Product/201203/o/634673971209212500.jpg" rating="4.5" tags="书籍" description="" >}
{< showcase-item title="《地海传奇》系列" creator="[美] 厄休拉·勒古恩" poster="https://s2.eslite.com/unsafe/fit-in/x900/s.eslite.com/Upload/Product/201203/o/634673971209212500.jpg" rating="4.5" tags="书籍" description="" >}
</div>
注意在 layout 栏要添加上之前的 showcase template。此外,必须要在短代码前后加上<div class="showcase-grid"></div>
的部分。只加一次就行,不需要每次调用短代码的时候都加上。
我其实有试图把showcase.html
里整个<section class="showcase">
都扔进.md
文件来,只留一个{{ .Content }}
在那边,想着万一在展柜部分下方还想写点什么,这样会比较方便。但很遗憾这样展柜格式会变得奇奇怪怪,遂作罢。如果要在.md
文件里添加别的内容,就在</div>
下方写好了。
以及在输入tags
时,一定要和showcase.html
的<div class="filter-bar">
里那些 button 的 data-filter 的值相同。比如我的展柜,可选的 tags 就是书籍、综艺、剧集、电影、音乐这几个。当然这部分也是可以自由地增减修改的。
- 用于自定义格式的
custom.css
,我的存放在/assets/css
里。
具体代码
.showcase {
display: flex;
flex-direction: column;
align-items: left;
}
.filter-bar {
text-align: center;
margin-bottom: 45px;
}
.filter-bar button {
margin-right: 10px;
padding: 3px 13px;
border: 1px solid #ccc;
border-radius: 7px;
background-color: #f9f9f9;
}
.filter-bar button:hover {
color: #00798c;
}
.filter-bar button.active {
background-color: #00798c;
color: whitesmoke;
}
.showcase-grid {
display: flex;
flex-wrap: wrap;
gap: 5px;
justify-content: flex-start;
}
.showcase-item {
flex: 1 1 195px;
max-width: 195px;
position: relative;
height: 275px;
overflow: hidden;
border-radius: 5px;
}
.showcase-item img {
width: 100%;
height: 100%;
object-fit: cover;
margin: 0 !important;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
color: whitesmoke;
opacity: 0;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
text-align: left;
transition: opacity 0.3s;
border-radius: 5px;
padding: 10px;
}
.overlay p,
.overlay strong,
.overlay h3 {
color: whitesmoke;
margin: 0 !important;
}
.showcase-item:hover .overlay {
opacity: 1;
}
这就没什么好说的了,我对 CSS 一窍不通、十分厌恶,直接抽打 GPT 弄的。有一些设置大概是为了覆盖掉主题本身的格式写的,抄走的话不一定用得上,可以根据自己的博客情况和需求自由修改。
未来优化 #
我想把喜爱程度的显示从数字换成可爱的小图标,但暂时没想到什么很好的办法,之前参考的那些作业都是直接把 svg 写进代码的,比较折腾。而且我在考虑我是不是需要更新一下 Hugo,GPT 给的代码里有些 function 我的 Hugo 不支持,不知道是 GPT 在瞎编还是我版本不够新。但更新了不知道又会出什么幺蛾子 bug,姑且先这样吧。
总觉得这个展柜不够精致,但我实在又很懒得折腾格式细节,唉,已经很不错了!放着吧!
以及还没来得及给展柜物品写我的碎碎念,之后再补!