Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bad space utilization when using lots of icons #63

Open
JRWilding opened this issue May 29, 2019 · 3 comments
Open

Bad space utilization when using lots of icons #63

JRWilding opened this issue May 29, 2019 · 3 comments

Comments

@JRWilding
Copy link

JRWilding commented May 29, 2019

Would it be possible to call ShelfPack's shrink when generating the image file, as currently we're seeing a large unused area of the sprite:
image

Whilst the png will compress the area, it is fully loaded as ARGB_8888 on Android wasting a lot of memory (especially on bigger @2x)

@mourner
Copy link
Member

mourner commented Nov 5, 2019

shrink won't help in this case due to the way ShelfPack algorithm works, however we can fix the issue by switching from ShelfPack to Potpack: https://github.com/mapbox/potpack — it's designed with static use case in mind (all sizes are known beforehand), and tries to generate a near-square layout with maximum space utilization.

@mourner mourner changed the title ShelfPack.shrink Bad space utilization when using lots of icons Nov 5, 2019
@jseppi jseppi mentioned this issue Apr 16, 2020
4 tasks
@jseppi
Copy link
Contributor

jseppi commented Apr 17, 2020

@JRWilding Could you provide fixtures and code that result in a sprite like the one shown in your original post?

@JRWilding
Copy link
Author

Hi @jseppi, I don't have access to the source svg files, but there are 1301 icons in a variety of sizes
Heres the code:

'use strict';
​
const spritezero = require('@mapbox/spritezero');
const fs = require('fs');
const glob = require('glob');
const path = require('path');
​
if (!fs.existsSync(path.join(__dirname, 'output'))) {
    fs.mkdirSync(path.join(__dirname, 'output'));
}
if (!fs.existsSync(path.join(__dirname, 'output/glyphs'))) {
    fs.mkdirSync(path.join(__dirname, 'output/glyphs'));
}
​
[1, 1.5, 2, 3, 4].forEach(function (pxRatio) {
    const svgs = glob.sync(path.resolve(path.join(__dirname, 'glyphs/*.svg')))
        .map(function (f) {
            return {
                svg: fs.readFileSync(f),
                id: path.basename(f).replace('.svg', '')
            };
        });
​
    let pngPath = '';
    let jsonPath = '';
    if (pxRatio === 1) {
        pngPath = path.resolve(path.join(__dirname, 'output/glyphs/sprite.png'));
        jsonPath = path.resolve(path.join(__dirname, 'output/glyphs/sprite.json'));
    } else {
        pngPath = path.resolve(path.join(__dirname, 'output/glyphs/sprite@' + pxRatio + 'x.png'));
        jsonPath = path.resolve(path.join(__dirname, 'output/glyphs/sprite@' + pxRatio + 'x.json'));
    }
​
​
    // Pass `true` in the layout parameter to generate a data layout
    // suitable for exporting to a JSON sprite manifest file.
    spritezero.generateLayoutUnique({imgs: svgs, pixelRatio: pxRatio, format: true, removeOversizedIcons: true}, function (err, dataLayout) {
        if (err) return;
        fs.writeFileSync(jsonPath, JSON.stringify(dataLayout));
    });
​
    // Pass `false` in the layout parameter to generate an image layout
    // suitable for exporting to a PNG sprite image file.
    spritezero.generateLayoutUnique({imgs: svgs, pixelRatio: pxRatio, format: false, removeOversizedIcons: true}, function (err, imageLayout) {
        spritezero.generateImage(imageLayout, function (err, image) {
            if (err) return;
            fs.writeFileSync(pngPath, image);
        });
    });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants