src/ispriter.js
function drawImageAndPositionBackground(spriteTask, callback) {

    var combinedCssRules,
        spriteArray = spriteTask.spriteArray,
        fileversion = spriteTask.fileversion;

    // 保存用了同一张精灵图的选择器, 用于最后输出 css 文件的时候统一设置 background-image
    combinedCssRules = {
        // './sprite_output/sprite_1.png': {imageName: '', selectors: []}
    };

    spriteTask.combinedCssRules = combinedCssRules;

    if (!spriteArray[spriteArray.length - 1].root) {

        /* 
         * 若最后一个元素, 没有root 属性, 说明它的样式都是复用已合并的图片的,
         * 直接替换样式即可
         */
        var styleObjArr = spriteArray.pop();

        styleObjArr.forEach(function(styleObj) {

            var imageInfo = styleObj.imageInfo,
                imageName = imageInfo.imageName;
            styleObj.fit = imageInfo.fit;

            if (!combinedCssRules[imageName]) {
                combinedCssRules[imageName] = [];
            }

            // 修改 background 属性
            replaceAndPositionBackground(imageName, styleObj,
                combinedCssRules[imageName], fileversion);
        });
    }

    var ep = new EventProxy();

    ep.after('drawSpriteImage', spriteArray.length, callback);

    spriteArray.forEach(function(styleObjArr, i) {
        var png,
            imageName,
            imageName2, // 用于输出 log 
            imageAbsName;

        png = createPng(styleObjArr.root.w, styleObjArr.root.h);

        imageName = createSpriteImageName(spriteTask.cssFileName, i,
            spriteArray.length);

        styleObjArr.forEach(function(styleObj) {

            var imageInfo = styleObj.imageInfo,
                image = imageInfo.image;

            imageInfo.drew = true;
            imageInfo.imageName = imageName;
            imageInfo.fit = styleObj.fit;

            if (!combinedCssRules[imageName]) {
                combinedCssRules[imageName] = [];
            }

            // 修改 background 属性
            replaceAndPositionBackground(imageName, styleObj,
                combinedCssRules[imageName], fileversion);

            // 对图片进行填充
            image.bitblt(png, 0, 0, image.width, image.height,
                imageInfo.fit.x, imageInfo.fit.y);

        });

        //  输出定位后的图片
        if (styleObjArr.length) { // 没必要输出一张空白图片
            imageName2 = path.join(spriteConfig.output.cssDist, imageName);
            imageName2 = path.normalize(imageName2);

            imageAbsName = path.join(spriteConfig.workspace, imageName2);
            imageAbsName = path.resolve(imageAbsName);
            nf.mkdirsSync(path.dirname(imageAbsName));
            png.pack().pipe(fs.createWriteStream(imageAbsName))
                .on('finish', function() {

                    info('>>Output image:', imageName2);
                    ep.emit('drawSpriteImage');
                });
        } else {
            ep.emit('drawSpriteImage');
        }
    });

}
function drawImageAndPositionBackground(spriteTask, callback) {

    var combinedCssRules,
        spriteArray = spriteTask.spriteArray,
        fileversion = spriteTask.fileversion;

    // 保存用了同一张精灵图的选择器, 用于最后输出 css 文件的时候统一设置 background-image
    combinedCssRules = {
        // './sprite_output/sprite_1.png': {imageName: '', selectors: []}
    };

    spriteTask.combinedCssRules = combinedCssRules;

    if (!spriteArray[spriteArray.length - 1].root) {

        /* 
         * 若最后一个元素, 没有root 属性, 说明它的样式都是复用已合并的图片的,
         * 直接替换样式即可
         */
        var styleObjArr = spriteArray.pop();

        styleObjArr.forEach(function(styleObj) {

            var imageInfo = styleObj.imageInfo,
                imageName = imageInfo.imageName;
            styleObj.fit = imageInfo.fit;

            if (!combinedCssRules[imageName]) {
                combinedCssRules[imageName] = [];
            }

            // 修改 background 属性
            replaceAndPositionBackground(imageName, styleObj,
                combinedCssRules[imageName], fileversion);
        });
    }

    var ep = new EventProxy();

    ep.after('drawSpriteImage', spriteArray.length, callback);

    spriteArray.forEach(function(styleObjArr, i) {
        var png,
            imageName,
            imageName2, // 用于输出 log 
            imageAbsName;

        png = createPng(styleObjArr.root.w, styleObjArr.root.h);

        imageName = createSpriteImageName(spriteTask.cssFileName, i,
            spriteArray.length);

        styleObjArr.forEach(function(styleObj) {

            var imageInfo = styleObj.imageInfo,
                image = imageInfo.image;

            imageInfo.drew = true;
            imageInfo.imageName = imageName;
            imageInfo.fit = styleObj.fit;

            if (!combinedCssRules[imageName]) {
                combinedCssRules[imageName] = [];
            }

            // 修改 background 属性
            replaceAndPositionBackground(imageName, styleObj,
                combinedCssRules[imageName], fileversion);

            // 对图片进行填充
            image.bitblt(png, 0, 0, image.width, image.height,
                imageInfo.fit.x, imageInfo.fit.y);

        });

        //  输出定位后的图片
        if (styleObjArr.length) { // 没必要输出一张空白图片
            imageName2 = path.join(spriteConfig.output.cssDist, imageName);
            imageName2 = path.normalize(imageName2);

            imageAbsName = path.join(spriteConfig.workspace, imageName2);
            imageAbsName = path.resolve(imageAbsName);
            nf.mkdirsSync(path.dirname(imageAbsName));
            png.pack().pipe(fs.createWriteStream(imageAbsName))
                .on('finish', function() {

                    info('>>Output image:', imageName2);
                    ep.emit('drawSpriteImage');
                });
        } else {
            ep.emit('drawSpriteImage');
        }
    });

}
**************************************************************** 5. 根据定位合并图片并输出, 同时修改样式表里面的background ****************************************************************