前端图片批量处理

181 阅读2分钟

背景

在商品展示类页面开发时,图片是经常要打交道的地方,当数量不多的时候,人为调整还是可以, 但是遇到十几 甚至是上百张图片时候,就需要借助工具解决 如:

  1. 拿到的图片是命名不规则的(有些带有空格 有些带有横杆不统一)
  2. 拿到的图片命名大小写没有区分
  3. 拿到的图片格式不一致, 有些是png, 有些是jpg, 有些是jpeg
  4. 拿到的图片需要的seo优化, 要把把文件命名为有意义的名称, 包括标签 alt title 等命名
  5. 页面上需要重复写入的<img>很多而且需要一定的格式

优化思路

  1. 先把图片素材通过工具,统一格式化所有图片命名和后缀
  2. 通过脚本实现自动化填补<img>

工具篇

mac系统自带

image.png 多选需要操作的图片, 选择重新命名

image.png mac系统支持 替换文本, 添加文本 和 修改格式

第三方软件

这里推荐使用Bluk File Rename工具(mac系统)

下载方式: 在appstore 搜索 rename 安装“批量文件名修改”

image.png

使用流程: 通过配置规则可以实现批量重命名,大写转小写,去空格 去横杆,去掉多余前缀

导入

image.png 我们以这几张图片为例, (有些包含- 有些有空格 有些开头大写)

image.png

设置规则

image.png 这里只需要配置 原文件名 和 扩展名 这两个属性就可以实现规范化的命名

生成结果

image.png 点击预览即可在下面看到 改名后的所有结果

image.png 点击右上角的改名4个文件就会默认覆盖原有路径文件

image.png 生成结果, 当然human .jpg没有处理好,可以重复导入再设置规则,这里就不再叙述.

代码篇

1.vscode 快捷指令

vscode 提供简单高效的快捷指令 如:

ul.piclist>li*6>a[href=#]>img[src=https://picsum.photos/200/300?random\=$]

回车后自动生成 image.png

image.png

这里picsum.photos/200/300 会动态返回不同的图片

2.node + ejs模版输出

源码地址(github.com/mjsong07/in…)

实现:

  1. 本地文件夹的资源遍历
  2. 遍历出来的变量结合ejs模版实现不同定制逻辑页面需求

项目结构

image.png

使用方法

启动命令

  "scripts": { 
    "img-build-1": "node ./src/util/generateImgContent.js  --ejs_path=./img-template-1.ejs --imgPath=static/images/products/product1/pc/*  --cdn=http://cdn/", 
    "img-build-2": "node ./src/util/generateImgContent.js  --ejs_path=./img-template-2.ejs --imgPath=static/images/products/product1/mobile/*  --cdn=../static/images/products/product1/mobile/" 
  }, 

直接运行

npm run img-build-1 
  1. img-build-1 会执行generateImgContent.js代码
  2. 遍历文件夹路径static/images/products/product1/pc/* 所有图片,输出变量
  3. 同时读取img-template-1.ejs 模版
  4. 把变量和模版内容混合输出在dist输出img-build.html文件

读取的文件夹图片列表

image.png

输出内容

image.png

<div class="floor-container">
  <h1>pc</h1>
  <div class="swiper-container">
    <div class="swiper-wrapper">
      <!-- 这里根据实际的情况 修改对应的模板内容 -->
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/1006-200x300.jpg" alt="1006 200x300" title="1006 200x300">
            <p>"1006 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/106-200x300.jpg" alt="106 200x300" title="106 200x300">
            <p>"106 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/171-200x300.jpg" alt="171 200x300" title="171 200x300">
            <p>"171 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/209-200x300.jpg" alt="209 200x300" title="209 200x300">
            <p>"209 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/252-200x300.jpg" alt="252 200x300" title="252 200x300">
            <p>"252 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/327-200x300.jpg" alt="327 200x300" title="327 200x300">
            <p>"327 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/402-200x300.jpg" alt="402 200x300" title="402 200x300">
            <p>"402 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/403-200x300.jpg" alt="403 200x300" title="403 200x300">
            <p>"403 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/437-200x300.jpg" alt="437 200x300" title="437 200x300">
            <p>"437 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/532-200x300.jpg" alt="532 200x300" title="532 200x300">
            <p>"532 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/559-200x300.jpg" alt="559 200x300" title="559 200x300">
            <p>"559 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/58-200x300.jpg" alt="58 200x300" title="58 200x300">
            <p>"58 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/660-200x300.jpg" alt="660 200x300" title="660 200x300">
            <p>"660 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/666-200x300.jpg" alt="666 200x300" title="666 200x300">
            <p>"666 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/670-200x300.jpg" alt="670 200x300" title="670 200x300">
            <p>"670 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/853-200x300.jpg" alt="853 200x300" title="853 200x300">
            <p>"853 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/929-200x300.jpg" alt="929 200x300" title="929 200x300">
            <p>"929 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/942-200x300.jpg" alt="942 200x300" title="942 200x300">
            <p>"942 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/950-200x300.jpg" alt="950 200x300" title="950 200x300">
            <p>"950 200x300"</p>
        </div> 
      </div>
      <div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/989-200x300.jpg" alt="989 200x300" title="989 200x300">
            <p>"989 200x300"</p>
        </div> 
      </div>
      
    </div>
  </div>
  <div class="swiper-button-prev"></div> 
  <div class="swiper-button-next"></div> 
</div>  

支持参数

  "scripts": { 
    "img-build-1": "node ./src/util/generateImgContent.js  --ejs_path=./img-template-1.ejs --imgPath=static/images/products/product1/pc/*  --cdn=http://cdn/", 
    "img-build-2": "node ./src/util/generateImgContent.js  --ejs_path=./img-template-2.ejs --imgPath=static/images/products/product1/mobile/*  --cdn=../static/images/products/product1/mobile/" 
  }, 
- ejs_path : "./img-template-1.ejs"; //这里为对应要输出的模板 
- imgPath : "static/images/products/product1/pc/*"; //这里为遍历的图片文件夹路径
- cdn : "http://cdn/"; //这里替换为实际的业务地址, 本地调试可以使用相对地址 ../static/images/products/product1/mobile/

模版文件

img-template-1.ejs

<div class="floor-container">
  <h1>pc</h1>
  <div class="swiper-container">
    <div class="swiper-wrapper">
      <!-- 这里根据实际的情况 修改对应的模板内容 -->
      <% lists.forEach(function(file){%><div class="swiper-wrapper"><div class="swiper-slide">
            <img src="../static/images/products/product1/pc/<%= file.fileNameAndExt %>" alt="<%= file.fileName %>" title="<%= file.fileName %>">
            <p>"<%= file.fileName %>"</p>
        </div> 
      </div>
      <% })%>
    </div>
  </div>
  <div class="swiper-button-prev"></div> 
  <div class="swiper-button-next"></div> 
</div>  

img-template-2.ejs

<div class="floor-container">
  <div class="row">
      <p class="title animation-item animation">mobile </p>
      <div class="product-text">  
        <% lists.forEach(function(file){%><img src="<%= file.cdn %><%= file.fileNameAndExt %>" alt="<%= file.fileName %>">
          <% })%>
      </div>
      <div class="product-img pc"> 
        <% lists.forEach(function(file){%><img src="<%= file.cdn %><%= file.fileNameAndExt %>" alt="<%= file.fileName %>"> 
        <% })%>
      </div>
      <div class="product-img mobile">
        <% lists.forEach(function(file){%><img src="<%= file.cdn %><%= file.fileNameAndExt %>" alt="<%= file.fileName %>"> 
        <% })%>
      </div>
      <div class="product-icon"> 
        <% lists.forEach(function(file){%><img src="<%= file.cdn %><%= file.fileNameAndExt %>" alt="<%= file.fileName %>">
        <% })%>
      </div>
  </div>
</div>

主要逻辑代码

generateImgContent.js

// 动态根据图片资源生成图片以及标签内容 包括 alt src 地址, title 名称
"use strict";
const glob = require("glob");
const path = require("path");
const ejs = require("ejs");
const fs = require("fs");

let imgTemplatePath = require('minimist')(process.argv.slice(2))['ejs_path']  //"./img-template-1.ejs"; //这里为对应要输出的模板 
let imgPath =require('minimist')(process.argv.slice(3))['imgPath']  // "static/images/products/product1/pc/*"; //这里为遍历的图片文件夹路径
let cdn =require('minimist')(process.argv.slice(4))['cdn']  // "http://cdn/"; //这里替换为实际的业务地址, 本地调试可以使用相对地址 ../static/images/products/product1/mobile/
console.log("imgTemplatePath",imgTemplatePath)
console.log("imgPath",imgPath)
console.log("cdn",cdn)  

const entryFiles = glob.sync(
  imgPath 
);

console.log("entryFiles", entryFiles);

// 写入文件夹操作
const writeToFile = (pathName, result) => {
  //先判断文件夹是否存在,不存在则创建
  const dirname = path.dirname(pathName);
  if(!fs.existsSync(dirname)){
      fs.mkdirSync(dirname);
  }
  // path: 目标文件夹的绝对路径(只支持绝对路径)
  return fs.promises.writeFile(pathName, result);
};

const getCompilerTxt = async (templateName, lists) => {
  // 根据用户执行的命令,拿到指定路径的模板,进行渲染创建
  const templateCurrentPath = `./${templateName}`;
  const templateAbsolutePath = path.resolve(__dirname, templateCurrentPath);
  // 读取HTML 标签
  return new Promise((resolve, reject) => {
    ejs.renderFile(templateAbsolutePath, { lists }, {}, (err, result) => {
      if (err) {
        reject(err);
        return;
      }
      resolve(result);
    });
  });
};

let outerList = [];
Object.keys(entryFiles).map(async (index) => {
  const entryFile = entryFiles[index];
  const fileInfo = path.parse(entryFile);
  let fileName = fileInfo.name;
  fileName = fileName.replaceAll("-", " ");
  const fileNameAndExt = fileInfo.base;   
  let file = {
    fileNameAndExt,
    fileName,
    cdn,
  };
  outerList.push(file);
}); 
async function run() {
  let html = await getCompilerTxt(imgTemplatePath, outerList);  
    const targetPath = path.resolve("./dist", `img-build.html`); 
    await writeToFile(targetPath, html); 
}
run();