HTML5 web приложение с фильтрами как в Instagram. Часть 1.

В этой серии статей я расскажу как можно сделать простое HTML5 веб-приложение для обработки изображений. Пользователь может выбрать или перетащить фотографию на своём компьютере в окно браузера и применить к нему фильтры, похожие на фильтры Instagram. После применения подходящего фильтра полученное изображение может быть скачано на компьютер.

Посмотреть демо приложения Вы можете на моём аккаунте codepen: http://codepen.io/nikitakiselev/full/kXyBAP/.

Содержание

  1. Техническое задание
  2. Введение
  3. Подготовка инструментов
  4. Добавление проекта на GitHub
  5. Написание HTML каркаса
  6. Написание Javascript кода
  7. Написание CSS кода
  8. Заключение

Техническое задание

Определим краткое техническое задание для разработки.

Необходимо создать веб приложение, позволяющее накладывать фильтры на изображение. Изображение должно загружаться с компьютера с помощью перетягивания "Drag'n'Drop". Предусмотреть возможность загрузки изображения с помощью стандартного диаголового окна выбора файла.

Разрешённые форматы изображений: jpg и png. Если пользователь пытается загрузить файл или изображение другого формата, необходимо уведомить его о том, что данный тип файла не поддерживается. В целях экономии ресурсов, изображение для обработки фильтрами должно масштабироваться до 500x500 пикселей.

После выбора изображения пользователь должен увидеть список фильтров, которые он сможет применять на изображении. Фильтры не должны смешиваться.

После выбора подходящего фильтра необходимо дать возможность пользователю скачать изображение на свой компьютер. К имени скачиваемого файла должен добавлять суффикс с названием фильтра, которым он обработан. Например, если пользователь загружает файл изображения с именем avatar.jpg и применяет фильтр "vintage", то скачиваемое изображение должно быть с именем avatar-vintage.png.

Веб приложение должно быть интуитивно понятным, с ненагруженным тёмным дизайном.

Все остальные, неописанные в данном разделе нюансы, делаются на усмотрение разработчика.

Введение

Для написания приложения нам понадобятся средующие ресурсы:

Caman.js
мощный инструмент для canvas, который позволяет применять различные эффекты и фильтры на изображение. Он поставляется с 18 предустановленными фильтрами, которые мы будем использовать в этом примере (но Вы можете создать больше, если хотите);
jQuery:
будем использовать версию 2.*;
jQuery Mousewheel
плагин для прокрутки списка эфеектов для изображений колесом мыши;

Разрабатывать приложение я буду на своей локальной машине, на которой установлена операционная система elementary OS 0.3.2 Freya (64-bit). Код я буду набирать в текстовом редакторе Sublime Text build 3114.

Для сборки проекта воспользуемся сборщиком Gulp. В качестве веб сервера будет выступать простой http сервер на node.js. В качестве препроцессора CSS будет использоваться SASS с синтаксисом SCSS. Так же, необходимо будет прогонять весь CSS код через autoprefixer, чтобы он автоматически добавлял префиксы к свойствам CSS.

Для написания javascript кода я буду использовать синтаксис ECMAScript 6. Компиляцией ECMA6 кода в ECMA5 будет заниматься Babel.

Подготовка инструментов

Создадим папку, в которой будет находиться наше приложение и перейдём в неё:

mkdir html5-insta-filters
cd html5-insta-filters

Создадим файл package.json коммандой

npm init -y

и установим все необходимые инструменты для работы:

npm install --save-dev gulp gulp-sourcemaps gulp-autoprefixer gulp-sass gulp-babel babel-preset-es2015 gulp-serve -y

Опишу подробнее, для чего нужен каждый из пакетов:

gulp
лучший сборщик проектов на node.js. Поможет автоматизировать огромное количество рутинных задач, таких как компиляция из SASS в CSS, добавление преффиксов к CSS свойствам, компиляция ECMA6 и т.д. http://gulpjs.com/
gulp-sourcemaps
генерирует css sourscemaps, что позволяет соотносить строки в файлах SCSS со строками уже откомпилированного CSS. Т.е. если в том же google chrome проинспектировать объект, то строки и файлы стилей будет показываться из SASS файлов, вместо откомпилированного CSS файла. https://www.npmjs.com/package/gulp-sourcemaps
gulp-autoprefixer
автоматически следит и добавляет необходимые префиксы к CSS свойствам. Можно писать CSS не задумываять о -webkit-, -moz и т.д. https://www.npmjs.com/package/gulp-autoprefixer
gulp-sass
обертка над node-sass, позволяет компилировать SASS код в CSS. https://www.npmjs.com/package/gulp-sass
gulp-babel и babel-preset-es2015
gulp-babel это обёртка над Babel. А Babel с пресетами babel-preset-es2015 позволяет уже сейчас пользоваться преимуществами нового синтаксиса ECMA6, не задумываях о поддержке его браузерами, т.к. babel будет компилировать код с старый ECMA5. https://www.npmjs.com/package/gulp-babel
gulp-serve
простой http сервер, написанный на node.js. На нём мы будем запускать приложение. https://www.npmjs.com/package/gulp-serve

Теперь займёмся настройкой gulp со всеми, только что установленными, пакетами. Для начала создадим файл gulpfile.js:

touch gulpfile.js

В нём нужно описать всю логику сборки проекта gulp'ом.

Компиляция SASS

Все SASS файлы приложения мы будем хранить в папке src/scss. Откомпилированные CSS файлы будут располагаться в папке css. Основным файлом будет являться файл src/scss/app.scss. Его и нужно будет компилировать. Создадим необходимые папки и файлы:

mkdir -p src/scss && touch src/scss/app.scss

Теперь напишем код для компиляции SCSS:

gulpfile.js

var gulp = require('gulp');
var sass = require('gulp-sass');
var sourcemaps = require('gulp-sourcemaps');
var autoprefixer = require('gulp-autoprefixer');

/* SCSS Compile */
gulp.task('sass', function () {
    return gulp.src('./src/scss/app.scss')
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(autoprefixer({browsers: ['last 3 versions']}))
        .pipe(sourcemaps.write('maps'))
        .pipe(gulp.dest('./css'));
});

Здесь берётся файл ./src/sass/app.scss, компилируется в css, далее по этому css "проходит" autoprefixer с поддержкой 3 последних браузеров, создаётся файл app.css.map с css sourcemap, откомпилированный SASS созраняется в папку ./css/app.css. Дальнейшие правки стилей должны проводиться в файле app.scss, а не app.css.

Теперь, если написать код в файле /src/sass/app.scss для примера:

.row {
    display: flex;
}

и запустим команду для компиляции sass

gulp sass

мы увидим, что создалась папка ./css а в ней файл app.css со уже добаленными нужными префиксами и строкой sourceMappingURL, которая указывает на файл css sourcemap.

.row {
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex; }

/*# sourceMappingURL=css/maps/app.css.map */

Настройка компилятора SASS завершена.

Компиляция ECMA6 в ECMA5

Т.к. ещё не все браузеры поддерживают спецификацию ECMA6, а писать на новом удобном синтаксисе уже хочется, существует babel, который компилирует код в ECMA5, который уже поддерживают все браузеры. Другими словами ECMA5 это и есть обычный javascript, к которому мы все привыкли.

Исходные файлы javascript будут находиться с папке ./src/js и компилироваться в папку ./scripts.

Создадим папку с файлом app.js в котором будем писать весь javasctipt код приложения.

mkdir src/js
touch src/js/app.js

Для компиляции ECMA6 необходимо написать новую задачу в файле gulpfile.js.

gulpfile.js

var babel = require('gulp-babel');

/* Compile ECMA6 -> ECMA5 */
gulp.task('babel', function() {
    return gulp.src('./src/js/app.js')
        .pipe(sourcemaps.init())
        .pipe(babel({
            presets: ['es2015']
        }))
        .pipe(sourcemaps.write('maps'))
        .pipe(gulp.dest('./scripts'));
});

При компиляции так же будет создаваться source map. На этом настройка компилятора закончена.

Настройка http сервера

Создадим точку входа в наше приложения - файл index.html и добавим в него содержимое:

echo "Web server works..." > index.html

Напишем задачу для запуска http сервера, всё так же в файле gulpfile.js:

gulpfile.js

var serve = require('gulp-serve');

gulp.task('serve', serve('./'));

Теперь, если запустить задачу gulp serve, и перейти по адресу http://127.0.0.1:3000/ можно увидеть текст "Web server works..." , который мы написали в файле index.html.

Сервер настроен и работает.

Настройка watcher

Каждый раз, когда мы будем изменять код проекта, необходимо запускать компиляцию gulp sass или gulp babel, что не очень удобно. Этот процесс можно автоматизировать и сделать так, чтобы задачи запускались автоматически, при изменении файлов. Для этого и существует watcher (наблюдатель), и он уже встроен в gulp.

Добавим новую задачу в gulpfile.js, котороя будет называться watch:

gulpfile.js

gulp.task('watch', function() {
    gulp.watch('src/js/**/*.js', function(event) {  
        gulp.run('babel');
    });

    gulp.watch('src/scss/**/*.scss', function(event) {  
        gulp.run('sass');
    });
});

Перед выполнением задачи watch запускается наш http сервер. Далее я создаю наблюдателей для всех файлов js в папке src/js, включая подпапки, и при их изменении будет запускаться задача "babel". То же самои и для файлов scss.

Теперь, перед тем как работать с проектом необходимо запустить watcher gulp watch, и спокойно писать код.

gulp watch

У стандартного watchera есть некоторые недостатки, например после запуска gulp watch он не "видит" новые файлы, нужно каждый раз после создания файла перезапускать watcher. Но для наших задач подойдёт и такой вариант, т.к. целью статьи является разработка именно приложения, а не инструкцию по продвитой настройке gulp.

Действие gulp по умолчанию

Если в консоли выполнить команду gulp, то ничего не произойдёт, т.к. мы не объявили действие умолчанию. Такая задача должна называться default. Давайте создадим её, чтобы при запуске этой команды проект компилировался:

gulpfile.js

gulp.task('default', ['sass', 'babel']);

Эта команда просто вызывает другие: sass и babel.

Добавление проекта на GitHub

Как обычно, добавим в проект систему контроля версий git и добавим весь проект на github. Перед добавлением необходимо создать файл .gitignore и прописать в нём папки и файлы, которые будут исключены при добавлении в репозиторий.

touch .gitignore

.gitignore

/css
/scripts
/node_modules

Теперь инициализируем git, добавляем проект и делаем первый коммит.

git init
git add .
git commit -m 'Init project'

Я создам на своём github аккаунте удалённый репозиторий, на котором размещу проект, чтобы читатели статьи могли посмотреть исходный код статьи и состояние проекта на каждой из стадий.

git remote add origin git@github.com:mblog-repository/html5-insta-filters.git
git push -u origin master

На этом первая часть статьи "HTML5 web приложение с фильтрами как в Instagram" завершена. Здесь я размещу ссылку на удалённый репозиторий с текущим состоянием проекта 0d2b24a. Если у вас есть какие либо вопросы, задавайте их в комментариях. Если вы сочли статью полезной, поделитесь ею с друзьями с соц сетях, ссылки даны ниже.

Продолжение HTML5 web приложение с фильтрами как в Instagram. Часть 2.