如何在hexo中实现自适应响应式相册功能

fangch fangch     2022-10-17     158

关键词:

用最清晰简洁的方法整合一个响应式相册
技术分享图片

效果

技术选型

  • 由于我选用的主题使用了fancyBox作为图片弹出展示的框架,查看后表示很不错,能满足需要
    http://fancyapps.com/fancybox/3/
  • 图片加载可能会太慢,所以还需要一个图片延迟加载插件 Lazyload
  • 想使用瀑布流作为展示,粗略了解了下,便使用开源的MiniGrid,原因是它很小巧也刚好满足需求(ps:它的文档让我看了很捉急,不完善的文档是个大坑)

相册文件夹

按照Hexo官方给的建议

资源(Asset)代表 source 文件夹中除了文章以外的所有文件,例如图片、CSS、JS 文件等。比方说,如果你的Hexo项目中只有少量图片,那最简单的方法就是将它们放在 source/images 文件夹中。然后通过类似于 ![](/images/image.jpg) 的方法访问它们。
对于那些想要更有规律地提供图片和其他资源以及想要将他们的资源分布在各个文章上的人来说,Hexo也提供了更组织化的方式来管理资源。这个稍微有些复杂但是管理资源非常方便的功能可以通过将 config.yml 文件中的 post_asset_folder 选项设为 true 来打开。

post_asset_folder: true

然后就可以在文件夹source下新建一个相册文件夹Images,将照片放入这个文件夹

相册页面

我们需要一个相册页面以加载所有照片

---
title: 相册
noDate: ‘true‘
---
<script src="https://cdn.bootcss.com/jquery_lazyload/1.9.7/jquery.lazyload.js"></script>
<script src="https://unpkg.com/[email protected]/dist/minigrid.min.js"></script>

<div class="ImageGrid"></div>

<script src="/js/photo.js"></script>

这里使用noDate来自定义一些HTML数据,加载一些JS文件(minigrid在bootcss中还是1.*的版本,只好使用它推荐的cdn了),其中photo.js是自定义的,用来加载照片,稍后提到。
现在,我们就有一个相册页面了,接下来的问题是怎么批量加载那些照片。

脚本

大家可以集思广益,我是用的是一个教程中的脚本改的,与其思路一致。
在博客主文件夹下新建tool.js

"use strict";
    const fs = require("fs");
    const sizeOf = require(‘image-size‘);
    const path = "./source/Images";
    const outputfile = "./source/Images/output.json";
    var dimensions;

    fs.readdir(path, function (err, files) {
        if (err) {
            return;
        }
        let arr = [];
        (function iterator(index) {
            if (index == files.length) {
                fs.writeFile(outputfile, JSON.stringify(arr, null, "\t"));
                return;
            }

            fs.stat(path + "/" + files[index], function (err, stats) {
                if (err) {
                    return;
                }
                if (stats.isFile()) {
                    dimensions = sizeOf(path + "/" + files[index]);
                    console.log(dimensions.width, dimensions.height);
                    arr.push(dimensions.width + ‘.‘ + dimensions.height + ‘ ‘ + files[index]);
                }
                iterator(index + 1);
            })
        }(0));
    });

每次在相册中更新照片后都要在控制台node tool.js一下,以便更新数据。
它会生成一个json文件,带有每张照片的长宽及文件名。
需要它的宽高是因为我们需要它满足瀑布流样式。
output.json样式类似于:

[
    "3120.4160 发票.jpg",
    "516.516 头像.jpg",
    "402.180 录音.jpeg",
    "720.758 截图1.jpg",
    "720.978 截图2.jpg"
]

photo.js

photo ={
    page: 1,
    offset: 20,
    init: function () {
        var that = this;
        $.getJSON("/photo/output.json", function (data) {
            that.render(that.page, data);
            //that.scroll(data);
        });
    },

    render: function (page, data) {
        var begin = (page - 1) * this.offset;
        var end = page * this.offset;
        if (begin >= data.length) return;
        var html, li = "";
        for (var i = begin; i < end && i < data.length; i++) {

            li += ‘<div class="card">‘ +
                    ‘<div class="ImageInCard">‘ + 
                      ‘<a data-fancybox="gallery" href="/Images/‘ + data[i] + ‘">‘ +
                        ‘<img src="/Images/‘ + data[i] + ‘"/>‘ +
                      ‘</a>‘ +
                    ‘</div>‘ +
                    ‘<div class="TextInCard">‘+data[i].split(‘.‘)[0]+‘</div>‘ +
                  ‘</div>‘ 

        }

        $(".ImageGrid").append(li);
        $(".ImageGrid").lazyload();
        this.minigrid();
    },

    minigrid: function() {
        var grid = new Minigrid({
            container: ‘.ImageGrid‘,
            item: ‘.card‘,
            gutter: 12
        });
        grid.mount();
        $(window).resize(function() {
           grid.mount();
        });
    }

}

photo.init();

js文件也可以放在Images文件夹下,只需要将相册页面加载的<script src="/js/photo.js"></script>改成<script src="/Images/photo.js"></script>即可。

css

这个样式是我自己写的,大家可以按照自己的想法自行更改:

.ImageGrid {width: 100%;max-width: 1040px;margin: 0 auto;text-align: center;}
.card {width:160px;height:260px;overflow: hidden;}
.ImageInCard {height:185px}
.ImageInCard img {height:100%;width: auto;padding: 0 0 0 0; }
.TextInCard {height:75;background-color: #fff;}

自动构建

我是使用travis-ci自动构建的。(用过以后表示很鸡肋)
如果你也使用了这个的话,在travis.yml中的script或者before_script,添加一句node tool.js,就可以将相册脚本也加入自动构建:

script:
  - node tool.js
  - hexo g











聊技术在android中实现自适应文本大小显示(代码片段)

本周的聊技术话题和大家说说如何在Android中实现自适应文本大小显示。想象一下,在布局中,通常显示文本的区域大小是固定的,但是文本长度并不总是固定的。比如列表中的文章标题、界面下方的按钮文本等等。... 查看详情

如何在 webflux 中实现自定义身份验证管理器时对未经授权的请求响应自定义 json 正文

】如何在webflux中实现自定义身份验证管理器时对未经授权的请求响应自定义json正文【英文标题】:Howtoresponsecustomjsonbodyonunauthorizedrequestswhileimplementingcustomauthenticationmanagerinwebflux【发布时间】:2020-11-2703:52:15【问题描述】:我正... 查看详情

如何在 Alamofire 中实现自签名证书?

】如何在Alamofire中实现自签名证书?【英文标题】:HowtoimplementselfsignedcertificatesinAlamofire?【发布时间】:2015-03-0500:56:19【问题描述】:我编写了一个基于swift的应用程序,带有自签名证书服务器通信。作为一个网络库,我想使用A... 查看详情

如何在 UIImagePicker 中实现自定义“使用”和“重拍”按钮?

】如何在UIImagePicker中实现自定义“使用”和“重拍”按钮?【英文标题】:Howtoimplementcustom\'Use\'and\'Retake\'buttoninUIImagePicker?【发布时间】:2011-03-2507:06:04【问题描述】:我的意思是,我已经关闭了相机控制器pickerCam.showsCameraContro... 查看详情

如何在 .NET EF Core 中实现自引用多对多关系

】如何在.NETEFCore中实现自引用多对多关系【英文标题】:Howtoimplementaself-referencingmany-to-manyrelationsin.NETEFCore【发布时间】:2021-10-2909:35:02【问题描述】:我正在制作一个作为社交网络的Web应用程序,但在EFCore(代码优先,SQLServer... 查看详情

如何在 keras 中实现自定义指标?

】如何在keras中实现自定义指标?【英文标题】:howtoimplementcustommetricinkeras?【发布时间】:2016-10-0601:13:54【问题描述】:我得到这个错误:sum()得到了一个意外的关键字参数\'out\'当我运行这段代码时:importpandasaspd,numpyasnpimportkera... 查看详情

如何在黄瓜中实现自定义监听器?

】如何在黄瓜中实现自定义监听器?【英文标题】:Howtoimplementcustomlistenersincucumber?【发布时间】:2021-12-2214:55:47【问题描述】:如何在cucumber中实现客户监听?哪个可以记录到控制台/报告失败方法的发生?使用黄瓜4.0注意:钩... 查看详情

如何在 Spark SQL(PySpark) 中实现自增

】如何在SparkSQL(PySpark)中实现自增【英文标题】:HowtoimplementautoincrementinsparkSQL(PySpark)【发布时间】:2016-10-2504:20:43【问题描述】:我需要在我的sparksql表中实现一个自动增量列,我该怎么做。请指导我。我正在使用pyspark2.0谢谢卡... 查看详情

如何在 TCPDF 中实现自定义字体

】如何在TCPDF中实现自定义字体【英文标题】:HowtoimplementcustomfontsinTCPDF【发布时间】:2011-07-1222:11:47【问题描述】:在TCPDF中,只有几种字体可供选择,用于创建pdf文件。我想将Tahoma设置为我的pdf字体。如何在TCPDF中包含Tahoma?... 查看详情

如何在canvas中实现自定义路径动画(代码片段)

...塞尔曲线,因此,这个动画也许是下面这个样子的:那么如何才能在canvas中实现这种动画效果呢?其实很简单,对于路径的处理svg非常在行,因此在canvas中实现自定义路径动画,我们需要借助svg的力量。创建Path制作动画前,先... 查看详情

如何在 rem 中实现响应式字体大小 - bootstrap

】如何在rem中实现响应式字体大小-bootstrap【英文标题】:Howtoimplementresponsivefontsizeinrem-bootstrap【发布时间】:2016-03-2023:40:45【问题描述】:我在我的项目中使用bootstrap3,我看到bootstrap中有2个font-size声明,如下所示:Scaffolding.less... 查看详情

如何在 JSON.NET 中实现自定义 JsonConverter?

】如何在JSON.NET中实现自定义JsonConverter?【英文标题】:HowtoimplementcustomJsonConverterinJSON.NET?【发布时间】:2011-12-2306:02:32【问题描述】:我正在尝试扩展此处给出的JSON.net示例http://james.newtonking.com/projects/json/help/CustomCreationConverter.... 查看详情

如何在 Access 中实现自反主键/外键关系?

】如何在Access中实现自反主键/外键关系?【英文标题】:HowcanIimplementareflexiveprimary/foreignkeyrelationshipinAccess?【发布时间】:2019-01-0823:08:01【问题描述】:MSOffice265专业增强版,Access2007-2016我是新手。我有一张名为pedigree的表。我... 查看详情

在drf中实现自定义响应类(代码片段)

我的views.py。classOptiResponse(Response):def__init__(self,token=None,code=None,headers=None):ifcode==0:iftoken:data="status":"code":0,"error_message":"","data":"token":token,data="status":"code":0,"error_message":"","data":data="status":"code":1,"error_message":"","data":self.token=tokenself.dat... 查看详情

如何在 QT 中实现自定义模型的 removeRow() 函数?

】如何在QT中实现自定义模型的removeRow()函数?【英文标题】:HowtoimplementremoveRow()functionforcustomizedmodelinQT?【发布时间】:2016-03-2404:02:48【问题描述】:我已经搜索了QT文档以供参考,但我有一些问题。这是QTdoc中的实现:boolTableMo... 查看详情

如何在 React Redux 中实现自包含组件?

】如何在ReactRedux中实现自包含组件?【英文标题】:Howtoimplementaselfcontainedcomponentinreactredux?【发布时间】:2016-10-2211:46:03【问题描述】:我正在基于reactredux构建一个文件管理器webui(我的目的是通过这个项目掌握react和redux)如... 查看详情

如何在 WCF 服务中实现自定义身份验证

】如何在WCF服务中实现自定义身份验证【英文标题】:HowtoImplementcustomauthenticationinWCFservice【发布时间】:2019-12-1403:26:43【问题描述】:我想为具有自定义身份验证的移动应用程序创建WCFrestful服务。第一个请求应该是登录,特别... 查看详情

如何在 WordPress 中实现自定义标头的引导小部件代码?

】如何在WordPress中实现自定义标头的引导小部件代码?【英文标题】:HowtocanimplementbootstrapwidgetcodeforcustomheaderinWordPress?【发布时间】:2019-07-1703:22:25【问题描述】:我在网站上工作,我不是引导程序的专业人士。这是我的主题标... 查看详情