mirror of
https://github.com/ful1e5/apple_cursor.git
synced 2025-05-13 22:54:45 -04:00
📂 Structure bitmaper
This commit is contained in:
parent
8ad5d2720e
commit
1108cfd7b4
71 changed files with 92 additions and 260 deletions
26
bitmap/package.json
Normal file
26
bitmap/package.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "apple_cursor_bitmap",
|
||||
"version": "1.0.7",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"watch": "nodemon --inspect src/index.ts",
|
||||
"render": "yarn ts-node src/index.ts"
|
||||
},
|
||||
"repository": "git@github.com:ful1e5/apple_cursor.git",
|
||||
"author": "Kaiz Khatri",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/pixelmatch": "^5.2.2",
|
||||
"@types/pngjs": "^3.4.2",
|
||||
"@types/puppeteer": "^5.4.2",
|
||||
"nodemon": "^2.0.7",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"pixelmatch": "^5.2.1",
|
||||
"pngjs": "^6.0.0",
|
||||
"puppeteer": "^5.5.0"
|
||||
}
|
||||
}
|
23
bitmap/src/config.ts
Normal file
23
bitmap/src/config.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import path from "path";
|
||||
import { readdirSync, existsSync } from "fs";
|
||||
|
||||
// Directory resolve
|
||||
const projectRoot = path.resolve(__dirname, "../../");
|
||||
|
||||
const outDir = path.resolve(projectRoot, "pngs");
|
||||
const staticSvgDir = path.resolve(projectRoot, "svg", "static");
|
||||
const animatedSvgDir = path.resolve(projectRoot, "svg", "animated");
|
||||
|
||||
// Generate a svg list
|
||||
if (!existsSync(staticSvgDir) || !existsSync(animatedSvgDir)) {
|
||||
throw new Error("svg directory not found");
|
||||
}
|
||||
|
||||
const staticCursors = readdirSync(staticSvgDir).map((f) =>
|
||||
path.resolve(staticSvgDir, f)
|
||||
);
|
||||
const animatedCursors = readdirSync(animatedSvgDir).map((f) =>
|
||||
path.resolve(animatedSvgDir, f)
|
||||
);
|
||||
|
||||
export { staticCursors, animatedCursors, outDir };
|
111
bitmap/src/index.ts
Normal file
111
bitmap/src/index.ts
Normal file
|
@ -0,0 +1,111 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import Pixelmatch from "pixelmatch";
|
||||
|
||||
import { PNG } from "pngjs";
|
||||
import puppeteer, { ElementHandle, Page } from "puppeteer";
|
||||
|
||||
import { animatedCursors, outDir, staticCursors } from "./config";
|
||||
import { getFrameName } from "./utils/getFrameName";
|
||||
import { toHTML } from "./utils/toHTML";
|
||||
|
||||
const getSVGElement = async (page: Page) => {
|
||||
const svg = await page.$("#container svg");
|
||||
|
||||
if (!svg) {
|
||||
throw new Error("svg element not found!");
|
||||
}
|
||||
return svg;
|
||||
};
|
||||
|
||||
const screenshot = async (element: ElementHandle<Element>): Promise<Buffer> => {
|
||||
return await element.screenshot({
|
||||
omitBackground: true,
|
||||
encoding: "binary",
|
||||
});
|
||||
};
|
||||
|
||||
const saveFrame = (key: string, frame: Buffer) => {
|
||||
const out_path = path.resolve(outDir, key);
|
||||
fs.writeFileSync(out_path, frame, { encoding: "binary" });
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
const browser = await puppeteer.launch({
|
||||
ignoreDefaultArgs: ["--single-process", "--no-sandbox"],
|
||||
headless: true,
|
||||
});
|
||||
|
||||
if (!fs.existsSync(outDir)) {
|
||||
fs.mkdirSync(outDir);
|
||||
} else {
|
||||
throw new Error(`out directory '${outDir}' already exists.`);
|
||||
}
|
||||
|
||||
for (const svgFilePath of staticCursors) {
|
||||
const svgData = fs.readFileSync(svgFilePath, "utf-8");
|
||||
if (!svgData) {
|
||||
throw new Error(`${svgFilePath} File Read error`);
|
||||
}
|
||||
|
||||
const page = await browser.newPage();
|
||||
const html = toHTML(svgData);
|
||||
|
||||
await page.setContent(html);
|
||||
const svg = await getSVGElement(page);
|
||||
|
||||
const key = `${path.basename(svgFilePath, ".svg")}.png`;
|
||||
const out = path.join(outDir, key);
|
||||
|
||||
console.log("Saving", key, "...");
|
||||
await svg.screenshot({ omitBackground: true, path: out });
|
||||
await page.close();
|
||||
}
|
||||
|
||||
for (const svgFilePath of animatedCursors) {
|
||||
const svgData = fs.readFileSync(svgFilePath, "utf8");
|
||||
if (!svgData) {
|
||||
throw new Error(`${svgFilePath} File Read error`);
|
||||
}
|
||||
|
||||
const page = await browser.newPage();
|
||||
const html = toHTML(svgData);
|
||||
|
||||
await page.setContent(html);
|
||||
const svg = await getSVGElement(page);
|
||||
|
||||
let index = 1;
|
||||
let breakRendering = false;
|
||||
|
||||
// Rendering 1st frame
|
||||
const img1 = await screenshot(svg);
|
||||
const key1 = getFrameName(index, svgFilePath);
|
||||
|
||||
console.log("Saving", key1, "...");
|
||||
saveFrame(key1, img1);
|
||||
|
||||
// Rendering frames till `imgN` matched to `img1`
|
||||
while (!breakRendering) {
|
||||
++index;
|
||||
const imgN = await screenshot(svg);
|
||||
const keyN = getFrameName(index, svgFilePath);
|
||||
|
||||
console.log("Saving", keyN, "...");
|
||||
saveFrame(keyN, imgN);
|
||||
|
||||
const { data: img1Data, width, height } = PNG.sync.read(img1);
|
||||
const { data: imgNData } = PNG.sync.read(imgN);
|
||||
|
||||
const diff = Pixelmatch(img1Data, imgNData, null, width, height);
|
||||
|
||||
if (diff <= 100) {
|
||||
breakRendering = !breakRendering;
|
||||
}
|
||||
}
|
||||
|
||||
await page.close();
|
||||
}
|
||||
await browser.close();
|
||||
};
|
||||
|
||||
main();
|
14
bitmap/src/utils/getFrameName.ts
Normal file
14
bitmap/src/utils/getFrameName.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import path from "path";
|
||||
|
||||
export const frameNumber = (index: number, endIndex: number) => {
|
||||
let result = "" + index;
|
||||
while (result.length < endIndex) {
|
||||
result = "0" + result;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export const getFrameName = (index: number, fileName: string) => {
|
||||
const frame = frameNumber(index, 2);
|
||||
return `${path.basename(fileName, ".svg")}-${frame}.png`;
|
||||
};
|
19
bitmap/src/utils/toHTML.ts
Normal file
19
bitmap/src/utils/toHTML.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
export const template = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Render Template</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<svginjection>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
export const toHTML = (svgData: string): string =>
|
||||
template.replace("<svginjection>", svgData);
|
12
bitmap/tsconfig.json
Normal file
12
bitmap/tsconfig.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"strictNullChecks": true,
|
||||
"esModuleInterop": true,
|
||||
"target": "ES2015",
|
||||
"module": "commonjs",
|
||||
"lib": ["es2015", "dom"],
|
||||
"noUnusedParameters": true
|
||||
}
|
||||
}
|
1195
bitmap/yarn.lock
Normal file
1195
bitmap/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue