С выпуском Chrome 88 мы получили поддержку
С помощью path () мы можем использовать определения пути для файла
С усилением поддержки появилась возможность попробовать
Создание пути
Чтобы сделать некоторые пути, мы можем использовать любой векторный графический редактор. В данном случае я использую Figma. И вместо того, чтобы создавать пути с нуля, мы можем использовать желаемую «точку» в качестве основы. Этот выглядит хорошо!
Пример Splat найден в Интернете
Пример Splat найден в Интернете
Хитрость здесь заключается в том, чтобы создать больше пятен на основе пятна основания. И нам нужно сделать это, не вводя и не удаляя никаких узлов. Вот три знака, которые я придумал. Но вы можете делать любые формы, которые вам нравятся, если вы придерживаетесь этого правила!
Три разных знака, построенных из одного знака
Три разных знака, построенных из одного знака
Вы можете заметить, что у третьего знака есть две капли, которые отделяются от основной формы. Это нормально, потому что определения пути SVG позволяют нам это сделать. Мы можем начать линию, закрыть ее и перейти к другой точке, чтобы начать другую.
Но разве я не говорил, что им нужно постоянное количество очков? Они делают. И это то, что мы имеем здесь! Эти две капли появляются для каждого знака. Но хитрость в том, что мы можем переместить их за остальную часть пути, когда они не нужны.
Figma показывает две капли позади основного пути
Figma показывает две капли позади основного пути
После того, как у нас есть наши знаки, мы можем экспортировать их и получить строки определения пути:
Применение знаков
Чтобы применить знаки, мы создадим переменные для каждого пути:
.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:Мы извлекаем dатрибут из pathэлементов и создаем для них переменные CSS. Далее нам нужен элемент, к которому мы применим их. Создадим элемент с классом «портретЗатем примените к нему некоторые стили:.portrait
—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;
transition:
}
И мы готовы идти! Вот демонстрация, в которой вы можете переключаться между различными состояниями клипа:
Обратите внимание, как форма переходит между тремя формами знака. Но также обратите внимание, как мы указали нашему элементу явную высоту и ширину. Этот размер соответствует размерам нашего экспорта SVG. Это важно. Это единственный недостаток использования
Это нормально, если мы помним о размерах вещей, которые мы обрезаем. Мы также могли бы создать разные переменные пути для разных размеров области просмотра. Но если у вас есть изображения, размеры которых плавно изменяются, другие решения, использующие SVG, будут более надежными.
Взаимодействие
Для нашей демонстрации мы хотим, чтобы знак был интерактивным. Мы можем сделать это только с помощью CSS. Мы можем использовать переменную CSS с ограниченной областью видимости — —clip— для управления текущим клипом. И тогда мы можем обновить эту переменную как для, так: hoverи для: active. Состояние —activeсрабатывает, когда мы нажимаем указатель вниз:
.portrait {
}
.portrait: hover {
—clip: var (—splattier) ;
}
.portrait: active {
—clip: var (—splatted) ;
}
Сложите это вместе, и мы получим
Добавление персонажа
Теперь, когда мы можем переместить кляксу, нужно
.portrait {
transition:
transform: scale (var (—scale, 1)) rotate (var (—rotate, 0deg));
}
.portrait: hover {
—scale: 1.15;
—rotate: 30deg;
}
.portrait: active {
—scale: 0.85;
—rotate: -10deg;
}
Используя переменные CSS с ограниченной областью действия для применения transform, мы можем
Добавление портрета
Теперь самое интересное! Я бы не рекомендовал использовать эти мои фотографии. Но ты можешь, если хочешь, ха! У меня была идея сделать три глупых снимка самого себя и заставить их ответить пользователю. Я получил некоторую помощь и в итоге получил эти три картинки:
Три глупые позы
Три глупые позы
Затем нам нужно поместить их в портрет:
Это будет выглядеть не очень. Им нужны некоторые стили:
.portrait {
position: relative;
}
.portrait__img {
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
}
Почти готово:
Как мы можем показать и скрыть их на: hoverи: active. Это немного многословно, но мы можем использовать
.portrait__img {
display: none;
}
.portrait__img:
display: block;
}
.portrait: hover.portrait__img:
.portrait: hover.portrait__img:
display: none;
}
.portrait: hover.portrait__img:
display: block;
}
.portrait: active.portrait__img:
.portrait: active.portrait__img:
display: none;
}
.portrait: active.portrait__img:
display: block;
}
Почему бы не реорганизовать эти стили и не сгруппировать их? Каскад сработает, и мы не получим желаемого эффекта.
Иконки параллакса
Мы приближаемся к этому, но это выглядит немного пресно. Мы могли бы создать рудиментарный эффект параллакса, если бы вытянули иконку. Пойдем с этим.
Значок с угловыми скобками вокруг косой черты.
Хитрость здесь заключается в том, чтобы использовать изображение в качестве фона для нашего элемента, но изменить его размер таким образом, чтобы он располагался в виде мозаики
.portrait {
}
Аккуратный.
Но нам нужен параллакс! Чтобы получить этот эффект параллакса, мы можем обновить
Начнем с создания утилиты, которая генерирует для нас функцию сопоставления. Возвращаемая функция даст нам результат сопоставления значения в одном диапазоне с другим:
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)
Заключительная часть связывает это с прослушивателем событий. Мы деструктурируем значение 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))
})
И теперь у нас есть значки параллакса!
Писк
Последний штрих. Это в названии. Нам нужны скрипы. Обычно я нахожу аудиобайты на таких сайтах, как freesound.org. Однако вы можете получить их в самых разных местах и даже записать их самостоятельно, если хотите.
Неплохая идея создать объект, на который вы можете ссылаться Audio:
const AUDIO = {
IN: new Audio ('/
OUT: new Audio ('/
}
Затем, чтобы воспроизвести аудиоклип, нам нужно сделать следующее:
AUDIO.IN.play ()
Нам нужно интегрировать это с нашим портретом. Здесь мы можем использовать события pointerdownand 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 ()
})
И это дает нам «Скрипучий портрет»!
Это оно!
Вот как вы делаете «Скрипучие портреты». Но действенная вещь здесь — это развлекаться, пробуя новые вещи.
Я мог бы преобразовать пару фигур и оставить их там. Но зачем останавливаться на достигнутом? Почему бы не придумать идею и не повеселиться? Это отличный способ попробовать
Подводя итог, мы:
создал клипы
преобразовал их с помощью переходов
сделал интерактивные изображения
добавлено аудио
создал параллакс с помощью картографической утилиты
Что вы могли бы сделать с