Typecho非插件实现文章相册功能
AI摘要:文章介绍了如何为Typecho 0.9默认主题添加图片排版和灯箱效果。作者通过修改`post.php`文件,使用DOMDocument处理HTML,为段落中的图片添加灯箱链接,并在`header.php`中引入Slimbox2插件。最后,作者分享了自定义CSS样式和Markdown图片插入方法,以实现图片的网格布局和单独排列。
最近在整理博客主题,我这个主题还是Typecho 0.9 系统默认的主题,比较老。
但是这个主题的好处就是比较简洁,代码很精简,在上面很方便改造,在追求内容方面很适合我这种不想太花哨的。
这次改造的就是给文章中增加图片排版,并且支持灯箱效果。
灯箱插件代码:https://wangdaodao.lanzn.com/ipNLk38sx3ij,下载了放在主题中,例如我主题所有的静态资源都在 assets
中,你也可以按照我这个方法,assets/plugin/slimbox2
方便后面维护。
我这个主题文章页面是 post.php
,其他主题应该也是这个名字吧,毕竟官方文档里面主题结构是这样:
文件名 | 作用 | 必须 |
---|---|---|
style.css | 主题样式文件 | 否 |
screenshot.png | 主题缩略图 | 否 |
index.php | 首页以及说明文件 | 是 |
404.php | 404页面文件 | 否 |
archive.php | 通用(分类、搜索、标签、作者)页面文件 | 否 |
category.php | 分类页面文件 | 否 |
search.php | 搜索页面文件 | 否 |
tag.php | 标签页面文件 | 否 |
author.php | 作者页面文件 | 否 |
comments.php | 评论页面文件 | 否 |
footer.php | 底部页面文件 | 否 |
functions.php | 主题函数文件 | 否 |
header.php | 头部页面文件 | 否 |
page.php | 独立页面文件 | 否 |
post.php | 日志页面文件 | 否 |
sidebar.php | 侧边栏页面文件 | 否 |
言归正传,重头戏来了,在 post.php
找到这段代码,这个就是输出内容的
<?php $this->content(); ?>
改造成:
<?php
// 使用DOMDocument来精确处理p标签的直接子集img
$doc = new DOMDocument();
@$doc->loadHTML('<?xml encoding="UTF-8">' . $this->content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
// 找到所有的p标签
$paragraphs = $doc->getElementsByTagName('p');
foreach ($paragraphs as $p) {
// 先收集所有需要处理的直接子元素img
$imgElements = array();
foreach ($p->childNodes as $child) {
if ($child->nodeType === XML_ELEMENT_NODE && $child->nodeName === 'img') {
$imgElements[] = $child;
}
}
// 统计当前p标签中的图片数量
$imgCount = count($imgElements);
if ($imgCount > 0) {
// 如果p标签中有多个图片,添加相应的class
if ($imgCount > 1) {
$p->setAttribute('class', 'album-group multiple-images');
} else {
$p->setAttribute('class', 'album-group');
}
}
// 处理收集到的img元素
foreach ($imgElements as $img) {
$src = $img->getAttribute('src');
$alt = $img->getAttribute('alt');
if ($src) {
// 创建新的a标签
$a = $doc->createElement('a');
$a->setAttribute('href', $src);
$a->setAttribute('rel', 'lightbox');
$a->setAttribute('title', $alt);
// 创建新的img标签
$newImg = $doc->createElement('img');
$newImg->setAttribute('loading', 'lazy');
$newImg->setAttribute('src', $src);
$newImg->setAttribute('alt', $alt);
// 将新的img添加到a标签
$a->appendChild($newImg);
// 替换原来的img标签
$p->replaceChild($a, $img);
}
}
}
// 获取处理后的HTML内容
$content = $doc->saveHTML();
echo $content;
?>
代码中有简单的注释,可以看看,看不懂的话,让AI解释一下也行。
然后在 header.php
中,在 <head></head>
标签中,增加以下代码:
<?php if ($this->is('single')): ?>
<script src="<?php $this->options->themeUrl('/assets/plugin/slimbox2/js/slimbox2.js'); ?>"></script>
<link rel="stylesheet" href="<?php $this->options->themeUrl('/assets/plugin/slimbox2/css/slimbox2.css'); ?>">
<?php endif; ?>
这里注意下引入的路径。
完成以上步骤,基本上算上完成了一大半了,剩下的就是改下样式,这里我提供我现在用的样式,动手能力强的可以自己再改造改造,让这个更符合自己的主题:
其中 post-content
是我自己博客内容的类名,需要根据自己的再调整一下
/* 图片灯箱效果 */
.post-content a[rel='lightbox'] img {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
transition: box-shadow 0.3s ease;
}
.post-content a[rel='lightbox']:hover {
cursor: zoom-in;
}
.post-content a[rel='lightbox']:hover img {
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
}
.post-content p.album-group img {
border-radius: 10px;
transition: all 0.2s ease;
}
.post-content p.album-group.multiple-images {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
grid-auto-rows: 250px;
grid-gap: 0.5rem;
}
.post-content p.album-group.multiple-images a {
display: block;
min-width: calc(50% - 10px);
margin: 0;
}
.post-content
p.album-group.multiple-images
a:nth-last-of-type(1):nth-of-type(odd) {
grid-column: 1 / -1;
}
.post-content p.album-group.multiple-images img {
object-fit: cover;
display: block;
width: 100%;
height: 100%;
}
.post-content p.album-group.multiple-images br {
display: none;
}
最后一步,就是发布文章时如何插入图片,由于我本人比较懒,一般都是用的typecho的默认编辑器,没有用其他的插件,所以这里也不准备弄什么标签啥的,懒……
如果每张图片想单独放一行,那就是这样:
<!--这里仅仅说明这里要空行-->
![图片1][1]
<!--这里仅仅说明这里要空行-->
注意啊,图片上下都要空一行,这样typecho的markdown的解析器,就会把这个转换成
<p>
<img />
</p>
如果想做成一个一组,那就是这样,同样一组上下都要空一行:
<!--这里仅仅说明这里要空行-->
![图片1][1]
![图片2][2]
![图片3][3]
![图片4][4]
<!--这里仅仅说明这里要空行-->
这样就转换成
<p>
<img />
<img />
<img />
<img />
</p>
效果就是这样:
目前针对移动端没有做效果,还是懒啊……
注意,如果用HTML压缩之类的,会破坏结构,这种情况会导致布局上的失效,所以如果发现没有生效,对比下HTML结构做调整吧。