前言

主题原来是自带相册的,后面被我改了没有分类了,直接所以的图片都展示在一个页面上,但是后面我考虑到如果图片多的话加载的速度可能会更久,所以我打算把相册独立出来.
同时在开发Halo主题的同时,发现了小孙同学博客的独立相册,但是吧这个相册要用typecho,PHP啥的太麻烦了,果断使用Astro搭建一个相册.

预览效果

第一版

第一版本我是模仿小孙同学的相册,只是框架不一样。就写了一个组件然后放到index.astro首页即可.

<header id="header">
<a style="cursor: pointer;" href="#">
<img class="site-logo" src='/bloghead.webp' alt="头像">
</a>
<h1>
<a style="cursor: pointer;" href="#">
<strong>{Website.name}</strong>
</a>
</h1>
<span class="discription">{Website.discription}</span>
<nav>
<ul>
<li>
<a class="icon solid fa-info-circle" style="cursor: pointer;">关于</a>
</li>
</ul>
</nav>
</header>
<div id="wrapper">
<div id="main">
{ImaAllList.map((item) => (
<article class="thumb img-area">
<a class="image my-photo" href={item.url} data-pswp-width={item.width}
data-pswp-height={item.height} >
<Picture class="zmki_px my-photo"
src={item.url}
widths={[200, 400, 800]}
aspectRatio="4:3"
sizes="(max-width: 1680px) 100vw, 1680px"
alt={item.discription}>
</Picture>
</a>
<h2>{item.discription}</h2>
<li class="tag-date">{item.time}</li>
<li class="tag-categorys">
<span>{item.address}</span>
</li>
</article>
))}
</div>
<footer id="footer" class="panel">
<div class="inner split">
<div class="inner split">
<div>
<section>
<h2>{About.atitle}</h2>
<p>{About.adiscription}</p>
<p>图片原存放于Apple icloud,可能存在失真.</p>
</section>
<section>
<h2>联系我</h2>
<ul class="icons">
<li>
<a href={About.ahome} target="_blank" class="icon" rel="noopener nofollow">
<img width="20px" height="30px" src="/house-solid.svg" alt="主页"/>
</a>
</li>
<li>
<a href={About.agithub} target="_blank" class="icon" rel="noopener nofollow">
<img width="20px" height="30px" src="/github.svg" alt="github"/>
</a>
</li>
</ul>
</section>
</div>
</div>
</div>
</footer>
</div>
<h1></h1>

提供数据的JS

图片使用杜老师图床,这一版本比较麻烦需要指定图片的宽高,不指定的话会在后面的预览中出现图片很大的问题

const Website={
name : '探人间',
discription : '遇见即是上上签!'
}

const About = {
atitle : '关于探人间',
adiscription : '用影像记录生活,用镜头传递美好.',
ahome : 'https://www.hydsb0.com',
agithub : 'https://github.com/xyhcode'
}

const ImaAllList = [
{
url:'https://bu.dusays.com/2023/06/18/648e955c009f2.jpeg',
address: '江西',
time: '2020-07-16',
width: '1321',
height: '594',
discription: '丁达尔效应'
},
{
url:'https://bu.dusays.com/2023/06/18/648e956ba0221.jpeg',
address: '广东',
time: '2022-07-17',
width: '728',
height: '568',
discription: '广州市'
}
]

export {Website,About,ImaAllList}

Picture

代码中使用的Picture组件其实是Astro官方提供的响应式的图片组件,还会生成 avifwebp 两种格式的图片,官方文档参考

安装

# Using NPM
npx astro add image
# Using Yarn
yarn astro add image
# Using PNPM
pnpm astro add image

导入

---
import { Picture } from '@astrojs/image/components';
---

踩坑

  • 如果是使用网址的形式的图片(远程图片)的话必须要有aspectRatio属性,否则构建的时候就无法计算出图片的高度
  • 远程图片如果有防盗链的话,一定不要在这里使用,否则构建的时候vercelnetlify都会报错,构建的时候会请求图片,后面网站显示的实际上是avif格式的图片,且有多张

图片预览

图片预览我使用的是一个插件photoswipe,前面图片提供宽高就是为了这个预览,这个插件预览玩法很多,感兴趣的可以瞅瞅

安装

npm i photoswipe --save

导入

import PhotoSwipeLightbox from 'photoswipe/lightbox';
import 'photoswipe/style.css';

使用

id为main的div中的a标签就是需要预览的图片,同时需要给a标签添加预览的宽高data-pswp-widthdata-pswp-height

//预览
const lightbox = new PhotoSwipeLightbox({
gallery: '#main',
children: 'a',
pswpModule: () => import('photoswipe')
});
lightbox.init();

滚动

最后给它来一个滚动渐显的效果,用起来更丝滑 scrollrevealjs

安装

npm install scrollreveal --save

导入

import ScrollReveal from 'scrollreveal';

使用

const sr = ScrollReveal({
distance: '50px',
duration: 2000,
delay: 100,
easing: 'ease',
});
const imageElements = document.querySelectorAll('.img-area');
imageElements.forEach((element) => {
sr.reveal(element, {
origin: 'bottom',
interval: 200,
});
});

第二版

第二版和第一版其实没有什么差异,在界面和渲染方面进行了改进,丢弃了第一版本使用的响应式的图片组件和预览插件,在数据方面进行了改进

相册信息的修改

第一版中数据需要自己放入JS文件中,考虑图多的情况下添加太多内容导致很麻烦,所以把网站信息的数据放入头部

const About = {
atitle : '关于探人间',
adiscription : '用影像记录生活,用镜头传递美好.',
ahome : 'https://www.hydsb0.com',
agithub : 'https://github.com/xyhcode'
}

const Website={
name : '探人间',
discription : '遇见即是上上签!'
}

图片信息生成

第一版需要提供的宽高一系列数据需要手动输入,后面找到一个项目自动生成图片的JSON文件 getImages

拉取代码

git clone https://github.com/AREA44/node-getImages

下载依赖

如果出现错误就更新pnpm,查看node版本是否大于等于18(node>=18+)

pnpm install

使用

把需要提取信息的图片放到images文件夹中,执行下面命令,执行完成会生成images.json文件,每个图片包含以下信息

  • src: 图片路径
  • width: 图片宽
  • height: 图片高
  • base64: 图片base64
node getImages.mjs

iShot_2023-07-06_17.24.46

渲染JSON

import images from '@/components/images.json';

<div id="main">
{
images.map((img) => (
<article class="thumb img-area">
<a class="image my-photo" href={img.src}>
<img
src={img.src}
width="1200"
height="900"
alt="各地风景"
/>
</a>
<h2>{img.discription}</h2>
<p>{img.time}</p>
</article>
))
}
</div>

最终版本

最终版本与第二版本修改的地方不大,主要在json文件和滚动条做了优化,第二版的图片因为存在本地的原因导致图片加载很慢,所以最终版本使用的是远程图片,图片使用了NPM发包. 且使用第一版的滚动条scrollrevealjs

部署渲染

当部署到Astro的时候有一个很严重的问题就是样式中使用的图片资源会无法编译正确,CSS编译后得到的名字不是原来的名字,在编译svg是会出现编译不完整的情况,只会编译出svg的一壳,所以会导致svg无法显示的问题(有小伙伴知道解决的可以评论或者联系我一下)

假设如下是一个关闭的svg图片

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
width="64px" height="64px" viewBox="0 0 64 64" zoomAndPan="disable">
<style>
line {
stroke: #fff;
stroke-width: 1.5px;
}
</style>
<line x1="20" y1="20" x2="44" y2="44" />
<line x1="20" y1="44" x2="44" y2="20" />
</svg>

编译后(丢失了原有内容)

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
width="64px" height="64px" viewBox="0 0 64 64" zoomAndPan="disable">
</svg>

解决方案(2023-07-08)

只需要在astro.config.mjs中添加svg的配置就可以解决这个问题

import compress from 'astro-compress';
import critters from 'astro-critters';
import { defineConfig } from 'astro/config';

export default defineConfig({
site: 'https://plog.hydsb0.com',
integrations: [
compress(
{
svg : false
}
),
critters()
],
});