tinyjs-resource-loader
Advanced tools
Comparing version 0.1.0 to 0.2.0
117
index.js
@@ -11,2 +11,3 @@ var path = require('path'); | ||
var urlLoader = require('url-loader'); | ||
var im = require('imagemagick-stream'); | ||
@@ -19,7 +20,15 @@ var spritesheetJS = path.resolve(__dirname, 'node_modules/spritesheet-js/index.js'); | ||
function copyFile (source, dest) { | ||
return new Promise (function (resolve) { | ||
function copyFile (source, dest, scale) { | ||
return new Promise(function (resolve) { | ||
var readStream = fs.createReadStream(source); | ||
var writeStream = fs.createWriteStream(dest); | ||
readStream.pipe(writeStream); | ||
if (scale && scale < 1) { | ||
var percentage = `${parseInt(scale * 100, 10)}%`; | ||
var resize = im().resize(percentage); | ||
readStream.pipe(resize).pipe(writeStream); | ||
} else { | ||
readStream.pipe(writeStream); | ||
} | ||
writeStream.on('finish', function () { | ||
@@ -32,4 +41,11 @@ resolve(); | ||
// 抽帧 | ||
function trimFrames (name, source, dest, skip) { | ||
var files = fs.readdirSync(source); | ||
function trimFrames (name, source, dest, config) { | ||
var files = []; | ||
if (config.files) { | ||
files = Object.keys(config.files); | ||
} else { | ||
files = fs.readdirSync(source); | ||
} | ||
fs.mkdirSync(dest); | ||
@@ -44,3 +60,3 @@ | ||
files.forEach(function (file, index) { | ||
var factor = skip + 1; | ||
var factor = config.skip + 1; | ||
@@ -50,5 +66,12 @@ if (index % factor !== 0) return false; | ||
var filePath = path.join(source, file); | ||
var fileIndex = zeroPad(parseInt(index / factor + 1, 10), 3); | ||
var filename = skip ? `${name}-${fileIndex}.png` : `${name}-${file}`; | ||
promises.push(copyFile(filePath, path.join(dest, filename))) | ||
var fileIndex, filename; | ||
if (config.files) { | ||
filename = `${name}-${config.files[file]}.png`; | ||
} else { | ||
fileIndex = zeroPad(parseInt(index / factor + 1, 10), 3); | ||
filename = config.skip ? `${name}-${fileIndex}.png` : `${name}-${file}`; | ||
} | ||
promises.push(copyFile(filePath, path.join(dest, filename), config.scale)); | ||
}); | ||
@@ -78,3 +101,3 @@ | ||
if (stderr) return reject(stderror); | ||
if (stderr) return reject(stderr); | ||
@@ -92,5 +115,5 @@ var jsonPath = path.join(output, `${name}.json`); | ||
function pngOptimize (source, dest, colors) { | ||
return new Promise(function (resolve) { | ||
return new Promise(function (resolve, reject) { | ||
var pngquant = new PngQuant([colors]); | ||
var readStream = fs.createReadStream(source) | ||
var readStream = fs.createReadStream(source); | ||
var writeStream = fs.createWriteStream(dest); | ||
@@ -123,3 +146,3 @@ readStream.pipe(pngquant).pipe(writeStream); | ||
var sheetConfig = JSON.parse(content); | ||
var imagePath = /\"([^\"]+)\"/.exec(imagePathStr)[1]; | ||
var imagePath = /"([^"]+)"/.exec(imagePathStr)[1]; | ||
sheetConfig.meta.image = imagePath; | ||
@@ -163,40 +186,45 @@ return JSON.stringify(sheetConfig); | ||
if (config.files) { | ||
Object.keys(config.files).forEach(function (filePath) { | ||
var fullPath = path.resolve(self.context, filePath); | ||
self.addDependency(fullPath); | ||
}); | ||
} | ||
var inputTemp = tempfile(); | ||
var outputTemp = tempfile(); | ||
trimFrames(name, self.context, inputTemp, config.skip) | ||
.then(function () { | ||
var source = path.join(inputTemp, '*.png'); | ||
return spritesheet(name, source, outputTemp, config); | ||
}) | ||
.then(function () { | ||
var source = path.join(outputTemp, `${name}.png`); | ||
var dest = path.resolve(query.output, `${name}.png`); | ||
return pngOptimize(source, dest, config.colors); | ||
}) | ||
.then(function () { | ||
var source = path.join(outputTemp, `${name}.json`); | ||
var dest = path.resolve(query.output, `${name}.json`); | ||
trimFrames(name, self.context, inputTemp, config) | ||
.then(function () { | ||
var source = path.join(inputTemp, '*.png'); | ||
return spritesheet(name, source, outputTemp, config); | ||
}) | ||
.then(function () { | ||
var source = path.join(outputTemp, `${name}.png`); | ||
var dest = path.resolve(query.output, `${name}.png`); | ||
return pngOptimize(source, dest, config.colors); | ||
}) | ||
.then(function () { | ||
var source = path.join(outputTemp, `${name}.json`); | ||
var dest = path.resolve(query.output, `${name}.json`); | ||
fse.copy(source, dest, function () { | ||
fse.copy(source, dest, function () { | ||
fse.remove(inputTemp); | ||
fse.remove(outputTemp); | ||
setTimeout(function () { | ||
var content = buildFiles(self, query, self.options, name); | ||
callback(null, content); | ||
}, 500); | ||
}); | ||
}) | ||
.catch(function () { | ||
self.emitWarning(`Error occurred in image processing, so ${name}.json and ${name}.png will be directly read from ouput directory. See https://github.com/ant-tinyjs/tinyjs-resource-loader for more info.`); | ||
fse.remove(inputTemp); | ||
fse.remove(outputTemp); | ||
setTimeout(function () { | ||
var content = buildFiles(self, query, self.options, name) | ||
callback(null, content); | ||
}, 500); | ||
var content = buildFiles(self, query, self.options, name); | ||
callback(null, content); | ||
}); | ||
}) | ||
.catch(function () { | ||
var source = path.resolve(query.output, `${name}.json`); | ||
var jsonStr = fs.readFileSync(source); | ||
self.emitWarning(`Error occurred in image processing, so ${name}.json and ${name}.png will be directly read from ouput directory. See https://github.com/ant-tinyjs/tinyjs-resource-loader for more info.`); | ||
fse.remove(inputTemp); | ||
fse.remove(outputTemp); | ||
var content = buildFiles(self, query, self.options, name) | ||
callback(null, content); | ||
}) | ||
}; | ||
@@ -208,5 +236,6 @@ | ||
trim: false, | ||
scale: 1, | ||
padding: '10', | ||
colors: 256, | ||
skip: 0 | ||
} | ||
}; |
{ | ||
"name": "tinyjs-resource-loader", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "用于处理 tiny.js 游戏资源的 webpack loader", | ||
@@ -29,2 +29,3 @@ "main": "index.js", | ||
"graceful-fs": "^4.1.11", | ||
"imagemagick-stream": "^4.1.1", | ||
"loader-utils": "^1.1.0", | ||
@@ -37,3 +38,11 @@ "node-fs-extra": "^0.8.2", | ||
"yaml-js": "^0.1.5" | ||
}, | ||
"devDependencies": { | ||
"eslint": "^4.4.1", | ||
"eslint-config-standard": "^10.2.1", | ||
"eslint-plugin-import": "^2.7.0", | ||
"eslint-plugin-node": "^5.1.1", | ||
"eslint-plugin-promise": "^3.5.0", | ||
"eslint-plugin-standard": "^3.0.1" | ||
} | ||
} |
# tinyjs-resource-loader | ||
用于处理 tinyjs 游戏资源的 webpack loader,旨在让 tinyjs 项目中的动画帧(雪碧图)合成流程更加符合 webpack 工作流 | ||
## 安装 | ||
`npm install tinyjs-resource-loader -D` | ||
## 使用方法 | ||
@@ -9,5 +12,5 @@ 1. 在动画帧(雪碧图)目录中创建 `.tileset` (或任意名称)配置文件 | ||
├── .tileset | ||
├── frame001.png | ||
├── frame002.png | ||
└── frame003.png | ||
├── 001.png | ||
├── 002.png | ||
└── 003.png | ||
``` | ||
@@ -18,2 +21,3 @@ 2. 参照[图片处理参数](#图片处理参数)以 `yaml` 格式对 `.tileset` 进行配置 | ||
colors: 16 | ||
scale: 0.5 | ||
``` | ||
@@ -72,3 +76,3 @@ 3. 在 `webpack.config.js` 中配置 `tinyjs-resource-loader`,该 loader 应作用于上面的配置文件 | ||
``` | ||
5. 最后通过 [url-loader](https://github.com/webpack-contrib/url-loader) 将 `game/images`中的 JSON 和图片构建到 `dist/resources` 中(由 webpack config 中的 `output.path` 指定) | ||
5. 最后通过 [url-loader](https://github.com/webpack-contrib/url-loader) 将 `game/images`中的 JSON 和图片构建到 `dist/resources` 中(由 webpack config 中的 `output.path` 指定)。这一步会自动将 JSON 中 `meta.image` 项替换为图片的 `publicPath` 或 `base64` 编码(取决于 `query.image` 的配置) | ||
```bash | ||
@@ -85,3 +89,3 @@ dist | ||
+ [pngquant](https://pngquant.org/):提供 [node-pngquant](https://github.com/papandreou/node-pngquant) 压缩图片所需的 `pngquant` 命令 | ||
> 注意:如果系统中没有安装以上的依赖,构建时会跳过处理过程中的前 3 步,直接从 `output` 读取 JSON 和图片,并通过 [url-loader](https://github.com/webpack-contrib/url-loader) 将它们构建到指定目录中,但会产生 webpack warning。这是为了确保项目在构建过一次以后,在 windows 环境或者远程机器也能够进行构建,兼顾跨平台或者云构建的需求 | ||
> 注意:如果系统中没有安装以上的依赖,构建时会跳过处理过程中的前 4 步,直接从 `output` 读取 JSON 和图片,并通过 [url-loader](https://github.com/webpack-contrib/url-loader) 将它们构建到指定目录中,但会产生 webpack warning。这是为了确保项目在构建过一次以后,在 windows 环境或者远程机器也能够进行构建,兼顾跨平台或者云构建的需求 | ||
@@ -95,4 +99,14 @@ ## 配置参数 | ||
+ `trim`:移除图片周围的空白,参照 [spritesheet.js](https://github.com/krzysztof-o/spritesheet.js),默认 `false` | ||
+ `scale`: 图片缩放比例,基于 [imagemagick-stream](https://github.com/eivindfjeldstad/imagemagick-stream) 对图片进行缩放,默认 `1` | ||
+ `padding`: 雪碧图中图片的间隙,参照 [spritesheet.js](https://github.com/krzysztof-o/spritesheet.js),默认 `10` | ||
+ `skip`:抽帧时跳过的帧数,如果指定为 N,会每跳过 N 帧保留一帧,默认 `0` | ||
+ `colors`:雪碧图进行图片压缩的颜色数,默认 `256` | ||
+ `files`: 以 `[path]-[name]` 对象格式配置的文件路径,如果配置了 `files`,将不会从 `.tileset` 所在目录读取动画帧,而且从 `files` 指定的路径中读取 | ||
`files` 配置的路径为相对于 `.tileset` 所在目录的路径,示例: | ||
```yaml | ||
files: | ||
../animation-a/001.png: animation-a | ||
../animation-b/001.png: animation-b | ||
../animation-c/001.png: animation-c | ||
``` |
14059
6
200
108
11
6
+ Addedimagemagick-stream@^4.1.1
+ Addedimagemagick-stream@4.1.1(transitive)