From 9afda5feb6e1c9a265503f19733fcf61237926db Mon Sep 17 00:00:00 2001 From: conechan Date: Thu, 20 Jul 2017 17:17:00 +0800 Subject: [PATCH] use jimp instead of lwip. --- .gitignore | 3 +- lib/sprite.js | 83 +++++++++++++++++------------- package.json | 9 ++-- test/result/style-willerce.css | 26 ++++++++++ test/result/style-willerce.png | Bin 0 -> 8151 bytes test/result/style-willerce@2x.png | Bin 0 -> 11267 bytes test/tmtsprite.js | 14 ++++- 7 files changed, 92 insertions(+), 43 deletions(-) create mode 100644 test/result/style-willerce.css create mode 100644 test/result/style-willerce.png create mode 100644 test/result/style-willerce@2x.png diff --git a/.gitignore b/.gitignore index c5f9c8d..55c7541 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules/ .idea/ *.ipr *.iws -*.iml \ No newline at end of file +*.iml +.vscode diff --git a/lib/sprite.js b/lib/sprite.js index 1b2369b..2ac37d2 100644 --- a/lib/sprite.js +++ b/lib/sprite.js @@ -8,7 +8,7 @@ var async = require('async') var lodash = require('lodash') var imageinfo = require('imageinfo') var layout = require('layout') -var lwip = require('node-lwip') +var Jimp = require('jimp') var fs = require('fs') var Color = require('color') @@ -32,13 +32,12 @@ module.exports = function (options) { if (err) throw err - lwip.open(data, imageinfo(data).format.toLowerCase(), function (err, img) { - + Jimp.read(data, function (err, img) { if (!err) { layer.addItem({ - height: img.height() + meta.margin, - width: img.width() + meta.margin, + height: img.bitmap.height + meta.margin, + width: img.bitmap.width + meta.margin, meta: lodash.extend({img: img}, meta) }) @@ -223,18 +222,21 @@ module.exports = function (options) { if (layerInfo.items.length > 0) { - lwip.create(layerInfo.width, layerInfo.height, opt.color, function (err, image) { + new Jimp(layerInfo.width, layerInfo.height, 0xFFFFFF00, function (err, image) { async.eachSeries(layerInfo.items, function (sprite, callback) { //图片合并 - image.paste(sprite.x + sprite.meta.margin, sprite.y + sprite.meta.margin, sprite.meta.img, callback) + image.composite(sprite.meta.img, sprite.x + sprite.meta.margin, sprite.y + sprite.meta.margin, function () { + //CSS替换 + var code = 'background-image: url("' + opt.spriteOut + cssBaseName + '.png");' + code += ' background-position: -' + (sprite.x + sprite.meta.margin) + 'px -' + (sprite.y + sprite.meta.margin) + 'px;' + + cssContent = cssContent.split(sprite.meta.backgroundCodeLine).join(code) + callback() + }); - //CSS替换 - var code = 'background-image: url("' + opt.spriteOut + cssBaseName + '.png");' - code += ' background-position: -' + (sprite.x + sprite.meta.margin) + 'px -' + (sprite.y + sprite.meta.margin) + 'px;' - cssContent = cssContent.split(sprite.meta.backgroundCodeLine).join(code) }, function () { image1x = image @@ -262,23 +264,27 @@ module.exports = function (options) { var retinaCssContent = '\n\n@media only screen and (-webkit-min-device-pixel-ratio: 2),only screen and (min--moz-device-pixel-ratio: 2),only screen and (min-resolution: 240dpi) {' - lwip.create(retinaLayerInfo.width, retinaLayerInfo.height, opt.color, function (err, image) { + new Jimp(retinaLayerInfo.width, retinaLayerInfo.height, 0xFFFFFF00, function (err, image) { async.eachSeries(retinaLayerInfo.items, function (sprite, callback) { //图片合并 - image.paste(sprite.x + sprite.meta.margin, sprite.y + sprite.meta.margin, sprite.meta.img, callback) + image.composite(sprite.meta.img, sprite.x + sprite.meta.margin, sprite.y + sprite.meta.margin, function () { + cssContent = cssContent.split(sprite.meta.backgroundCodeLine).join(''); + + //添加 media query + lodash.each(sprite.meta.className2x, function (item) { + retinaCssContent += item + retinaCssContent += '{background-image:url("' + opt.spriteOut + cssBaseName + '@2x.png");' + retinaCssContent += '-webkit-background-size:' + retinaLayerInfo.width / 2 + 'px;' + retinaCssContent += 'background-size:' + retinaLayerInfo.width / 2 + 'px;' + retinaCssContent += 'background-position: -' + ((sprite.x + sprite.meta.margin) / 2) + 'px -' + ((sprite.y + sprite.meta.margin) / 2) + 'px;}' + }) + + callback() + }) - cssContent = cssContent.split(sprite.meta.backgroundCodeLine).join(''); - //添加 media query - lodash.each(sprite.meta.className2x, function (item) { - retinaCssContent += item - retinaCssContent += '{background-image:url("' + opt.spriteOut + cssBaseName + '@2x.png");' - retinaCssContent += '-webkit-background-size:' + retinaLayerInfo.width / 2 + 'px;' - retinaCssContent += 'background-size:' + retinaLayerInfo.width / 2 + 'px;' - retinaCssContent += 'background-position: -' + ((sprite.x + sprite.meta.margin) / 2) + 'px -' + ((sprite.y + sprite.meta.margin) / 2) + 'px;}' - }) }, function () { retinaCssContent += "}" @@ -317,24 +323,27 @@ module.exports = function (options) { var retinaCssContent = '\n\n@media only screen and (min-device-width: 414px) and (-webkit-min-device-pixel-ratio: 3) {' - lwip.create(retinaLayerInfo.width, retinaLayerInfo.height, opt.color, function (err, image) { + new Jimp(retinaLayerInfo.width, retinaLayerInfo.height, 0xFFFFFF00, function (err, image) { async.eachSeries(retinaLayerInfo.items, function (sprite, callback) { //图片合并 - image.paste(sprite.x + sprite.meta.margin, sprite.y + sprite.meta.margin, sprite.meta.img, callback) - - cssContent = cssContent.replace(sprite.meta.backgroundCodeLine, '') - - //添加 media query - lodash.each(sprite.meta.className3x, function (item) { - retinaCssContent += item - retinaCssContent += '{background-image:url("' + opt.spriteOut + cssBaseName + '@3x.png");' - retinaCssContent += '-webkit-background-size:' + retinaLayerInfo.width / 3 + 'px;' - retinaCssContent += 'background-size:' + retinaLayerInfo.width / 3 + 'px;' - retinaCssContent += 'background-position: -' + ((sprite.x + sprite.meta.margin) / 3) + 'px -' + ((sprite.y + sprite.meta.margin) / 3) + 'px;}' + image.composite(sprite.meta.img, sprite.x + sprite.meta.margin, sprite.y + sprite.meta.margin, function () { + cssContent = cssContent.replace(sprite.meta.backgroundCodeLine, '') + + //添加 media query + lodash.each(sprite.meta.className3x, function (item) { + retinaCssContent += item + retinaCssContent += '{background-image:url("' + opt.spriteOut + cssBaseName + '@3x.png");' + retinaCssContent += '-webkit-background-size:' + retinaLayerInfo.width / 3 + 'px;' + retinaCssContent += 'background-size:' + retinaLayerInfo.width / 3 + 'px;' + retinaCssContent += 'background-position: -' + ((sprite.x + sprite.meta.margin) / 3) + 'px -' + ((sprite.y + sprite.meta.margin) / 3) + 'px;}' + }) + + callback() }) + }, function () { retinaCssContent += "}" @@ -371,7 +380,7 @@ module.exports = function (options) { async.series([ function (next) { if (image1x) { - image1x.toBuffer('png', {}, function (err, spriteBuffer) { + image1x.getBuffer('image/png', function (err, spriteBuffer) { _this.push(new File({ base: opt.spriteOut, @@ -388,7 +397,7 @@ module.exports = function (options) { function (next) { if (image2x) { - image2x.toBuffer('png', {}, function (err, retinaSpriteBuffer) { + image2x.getBuffer('image/png', function (err, retinaSpriteBuffer) { _this.push(new File({ base: opt.spriteOut, @@ -406,7 +415,7 @@ module.exports = function (options) { function (next) { if (image3x) { - image3x.toBuffer('png', {}, function (err, retinaSpriteBuffer) { + image3x.getBuffer('image/png', function (err, retinaSpriteBuffer) { _this.push(new File({ base: opt.spriteOut, diff --git a/package.json b/package.json index 321bcda..1f7dfa7 100755 --- a/package.json +++ b/package.json @@ -39,18 +39,19 @@ "async": "^2.0.0-rc.6", "color": "^0.11.3", "imageinfo": "^1.0.4", + "jimp": "^0.2.28", "layout": "~2.2.0", "lodash": "^4.13.1", - "node-lwip": "^0.2.1", "through2": "^2.0.1", "vinyl": "^1.1.1" }, "devDependencies": { - "mocha": "^2.1.0", - "mocha-lcov-reporter": "^0.0.2", "coveralls": "^2.11.2", "istanbul": "^0.3.7", - "should": "^5.1.0" + "mocha": "^2.1.0", + "mocha-lcov-reporter": "^0.0.2", + "should": "^5.1.0", + "vinyl-fs": "^2.4.4" }, "readmeFilename": "README.md" } diff --git a/test/result/style-willerce.css b/test/result/style-willerce.css new file mode 100644 index 0000000..f7f2653 --- /dev/null +++ b/test/result/style-willerce.css @@ -0,0 +1,26 @@ +.icon-excel { + background-image: url("../sprite/style-willerce.png"); background-position: -0px -0px;; + height: 64px; + width: 64px; +} + +.icon-project { + background-image: url("../sprite/style-willerce.png"); background-position: -64px -0px;; + height: 64px; + width: 64px; +} + +.icon-word { + background-image: url("../sprite/style-willerce.png"); background-position: -0px -64px;; + height: 64px; + width: 64px; +} + +.icon-word_2 { + background-image: url("../sprite/style-willerce.png"); background-position: -0px -64px;; + height: 64px; + width: 64px; +} + + +@media only screen and (-webkit-min-device-pixel-ratio: 2),only screen and (min--moz-device-pixel-ratio: 2),only screen and (min-resolution: 240dpi) {} \ No newline at end of file diff --git a/test/result/style-willerce.png b/test/result/style-willerce.png new file mode 100644 index 0000000000000000000000000000000000000000..5ef1cf4dddc9b970eca32eb062233b441fc39a4c GIT binary patch literal 8151 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 literal 0 HcmV?d00001 diff --git a/test/result/style-willerce@2x.png b/test/result/style-willerce@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c319dd86176415d3293e3215ae09321cd50f0d2c GIT binary patch literal 11267 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