前言
最近,女王大大日常找我弄图片,本来之前我一直是 ps 帮他弄得,后来- -,ps 不能分割过长的图片,我就想想能不能通过代码来帮他实现好了。
经过我在npm
搜索一番,发现没有一个纯代码层面的high tools
来实现这个功能,索性就自己通过node-canvas
这个库弄个小例子出来,自己使用好了
gm 这个库是可以实现的,但是他需要额外安装两个工具,所以- -我就放弃了
简单搭建一下
简单的使用一下
首先,先说说我的需求,下面是一张名为 clip.png
的图片,
我们需要做的就是把他均分为 3 等分,所以,我们尝试写一下我们的代码
const { createWriteStream } = require("fs");
const archiver = require("archiver");
const { createCanvas, loadImage } = require("canvas"); !(async () => { const image = await loadImage("./clip.png"); const { width, height } = image; const mainCanvas = createCanvas(width, height); const ctx = mainCanvas.getContext("2d"); ctx.drawImage(image, 0, 0); const archive = archiver("zip", { zlib: { level: 9 }, }); const output = createWriteStream(__dirname + "/clip.zip"); archive.pipe(output); const num = 3; const oneHeight = height / num; for (let i = 0; i < num; i++) { let clipCanvas = createCanvas(width, oneHeight); const clipCtx = clipCanvas.getContext("2d"); clipCtx.drawImage( mainCanvas, 0, oneHeight * i, width, oneHeight, 0, 0, width, oneHeight ); archive.append(clipCanvas.toBuffer(), { name: `${i + 1}.png` }); clipCanvas = null; } archive.finalize(); })();
|
跑一下我们写的程序,你会惊奇的发现,目录下多了一个clip.zip
的压缩包,解压出来就是我们需要的图片啦
看到这里,其实我们已经实现我们想要的效果了,但是你会发现我们只是实现了水平的切割,如何实现垂直的呢?
也许你会说,加个判断不就好了?
if (direction === "vertical") { const oneHeight = height / num; for (let i = 0; i < num; i++) { let clipCanvas = createCanvas(width, oneHeight); clipCtx.drawImage( mainCanvas, 0, oneHeight * i, width, oneHeight, 0, 0, width, oneHeight ); } } else { const oneWidth = width / num; for (let i = 0; i < num; i++) { let clipCanvas = createCanvas(oneWidth, height); clipCtx.drawImage( mainCanvas, oneWidth * i, 0, width, oneHeight, 0, 0, width, oneHeight ); } }
|
的确,这样写是可以,但是会不会觉得很不优雅?那我们是不是可以找找规律,把他封装成一份呢?答案是肯定可以的
这里我们可以新建一个数组配置,用来判断我们传递的参数来判断是 width/num
还是 height/num
,闲话不多少了,开始写我们的代码把
const { createWriteStream } = require("fs");
const archiver = require("archiver");
const { createCanvas, loadImage } = require("canvas");
const directionConfig = ["vertical", "horizontal"]; !(async () => { const image = await loadImage("./clip.png"); const { width, height } = image; const mainCanvas = createCanvas(width, height); const ctx = mainCanvas.getContext("2d"); ctx.drawImage(image, 0, 0); const archive = archiver("zip", { zlib: { level: 9 }, }); const output = createWriteStream(__dirname + "/clip.zip"); archive.pipe(output); const clip = clipNumImage({ canvas: mainCanvas, width, height }, 3); clip.forEach((img, idx) => { archive.append(img, { name: `${idx + 1}.png` }); }); archive.finalize(); })();
function clipNumImage(options, num, direction = "horizontal") { const { canvas, ...canvasSize } = options; let directionIdx = getIdx(direction); const directionOptions = getOptions(canvasSize, directionIdx, num); const clip = []; for (let i = 0; i < num; i++) { let clipCanvas = createCanvas(...directionOptions); const clipCtx = clipCanvas.getContext("2d"); clipCtx.drawImage( canvas, ...directionOptions.map((val, idx) => idx === directionIdx ? val * i : 0 ), ...directionOptions, 0, 0, ...directionOptions ); clip.push(clipCanvas.toBuffer()); clipCanvas = null; } return clip; }
function getIdx(direction) { let directionIdx = directionConfig.indexOf(direction); if (directionIdx === -1) { directionIdx = 1; } return directionIdx; }
function getOptions(size, directionIdx, num) { return Object.values(size).map((val, idx) => idx === directionIdx ? val / num : val ); }
|
通过数组,是不是感觉到我们代码比以前更加简洁了呢?好啦,这次小 demo 我们也写完啦,希望你通过这篇文章也学习到一点知识。感谢你的观看
gitee 地址,github 地址
ps: 对了,还有一个长图切割器,不写代码的话,直接下载用也是极好的,点我下载
最后
感谢各位观众老爷的观看 O(∩_∩)O