Создание редактора изображений с помощью CamanJS: применение базовых фильтров
Russian (Pусский) translation by Anna Goorikova (you can also view the original English article)
Некоторое время назад я написал несколько руководств, в которых описывалось, как применять различные виды фильтров и режимов наложения к изображению, используя только CSS. Это может быть очень полезно в ситуациях, когда вы хотите показать оттенки серого, размытые или высококонтрастные версии одного и того же изображения. Вместо того чтобы создавать четыре разных изображения, вы можете просто применить эти эффекты к исходному изображению, используя несколько строк в CSS.
Использование CSS фильтров и режимов наложения в большинстве случаев работает хорошо. Однако CSS не изменяет пиксели самого изображения. Другими словами, фильтры и режимы наложения или любые другие эффекты не являются постоянными.
Если кто-то загружает изображение с применяемыми к нему фильтрами CSS, он получит исходное изображение, а не модифицированную версию. Это может стать серьезным препятствием, если вы планируете создать редактор изображений для своих пользователей.
Если вы хотите, чтобы изменения изображений были постоянными и чтобы пользователь мог загрузить измененное изображение, вы можете использовать холст(canvas) HTML5. Элемент canvas позволяет вам делать много вещей, включая рисование линий и фигур, написание текста и анимацию рендеринга.
В этом уроке мы сосредоточимся на редактировании изображений, загруженных на холст. CSS3 уже имеет встроенные функции, позволяющие применять эффекты, такие как контраст, яркость и размытие. При работе с холстом HTML5 мы будем использовать библиотеку манипуляций с холстом для редактирования изображений, называемую CamanJS.
Библиотека поддерживает основные эффекты, такие как яркость, контрастность и насыщенность. Это позволит сэкономить время и позволит нам создавать более сложные фильтры на основе этих базовых.
Основы CamanJS
Имя этой библиотеки основано на том, что она используется для выполнения (ca) nvas (man) ipulation на JavaScript (JS). Прежде чем вы сможете начать использовать различные функции библиотеки, вам придется включить ее в свой проект. Это можно сделать либо путем загрузки библиотеки и ее размещения самостоятельно, либо путем непосредственного связывания с CDN.
Существует два способа использования библиотеки. Первый вариант - использовать атрибут data-caman с вашими элементами изображения. Этот атрибут может принимать комбинацию различных фильтров CamanJS в качестве значения. Например, если вы хотите увеличить яркость изображения на 20 и контраст на 10, вы можете использовать следующий HTML:
1 |
<img src="path/to/image.jpg" |
2 |
data-caman="brightness(20) contrast(10)"> |
Аналогично, вы можете применять другие фильтры, такие как насыщенность, экспозиция, шум, сепия и т. д. Помимо основных фильтров, CamanJS также предоставляет вам доступ к более сложным фильтрам из коробки. Эти фильтры могут быть применены к изображению аналогичным образом. Чтобы применить фильтр sunrise , вы можете просто использовать следующий HTML:
1 |
<img src="path/to/image.jpg" |
2 |
data-caman="sunrise()"> |
Второй способ манипулирования изображениями - вызов Caman() с id холста, где вы визуализировали изображение и различные фильтры, которые вы хотите применить к визуализированному изображению.
1 |
Caman('#canvas-id', function () { |
2 |
this.brightness(20); |
3 |
this.contrast(10); |
4 |
this.render(); |
5 |
});
|
В этом курсе мы будем использовать JavaScript для создания нашего редактора изображений.
Реализация функций загрузки и выгрузки
Необходимо предоставить пользователям способ загрузки изображений, которые они хотят редактировать, чтобы их можно было отобразить на холсте для дальнейшей обработки. После внесения изменений пользователи также смогут загружать отредактированные изображения. В этом разделе мы добавим эти две функции редактора изображений.
Начнем с HTML, необходимого для добавления холста и кнопок загрузки/выгрузки:
1 |
<div class="preview-wrapper"> |
2 |
<canvas id="canvas"></canvas> |
3 |
<p class="process-message"></p> |
4 |
</div>
|
5 |
|
6 |
<div class="editor-buttons"> |
7 |
<input type="file" id="upload-file" placeholder="Upload a Picture" /> |
8 |
<label for="upload-file">Upload a Picture</label> |
9 |
<button id="download-btn">Download Image</button> |
10 |
<br/>
|
11 |
</div>
|
Ниже приведен код для реализации базовой функции загрузки изображений:
1 |
var img = new Image(); |
2 |
var canvas = document.getElementById('canvas'); |
3 |
var ctx = canvas.getContext('2d'); |
4 |
var fileName = ''; |
5 |
|
6 |
$("#upload-file").on("change", function(){ |
7 |
var file = document.querySelector('#upload-file').files[0]; |
8 |
var reader = new FileReader(); |
9 |
if (file) { |
10 |
fileName = file.name; |
11 |
reader.readAsDataURL(file); |
12 |
}
|
13 |
reader.addEventListener("load", function () { |
14 |
img = new Image(); |
15 |
img.src = reader.result; |
16 |
img.onload = function () { |
17 |
canvas.width = img.width; |
18 |
canvas.height = img.height; |
19 |
ctx.drawImage(img, 0, 0, img.width, img.height); |
20 |
$("#canvas").removeAttr("data-caman-id"); |
21 |
}
|
22 |
}, false); |
23 |
});
|
Мы начнем с создания некоторых переменных для хранения имени файла изображения, выбранного пользователем, и контекста для нашего холста. После этого мы пишем код, чтобы получить файл изображения из файла input после запуска события change. Файлы, выбранные пользователем, хранятся в FileList, и мы можем получить первый файл из списка, используя .files[0].
Когда у нас уже есть файл, мы используем объект FileReader, чтобы прочитать его содержимое. Событие onload для FileReader запускается после успешного чтения выбранного файла.
Внутри обработчика событий onload для объекта FileReader мы создаем экземпляр HTMLImageElement с помощью конструктора Image(). Атрибут src изображения затем устанавливается в значение свойства result нашего FileReader.
После успешной загрузки изображения мы устанавливаем ширину и высоту холста равной width и height выбранного пользователем изображения. После этого мы рисуем изображение на холсте и удаляем атрибут data-caman-id с холста.
Атрибут добавляется автоматически CamanJS при настройке холста для редактирования изображения. Мы должны удалять его каждый раз, когда пользователь выбирает новый файл, чтобы избежать путаницы между старым файлом изображения, который мы редактировали, и новым файлом, выбранным пользователем.
Помимо загрузки файла изображения на холст, мы также установили значение переменной fileName равным имени файла, выбранного пользователем. Это будет полезно при сохранении отредактированного изображения.
Теперь пользователи смогут загружать различные изображения в редактор изображений. После того, как они отредактировали изображение, они также хотели бы, скачать их. Давайте напишем код, который позволит пользователям сохранить отредактированный файл изображения.
1 |
$('#download-btn').on('click', function (e) { |
2 |
var fileExtension = fileName.slice(-4); |
3 |
if (fileExtension == '.jpg' || fileExtension == '.png') { |
4 |
var actualName = fileName.substring(0, fileName.length - 4); |
5 |
}
|
6 |
download(canvas, actualName + '-edited.jpg'); |
7 |
});
|
8 |
|
9 |
function download(canvas, filename) { |
10 |
var e; |
11 |
var lnk = document.createElement('a'); |
12 |
|
13 |
lnk.download = filename; |
14 |
lnk.href = canvas.toDataURL("image/jpeg", 0.8); |
15 |
|
16 |
if (document.createEvent) { |
17 |
e = document.createEvent("MouseEvents"); |
18 |
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); |
19 |
lnk.dispatchEvent(e); |
20 |
}
|
21 |
else if (lnk.fireEvent) { |
22 |
lnk.fireEvent("onclick"); |
23 |
}
|
24 |
}
|
Мы используем метод jQuery .on() для выполнения фрагмента кода каждый раз, когда событие click срабатывает для кнопки загрузки. Этот код удаляет расширение файла из имени файла изображения, выбранного пользователем, и заменяет его с суффиксом-edited.jpg. Затем это имя передается в функцию download вместе со ссылкой на холст, где мы отрисовывали и редактировали изображение.
Функция download создает ссылку и устанавливает ее атрибут download в filename. Атрибут href содержит URI данных для редактируемого изображения. После установки значения этих двух атрибутов мы программно запускаем событие click для вновь созданной ссылки. Этот клик запускает загрузку отредактированного изображения.
Применение встроенных фильтров
Как я уже упоминал в начале урока, CamanJS поставляется с базовыми встроенными фильтрами. Таким образом, вы можете непосредственно применять яркость, контраст, сепию, насыщенность, экспозицию, шум, резкость, вибрацию и оттенок. Некоторые фильтры, такие как яркость и контрастность, могут иметь как отрицательное, так и положительное значение.
Вы можете сделать значения такими высокими или низкими, как хотите, но разумным выбором будет устанавливать их между -100 и 100. Например, изображение становится белым при установке яркости 100. Поэтому любое значение выше 100 будет бесполезно. Аналогично, изображение станет полностью серым, если установить значение контраста в -100.
Другие фильтры, такие как сепия, шум, резкость и размытие, принимают только положительные значения. Имейте в виду, что фильтр оттенков покрывает полный круг 360 градусов со значениями от 0 до 100. Изображение будет выглядеть точно так же, когда вы установите оттенок в 0 или 100.
Вот HTML, чтобы добавить кнопки для нашего редактора изображений:
1 |
<div class="filter-buttons"> |
2 |
<div class="filter-group"> |
3 |
<button id="brightness-dec">-</button> |
4 |
<span class="filter-name">Brightness</span> |
5 |
<button id="brightness-inc">+</button> |
6 |
</div>
|
7 |
<!-- More Such Buttons -->
|
8 |
<div class="filter-group"> |
9 |
<button id="gamma-dec" class="disabled">-</button> |
10 |
<span class="filter-name">Gamma</span> |
11 |
<button id="gamma-inc">+</button> |
12 |
</div>
|
13 |
</div>
|
14 |
<div class="editor-buttons"> |
15 |
<input type="file" id="upload-file" placeholder="Upload a Picture" /> |
16 |
<label for="upload-file">Upload a Picture</label> |
17 |
<button id="download-btn">Download Image</button> |
18 |
<br/>
|
19 |
<button id="vintage-btn">Vintage</button> |
20 |
<!-- More Such Buttons -->
|
21 |
<button id="lomo-btn">Lomo</button> |
22 |
</div>
|
Все фильтры, такие как яркость и контрастность, получили кнопки увеличения и уменьшения. Тем не менее, кнопка уменьшить была отключена для некоторых фильтров, таких как шум, потому что они не могут иметь значимое отрицательное значение.
Мы будем применять соответствующие фильтры на основе кнопки, нажатой с помощью следующего JavaScript.
1 |
/* Similar Code for All Other Buttons */
|
2 |
|
3 |
$('#brightness-inc').on('click', function (e) { |
4 |
Caman('#canvas', img, function () { |
5 |
this.brightness(10).render(); |
6 |
});
|
7 |
});
|
8 |
|
9 |
$('#brightness-dec').on('click', function (e) { |
10 |
Caman('#canvas', img, function () { |
11 |
this.brightness(-10).render(); |
12 |
});
|
13 |
});
|
14 |
|
15 |
|
16 |
/* Similar Code for All Inbuilt Filters */
|
17 |
|
18 |
$('#nostalgia-btn').on('click', function (e) { |
19 |
Caman('#canvas', img, function () { |
20 |
this.nostalgia().render(); |
21 |
});
|
22 |
});
|
23 |
|
24 |
$('#majestic-btn').on('click', function (e) { |
25 |
Caman('#canvas', img, function () { |
26 |
this.herMajesty().render(); |
27 |
});
|
28 |
});
|
Для кнопок увеличения и уменьшения сила фильтра зависит от того, как масштабируется его эффект. Например, яркость и контрастность увеличиваются на 10, а значение гаммы увеличивается только на 0.1 после каждого клика.
Следующая демонстрация CodePen показывает в действии редактор изображений CamanJS, который мы создали.
Некоторые фильтры могут занять какое-то время, прежде чем вы увидите их конечный результат. В таких случаях пользователи могут подумать, что фильтр не работает. Мы будем использовать события, чтобы держать пользователей в курсе прогресса фильтра. Все это будет обсуждаться в следующем уроке.
Заключительные мысли
Первое учебное пособие предназначалось для того, чтобы научить вас создавать редактор изображений с базовыми функциями загрузки и скачки изображений, которые пользователи могут использовать для редактирования изображений. Мы использовали базовые фильтры, такие как шум, контраст и яркость, а также некоторые более сложные эффекты, такие как Vintage и Nostalgia, которые встроены в библиотеку.
В следующем уроке вы узнаете больше о возможностях CamanJS, таких как слои, режимы смешивания и события. А пока не забывайте просматривать то, что есть на Envato Market для покупки, изучения, использования и обзора.



