JS30. Задание 3 CSS Variables and JS
Демо: https://js3003.github.io/
Код: https://github.com/js3003/js3003.github.io
Должно получиться приложение для редактирования фото, движением ползунков регулирующее ширину рамки, размытие фото и цвет рамки.
Мне бы хотелось применить к фото больше фильтров css, благо, работают они хорошо и эффекты предлагают интересные, менять цвет всего фона, а не только рамки, и, возможно, менять размер всего фото, а не только рамки (здесь нужно подумать)
Но пока сделаю точную копию, посмотрю что получится. Потому что трудно представить, но весь js-код этого приложения у автора поместился всего в шесть строчек (!!!)
Вот как он выглядит:
const inputs = document.querySelectorAll('.controls input');
function handleUpdate() {
const suffix = this.dataset.sizing || '';
document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);
}
inputs.forEach(input => input.addEventListener('change', handleUpdate));
inputs.forEach(input => input.addEventListener('mousemove', handleUpdate));
Попробую разобраться как ему это удалось.
Первое наблюдение.
Код не такой уж минималистичный, часть кода вынесена в css
:root {
--base: #ffc600;
--spacing: 10px;
--blur: 10px;
}
img {
padding: var(--spacing);
background: var(--base);
filter: blur(var(--blur));
}
.hl {
color: var(--base);
}
Странная конструкция.
Предположим, :root это некие базовые цвета и значения.
А зачем вначале две точки? Это псевдокласс? Не похоже. В коде этот :root встречается только один раз - откуда css будет знать какому элементу его присваивать?
Поэкспериментировала. Если убрать две точки и изменить имя, всё работает по-прежнему. Если полностью убрать :root, тоже работает. И если фигурные скобки убрать, работает. А если вместо двух чёрточек ставить одну - уже не работает. И без фигурных скобок теперь тоже не работает. В общем, какие-то чудеса.
Нашла. Это называется пользовательские свойства CSS - Custom Properties
Достаточно новые, кстати, статьи о них датируются 2016-2017 годами. Название одной особенно говорящее "Вы не знаете CSS!". Согласна, действительно не знаю.
Хотя, нет. На хабре о них была статья ещё в 2013 г. Хабр молодцы.
CSS - Custom Properties
Пользовательские свойства, объявляющие переменные, должны именоваться начиная с var-
Общие значения объявляются в стилевых правилах для корневого элемента :root, они будут доступны для каждого элемента документа:
:root {
var-color: #009EE0;
var-spacing: 24px;
}
Обращаться к переменным можно в любом месте внутри значения другого свойства:
h1 {
color: var(color);
}
p {
margin-top: var(spacing);
}
Можно подстраховаться и написать что-то вроде
h1 {
color: var(color, red);
}
Это значит, что элемент h1 будет цвета color, указанного в корневом элементе :root, но если переменная color почему-то не определена, h1 будет красным (red).
Это было в 2013 году.
В 2017 синтаксис немного изменился. Смотрим MDN
CSS переменные (пользовательские CSS-свойства) это сущности, определяемие автором CSS, хранящие конкретные значения, которые можно повторно использовать в документе. Они устанавливаются с использованием custom property нотации (например. --main-color: black;) и доступны через функцию var() (например. color: var(--main-color);) .
Note: В более ранней спецификации префикс для переменных был
var-
, но позже был изменен на --
Теперь понятно зачем нужны две чёрточки вначале.
CSS переменные подчиняются каскаду и наследуют значения от своих родителей.
Объявив переменную в псевдо-классе :root, автор CSS может избежать ненужных повторений, используя эту переменную.
Вроде бы как разобралась )
То есть автор установил базовые значения пользовательских свойств, применил их к элементам документа, и теперь, очевидно, будет менять базовые значения при помощи js.
Заслуживает внимания разметка.
<input type="range">
Этот элемент сразу даст нам шкалу с ползунком, который передвигается мышкой. Он полностью прорисовывается самим браузером и не требует стилизации в css и настройки в js.
Подробнее: http://htmlbook.ru/samhtml5/formy/polzunok
<input type="color">
Это окно для выбора цвета. Как и для предыдущего элемента, стили для него прописаны в самом браузере.
Разбираем код по строчкам
1. const inputs = document.querySelectorAll('.controls input'); - метод поиска элементов нашёл все input и присвоил их переменной inputs. В результате получили что-то вроде массива элементов. На самом деле это не массив, а объект NodeList (неожиданно, да) о его отличиях от массива можно почитать здесь
основное отличие - у NodeList работают не все методы массива. Впрочем for (var i = 0; i < myNodeList.length; i++) работает, и этого достаточно. Но ещё лучше, что работает метод .forEach() Хоть я им, к сожалению, до сих пор ни разу не пользовалась. Почитать о методе можно здесь.
2. function handleUpdate() { - красивое говорящее название функции подсказывает, что она будет обновлять положение ползунка. Наверное
const suffix = this.dataset.sizing || ''; это он создал новую переменную suffix (кстати, почему он переменные константами называет?) и присвоил ей значение px или пустая строка
this.dataset возвращает объект, содержащий все значения атрибута data-.
То есть this.dataset.sizing вернёт px, если data-sizing="px", или пустую строку, если у элемента нет атрибута data-
Перескакиваем через строку и видим два слушателя:
inputs.forEach(input => input.addEventListener('change', handleUpdate));
inputs.forEach(input => input.addEventListener('mousemove', handleUpdate));
Ну, во-первых, здесь появилась функция стрелки. Вообще-то это новая функция, которую ввели только в ECMAScript 6
Она вызывается для каждого элемента inputs (inputs.forEach) принимает его в качестве аргумента input и возвращает input.addEventListener(), который отслеживает события change и mousemove и вызывает функцию handleUpdate.
Событие change происходит по окончании изменении значения элемента формы, когда это изменение зафиксировано.
Событие mousemove срабатывает при передвижении мыши
И осталась последняя строка кода. Что же делает функция handleUpdate кроме того, что определяет значение атрибута data-sizing и присваивает его переменной suffix.
Строка:
document.documentElement.style.setProperty(`--${this.name}`, this.value + suffix);
Расшифровываю практически посимвольно
document.documentElement - это корневой элемент документа. То есть html? Хотя нет. Раз функция вызывается для input, возможно, именно его она и меняет?
И вот этому корневому элементу мы добавляем стиль - css-правило
setProperty - метод, использующийся для задания стилевых свойств. Метод имеет два аргумента: name - имя свойства, которое меняется, и value - значение свойства.
Что же это за правило?
(`--${this.name}`, this.value + suffix)
- две чёрточки - это то, с чего начинается пользовательское css-свойство
- $ - знак доллара это не просто один из разрешённых символов в имени переменной в js, как, например, уверяют здесь, а часть шаблонной строки - новой экспериментальной технологии, предложенной ECMAScript 6
Шаблонные строки заключены в обратные кавычки (` `) вместо двойных или одинарных. Они могут содержать местозаполнители, которые обозначаются знаком доллара и фигурными скобками (
${выражение}
). Выражения в местозаполнителях и текст между ними передаются в функцию. Соответственно, `--${this.name}` это две чёрточки и name input бля которого слушатель заметил изменение. То есть document.documentElement действительно не html, у которого никакого name нет, а input, name которого указано таким же, как и имя свойства, за которое он отвечает.
<input type="range" name="spacing"> - отвечает за отступ,
<input type="range" name="blur"> - отвечает за размытие и т.д
Итак, у нас есть две чёрточки и свойство, дальше идёт запятая значение this.value и единицы измерения - suffix
М-да. 5 часов (!!!) я разбирала 6 строчек кода
В оправдание могу сказать, что код новый, современный и узнала я много нового
- пользовательские свойства CSS - Custom Properties
- ползунок input type="range"
- шаблонные строки
- функция стрелки
И ещё много всего разного.
Ну что ж, удачи мне. Попробую применить полученные знания на практике.