Страницы

Поиск по вопросам

суббота, 11 января 2020 г.

Настройка gulp.spritesmith

#javascript #nodejs #gulp


Пытаюсь разобраться с плагином  gulp.spritesmith, исходя и оф. документации самая
простая задача выглядит так:     

gulp.task('imgsprite', function() {
    var spriteData = gulp.src('dev/**/sprite/**/*.{jpg,jpeg,png,gif}')
    .pipe(spriteImg({
        imgName: 'sprite.png', // название собраного спрайта
        cssName: 'sprite.css', // название css файла
    }));
    var stylStream = spriteData.css
    .pipe(gulp.dest('app/'));

    var imgStream = spriteData.img
    .pipe(gulp.dest('app/'));

    return merge (imgStream, stylStream);
});


Что я хочу? Я хочу название спрайта генерировать автоматически, в зависимости от
папки где лежат исходные картинки.
Допустим путь к картинам такой:
dev/project/img/sprites/social/
Значит собранный спрайт должен называться social.png
путь:
dev/project/img/sprites/menu-icon/
собранный спрайт должен называться menu-icon.png
Для чего это нужно?
В проекте может быть несколько спрайтов, соответственно исходные картинки размещаем
в папке sprites и раскладываем по отдельным папкам, название которой и будет именем
генерируемого спрайта.
Вторая задача - это пути выходных файлов, лежат исходные картинки допустим по пути
dev/project/img/sprites/menu-icon/, значит генерированный спрайт должен положиться
app/project/img/menu-icon.png.
Насколько я понимаю нужно анализировать путь к файлам, которые попали в gulp.src,
вытаскивать нужные фрагменты, обрабатывать, сохранять в переменные и уже затем использовать
их в настройках gulp.spritesmith.
Но как это сделать придумать не могу.   Может быть я сейчас велосипед пытаюсь придумать
и уже все есть, буду признателен если кто поделится решением. В сети ничего подобного
не встречал. 
    


Ответы

Ответ 1



И так, в поисках решения данной задачи я столкнулся с несколькими проблемами, и самая главная - это не очень хорошее понимание процессов NODE.js Вторая проблема - заключалась в получении путей к тем файлам, которые попали в gulp.src, дело в том, что у него нет метода который их возвращает. Он просто создает потоки данных используя vinyl fs и передает их для дальнейшей работы с ними..... Что ж, а что же мешает создать собственный экземпляр glob объекта, тем более последним аргументом конструктор принимает колбэк, в который первым приходит объект ошибки, если таковая случилась, а вторым массив с файлами попавшими в выборку. То что и нужно!. Осталось подключить модуль glob , ну и заодно merge-stream, понадобиться для объединения источников спрайта и файла стилей к нему в один выходной поток. var glob = require("glob").Glob; var glob = require("glob").Glob; Ну и создадим саму задачу, создадим в ней новый glob объект с интересующей выборкой и введем несколько переменных: gulp.task('test', function() { var tmp = new glob('dev/**/sprite/**/*.{jpg,jpeg,png,gif}', {}, function(err, matches) { var dirnames = []; // имена каталогов с картинками для спрайтов var files = []; // массив с данными для spritesmith var destination = []; // каталоги назначения }); }); Далее сформируем массивы с именами каталогов - его будем использовать для названий выходных файлов и массивом с путями назначения - там будут лежать пути, по которым необходимо разложить полученные спрайты. Для этого пройдемся в цикле по массиву matches и вытащим необходимую инфу, а в него попадает Красным выделено то, что попадет в dirnames, синим в destination. for(var i = 0; i < matches.length; i++) { var itemPath = matches[i].split('/'); dirnames.push(itemPath[itemPath.length - 2]); itemPath[0] = 'app'; itemPath.length = 4; itemPath.push('/'); destination.push(itemPath.join('/')); } dirnames = Array.from(new Set(dirnames)); destination = Array.from(new Set(destination)); теперь наши массивы выглядят так: Теперь необходимо заполнить массив files, для этого снова воспользуемся циклом, но теперь уже по массиву dirnames, ведь в нем лежат название каталогов с картинками для спрайтов и соответственно сколько каталогов, столько и необходимо объектов в массиве files ключи которого будут: data - это массив, в нем будут лежать пути к картинкам в определенном каталоге (этот же массив и будум передавать в gulp.src, он же принимает массив с путями... вот и чудно). filename - сюда положим название каталога и будем использовать для названия спрайта и стилей к нему. for(var i = 0; i < dirnames.length; i++) { files[i] = {}; files[i].data = []; files[i].filename = dirnames[i]; for(var j = 0; j < matches.length; j++) { if(matches[j].indexOf(dirnames[i]) != -1) { files[i].data.push(matches[j]); } } } И еще один цикл, что-бы добавить в каждый объект путь для спрайта: for(var i = 0; i < files.length; i++) { files[i].destImg =''; for(var j = 0; j < destination.length; j++ ) { var str = destination[j].split('/'); if(files[i].data[0].indexOf(str[2]) != -1) { files[i].destImg = destination[j]; } } } В итоге получим: Ну и осталось теперь пройтись по массиву files и для каждого объекта в нем выполнить функцию: files.forEach(function(item, i, arr){ var spriteData = gulp.src(arr[i].data) .pipe(spriteImg({ imgName: arr[i].filename + '.png', cssName: arr[i].filename + '.css', imgPath: '../img/' + arr[i].filename + '.png' })); var stylStream = spriteData.css .pipe(gulp.dest('app/tmp/' + arr[i].filename + '/')); var imgStream = spriteData.img .pipe(gulp.dest(arr[i].destImg)) return merge (imgStream, stylStream); }); В итоге все спрайты разложаться по нужным директория, названия спрайта будет соответствовать названию каталога в котором лежали исходные картинки, а стили сложатся в паку tmp в корне проекта и так же будут разложены по папкам с названиями каталогов. Весь код полностью: gulp.task('test', function() { var tmp = new glob('dev/**/sprite/**/*.{jpg,jpeg,png,gif}', {}, function(err, matches) { var dirnames = []; // имена каталогов с картинками для спрайтов var files = []; // массив с данными для spritesmith var destination = []; // каталоги назначения for(var i = 0; i < matches.length; i++) { var itemPath = matches[i].split('/'); dirnames.push(itemPath[itemPath.length - 2]); itemPath[0] = 'app'; itemPath.length = 4; destination.push(itemPath.join('/')); } dirnames = Array.from(new Set(dirnames)); destination = Array.from(new Set(destination)); for(var i = 0; i < dirnames.length; i++) { files[i] = {}; files[i].data = []; files[i].filename = dirnames[i]; for(var j = 0; j < matches.length; j++) { if(matches[j].indexOf(dirnames[i]) != -1) { files[i].data.push(matches[j]); } } } for(var i = 0; i < files.length; i++) { files[i].destImg =''; for(var j = 0; j < destination.length; j++ ) { var str = destination[j].split('/'); if(files[i].data[0].indexOf(str[2]) != -1) { files[i].destImg = destination[j]; } } } console.log(files) files.forEach(function(item, i, arr){ var spriteData = gulp.src(arr[i].data) .pipe(spriteImg({ imgName: arr[i].filename + '.png', cssName: arr[i].filename + '.css', imgPath: '../img/' + arr[i].filename + '.png' })); var stylStream = spriteData.css .pipe(gulp.dest('app/tmp/' + arr[i].filename + '/')); var imgStream = spriteData.img .pipe(gulp.dest(arr[i].destImg)) return merge (imgStream, stylStream); }); }); }); P.S Возможно кто-то более опытный сделает лучше и красивее, буду рад если поделится....

Комментариев нет:

Отправить комментарий