Страницы

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

вторник, 5 марта 2019 г.

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

Пытаюсь разобраться с плагином 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 Но как это сделать придумать не могу. Может быть я сейчас велосипед пытаюсь придумать и уже все есть, буду признателен если кто поделится решением. В сети ничего подобного не встречал.


Ответ

И так, в поисках решения данной задачи я столкнулся с несколькими проблемами, и самая главная - это не очень хорошее понимание процессов 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 Возможно кто-то более опытный сделает лучше и красивее, буду рад если поделится....

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

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