twolfson / gulp.spritesmith

Convert a set of images into a spritesheet and CSS variables via gulp

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How can I use gulp.spritesmith to make multi images

zswxp32 opened this issue · comments

I have used grunt-spritesmith before and find that I can parse a image-config to grunt-spritesmith, it works perfect.
Now I don't know how gulp.spritesmith do with multi image-config, I had tried "merge-stream", but it only works for one of image-config.
Please tell me how to do with this situation, how to correctly return.

Now I use like this and don't know if it's correct...haha

gulp.task('sprite', () => {

    console.log('sprite start!');

    _.forEach(spriteConfig, (val, key) => {

        let spritesmithOptions = {
            imgName: key + '.png',
            cssName: key + '.less',
            padding: 10,
            engine: 'pixelsmith',
            algorithm: 'binary-tree',
            cssOpts: Object.assign(
                {
                    base64: false
                },
                val.cssOpts
            )
        }

        let spriteData = gulp.src(val.src)
            .pipe(spritesmith(spritesmithOptions));
        
        let imgStream = spriteData.img
            .pipe(gulp.dest('./image_new/sprite'));
        
        let lessStream = spriteData.css
            .pipe(gulp.dest('./less_new/sprite'));

        return merge(imgStream, lessStream);
    });

});

You were so close to the answer o.o

The issue is Gulp needs some way of knowing a task completes. It has a few mechanisms for this:

  • Running task synchronously (return nothing)
  • Async callback (ask for done as parameter in task)
  • Stream (return stream so it can listen for finish event)
  • Promise (return promise so it can listen to error and then actions)

In our scenario, we are dealing with streams so we need to return a stream with all of our items on it. We can merge our merge stream results and return that to get the result:

gulp.task('sprite', () => {

    console.log('sprite start!');

    // Updated to `_.map` and saved variable
    var retStreams = _.map(spriteConfig, (val, key) => {

        let spritesmithOptions = {
            imgName: key + '.png',
            cssName: key + '.less',
            padding: 10,
            engine: 'pixelsmith',
            algorithm: 'binary-tree',
            cssOpts: Object.assign(
                {
                    base64: false
                },
                val.cssOpts
            )
        }

        let spriteData = gulp.src(val.src)
            .pipe(spritesmith(spritesmithOptions));
        
        let imgStream = spriteData.img
            .pipe(gulp.dest('./image_new/sprite'));
        
        let lessStream = spriteData.css
            .pipe(gulp.dest('./less_new/sprite'));

        return merge(imgStream, lessStream);
    });

    // Returned a merge stream of array of streams
    return merge(retStreams);
});

merge-stream doesn't document this well but it supports infinite levels of arrays as a parameters due to its recursion:

https://github.com/grncdr/merge-stream/blob/v1.0.1/index.js#L16-L24

Another option would be to define separate sprite tasks (e.g. sprite-foo, sprite-bar) and define a sprite task which calls those (i.e. gulp.task('sprite', ['sprite-foo', 'sprite-bar']))

@twolfson Thank you for your answer! This really works!