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