Мне было поручено создать вводный текст на сайте портфолио, который я создаю на gatsby.js
, который имеет отдельную анимацию для каждой буквы - поэтому, когда вы наводите курсор на одну букву, она отскакивает и масштабируется, и затем, оставляя курсор, он отскакивает и снова уменьшается.
Я написал компонент, который берет текст, разбивает строку на массив, отображает каждую букву в другом компоненте и оборачивает каждый символ в теге соответствующими слушателями событий и именами классов.
Вот как это выглядит:
IntroText.js
export default function IntroText({children}) {
return (
<div>
<p className='intro-text'>
{children.split('').map((e, i) => <IntroLetter key={i} char={e}/>)}
</p>
</div>
)
}
IntroLetter.js
export default function IntroLetter({char}) {
const [ hoverClass, setHoverClass ] = useState('single-letter')
if (char === ' ') {
return <span> </span>
} else {
return (
<span
className={hoverClass}
onMouseOver={() => setHoverClass('single-letter hovered')}
onMouseLeave={() => setHoverClass('single-letter unhovered')}
>
{ char }
</span>
)
}
}
и css:
.intro-text {
width: 80%;
.single-letter {
display: inline-block;
transform-origin: 50% 84%;
}
.hovered {
animation-name: stretch;
animation-duration: 0.15s;
animation-timing-function: linear;
animation-fill-mode: forwards
}
.unhovered {
animation-name: stretch-back;
animation-duration: 0.25s;
animation-timing-function: linear;
}
}
Если я оставлю .single-letter
как встроенный элемент, анимация не будет работать, но текст будет отображаться нормально, поэтому, несмотря на то, что каждый символ заключен в отдельный <span>
, строки разбиваются в правильных местах. Если я установлю .single-letter
в качестве элемента inline-block
, анимация будет работать отлично, но пробелы сжимаются (отсюда условие, чтобы проверить, является ли char === ' '
в SingleLetter.js
). Если я оставлю свои пробелы в качестве встроенных элементов span, а остальные символы как inline-block
span, пробелы будут отображаться правильно, анимация будет работать, но тогда мои разрывы строк не сохранят слова.
Я мог бы разделить мою строку на несколько IntroText
компонентов, каждый из которых соответствует одной строке, но это, очевидно, не является жизнеспособным решением на адаптивном сайте. Что мне делать?
редактировать: я сделал пример CodeSandbox: CodeSandbox