Данный Q-A является продолжением прошлого(стилизация текста SVG).
В этом Q-A(Question-Answer) мы рассмотрим Crack effect, ниже будут приведены примеры этого эффекта, всего их будет 3 штуки.
Первый пример (появление трещины вдоль текста с дальнейшей трансформацией):
Второй пример (верхняя часть текста отламывается и плавно съезжает после взмаха мечом, при том, что сам текст должен находится под наклоном примерно в 1-2deg):
Третий пример (похож на второй, но есть своё отличие, происходит два взмаха вдоль и поперёк текста):
Текст будет реализован на SVG, его размещение через clipPath, а анимация с помощью @keyframes.
P.S. Все примеры срабатывают после клика.
rect, сам текст мы вставляем в них с
помощью clipPath, а затем позиционируем их по оси Y, вот пример
позиционирования первой и второй половины текста:* {
margin: 0;
padding: 0;
}
body {
background-color: #000000;
display: flex;
justify-content: center;
align-items: center;
}
svg text {
font-family: 'Russo One', sans-serif;
text-transform: uppercase;
font-size: 5em;
pointer-events: none;
user-select: none;
}
<link href="https://fonts.googleapis.com/css?family=Russo+One" rel="stylesheet">
<svg width="710" height="200" viewBox="0 0 710 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="clip">
<text text-anchor="middle" x="50%" y="50%">Breaking text</text>
</clipPath>
</defs>
<rect id="top" class="rectangle" clip-path="url(#clip)" width="710" height="50" fill="white">
<!--Смещение по оси Y-->
<animate attributeName="y" values="-10;26;-10" dur="3s" repeatCount="indefinite"/>
</rect>
<rect id="bottom" class="rectangle" clip-path="url(#clip)" width="710" height="50" fill="white">
<!--Смещение по оси Y-->
<animate attributeName="y" values="103;75;103" dur="3s" repeatCount="indefinite"/>
</rect>
</svg>
transform и добавим transition, а именно
cubic-bezier. Но сначала мы пройдемся по каждому rect'у и дадим
им класс active:function crack() {
var rect = document.getElementsByTagName("rect");
Array.from(rect).forEach(x => x.classList.toggle("active"));
}
* {
margin: 0;
padding: 0;
}
body {
background-color: #000000;
display: flex;
justify-content: center;
align-items: center;
}
svg text {
font-family: 'Russo One', sans-serif;
text-transform: uppercase;
font-size: 5em;
pointer-events: none;
user-select: none;
}
svg rect {
transition: cubic-bezier(0.1, 0.3, 0.5, 1) .1s;
}
rect.active {
transform: translateX(-3px) rotate(-0.15deg);
}
rect.active:last-child {
transform: translateX(3px) rotate(0.15deg);
}
<link href="https://fonts.googleapis.com/css?family=Russo+One" rel="stylesheet">
<svg width="710" height="200" viewBox="0 0 710 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="clip">
<text text-anchor="middle" x="50%" y="50%">Breaking text</text>
</clipPath>
</defs>
<g onclick="crack()">
<rect id="top" class="rectangle" clip-path="url(#clip)" width="710" height="50" y="26" fill="white"/>
<rect id="bottom" class="rectangle" clip-path="url(#clip)" width="710" height="50" y="75" fill="white"/>
</g>
</svg>
rect мы будем использовать четыре, для каждых двух
частей я сделал по clipPath( не нашёл способа лучше, буду рад
предложениям, как сделать это "чище":) ):* {
margin: 0;
padding: 0;
}
body {
background-color: #000000;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
svg rect {
fill: white;
}
<svg viewBox="-30 0 740 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- FOUR RECTS -->
<g>
<rect clip-path="url(#clip)" width="336" height="50" y="26">
<animateTransform attributeName="transform" type="translate" values="0 0; -20 -20; 0 0" dur="3s" repeatCount="indefinite"/>
</rect>
<rect clip-path="url(#clip)" width="336" height="50" y="75">
<animateTransform attributeName="transform" type="translate" values="0 0; -20 20; 0 0" dur="3s" repeatCount="indefinite"/>
</rect>
<rect clip-path="url(#clip)" width="336" height="50" x="336" y="26">
<animateTransform attributeName="transform" type="translate" values="0 0; 20 -20; 0 0" dur="3s" repeatCount="indefinite"/>
</rect>
<rect clip-path="url(#clip)" width="336" x="336" height="50" y="75">
<animateTransform attributeName="transform" type="translate" values="0 0; 20 20; 0 0" dur="3s" repeatCount="indefinite"/>
</rect>
</g>
</svg>
rect( не сочтите за
лень:))) ) добавляются классы, собственно вот, воззрите:function doubleCrack() {
var rect = document.getElementsByTagName("rect");
var polygon = document.getElementById("horizontal");
var polygonTwo = document.getElementById("vertical");
polygon.classList.add("_activate");
polygonTwo.classList.add("_activate");
Array.from(rect).forEach(x => x.classList.add("_activate-rect"));
}
* {
margin: 0;
padding: 0;
}
body {
background-color: #000000;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
svg text {
font-family: "Russo One", sans-serif;
text-transform: uppercase;
font-size: 5em;
pointer-events: none;
}
svg rect {
transition: 2s;
transition-delay: 1s;
fill: white;
}
#horizontal {
transform: translateX(-100px);
}
#vertical {
transform: translate(335px, 150px);
}
#horizontal._activate {
animation: attack 0.4s 1;
}
#vertical._activate {
animation: attack-2 0.4s 1;
animation-delay: 0.4s;
}
#top._activate-rect {
transform: translate(-20px, -20px);
opacity: 0;
}
#bottom._activate-rect {
transform: translate(-20px, 20px);
opacity: 0;
}
#topN._activate-rect {
transform: translate(20px, -20px);
opacity: 0;
}
#bottomN._activate-rect {
transform: translate(20px, 20px);
opacity: 0;
}
@keyframes attack {
to {
transform: translateX(750px);
}
}
@keyframes attack-2 {
to {
transform: translateX(335px) translateY(-150px);
}
}
@keyframes break {
to {
transform: translateX(320px);
}
}
<link href="https://fonts.googleapis.com/css?family=Russo+One" rel="stylesheet">
<svg viewBox="0 0 740 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<!-- FIRST SIDE -->
<clipPath id="clip">
<text text-anchor="middle" x="368" y="50%">Breaking text</text>
</clipPath>
<!-- SECOND SIDE -->
<clipPath id="clipN">
<text text-anchor="middle" x="370" y="50%">Breaking text</text>
</clipPath>
</defs>
<!-- FOUR RECTS -->
<g onclick="doubleCrack()">
<rect id="top" clip-path="url(#clip)" width="336" height="50" y="26"/>
<rect id="bottom" clip-path="url(#clip)" width="336" height="50" y="75"/>
<rect id="topN" clip-path="url(#clipN)" width="380" height="50" x="335" y="26"/>
<rect id="bottomN" clip-path="url(#clipN)" width="380" height="50" x="335" y="75"/>
</g>
<!-- SWORDS -->
<g>
<polygon id="horizontal" points="0,75 55,67 70,75 56,80" fill="silver"/>
<polygon id="vertical" points="0,60 5,68 0,100 -5,68" fill="silver"/>
</g>
</svg>
rect'ы на 1deg и после клика добавлять
transform: translateX(N):* {
margin: 0;
padding: 0;
}
body {
background-color: #000000;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
svg text {
font-family: 'Russo One', sans-serif;
text-transform: uppercase;
font-size: 4em;
pointer-events: none;
}
svg rect {
transform: rotate(-1deg);
transition: cubic-bezier(1, 0.3, 0.6, 1) 3.5s;
}
#top {
animation: offsetXF 1s infinite;
}
#bottom {
animation: offsetXT 1s infinite;
}
@keyframes offsetXF {
50% {
transform: translateX(-30px) rotate(-1deg);
opacity: 0;
}
}
@keyframes offsetXT {
50% {
transform: translateX(30px) rotate(-1deg);
opacity: 0;
}
}
<link href="https://fonts.googleapis.com/css?family=Russo+One" rel="stylesheet">
<svg viewBox="0 0 710 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="clip">
<text text-anchor="middle" x="50%" y="49%">Breaking text</text>
</clipPath>
</defs>
<g>
<!--Смещение по оси X-->
<rect id="top" clip-path="url(#clip)" width="710" height="50" y="26" fill="white"/>
<rect id="bottom" clip-path="url(#clip)" width="710" height="50" y="75" fill="white"/>
</g>
</svg>
polygon, который будет имитировать взмах мечом(или катаной:D), а в финальной версии этого примера мы будем смещать его также по оси X, примерно на 700-800px:<svg viewBox="0 0 710 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<polygon id="sword" points="0,75 55,67 70,75 56,80" fill="silver" transform="scale(2)"/>
</svg>
polygon, при
этом добавляется класс для #top, из-за чего и происходит смещение верхней части текста, также видна задержка после взмаха, так как у rect добавлен
transition-delay:function crack() {
var rect = document.getElementById("top");
var polygon = document.getElementById("sword");
rect.classList.add("active");
polygon.classList.add("_activate");
}
* {
margin: 0;
padding: 0;
}
body {
background-color: #000000;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
svg text {
font-family: 'Russo One', sans-serif;
text-transform: uppercase;
font-size: 4em;
pointer-events: none;
}
svg rect {
transform: rotate(-1deg);
transition: cubic-bezier(1, 0.3, 0.6, 1) 3.5s;
transition-delay: 1s;
}
#top.active {
transform: translateX(-30px) rotate(-1deg);
opacity: 0;
}
#sword {
transform: rotate(-1deg) translateX(-100px);
}
#sword._activate {
animation: attack 0.4s 1;
}
@keyframes attack {
to {
transform: rotate(-1deg) translateX(750px);
}
}
<link href="https://fonts.googleapis.com/css?family=Russo+One" rel="stylesheet">
<svg viewBox="0 0 710 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="clip">
<text text-anchor="middle" x="50%" y="49%">Breaking text</text>
</clipPath>
</defs>
<g onclick="crack()">
<rect id="top" clip-path="url(#clip)" width="710" height="50" y="26" fill="white"/>
<rect clip-path="url(#clip)" width="710" height="50" y="75" fill="white"/>
<polygon id="sword" points="0,75 55,67 70,75 56,80" fill="silver"/>
</g>
</svg>
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости