Функция CSS path

Хитрость здесь в том, чтобы создать больше знаков Программирование и разработка

В выпуске Chrome 88 мы получили поддержку clip-path: path(). Это означает, что теперь он поддерживается «большинством» основных браузеров!

С помощью path()мы можем использовать определения пути для файла clip-path. (Вы нагнать то, что clip-pathнаходится здесь ). Эти строки определения пути такие же, как и те, которые мы можем использовать с элементом пути SVG. Что в этом круто, так это то, что он позволяет создавать фигуры, которые раньше, возможно, означали использование SVG. Мы даже можем создавать пути, которые ломаются, не требуя каких-либо уловок.

Благодаря возросшей поддержке появилась возможность попробовать что-нибудь интересное! Сделаем «Писклявые портреты»! Это забавный clip-path: path()способ закрепить видимую область элемента в этих значках в стиле Никелодеона.

«Писклявые портреты 👇😅»

Не закончил играть с CSS clip-path: path () 😂

Нацелен на шлепок, но остановился на писклявом звуковом эффекте 😆

Работает на переменных с ограниченной областью видимости! 💪

(Лучше со звуком 👍)

👉 https://t.co/Nuqyivpm5Y через @CodePen pic.twitter.com/TCCouglKpd

— Jhey 🐻🛠 (@ jh3yy) 12 февраля 2021 г.

Создание пути

Во-первых, нам нужна наша собственная строка определения пути в стиле SVG. И в данном случае более одного. Самое интересное в том, clip-pathчто мы можем преобразовать их с помощью CSS. Пока clip-pathфункция и количество узлов согласованы, мы можем переходить.

Чтобы проложить несколько путей, мы можем перейти в любой редактор векторной графики. В данном случае я использую Фигму. И вместо того, чтобы создавать пути с нуля, мы можем использовать желаемый «splat» в качестве основы. Это хорошо выглядит!

Хитрость здесь в том, чтобы создать больше знаков

Хитрость здесь в том, чтобы создать больше знаков на основе знака основания. И нам нужно сделать это, не вводя и не удаляя никаких узлов. Вот три знака, которые я придумал. Но вы можете создавать любые формы, если будете придерживаться этого правила!

Вы можете заметить, что на третьем значке есть две капли

Вы можете заметить, что на третьем значке есть две капли, которые отделяются от основной формы. Это нормально, потому что определения путей SVG позволяют нам это делать. Мы можем начать линию, закрыть ее и перейти к другой точке, чтобы начать новую.

Но разве я не сказал, что им нужно постоянное количество очков? Они делают. И вот что мы имеем здесь! Эти две капли появляются для каждого знака. Но хитрость в том, что мы можем переместить их за оставшуюся часть пути, когда они не нужны.

Но разве я не сказал, что им нужно постоянное количество очков

Когда у нас есть знаки, мы можем экспортировать их и получить строки определения пути:

PUG: 

<svg width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M232.5 256C225 251 209.5 262.5 224 281.5C232.736 292.948 238.561 297.756 251 290.5C257 287 256.114 271.924 250 264.5C243.886 257.076 240 261 232.5 256ZM147 92.5C118.738 94.6708 118 17 93 44C68 71 123.543 76.5 108 101.5C90.5 115 70.81 98.3664 64 115C56.7766 132.643 91.1967 136.948 90.5 156C89.4406 184.974 19.1766 161.499 24.5 190C29.9178 219.006 78.6461 172.635 100 193C130.207 221.808 1 248.5 58.5 291.5C94.5576 318.465 114.991 206.551 140.5 211C183.5 218.5 134.5 294 186.5 279.5C207.5 273 174.638 224.658 196 204C223.117 177.777 275.916 253 291.5 218.5C311.375 174.5 228.698 194.565 224 160C219.553 127.282 291.5 123.5 267.5 87.5C238.5 57 247 125.5 196 105.5C147 92.5 229.5 13.5 173.5 2.5C140.5 2.49999 183.532 89.694 147 92.5ZM45 92.5C36.8766 80.3149 14.1234 75.3149 6.00001 87.5C0.584412 95.6234 2.00001 120.357 14.5 115C27.9606 109.231 36.8766 124.685 45 112.5C50.4156 104.377 50.4156 100.623 45 92.5Z" fill="#A91CFF"/>
</svg>
<svg width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M161 188.375C170 193.5 177.919 193.854 186 188.375C197.919 180.294 197.919 159.581 186 151.5C177.919 146.021 169.081 146.021 161 151.5C149.081 159.581 152 183.25 161 188.375ZM145.5 70.5C127 70.5 112 24.5202 89.5 42C77.6254 51.2251 94.3244 85.6756 87.5 92.5C81.0365 98.9635 61.5 85.5 53.5 112C45.5 138.5 74.5 143.25 74.5 154C74.5 164.751 36.6441 162.082 39.5 185.5C42 206 86.5365 194.537 93 201C100.5 213.5 52 251.495 80 263.5C103 273.362 118 222.5 141 222.5C151.261 222.5 156.5 271.5 182.5 268C202.988 265.242 192.5 222.5 205.5 213.5C218.5 204.5 267.5 235 279.5 213.5C292.936 189.427 235.5 171 235.5 154C232.5 135.5 282.5 113.5 267.5 87.5C254.5 70.5 218 96 201.5 92.5C186 84 196 42 175.5 38C157.5 31.5 155.991 70.5 145.5 70.5ZM138 129C129.877 116.815 108.623 116.815 100.5 129C95.0844 137.123 95.0844 145.877 100.5 154C108.623 166.185 129.877 166.185 138 154C143.416 145.877 143.416 137.123 138 129Z" fill="#173CFF" />
</svg>
<svg width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M161 188.375C170 193.5 177.919 193.854 186 188.375C197.919 180.294 197.919 159.581 186 151.5C177.919 146.021 169.081 146.021 161 151.5C149.081 159.581 152 183.25 161 188.375ZM141.5 59.5C131.26 59.5 117.936 45.0628 100.5 52C81.6499 59.5 86.0351 73.5325 78.5 85.5C70 99 57.9171 96.3659 49.5 115C40.4659 135 58.5 138 58.5 154C58.5 170 41 166.5 46.5 185.5C52 204.5 72.5 196 81.6499 209C94.5 218.5 81.6499 233.418 100.5 241.5C122.657 251 121.5 232 141.5 237C154.5 237 154.5 257 180.5 251C203.99 245.579 193.5 230 211 222.5C226.5 212.5 236.5 226 255 206C272.51 187.07 247.5 177 249 154C253 132.5 273.5 120 258.5 94C245.5 77 235 78.5 211 75.5C190.5 68 200 53 177.5 49.5C153.5 43.5 161 59.5 141.5 59.5ZM138 129C129.877 116.815 108.623 116.815 100.5 129C95.0844 137.123 95.0844 145.877 100.5 154C108.623 166.185 129.877 166.185 138 154C143.416 145.877 143.416 137.123 138 129Z" fill="#FF0B0B"/>
</svg>

Stylus:

*
  box-sizing border-box
  
body
  min-height 100vh
  display flex
  align-items center
  justify-content center
  flex-wrap wrap

Применение знаков

Чтобы применить знаки, мы собираемся создать переменные для каждого пути:

.portrait {
  --splat: "M161 188.375C170 193.5 177.919 193.854 186 188.375C197.919 180.294...";
  --splattier: "M161 188.375C170 193.5 177.919 193.854 186 188.375C197.919...";
  --splatted: "M232.5 256C225 251 209.5 262.5 224 281.5C232.736 292.948...";
}

Это пути, которые мы проложили прямо из экспортированного SVG.

Мы будем использовать названия «splat», «splattier» и «splatted». Называть вещи сложно. Ха! Но возьмем, к примеру, SVG со шлепками:

<svg width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M232.5 256C225 251 209.5 262.5 224 281.5C232.736 292.948 238.561 297.756 251 290.5C257 287 256.114 271.924 250 264.5C243.886 257.076 240 261 232.5 256ZM147 92.5C118.738 94.6708 118 17 93 44C68 71 123.543 76.5 108 101.5C90.5 115 70.81 98.3664 64 115C56.7766 132.643 91.1967 136.948 90.5 156C89.4406 184.974 19.1766 161.499 24.5 190C29.9178 219.006 78.6461 172.635 100 193C130.207 221.808 1 248.5 58.5 291.5C94.5576 318.465 114.991 206.551 140.5 211C183.5 218.5 134.5 294 186.5 279.5C207.5 273 174.638 224.658 196 204C223.117 177.777 275.916 253 291.5 218.5C311.375 174.5 228.698 194.565 224 160C219.553 127.282 291.5 123.5 267.5 87.5C238.5 57 247 125.5 196 105.5C147 92.5 229.5 13.5 173.5 2.5C140.5 2.49999 183.532 89.694 147 92.5ZM45 92.5C36.8766 80.3149 14.1234 75.3149 6.00001 87.5C0.584412 95.6234 2.00001 120.357 14.5 115C27.9606 109.231 36.8766 124.685 45 112.5C50.4156 104.377 50.4156 100.623 45 92.5Z" fill="#A91CFF"/>
</svg>

Мы извлекаем dатрибут из pathэлементов и создаем для них переменные CSS. Затем нам нужен элемент, к которому они будут применяться. Создадим элемент с классом «портрет»:

<div class="portrait"></div>

Затем примените к нему немного стиля:

.portrait {
  --splat: "M161 188.375C170 193.5 177.919 193.854 186 188.375C197.919 180.294...";
  --splattier: "M161 188.375C170 193.5 177.919 193.854 186 188.375C197.919...";
  --splatted: "M232.5 256C225 251 209.5 262.5 224 281.5C232.736 292.948...";
  --none: "";
  height: 300px;
  width: 300px;
  background: #daa3f5;
  clip-path: path(var(--clip, var(--none)));
  transition: clip-path 0.2s;
}

Обратите внимание на то, как фигура переходит между тремя фигурами знака. Но также обратите внимание, как мы дали нашему элементу явную высоту и ширину. Этот размер соответствует размерам нашего экспорта SVG. Это важно. Это единственный недостаток использования clip-path: path(). Это не реагирует. Определение пути зависит от размеров вашего элемента. Это та же проблема, с которой сталкиваются пути движения CSS.

Это нормально, если мы помним о размерах объектов, которые мы обрезаем. Мы также могли бы создать разные переменные пути для разных размеров области просмотра. Но если у вас есть изображения, размер которых изменяется плавно, другие решения, использующие SVG, будут более надежными.

Взаимодействие

В нашей демонстрации мы хотим, чтобы значок был интерактивным. Мы можем сделать это только с помощью CSS. Мы можем использовать переменную CSS с ограниченной областью видимости — —clip- для управления текущим клипом. И затем мы можем обновить эту переменную на обоих :hoverи :active. —activeСостояние срабатывает, когда мы нажмем наш указатель вниз:

.portrait {
  clip-path: path(var(--clip, var(--splat)));
}
.portrait:hover {
  --clip: var(--splattier);
}
.portrait:active {
  --clip: var(--splatted);
}

Добавление персонажа

Теперь, когда мы можем преобразовать знак, нужно кое-что еще. Что, если мы трансформируем его и в этих состояниях?

.portrait {
  transition: clip-path 0.2s, transform 0.2s;
  transform: scale(var(--scale, 1)) rotate(var(--rotate, 0deg));
}
.portrait:hover {
  --scale: 1.15;
  --rotate: 30deg;
}
.portrait:active {
  --scale: 0.85;
  --rotate: -10deg;
}

Используя переменные CSS с областью видимости для применения a transform, мы можем что-то добавить. Здесь мы обновляем scaleи rotationнашего splat. Здесь мы можем поэкспериментировать с разными значениями и поиграть с разными эффектами. Может получиться неплохо сделать небольшой перевод элемента?

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

А теперь самое интересное! Я бы не рекомендовал использовать эти мои фотографии. Но вы можете, если хотите, ха! У меня была идея, что я сделаю три глупых фотографии себя и заставлю их ответить пользователю. Мне помогли, и в итоге я получил эти три картинки:

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

Затем нам нужно поместить их в портрет:

<div class="portrait">
  <img class="portrait__img" src="/me--standing.png" alt="Me"/>
  <img class="portrait__img" src="/me--noticing.png" alt="Me"/>
  <img class="portrait__img" src="/me--falling.png" alt="Me"/>
</div>

Это будет выглядеть не лучшим образом. Им нужны стили:

.portrait {
  position: relative;
}
.portrait__img {
  height: 100%;
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
}

Почти готово:

Как мы можем показать и спрятать их на :hoverи :active. Это немного многословно, но мы можем использовать его nth-of-typeс display: none:

.portrait__img {
  display: none;
}
.portrait__img:nth-of-type(1) {
  display: block;
}
.portrait:hover .portrait__img:nth-of-type(1),
.portrait:hover .portrait__img:nth-of-type(3) {
  display: none;
}
.portrait:hover .portrait__img:nth-of-type(2) {
  display: block;
}
.portrait:active .portrait__img:nth-of-type(1),
.portrait:active .portrait__img:nth-of-type(2) {
  display: none;
}
.portrait:active .portrait__img:nth-of-type(3) {
  display: block;
}

Почему бы не провести рефакторинг этих стилей и не сгруппировать их? Каскад сработает, и мы не получим желаемого эффекта.

Иконки параллакса

Мы приближаемся к цели, но это выглядит немного пресным. Мы могли бы создать элементарный эффект параллакса, если бы втянули иконку. Пойдем с этим.

Иконки параллакса

Хитрость здесь в том, чтобы использовать изображение в качестве фона для нашего элемента, но изменить его размер так, чтобы оно было мозаично с background-repeat:

.portrait {
  background-image: url("/code-icon.svg");
  background-color: hsl(10, 80%, 70%);
}

Но нам нужен параллакс! Чтобы получить этот эффект параллакса, мы можем обновить background-positionв ответ на движение указателя. И мы можем сопоставить положение указателя с некоторым пределом, который мы определяем.

Начнем с создания утилиты, которая генерирует для нас функцию отображения. Возвращенная функция даст нам результат отображения значения из одного диапазона в другой:

const genMapper = (inputLower, inputUpper, outputLower, outputUpper) => {
  const inputRange = inputUpper - inputLower
  const outputRange = outputUpper - outputLower
  const MAP = input => outputLower + (((input - inputLower) / inputRange) * outputRange || 0)
  return MAP
}

Найдите минутку, чтобы понять, что здесь происходит. Например, если наш входной диапазон был 0в 500и наш выходной диапазон был 0на то 100, что будет результатом вызова возвращаемая функция будет с 250? Это было бы 50:

// Generate a function
genMapper(0, 500, 0, 100)
// Returns a function by going through these steps
const inputRange = 500
const outputRange = 100
const MAP => input => 0 + (((input - 0) / 500) * 100)
// If our input value is 250
(250 / 500) * 100
0.5 * 100
// The result!
50

Когда у нас есть служебная функция для генерации функций сопоставления, нам понадобится ограничение для использования с ней. И нам нужно сгенерировать маппер как для горизонтальной, так и для вертикальной осей:

const LIMIT = 25 // The amount our icons can move in pixels in either direction
const getX = genMapper(0, window.innerWidth, -LIMIT, LIMIT)
const getY = genMapper(0, window.innerHeight, -LIMIT, LIMIT)

Последняя часть связывает это со слушателем событий. Мы destructure xи yзначения от событий и набора CSS переменных на портретном элементе. Значение поступает от передачи xи yв соответствующие функции отображения:

const PORTRAIT = document.querySelector('.portrait')
document.addEventListener('pointermove', ({ x, y }) => {
  PORTRAIT.style.setProperty('--x', getX(x))
  PORTRAIT.style.setProperty('--y', getY(y))
})

И теперь у нас есть иконки с параллаксом!

The Squeak

Последнее прикосновение. Это в названии. Нам нужны скрипы. Я обычно нахожу байты аудио на таких сайтах, как freesound.org. Однако вы можете получить их в самых разных местах и ​​даже записать их сами, если хотите.

Неплохая идея создать объект, в котором вы можете ссылаться на свои Audio:

const AUDIO = {
  IN: new Audio('/squeak-in.mp3'),
  OUT: new Audio('/squeak-out.mp3'),
}

Затем, чтобы воспроизвести аудиоклип, все, что нам нужно сделать, это следующее:

AUDIO.IN.play()

Нам нужно интегрировать это с нашим портретом. Здесь мы можем использовать события pointerdownи pointerup- идея состоит в том, что мы воспроизводим один писк при нажатии, а другой — при отпускании.

Если пользователь часто щелкает по портрету в быстрой последовательности, это может вызвать нежелательные эффекты. Уловка состоит в том, чтобы воспроизвести желаемый звук и в то же время остановить другой. Чтобы «остановить» кусок Audio, мы можем приостановить его и установить currentTimeзначение 0:

PORTRAIT.addEventListener('pointerdown', () => {
  AUDIO.OUT.pause()
  AUDIO.IN.currentTime = AUDIO.OUT.currentTime = 0
  AUDIO.IN.play()
})
PORTRAIT.addEventListener('pointerup', () => {
  AUDIO.IN.pause()
  AUDIO.IN.currentTime = AUDIO.OUT.currentTime = 0
  AUDIO.OUT.play()
})

И это дает нам «Писклявый портрет»!

Это оно!

Вот как делают «Писклявые портреты». Но действенная вещь здесь — это весело проводить время, пробуя что-то новое.

Я мог бы трансформировать пару фигур и оставить их там. Но зачем останавливаться на достигнутом? Почему бы не придумать идею и не повеселиться? Это отличный способ попробовать что-то и изучить техники.

Таким образом, мы:

  • создал клипы
  • трансформировал их с переходами
  • сделал интерактивные изображения
  • добавлено аудио
  • созданный параллакс с помощью картографической утилиты
Читайте также:  Массивы в руководстве по Java: как объявлять и инициализировать массивы Java
Оцените статью
bestprogrammer.ru
Добавить комментарий