Давайте посмотрим, как получить положение мыши пользователя и отобразить его в настраиваемых свойствах CSS: - positionX и - positionY .
Мы могли бы сделать это с помощью JavaScript. Если бы мы это сделали, мы могли бы делать такие вещи, как сделать элемент перетаскиваемым или перемещать фон. Но на самом деле мы все еще можем делать то же самое, но не использовать JavaScript!
Я использовал этот метод как часть демонстрации, которую я сделал для получения эффекта «Щелкни и перетащи» с помощью чистого CSS. Я использовал советы перспективы из моей предыдущей статьи. Это довольно изящный эффект — сделать это полностью на CSS, который может иметь более широкую пользу, чем моя демонстрация, так что давайте взглянем.
Наша первая демонстрация будет использовать настраиваемые свойства - positionX и - positionY для установки ширины и высоты элемент.
Внимание, здесь мы используем SCSS только для краткости, но все это можно сделать на чистом CSS.
Это наше исходное состояние. У нас есть «обертка»
с классом .content который распространяется на ширину и высоту корпуса. Этот
будет содержать содержимое нашего проекта и элементы, которыми мы хотим управлять с помощью позиции мыши — в данном случае элемент .square .
Мы также добавили два настраиваемых свойства к содержимому . мы будем использовать положение мыши, чтобы установить значения этих свойств, а затем с их помощью установить .square элемент ширину и высоту соответственно.
После того, как мы сопоставили настраиваемые свойства для положения мыши, мы можем использовать их, чтобы делать практически все, что захотим. Например, мы могли бы использовать их, чтобы установить свойства top / left для позиционированного элемента absolute управлять свойством transform установить background-position управлять цветами или даже устанавливать содержание псевдоэлемента. Мы увидим некоторые из этих бонусных демонстраций в конце статьи.
Сетка
Цель состоит в том, чтобы создать невидимую сетку на экране и использовать псевдокласс : hover для сопоставления каждой «ячейки» с набором значений, которые мы назначим к настраиваемым свойствам. Таким образом, когда курсор мыши перемещается в правую часть экрана, значение - positionX будет выше; и когда он перемещается влево, он становится ниже. Мы сделаем то же самое с - positionY : значение будет ниже, когда курсор перемещается вверх, и выше, когда он перемещается вниз.
Несколько слов о размере сетки, которую мы используем: мы действительно можем сделать сетку любого размера, какой захотим. Чем он больше, тем точнее будут значения наших настраиваемых свойств. Но это также означает, что у нас будет больше ячеек, что может привести к проблемам с производительностью. Важно поддерживать правильный баланс и настраивать размер сетки в соответствии с конкретными потребностями каждого проекта.
А пока предположим, что нам нужна сетка 10 × 10 для всего 100 ячеек в нашей разметке. (И да, для этого можно использовать Pug, хотя я не буду в этом примере.)
Вы, наверное, задаетесь вопросом, почему элементы .cell предшествуют .content . Это из-за каскада.
Мы хотим использовать класс .cell для управления .square и способ работы каскада (на данный момент) таков, что элемент может управлять только своими дочерними элементами (или потомки) и его братьев и сестер (или их потомков) — но только до тех пор, пока брат находится после контролирующего элемента.
Это означает две вещи:
Каждая .cell должна стоять перед элементом, которым мы хотим управлять (в данном случае, .square ).
Мы не можем поместите эти .cell в контейнер, потому что в этом случае .content больше не будет их родственником.
Размещение камер
Есть несколько способов позиционирования .cell s. мы можем позиционировать : абсолютные их и компенсировать их свойствами top и left . Или мы можем перевести их в положение, используя преобразование . Но самый простой вариант, вероятно, использовать display: grid .
Граница временная, поэтому мы могли видеть на экране ячейки . мы удалим его позже.
z-index важен, потому что мы хотим, чтобы ячейка располагалась перед содержимым .
Вот что у нас есть на данный момент:
Добавление значений
Мы хотим использовать .cell для установки значений - positionX и - positionY .
Когда мы наводим курсор на .cell который находится в первом (левом) столбце, значение - positionX должно быть 0 . Когда мы наводим курсор на .cell во втором столбце, значение должно быть 1 . В третьем столбце должно быть 2 и т. Д.
То же самое и для оси y. Когда мы наводим курсор на .cell который находится в первом (верхнем) ряду, - positionY должен быть 0 а когда мы наводим курсор на ] ячейку во второй строке, значение должно быть 1 и т. д.
Цифры на этом изображении представляют собой номера элементов ячеек в сетке. Если мы возьмем только одну .cell в качестве примера — скажем, ячейку 42 — мы можем выбрать ее, используя : nth-child () :
.cell: nth-child (42) {}
Но нам нужно помнить пару вещей:
Мы хотим, чтобы этот селектор работал только при наведении курсора на ячейку, поэтому мы прикрепим к нему : hover .
Мы хотим выбрать . содержимое вместо самой ячейки, поэтому мы будем использовать для этого General Sibling Combinator ( ~ ).
Итак, чтобы установить - от -positionX до 1 и - positionY до 3 для .content когда 42-я ячейка зависает, нам нужно сделать что-то вроде этого:
Но кто хочет сделать это 100 раз !? Есть несколько способов упростить задачу:
Используйте цикл Sass @for чтобы просмотреть все 100 ячеек, и выполните некоторые вычисления, чтобы установить правильные - positionX и - positionY значений для каждой итерации.
Разделите оси x и y, чтобы выбрать каждую строку и каждый столбец индивидуально с помощью функциональной записи : nth-child .
] Объедините эти два подхода и используйте цикл Sass @for и : nth-child функциональную нотацию.
Я долго думал и твердо о том, что было бы лучшим и самым простым подходом, и хотя у всех этих подходов есть свои плюсы и минусы, я остановился на третьем подходе. Объем кода, который нужно написать, качество скомпилированного кода и математическая сложность — все это у меня в голове. Не согласен? Расскажите почему в комментариях!
Установка значений с помощью цикла @for
@ for $ i от 0 до 10 {
.cell: nth-child (???): hover ~ .content {
--positionX: # {$ i};
}
.cell: nth-child (???): hover ~ .content {
--positionY: # {$ i};
}
}
Это основной цикл. Мы повторим это 10 раз, так как у нас 10 строк и 10 столбцов. И мы разделили оси x и y, чтобы установить - positionX для каждого столбца и - positionY для каждой строки. Все, что нам нужно сделать сейчас, это заменить эти элементы ??? на правильную нотацию для выбора каждой строки и столбца.
Начнем с оси x
Возвращаясь к нашему изображению сетки (изображенному с числами), мы видим, что номера всех ячеек во втором столбце кратны 10 плюс 2. Ячейки в третьем столбце кратны 10 плюс 3 . И так далее.
Теперь давайте «переведем» его в функциональную нотацию : nth-child . Вот как это выглядит для второго столбца:
: nth-ребенок (10n + 2)
10n выбирает каждое кратное 10.
2 — номер столбца.
И для нашего цикла , мы заменим номер столбца на # {$ i + 1} для последовательной итерации:
Посмотрите еще раз на изображение сетки и сосредоточьтесь на четвертой строке. Номера ячеек находятся где-то от 41 до 50. Ячейки в пятой строке — от 51 до 60 и так далее. Чтобы выбрать каждую строку, нам нужно определить ее диапазон. Например, диапазон для четвертой строки:
.cell: nth-child (n + 41): nth-child (-n + 50)
(n + 41) — начало диапазона.
(- n + 50) — конец диапазона.
Теперь мы заменим числа математическими вычислениями для значения $ i . Для начала диапазона мы получаем (n + # {10 * $ i + 1}) а для конца диапазона мы получаем (- n + # {10 * ( $ i + 1)}) .
Итак, последний цикл @for выглядит так:
@ for $ i от 0 до 10 {
.cell: nth-child (10n + # {$ i + 1}): hover ~ .content {
--positionX: # {$ i};
}
.cell: nth-child (n + # {10 * $ i + 1}): nth-child (-n + # {10 * ($ i + 1)}): hover ~ .content {
--positionY: # {$ i};
}
}
Отображение готово! Когда мы наводим курсор на элементы, - positionX и - positionY меняются в зависимости от положения мыши. Это означает, что мы можем использовать их для управления элементами внутри .content .
Обработка пользовательских свойств
Хорошо, теперь у нас есть положение мыши, сопоставленное с двумя настраиваемыми свойствами. Следующее, что нужно использовать, — это использовать их для управления .square элементами шириной и высотой значения.
Давайте начнем с ширины и скажем, что мы хотим, чтобы минимальная ширина .square была 100 пикселей (т. Е. Когда курсор мыши находится в левой части экрана), и мы хотим, чтобы он увеличивался 20 пикселей с каждым шагом, когда курсор мыши перемещается вправо.
Вот и все! Теперь у нас есть простой элемент .square с шириной и высотой который управляется положением мыши. Наведите курсор мыши на окно и посмотрите, как квадрат изменяет свою ширину и высоту соответственно.
Я добавил небольшой переход чтобы сделать эффект более плавным. Конечно, это не обязательно. И я также прокомментировал границу .cell .
Давайте попробуем альтернативный метод
Возможно, вы захотите «обойти» - positionX и - positionY и установить конечное значение непосредственно внутри @for ] петля. В нашем примере это будет выглядеть так:
@ for $ i от 0 до 10 {
.cell: nth-child (10n + # {$ i + 1}): hover ~ .content {
--squareWidth: # {100 + $ i * 20} пикселей;
}
.cell: nth-child (n + # {10 * $ i + 1}): nth-child (-n + # {10 * ($ i + 1)}): hover ~ .content {
--squareHeight: # {100 + $ i * 20} px ;: # {$ i};
}
}
Тогда .square будет использовать такие настраиваемые свойства:
.square {
ширина: var (- squareWidth);
высота: var (- squareHeight);
}
Этот метод немного более гибкий, поскольку он позволяет использовать более сложные математические (и строковые) функции Sass. Тем не менее, общий принцип абсолютно тот же, что мы уже рассмотрели.
Что дальше?
Что ж, остальное зависит от вас — а возможности безграничны! Как вы думаете, вы бы это использовали? Можете ли вы пойти дальше? Попробуйте использовать этот трюк в своем CSS и поделитесь своей работой в комментариях или дайте мне знать об этом в Twitter. Было бы здорово увидеть их целую коллекцию.
Вот несколько примеров, чтобы у вашего хомячка вращалось колесо: