Как нарисовать и анимировать спичку?
Меня заинтересовала работа участника @Qwertiy♦, где он нарисовал спичку с использованием технологии CSS.
Вот его ответ на вопрос Как нарисовать спичку на CSS не изменяя HTML:
html {
font-size: .952vmin;
}
body {
margin: 1vh auto;
max-width: 35vmin;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
.match {
outline: 1px dotted blue;
position: relative;
padding-top: 272%;
}
.match>* {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
.stick {
top: 45%;
bottom: .5%;
width: 12%;
border: 1px solid #A34639;
background: linear-gradient(to right, #A34639, #E5A56B);
z-index: -1;
}
.top {
top: 37%;
bottom: 51.5%;
width: 24%;
border-radius: 50%;
border: 1px solid black;
background: #472814;
filter: drop-shadow(0 -.5rem 3rem white);
}
.top::after {
content: "";
position: absolute;
top: -2.5%;
height: 30%;
width: 80%;
left: 0;
right: 0;
margin: auto;
border-radius: 50% / 80% 80% 20% 20%;
background: white;
filter: blur(.8rem);
transform: scale(2);
}
.fire::before,
.fire::after {
content: "";
position: absolute;
left: -1%;
right: -1%;
padding-top: 102%;
bottom: 52%;
border-radius: 0 50% 50% 50% / 50% 50% 50% 50%;
transform: scaleX(.9) rotate(45deg);
background: linear-gradient(-45deg, #EFE33E, #E73625);
}
.fire::before {
filter: blur(2rem);
}
<div class="match">
<div class="fire"></div>
<div class="top"></div>
<div class="stick"></div>
</div>
Автор: @Qwertiy♦
Вопрос: возможно ли нарисовать и воспроизвести анимацию зажженной спички, используя любые средства и технологии для рисования и создания эффекта анимации и трансформации, указанные в метках вопроса?
Ответы (2 шт):
Мой ответ на основе ответа участника @Qwertiy♦, с использованием всё той же технологии — CSS.
Для начала немного видоизменим изображение спички. Чтобы огонь от нее казался более реалистичным, для этого добавим дополнительно еще несколько элементов:
html {
font-size: .952vmin;
}
body {
margin: 1vh auto;
max-width: 35vmin;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
.match {
outline: 1px dotted blue;
position: relative;
padding-top: 272%;
}
.match>* {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
.stick {
top: 45%;
bottom: .5%;
width: 12%;
border: 1px solid #A34639;
background: linear-gradient(to right, #A34639, #E5A56B);
z-index: -1;
}
.top {
top: 35%;
bottom: 51.5%;
width: 24%;
border-radius: 50%;
border: 1px solid blue;
background: SlateBlue;
filter: drop-shadow(0 -.5rem 3rem white) blur(0.5rem);
}
.top::after {
content: "";
position: absolute;
top: -2.5%;
height: 30%;
width: 80%;
left: 0;
right: 0;
margin: auto;
border-radius: 50% / 80% 80% 20% 20%;
background: white;
filter: blur(.8rem);
transform: scale(2);
}
.fire_red::before,
.fire_red::after {
content: "";
position: absolute;
left: -1%;
right: -1%;
padding-top: 102%;
bottom: 52%;
border-radius: 0 50% 50% 50% / 50% 50% 50% 50%;
transform: scaleX(.9) rotate(45deg);
background: OrangeRed;
}
.fire_red::before {
filter: blur(2rem);
}
.fire_orange::before,
.fire_orange::after {
content: "";
position: absolute;
left: -1%;
right: -1%;
padding-top: 102%;
bottom: 48.5%;
border-radius: 0 50% 50% 50% / 50% 50% 50% 50%;
transform: scaleX(0.85) scaleY(0.8) rotate( 45deg);
background: orange;
}
.fire_orange::before {
filter: blur(2rem);
}
.fire_yellow::before,
.fire_yellow::after {
content: "";
position: absolute;
left: -1%;
right: -1%;
padding-top: 102%;
bottom: 44.5%;
border-radius: 0 50% 50% 50% / 50% 50% 50% 50%;
transform: scaleX(0.75) scaleY(0.6) rotate( 45deg);
background: gold;
}
.fire_yellow::before {
filter: blur(2rem);
}
.fire_white::before,
.fire_white::after {
content: "";
position: absolute;
left: -1%;
right: -1%;
padding-top: 102%;
bottom: 40%;
border-radius: 0 50% 50% 50% / 50% 50% 50% 50%;
transform: scaleX(0.4) scaleY(0.4) rotate( 45deg);
background: white;
}
.fire_white::before {
filter: blur(2rem);
}
<div class="match">
<div class="fire_red"></div>
<div class="fire_orange"></div>
<div class="fire_yellow"></div>
<div class="fire_white"></div>
<div class="top"></div>
<div class="stick"></div>
</div>
А теперь, отвечая на заданный вопрос, добавим легкую анимацию. С помощью правила @keyframes для всех вместе взятых элементов, которые составляют огонь, установим общие ключевые кадры и включим в них свойства трансформации для воспроизведения эффекта анимации зажженной спички.
Результат такой несложной анимации оказался следующим:
html {
font-size: .952vmin;
}
body {
margin: 1vh auto;
max-width: 35vmin;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
.match {
position: relative;
padding-top: 272%;
}
.match>*,
.fire>* {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
.stick {
top: 45%;
bottom: .5%;
width: 12%;
border: 1px solid #A34639;
background: linear-gradient(to right, #A34639, #E5A56B);
z-index: -1;
}
.top {
top: 33%;
bottom: 51.5%;
width: 24%;
border-radius: 50%;
border: 1px solid blue;
background: SlateBlue;
filter: drop-shadow(0 -.5rem 3rem white) blur(0.5rem);
}
.top::after {
content: "";
position: absolute;
top: -2.5%;
height: 30%;
width: 80%;
left: 0;
right: 0;
margin: auto;
border-radius: 50% / 80% 80% 20% 20%;
background: white;
filter: blur(.8rem);
transform: scale(2);
}
.fire_red::before,
.fire_red::after {
content: "";
position: absolute;
left: -1%;
right: -1%;
padding-top: 102%;
bottom: 52%;
border-radius: 0 50% 50% 50% / 50% 50% 50% 50%;
transform: scaleX(.9) rotate(45deg);
background: OrangeRed;
}
.fire_red::before {
filter: blur(2rem);
}
.fire_orange::before,
.fire_orange::after {
content: "";
position: absolute;
left: -1%;
right: -1%;
padding-top: 102%;
bottom: 48.5%;
border-radius: 0 50% 50% 50% / 50% 50% 50% 50%;
transform: scaleX(0.85) scaleY(0.8) rotate( 45deg);
background: orange;
}
.fire_orange::before {
filter: blur(2rem);
}
.fire_yellow::before,
.fire_yellow::after {
content: "";
position: absolute;
left: -1%;
right: -1%;
padding-top: 102%;
bottom: 44.5%;
border-radius: 0 50% 50% 50% / 50% 50% 50% 50%;
transform: scaleX(0.75) scaleY(0.6) rotate( 45deg);
background: gold;
}
.fire_yellow::before {
filter: blur(2rem);
}
.fire_white::before,
.fire_white::after {
content: "";
position: absolute;
left: -1%;
right: -1%;
padding-top: 102%;
bottom: 40%;
border-radius: 0 50% 50% 50% / 50% 50% 50% 50%;
transform: scaleX(0.4) scaleY(0.4) rotate( 45deg);
background: white;
}
.fire_white::before {
filter: blur(2rem);
}
.fire {
animation-name: fire;
animation-duration: 3ms;
animation-delay: 200ms;
animation-timing-function: ease-in;
animation-iteration-count: infinite;
animation-direction: alternate;
}
@keyframes fire {
0% {
transform: rotate(-1deg);
}
20% {
transform: rotate(1deg);
}
40% {
transform: rotate(-1deg);
}
60% {
transform: rotate(1deg) scaleY(1.05);
}
80% {
transform: rotate(-2deg) scaleY(0.90);
}
100% {
transform: rotate(1deg);
}
}
<div class="match">
<div class="fire">
<div class="fire_red"></div>
<div class="fire_orange"></div>
<div class="fire_yellow"></div>
<div class="fire_white"></div>
<div class="top"></div>
</div>
<div class="stick"></div>
</div>
Ответ на основе моего ответа, с использованием всё той же технологии — CSS.
Анимация начинается после нажатия на кнопку и занимает полный процесс сгорания спички.
var fire_flame = document.getElementsByClassName('.fire_flame'); document.querySelector('.start').onclick = function() {this.setAttribute('disabled', true); document.querySelector('.sulfur').classList.add('sulfur__active'); var fire_flame = document.querySelectorAll('.fire_flame'); for (var i = 0; i < fire_flame.length; i++) {fire_flame[i].className += " fire_flame__active";} document.querySelector('.fire').classList.add('fire__active'); document.querySelector('.ember').classList.add('ember__active'); document.querySelector('.wick').classList.add('wick__active');}
.fire_container {
position: relative;
width: 100%;
padding-top: 50%;
}
.fire {
position: absolute;
width: 20%;
padding-top: 20%;
bottom: 55%;
transform-origin: center bottom;
}
@keyframes fire {
0% {
transform: rotate(-1deg);
}
20% {
transform: rotate(1deg);
}
40% {
transform: rotate(-1deg);
}
60% {
transform: rotate(1deg) scaleY(1.05);
}
80% {
transform: rotate(-2deg) scaleY(0.90);
}
100% {
transform: rotate(1deg);
}
}
.fire__active {
animation: 3ms fire ease-in infinite alternate 200ms, 10s fire_active linear forwards 1s;
/*animation-duration: 3ms;
animation-delay: 200ms;
animation-timing-function: ease-in;
animation-iteration-count: infinite;
animation-direction: alternate;*/
}
@keyframes fire_active {
0% {
bottom: 55%;
}
100% {
bottom: -2%;
}
}
.fire_flame {
z-index: 1;
position: absolute;
bottom: 0;
border-radius: 50% 0 50% 50%;
transform: rotate(45deg) scale(0, 0);
}
.fire_flame__active {
/*transform: rotate(-45deg) scale(0.7, 0.7);*/
animation: 0.5s fire_flame__active forwards, 0.5s fire_flame__deactive forwards 11s;
}
@keyframes fire_flame__active {
0% {
transform: rotate(45deg) scale(0, 0);
}
30% {
transform: rotate(15deg) scale(1, 1);
}
100% {
transform: rotate(-45deg) scale(0.7, 0.7);
}
}
@keyframes fire_flame__deactive {
0% {
transform: rotate(-45deg) scale(0.7, 0.7);
}
100% {
transform: rotate(45deg) scale(0, 0);
}
}
.fire_flame_red {
left: 5%;
width: 90%;
height: 90%;
background: OrangeRed;
box-shadow: 0 0 3px 2px OrangeRed;
}
.fire_flame_orange {
left: 15%;
width: 70%;
height: 70%;
background: orange;
box-shadow: 0 0 4px 2px orange;
}
.fire_flame_yellow {
left: 25%;
width: 50%;
height: 50%;
background: gold;
box-shadow: 0 0 4px 2px gold;
}
.fire_flame_white {
left: 37.5%;
width: 25%;
height: 25%;
background: white;
box-shadow: 0 0 5px 2px white;
}
.sulfur {
position: absolute;
z-index: 3;
position: absolute;
left: 41%;
bottom: 6%;
width: 18%;
height: 20%;
/*background: SlateBlue;
box-shadow: 0 0 3px 2px slateblue;*/
border: 1px solid black;
background: #472814;
border-radius: 50%;
transform: rotate(0deg) scale(1, 1);
}
.sulfur__active {
border: none;
background: SlateBlue;
box-shadow: 0 0 3px 2px slateblue;
animation: 0.5s sulfur__deactive forwards 12s;
}
@keyframes sulfur__deactive {
0% {
transform: rotate(0deg) scale(1, 1) translateY(0);
}
10% {
transform: rotate(0deg) scale(1, 1) translateY(50%);
}
100% {
transform: rotate(0deg) scale(0, 0) translateY(100%);
}
}
.wick {
z-index: -1;
position: absolute;
width: 1.5%;
height: 58%;
bottom: 0;
left: 9.1%;
background: chocolate;
border: 0.2vw solid brown;
}
.wick__active {
animation: 10s wick__active linear forwards 1s;
}
@keyframes wick__active {
0% {
height: 58%;
border: 0.2vw solid brown;
}
99.99% {
height: 0;
border: 0.2vw solid brown;
}
100% {
height: 0;
border: none;
}
}
.ember {
z-index: -2;
position: absolute;
width: 10%;
height: 58%;
bottom: 0;
left: 9.5%;
border-left: 1.25vw solid black;
}
.ember__active {
animation: 12s ember__active linear forwards 1s;
}
@keyframes ember__active {
0% {
width: 10%;
height: 58%;
border-left: 1.25vw solid black;
border-radius: 0;
}
1% {
width: 10%;
height: 70%;
border-left: 1.25vw solid black;
border-radius: 0;
}
99% {
width: 10%;
height: 70%;
border-left: 1.25vw solid black;
border-radius: 100% 0 0 0;
}
100% {
width: 0;
height: 4%;
border-left: 15vw solid black;
border-radius: 100%;
}
}
button {
display: block;
margin-left: 30%;
transform: translateY(-20px);
}
<div class="fire_container">
<div class="fire">
<div class="fire_flame_red fire_flame"></div>
<div class="fire_flame_orange fire_flame"></div>
<div class="fire_flame_yellow fire_flame"></div>
<div class="fire_flame_white fire_flame"></div>
<div class="sulfur"></div>
</div>
<div class="ember"></div>
<div class="wick"></div>
</div>
<button class="start">Зажечь спичку</button>