为 Hexo NexT 主题添加相册功能

前提准备

  1. 你需要 python,以及下载python的插件工具pip
  2. 一个码云账号或者github账号。

创建相册文件夹(远程)

在你的码云或者github账号下新建一个仓库,名字任意,但是记住一定要是公开的仓库,否则博客中无法正常显示。并在改仓库中新建两个文件夹photomini_photo

photo文件夹中存放的是照片原图,而mini_photo中存放的是照片的略缩图

照片的命名方式请按照yyyy-MM-dd_图片描述.png/jpg的格式,方便管理以及程序对照片进行处理

对照片进行处理

在本地博客的上级目录中存放本地相册,在博客/source文件夹中新建photos目录

git clone  你的git仓库

这里我们采用python脚本对照片进行处理,将脚本放在本地相册文件夹中

#coding: utf-8
from PIL import Image
import os
import sys
import json
from datetime import datetime
from ImageProcess import Graphics
# 定义压缩比,数值越大,压缩越小
SIZE_normal = 1.0
SIZE_small = 1.5
SIZE_more_small = 2.0
SIZE_more_small_small = 3.0


def make_directory(directory):
    """创建目录"""
    os.makedirs(directory)

def directory_exists(directory):
    """判断目录是否存在"""
    if os.path.exists(directory):
        return True
    else:
        return False

def list_img_file(directory):
    """列出目录下所有文件,并筛选出图片文件列表返回"""
    old_list = sorted(os.listdir(directory), reverse=True)
    print(old_list)
    new_list = []
    for filename in old_list:
        name, fileformat = filename.split(".")
        if fileformat.lower() == "jpg" or fileformat.lower() == "png" or fileformat.lower() == "gif" or fileformat.lower() == "jpeg":
            new_list.append(filename)
    # print new_list
    return new_list


def print_help():
    print("""
    This program helps compress many image files
    you can choose which scale you want to compress your img(jpg/png/etc)
    1) normal compress(4M to 1M around)
    2) small compress(4M to 500K around)
    3) smaller compress(4M to 300K around)
    """)

def compress(choose, des_dir, src_dir, file_list):
    """压缩算法,img.thumbnail对图片进行压缩,
    
    参数
    -----------
    choose: str
            选择压缩的比例,有4个选项,越大压缩后的图片越小
    """
    if choose == '1':
        scale = SIZE_normal
    if choose == '2':
        scale = SIZE_small
    if choose == '3':
        scale = SIZE_more_small
    if choose == '4':
        scale = SIZE_more_small_small
    for infile in file_list:
        img = Image.open(src_dir+infile)
        # size_of_file = os.path.getsize(infile)
        w, h = img.size
        img.thumbnail((int(w/scale), int(h/scale)))
        img.save(des_dir + infile)
def compress_photo():
    '''调用压缩图片的函数
    '''
    src_dir, des_dir = "photos/", "min_photos/"
    
    if directory_exists(src_dir):
        if not directory_exists(src_dir):
            make_directory(src_dir)
        # business logic
        file_list_src = list_img_file(src_dir)
    if directory_exists(des_dir):
        if not directory_exists(des_dir):
            make_directory(des_dir)
        file_list_des = list_img_file(des_dir)
        # print file_list
    '''如果已经压缩了,就不再压缩'''
    for i in range(len(file_list_des)):
        if file_list_des[i] in file_list_src:
            file_list_src.remove(file_list_des[i])
    compress('4', des_dir, src_dir, file_list_src)

def handle_photo():
    '''根据图片的文件名处理成需要的json格式的数据
    
    -----------
    最后将data.json文件存到博客的source/photos文件夹下
    '''
    src_dir, des_dir = "photos/", "min_photos/"
    file_list = list_img_file(src_dir)
    print(file_list)
    list_info = []
    for i in range(len(file_list)):
        filename = file_list[i]
        date_str, info = filename.split("_")
        info, _ = info.split(".")
        date = datetime.strptime(date_str, "%Y-%m-%d")
        year_month = date_str[0:7]            
        if i == 0:  # 处理第一个文件
            new_dict = {
    
    "date": year_month, "arr":{
    
    'year': date.year,
                                                                   'month': date.month,
                                                                   'link': [filename],
                                                                   'text': [info],
                                                                   'type': ['image']
                                                                   }
                                        } 
            list_info.append(new_dict)
        elif year_month != list_info[-1]['date']:  # 不是最后的一个日期,就新建一个dict
            new_dict = {
    
    "date": year_month, "arr":{
    
    'year': date.year,
                                                   'month': date.month,
                                                   'link': [filename],
                                                   'text': [info],
                                                   'type': ['image']
                                                   }
                        }
            list_info.append(new_dict)
        else:  # 同一个日期
            list_info[-1]['arr']['link'].append(filename)
            list_info[-1]['arr']['text'].append(info)
            list_info[-1]['arr']['type'].append('image')
    list_info.reverse()  # 翻转
    tmp = bubbleYear(list_info)
    bubble(tmp)
    final_dict = {
    
    "list": list_info}
    with open("../hexoBlog/source/photos/data.json","w") as fp:
        json.dump(final_dict, fp)

def cut_photo():
    """裁剪算法
    
    ----------
    调用Graphics类中的裁剪算法,将src_dir目录下的文件进行裁剪(裁剪成正方形)
    """
    src_dir = "photos/"
    if directory_exists(src_dir):
        if not directory_exists(src_dir):
            make_directory(src_dir)
        # business logic
        file_list = list_img_file(src_dir)
        # print file_list
        if file_list:
            print_help()
            for infile in file_list:
                img = Image.open(src_dir+infile)
                img = img.convert('RGB')
                Graphics(infile=src_dir+infile, outfile=src_dir + infile).cut_by_ratio()            
        else:
            pass
    else:
        print("source directory not exist!")     



def git_operation():
    '''
    git 命令行函数,将仓库提交
    
    ----------
    需要安装git命令行工具,并且添加到环境变量中
    '''
    os.system('git add --all')
    os.system('git commit -m "add photos"')
    os.system('git push origin master')


def bubble(bubbleList):
    listLength = len(bubbleList)
    while listLength > 0:
        for i in range(listLength - 1):    # 这个循环负责设置冒泡排序进行的次数
            # print(bubbleList[i])
            for j in range(listLength-i-1):  # j为列表下标
                if(bubbleList[j].get('arr').get('year') == bubbleList[j+1].get('arr').get('year')):
                    if bubbleList[j].get('arr').get('month') < bubbleList[j+1].get('arr').get('month'):
                
                        bubbleList[j], bubbleList[j+1] = bubbleList[j+1], bubbleList[j]
        return bubbleList

    
        # for i in range(listLength - 1):
        #     if(bubbleList[i].get('arr').get('year') == bubbleList[i+1].get('arr').get('year')):
        #         if bubbleList[i].get('arr').get('month') > bubbleList[i+1].get('arr').get('month'):
        #             bubbleList[i] = bubbleList[i] + bubbleList[i+1]
        #             bubbleList[i+1] = bubbleList[i] - bubbleList[i+1]
        #             bubbleList[i] = bubbleList[i] - bubbleList[i+1]
        # listLength -= 1
    
def bubbleYear(bubbleList):
    listLength = len(bubbleList)
    while listLength > 0:
        for i in range(listLength - 1):
            for j in range(listLength-i-1):
                if bubbleList[j].get('arr').get('year') < bubbleList[j+1].get('arr').get('year'):
                    
                    bubbleList[j], bubbleList[j+1] = bubbleList[j+1], bubbleList[j]
        # print(bubbleList)
        return bubbleList


if __name__ == "__main__":
    cut_photo()        # 裁剪图片,裁剪成正方形,去中间部分
    compress_photo()   # 压缩图片,并保存到mini_photos文件夹下
    git_operation()    # 提交到github仓库
    handle_photo()     # 将文件处理成json格式,存到博客仓库中

其中文件中的内容进行修改,将../hexoBlog/source/photos/data.json 改为你自己的本地博客地址
还需要一个额外的python脚本ImageProcess.py(上网搜了好久都没有,后面找到了源代码赶紧保存了下来)

# coding=utf-8  
from PIL import Image  
import shutil  
import os  

class Graphics:  
    ''' 图片处理类
    
    参数
    -------
    infile: 输入文件路径
    outfile: 输出文件路径
    '''
    def __init__(self, infile, outfile):
        self.infile = infile
        self.outfile = outfile

    def fixed_size(self, width, height):  
        """按照固定尺寸处理图片"""  
        im = Image.open(self.infile)  
        out = im.resize((width, height),Image.ANTIALIAS)  
        out.save(self.outfile)  


    def resize_by_width(self, w_divide_h):  
        """按照宽度进行所需比例缩放"""  
        im = Image.open(self.infile)  
        (x, y) = im.size   
        x_s = x  
        y_s = x/w_divide_h  
        out = im.resize((x_s, y_s), Image.ANTIALIAS)   
        out.save(self.outfile)  


    def resize_by_height(self, w_divide_h):  
        """按照高度进行所需比例缩放"""  
        im = Image.open(self.infile)  
        (x, y) = im.size   
        x_s = y*w_divide_h  
        y_s = y  
        out = im.resize((x_s, y_s), Image.ANTIALIAS)   
        out.save(self.outfile)  


    def resize_by_size(self, size):  
        """按照生成图片文件大小进行处理 (单位 KB)"""  
        size *= 1024  
        im = Image.open(self.infile)  
        size_tmp = os.path.getsize(self.infile)  
        q = 100  
        while size_tmp > size and q > 0:  
            print (q)  
            out = im.resize(im.size, Image.ANTIALIAS)  
            out.save(self.outfile, quality=q)  
            size_tmp = os.path.getsize(self.outfile)  
            q -= 5  
        if q == 100:  
            shutil.copy(self.infile, self.outfile)  

  
    def cut_by_ratio(self):  
        """ 按照图片长宽进行分割
        
        ------------
        取中间的部分,裁剪成正方形
        """  
        im = Image.open(self.infile)  
        (x, y) = im.size  
        if x > y:  
            region = (int(x/2-y/2), 0, int(x/2+y/2), y)  
            #裁切图片  
            crop_img = im.crop(region)  
            #保存裁切后的图片  
            crop_img.save(self.outfile)             
        elif x < y:  
            region = (0, int(y/2-x/2), x, int(y/2+x/2))
            #裁切图片  
            crop_img = im.crop(region)  
            #保存裁切后的图片  
            crop_img.save(self.outfile)    

在运行之前还需要安装python插件

pip install Pillow

将这两个文件都放在照片的文件夹里,运行脚本

python imageDeal.py

执行完后重新git到远程仓库

如果提示缺少什么库,请自行使用pip安装即可

上面两个文件若是出错,可以到我的码云中下载

运行完成后会在你的博客目录/source/photos中出现data.json

修改 Next 主题中的配置

增加相册 style

在 next 主题目录next/layout下面增加 photo.swig 页面

{
    
    % extends '_layout.swig' %}
{
    
    % import '_macro/post-collapse.swig' as post_template %}
{
    
    % import '_macro/sidebar.swig' as sidebar_template %}

{
    
    % block title %}{
    
    {
    
     page.title }} | {
    
    {
    
     config.title }}{
    
    % endblock %}

{
    
    % block content %}

  {
    
    #################}
  {
    
    ### Photo BLOCK ###}
  {
    
    #################}
  <div class="post-block photo">

    <div id="posts" class="posts-collapse">
      
    </div>

  </div>
  
  {
    
    #####################}
  {
    
    ### END Photo BLOCK ###}
  {
    
    #####################}

  {
    
    % include '_partials/pagination.swig' %}
{
    
    % endblock %}

{
    
    % block sidebar %}
  {
    
    {
    
     sidebar_template.render(false) }}
{
    
    % endblock %}

生成相册页面

生成相册页面和生成分类和标签页面一样

hexo new page photos

修改博客/source/photos/index.md

<link rel="stylesheet" href="./ins.css">
<link rel="stylesheet" href="./photoswipe.css"> 
<link rel="stylesheet" href="./default-skin/default-skin.css"> 

<div class="photos-btn-wrap">
    <a class="photos-btn active" href="javascript:void(0)">照片美如画</a>
</div>
<div class="instagram itemscope">
    http://localhost:4000/mrxun" target="_blank" class="open-ins">图片正在加载中…
</div>
 
<script>
  (function() {
    var loadScript = function(path) {
      var $script = document.createElement('script')
      document.getElementsByTagName('body')[0].appendChild($script)
      $script.setAttribute('src', path)
    }
    setTimeout(function() {
        loadScript('./ins.js')
    }, 0)
  })()
</script>

将其中的网址http://localhost:4000/mrxun换成你自己的域名

另外还需要三个css,以及js

photoswipe.css
ins.css
default-skin/default-skin.css(新建文件夹后在放入css文件)
ins.js

这些文件我也放在码云

添加查看相册插件 photoswipe

/theme/next/source/js中添加photoswipe.min.jsphotoswipe-ui-default.min.js,这两个文件可以在github上下载

/theme/next/layout/_scripts/pages/post-details.swig 中插入以下两行(没有的话直接新建即可)

<script src="{
    
    { url_for(theme.js) }}/src/photoswipe.min.js?v={
    
    { theme.version }}"></script>
<script src="{
    
    { url_for(theme.js) }}/src/photoswipe-ui-default.min.js?v={
    
    { theme.version }}"></script>

/theme/next/layout/_layout.swighead标签中添加下面几行

{
    
    % if page.type === "photos" %}
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="pswp__bg"></div>
    <div class="pswp__scroll-wrap">
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
                <button class="pswp__button pswp__button--share" title="Share"></button>
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
                
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>
{
    
    % endif %}

至此相册查看插件 photoswipe 已经配置完毕

总结

我们回顾以下整个流程

  1. 远程仓库 photos
  2. 本地文件夹,从远程仓库 git clone
  3. 博客中新建photos 页面
  4. 执行python脚本处理照片
  5. 重新提交到github码云
  6. 修改博客/source/photos中的index.md,以及添加cssjs文件
  7. 修改主题/layout文件夹中的一些文件
  8. 主题/source/js文件夹中添加js文件

主要参考的文章:https://lovexinforever.github.io/
十分感谢,并且其他添加相册的方法全部失效
原博的顺序以及文件已经非常不全面,我将过程重新梳理,所有需要的插件全部上传到码云,供大家使用

猜你喜欢

转载自blog.csdn.net/qq_32115939/article/details/106377472