Новогодний конкурс 2024-2025 года!
Поздравляем победителей конкурса НГ 2025: ΝNL993 и Andrei Fedorov, Sevastopol'!
Преамбула и условия конкурса:
Новый год, это практический единственный праздник, который празднуют все. Дарят подарки, веселятся, поздравляют всех, даже тех с кем давно не общались и конечно загадывают желания.
Давайте весело отпразднуем НГ 2024-2025 творческими работами, несмотря ни на что!
Ссылки на предыдущие конкурсы НГ:
- Анимация новогодней ёлочки (2018г.)
- Новогодний конкурс 2020 года!
- Новогодний конкурс 2021 года!
- Новогодний конкурс 2022 года!
Перечень тем :
- Анимация заголовка С Новым 2025 годом!
- Изображение Деда Мороза, Снегурочки
- Новогодняя ёлочка: ёлочные игрушки, гирлянды
- Изображение, анимация звездного неба
- Анимация снежинок, снегопада
- Фейерверки, хлопушки
Дополнительные материалы:
- фоновое изображение с ёлочкой
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
</svg>
- Ёлочка+ снеговик
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<!-- Елочка -->
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Снеговик -->
<image id="Snowman" transform="translate(950 720) scale(1 1)" x="0" xlink:href="https://i.sstatic.net/mbefD.png" width="13%" height="13%" />
</svg>
- Ёлочка + Дед Мороз
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<image id="Ded_Moroz" transform="translate(250 550) scale(1 1)" xlink:href="https://i.sstatic.net/TYaVo.png" width="30%" height="30%" opacity="1">
</svg>
- Снегурочка
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Снегурочка -->
<image id="Girl" transform="translate(850 670) scale(0.8 0.8)" xlink:href="https://i.sstatic.net/RDght.png" width="30%" height="30%" opacity="1">
</svg>
- Заяц с гитарой
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Заяц -->
<image id="zayka" transform="translate(450 750) scale(0.75)"
x="0" xlink:href=" https://i.sstatic.net/3xzEW.png"
/>
</svg>
Update 02.01.2025
- Символ 2025 года + фон заставка
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<!-- Фон -->
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Змея - символ 2025 года -->
<image id="snake" x="250" y="350" transform="scale(2)" xlink:href="https://i.sstatic.net/QkvLYcnZ.png"/>
</svg>
NOTE
Просьба к отвечающим:
Не копируйте в ответах чужой код один к одному
Если используете чужой код, обязательно указывайте ссылки на источник и автора и что вы конкретно доработали.
Для участия в конкурсе вам понадобится хорошее праздничное настроение, желание сделать что-то яркое, веселое, запоминающееся. Желание творчески создать что-то свое, о чём вы будете вспоминать с теплотой и гордостью весь следующий год.
Главное в Новогоднем конкурсе не победа, а участие!
Победителем конкурса
будет признана та работа, в которой будет раскрыта одна или несколько тем из раздела - Перечень тем, а также получившая наибольшее количество положительных отзывов в виде баллов.
Update
Посмотрите пожалуйста ответы в подвале топика. Они не заслуженно обойдены вниманием.
Есть интересные решения.
Ответы (10 шт):
Ответ на конкурсный вопрос:
Анимация заголовка С Новым 2025 годом!
Задача выполнить отражение заголовка с помощью нового атрибута css
box-reflect: below -25px linear-gradient(transparent, rgba(0, 0, 0, .50));
А также реализована анимация букв заголовка с помощью команды трансформации CSS:
0% {transform: translateY(0)}
25% {transform: translateY(-15px)}
body {
background: rgb(131, 58, 180);
background: radial-gradient(circle, rgba(131, 58, 180, 1) 0%, rgba(253, 29, 29, 1) 0%, rgba(252, 176, 69, 1) 100%);
}
.ny {
position: relative;
text-align: center;
font-size: 50px;
color: white;
font-family: monospace;
-webkit-box-reflect: below -25px linear-gradient(transparent, rgba(0, 0, 0, .50));
box-reflect: below -25px linear-gradient(transparent, rgba(0, 0, 0, .50));
}
.ny span {
display: inline-block;
animation: ny 0.8s infinite;
animation-delay: calc(0.25s*var(--ny));
}
@keyframes ny {
0% {transform: translateY(0)}
25% {transform: translateY(-15px)}
50% {transform: translateY(0)}
100% {transform: translateY(0)}
}
<body>
<div class="ny">
<span style="--ny:1">2</span>
<span style="--ny:2">0</span>
<span style="--ny:3">2</span>
<span style="--ny:4">5</span>
</div>
</body>
@property --bpx1 {
syntax: "<length>";
inherits: false;
initial-value: -64px;
}
@property --bpy1 {
syntax: "<length>";
inherits: false;
initial-value: -64px;
}
@property --bpx2 {
syntax: "<length>";
inherits: false;
initial-value: -128px;
}
@property --bpy2 {
syntax: "<length>";
inherits: false;
initial-value: -128px;
}
@property --bpx3 {
syntax: "<length>";
inherits: false;
initial-value: -256px;
}
@property --bpy3 {
syntax: "<length>";
inherits: false;
initial-value: -256px;
}
body {
background-color: #001;
margin: 0;
}
div {
display: grid;
place-content: center;
font: 700 clamp(6.25rem, 2.778rem + 13.889vw, 25rem)/1 sistem-ui, sans-serif;
text-align: center;
min-height: 100dvh;
--s: 0.01em;
--c: #fff;
color: #0088;
background-image:
radial-gradient(oklch(from var(--c) l c h / 0.4) calc(3 * var(--s)),
transparent calc(6 * var(--s))),
radial-gradient(oklch(from var(--c) l c h / 0.6) calc(12 * var(--s)),
transparent calc(24 * var(--s))),
radial-gradient(oklch(from var(--c) l c h / 0.8) calc(24 * var(--s)),
transparent calc(48 * var(--s)));
background-size:
calc(32 * var(--s)) calc(32 * var(--s)),
calc(64 * var(--s)) calc(64 * var(--s)),
calc(128 * var(--s)) calc(128 * var(--s));
background-position-x: var(--bpx1), var(--bpx2), var(--bpx3);
background-position-y: var(--bpy1), var(--bpy2), var(--bpy3);
background-clip: text;
animation: animx1 2.7s ease-in-out infinite,
animy1 3.14s ease-in-out infinite, animx2 2.7s ease-in-out infinite,
animy2 3.14s ease-in-out infinite, animx3 2.7s ease-in-out infinite,
animy3 3.14s ease-in-out infinite;
}
@keyframes animx1 {
from,
to {
--bpx1: -64px;
}
50% {
--bpx1: 64px;
}
}
@keyframes animy1 {
from,
to {
--bpy1: -64px;
}
50% {
--bpy1: 64px;
}
}
@keyframes animx2 {
from,
to {
--bpx2: -128px;
}
50% {
--bpx2: 128px;
}
}
@keyframes animy2 {
from,
to {
--bpy2: -128px;
}
50% {
--bpy2: 128px;
}
}
@keyframes animx3 {
from,
to {
--bpx3: -256px;
}
50% {
--bpx3: 256px;
}
}
@keyframes animy3 {
from,
to {
--bpy3: -256px;
}
50% {
--bpy3: 256px;
}
}
<div>С Новым<br>2025<br>Годом!</div>
Ответ на конкурсный вопрос:
Анимация снежинок, снегопада
Задача была создать программу, которая реализует круговое движение падающих снежинок, создающих иллюзию метели.
Тут кривовато выглядит, поэтому ссылка codepen - https://codepen.io/aliencash/pen/ByBdLRW
const wrapper = document.querySelector(".perspective");
for (i = 0; i < window.innerHeight; i++) {
let addPoint = document.createElement("div");
addPoint.classList.add("point");
addPoint.style.width = 5 + Math.random() * 90 + "vw";
if (Math.random() < .5) {
addPoint.style.setProperty("--pointLeft", "unset");
addPoint.style.setProperty("--pointRight", 0);
} else {
addPoint.style.setProperty("--pointLeft", 0);
addPoint.style.setProperty("--pointRight", "unset");
}
addPoint.style.animationDelay = Math.random() * 2 + "s";
wrapper.appendChild(addPoint);
}
.perspective {
perspective: 1000px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column
}
.point {
width: 100px;
height: 1px;
animation: anim 2s linear infinite;
position: relative;
}
.point::before {
content: '';
position: absolute;
left: var(--pointLeft);
right: var(--pointRight);
width: 3px;
height: 2px;
border-radius: 100%;
background-color: #fff;
box-shadow: 0 0 6px #fff;
}
@keyframes anim {
from {
transform: rotateY(0deg) translatey(-10vh);
}
to {
transform: rotateY(360deg) translatey(10vh);
}
}
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100dvh;
background-image: url(https://i.sstatic.net/PBRad.jpg);
background-position: center;
background-attachment: fixed;
background-size: cover;
background-position: center;
overflow: hidden;
}
<div class="perspective"></div>
Ответ на конкурсные вопросы:
Новогодняя ёлочка: ёлочные игрушки, гирлянды
Анимация снежинок, снегопада
Ответ на первый вопрос: создание скрипта, рисующего новогоднюю елочку и снеговика. Подробное описание с примерами, как это сделано, смотрите ниже
Ответ на второй вопрос: Анимация снежинок реализован с помощью скрипта JS. Обратите внимание,- если мышкой перетащить из области сугробов вверх, то падает одиночный комок снега
Ёлочка:
const canvasWidth = 600
const canvasHeight = 400
const centerX = canvasWidth / 2
const stars = []
function setup() {
createCanvas(canvasWidth, canvasHeight);
for (let i = 0; i < 500; i++) {
stars[i] = [random(canvasWidth), random(canvasHeight), random(2.5), random() > 0.5]
}
}
let angle = 0
function draw() {
background(0)
// Звёздное небо
stroke(255)
for (let i = 0; i < stars.length; i++) {
const [x, y, weight, decrease] = stars[i]
strokeWeight(weight)
point(x, y)
if (weight >= 2.5) {
stars[i][3] = true
} else if (weight <= 1) {
stars[i][3] = false
}
if (decrease) {
stars[i][2] -= 0.025
} else {
stars[i][2] += 0.025
}
}
// Типа хвоя
stroke([0, 255, 0])
strokeWeight(1)
for (let i = 0; i < 5; i++) {
for (let j = 0; j < i * 10 + 20; j++) {
const lineY = (i - 1) * 50 + 100
const lineYEnd = i * 50 + 100
line(centerX, lineY, centerX + (i * 20 + 40) * Math.cos(angle + j), lineYEnd)
}
}
// Звезда
push()
translate(centerX, 40)
rotate(angle)
stroke([250, 225, 0])
strokeWeight(2)
const radius = 25
const step = Math.PI * 2 / 5
const innerRadius = radius / 2
for (let i = 0; i < 5; i++) {
line(
radius * Math.cos(step * i - Math.PI / 2),
radius * Math.sin(step * i - Math.PI / 2),
innerRadius * Math.cos(step * (i + 0.5) - Math.PI / 2),
innerRadius * Math.sin(step * (i + 0.5) - Math.PI / 2)
)
line(
radius * Math.cos(-step * i - Math.PI / 2),
radius * Math.sin(step * i - Math.PI / 2),
innerRadius * Math.cos(-step * (i + 0.5) - Math.PI / 2),
innerRadius * Math.sin(step * (i + 0.5) - Math.PI / 2)
)
}
pop()
// Ствол (не волнуйтесь, у меня есть лицензия на огнестрельное)
stroke([96, 64, 32])
for (let i = 0; i < 20; i++) {
const x = centerX + 10 * Math.cos(angle + i)
line(x, 300, x, 350)
}
angle += 0.01
}
<script src="https://github.com/processing/p5.js/releases/download/v1.11.2/p5.min.js"></script>
Очень много снега:
(можно сделать снежок перетащив снег навверх)
const stars = []
const snow = []
const userSnow = []
const snowflakes = []
let inside = false
let holdsSnow = false
function setup() {
createCanvas(600, 400);
for (let i = 0; i < 125; i++) {
stars.push([random(width), random(height), random(2.5), random() > 0.5])
}
for (let i = 0; i < 10; i++) {
snow.push([100 * i + random(10), height, random(100) + 100])
}
for (let i = 0; i < 100; i++) {
snowflakes.push([random(width), -random(height * 2), random(2) + 2, random(10), random() / 25])
}
}
function draw() {
background(0);
// stars
stroke([255, 255, 255, 255 * 0.25])
for (let i = 0; i < stars.length; i++) {
const [x, y, weight, decrease] = stars[i]
strokeWeight(weight)
point(x, y)
if (weight >= 2.5) {
stars[i][3] = true
} else if (weight <= 1) {
stars[i][3] = false
}
if (decrease) {
stars[i][2] -= 0.025
} else {
stars[i][2] += 0.025
}
}
// snow
for (let i = 0; i < snow.length; i++) {
const [x, y, r] = snow[i]
circle(x, y, r)
}
// snowflakes
for (let i = 0; i < snowflakes.length; i++) {
const [x, y, r, a, s] = snowflakes[i]
circle(x, y, r)
snowflakes[i][0] += Math.cos(a)
snowflakes[i][1] += 0.5
snowflakes[i][3] += s
if (y > height + r) {
snowflakes[i][0] = random(width)
snowflakes[i][1] = -random(height * 2)
snowflakes[i][2] = random(2) + 2
snowflakes[i][3] = random(10)
}
}
// cursor
if (inside) {
if (mouseIsPressed) {
holdsSnow = true
cursor('grabbing')
} else {
holdsSnow = false
cursor('grab')
}
} else {
if (holdsSnow) {
cursor('grabbing')
} else {
cursor('default')
}
}
if (holdsSnow) {
circle(mouseX, mouseY, 15)
}
for (let i = 0; i < userSnow.length; i++) {
const [x, y, r, s] = userSnow[i]
circle(x, y, r)
userSnow[i][1] += s
userSnow[i][3] += 0.125
if (y > height + r) {
userSnow.splice(i, 1)
}
}
}
function mouseMoved() {
checkIfInside()
}
function mouseReleased() {
checkIfInside()
if (holdsSnow && !inside) {
holdsSnow = false
userSnow.push([mouseX, mouseY, 15, 1])
}
}
function checkIfInside() {
let isInside = false
for (let i = 0; i < snow.length; i++) {
const [x, y, r] = snow[i]
if(pointIsInCircle(mouseX, mouseY, x, y, r / 2)) {
isInside = true
break
}
}
inside = isInside
}
function pointIsInCircle(x1, y1, x2, y2, r) {
return distance(x1, y1, x2, y2) < r
}
function distance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
}
<script src="https://github.com/processing/p5.js/releases/download/v1.11.2/p5.min.js"></script>
Ёлочка и снеговик (авто-рисовалка):
function setup() {
createCanvas(600, 400)
}
const centerX = 300
const centerY = 200
let angle = 0
let length = 50
let lineX = centerX
let lineY = 100
let lineXEnd = centerX
let lineYEnd = 50
let lastX = 0
let lastY = 0
let lines = []
let y = 100
function draw() {
background(0)
for (let i = 0; i < lines.length; i++) {
const [x1, y1, x2, y2, color] = lines[i]
stroke(color)
line(x1, y1, x2, y2)
}
// Ёлка
if (angle < 110) {
// angle < 90 нужен для того, чтобы рисовалка прошлась пару раз по одному и тому же месту
if (angle < 90) {
length = 50 + 20 * Math.floor(angle / 10)
y = 100 + 30 * Math.floor(angle / 10)
}
lineX = centerX + length * Math.cos(angle)
lineY = y
lineYEnd = y + -Math.abs(length * Math.sin(angle))
noFill()
stroke(255)
line(lineX, lineY, lineXEnd, lineYEnd)
lines.push([lineX, lineY, lineXEnd, lineYEnd, [50, 200, 50]])
}
// Пень
if (angle > 110 && angle < 120) {
lineY = 100 + 30 * 8 // 8 = кол-во уровней ёлки - 1
lineYEnd = lineY + 50
lineX = centerX + 25 * Math.cos(angle)
lineXEnd = lineX
noFill()
stroke(255)
line(lineX, lineY, lineXEnd, lineYEnd)
lines.push([lineX, lineY, lineXEnd, lineYEnd, [96, 64, 32]])
}
// Снеговик
if (angle > 120 && angle < 180) {
length = Math.floor((angle - 120) / 20 + 1) * 20
lineX = width - 100
lineY = centerY - 50 + 50 * -Math.floor((120 - angle) / 20)
lineXEnd = lineX + length * Math.cos(angle)
lineYEnd = lineY + length * Math.sin(angle)
noFill()
stroke(255)
line(lineX, lineY, lineXEnd, lineYEnd)
lines.push([lineX, lineY, lineXEnd, lineYEnd, [255, 255, 255]])
}
// Типа пуговицы
if (angle > 180 && angle < 200) {
length = 4
lineX = width - 100
lineY = centerY + 25 * Math.floor((angle - 180) / 6.67 + 1)
lineXEnd = lineX + length * Math.cos(angle)
lineYEnd = lineY + length * Math.sin(angle)
noFill()
stroke(255)
line(lineX, lineY, lineXEnd, lineYEnd)
lines.push([lineX, lineY, lineXEnd, lineYEnd, [0, 0, 0]])
}
angle += 0.05
}
<script src="https://github.com/processing/p5.js/releases/download/v1.11.2/p5.min.js"></script>
Авторисовалка
Прицип рисования ёлочки
В первую очередь я взял обычную форму для рисования круга:
function setup() {
createCanvas(600, 200)
}
const radius = 150
const strokeWidth = 7
const lines = []
let x = 100 + radius / 2
let y = 100
let lastX = x
let lastY = y
let angle = 0
function draw() {
background(0)
strokeWeight(strokeWidth)
for (let i = 0; i < lines.length; i++) {
const lineItem = lines[i]
const [x1, y1, x2, y2] = lineItem
stroke([0, 255, 0])
line(x1, y1, x2, y2)
lines[i][0] += 1
lines[i][2] += 1
if (x1 > width) {
lines.splice(i, 1)
}
}
stroke([120, 120, 120])
line(0, height/2, width, height/2)
line(height/2, 0, height/2, height)
stroke(255)
noFill()
circle(height/2, height/2, radius)
noStroke()
fill([255, 0, 0])
circle(x, y, strokeWidth * 2)
lastX = x
lastY = y
x = height/2 + radius/2 * Math.cos(angle)
y = height/2 + radius/2 * Math.sin(angle)
angle += 0.02
lines.push([x, y, lastX, lastY])
}
<script src="https://github.com/processing/p5.js/releases/download/v1.11.2/p5.min.js"></script>
И завернул синус угла в модуль и добавил минус (то-есть тот который отвечает за движение по оси y), что предатвратило движение в минусовой части сетки координат по оси y.
function setup() {
createCanvas(600, 200)
}
const radius = 150
const strokeWidth = 7
const lines = []
let x = 100 + radius / 2
let y = 100
let lastX = x
let lastY = y
let angle = 0
function draw() {
background(0)
strokeWeight(strokeWidth)
for (let i = 0; i < lines.length; i++) {
const lineItem = lines[i]
const [x1, y1, x2, y2] = lineItem
stroke([0, 255, 0])
line(x1, y1, x2, y2)
lines[i][0] += 1
lines[i][2] += 1
if (x1 > width) {
lines.splice(i, 1)
}
}
stroke([120, 120, 120])
line(0, height/2, width, height/2)
line(height/2, 0, height/2, height)
stroke(255)
noFill()
circle(height/2, height/2, radius)
noStroke()
fill([255, 0, 0])
circle(x, y, strokeWidth * 2)
lastX = x
lastY = y
x = height/2 + radius/2 * Math.cos(angle)
y = height/2 + radius/2 * -Math.abs(Math.sin(angle))
angle += 0.02
lines.push([x, y, lastX, lastY])
}
<script src="https://github.com/processing/p5.js/releases/download/v1.11.2/p5.min.js"></script>
И в итоге получил что-то такое:
function setup() {
createCanvas(300, 200)
}
const length = 100
let x = 150
let y = 100
let x2 = x
let y2 = y
let angle = 0
function draw() {
background(0)
strokeWeight(7)
x = width/2 + length * Math.cos(angle)
y2 = height/2 + length * -Math.abs(Math.sin(angle))
stroke(255)
line(x, y, x2, y2)
angle += 0.02
}
<script src="https://github.com/processing/p5.js/releases/download/v1.11.2/p5.min.js"></script>
А дальше дело осталось за малым, просто добавлять к y координате какое-то число n, тоже самое с длиной линии. Также необходимо было сохранять позицию и желаемый цвет (цвет сохраняем сейчас, чтобы потом можно было использовать другой). Переход на следующий уровень происходит когда угл проходит порог 6 градусов (далее на 12, 18, 24 и т.д.)
function setup() {
createCanvas(300, 200)
}
let length = 10
const lines = []
let x = 150
let y = 42
let x2 = x
let y2 = y
let angle = 0
function draw() {
background(0)
strokeWeight(2)
for (let i = 0; i < lines.length; i++) {
const l = lines[i]
stroke(l[4])
line(l[0], l[1], l[2], l[3])
}
length = 10 + 10 * Math.floor(angle / 6)
y = 42 + 15 * Math.floor(angle / 6)
x = width/2 + length * Math.cos(angle)
y2 = y + length * -Math.abs(Math.sin(angle))
stroke(255)
line(x, y, x2, y2)
angle += 0.1
lines.push([x, y, x2, y2, [100, 255, 150]])
}
<script src="https://github.com/processing/p5.js/releases/download/v1.11.2/p5.min.js"></script>
Далее просто нужно добавить лимит до которого ёлочка будет рисоваться. (Допустим: if (angle < 60) { ... }
)
Пенёк
Пенёк рисуется лечге всего, для него банально нужно двигать линию влево-вправо по оси x, а ось y записывается вообще только с базовыми вычислениями +
и *
(с.м. код авто рисовалки).
function setup() {
createCanvas(300, 200)
}
let length = 20
const lines = []
let x = 150
let y = 42
let x2 = x
let y2 = y
let angle = 0
function draw() {
background(0)
strokeWeight(2)
for (let i = 0; i < lines.length; i++) {
const l = lines[i]
stroke(l[4])
line(l[0], l[1], l[2], l[3])
}
x = width/2 + length * Math.cos(angle)
x2 = x
y = 75
y2 = y + 50
stroke(255)
line(x, y, x2, y2)
angle += 0.1
lines.push([x, y, x2, y2, [137, 81, 41]])
}
<script src="https://github.com/processing/p5.js/releases/download/v1.11.2/p5.min.js"></script>
Снеговик
Снеговик рисуется по принципу ёлочки, но только мы оставляем формулу рисования круга как она есть.
function setup() {
createCanvas(300, 200)
}
let length = 10
const lines = []
let x = 150
let y = 42
let x2 = x
let y2 = y
let angle = 0
function draw() {
background(0)
strokeWeight(2)
for (let i = 0; i < lines.length; i++) {
const l = lines[i]
stroke(l[4])
line(l[0], l[1], l[2], l[3])
}
length = 10 + 10 * Math.floor(angle / 12)
y = 42 + 30 * Math.floor(angle / 12)
x = width/2
x2 = x + length * Math.cos(angle)
y2 = y + length * Math.sin(angle)
stroke(255)
line(x, y, x2, y2)
angle += 0.1
lines.push([x, y, x2, y2, [255, 255, 255]])
}
<script src="https://github.com/processing/p5.js/releases/download/v1.11.2/p5.min.js"></script>
Пуговицы
Они рисуются точно также как снеговик, но только длина не меняется.
function setup() {
createCanvas(300, 200)
}
let length = 4
const lines = []
let x = 150
let y = 42
let x2 = x
let y2 = y
let angle = 0
function draw() {
background(0)
strokeWeight(2)
for (let i = 0; i < lines.length; i++) {
const l = lines[i]
stroke(l[4])
line(l[0], l[1], l[2], l[3])
}
y = 42 + 30 * Math.floor(angle / 6.67)
x = width/2
x2 = x + length * Math.cos(angle)
y2 = y + length * Math.sin(angle)
stroke(255)
line(x, y, x2, y2)
angle += 0.1
lines.push([x, y, x2, y2, [255, 255, 255]])
}
<script src="https://github.com/processing/p5.js/releases/download/v1.11.2/p5.min.js"></script>
const primeLengths = [1, 3, 5, 7, 11, 13, 16, 19, 21, 24];
const trunkLengths = [3, 3];
const tree = document.getElementById("tree");
const trunk = document.getElementById("trunk");
const getRandomBinaryString = length => Array.from({
length
}, () => Math.random() < 0.5 ? "0" : "1").join("");
const fillTheTree = (arr, place) => {
place.innerHTML = arr.map(length => `<span>${getRandomBinaryString(length)}</span>`).join("");
};
fillTheTree(primeLengths, tree);
fillTheTree(trunkLengths, trunk);
const animateTree = () => {
const spans = tree.querySelectorAll("span:not(:first-child)");
spans.forEach(span => {
const chars = Array.from(span.textContent, () => (Math.random() < 0.5 ? "0" : "1"));
const glowCount = Math.floor(Math.random() * chars.length) + 1;
const indicesToGlow = new Set(Array.from({
length: glowCount
}, () => Math.floor(Math.random() * chars.length)));
span.innerHTML = chars
.map((char, i) => indicesToGlow.has(i) ? `<b class="glow">${char}</b>` : char)
.join("");
});
};
setInterval(animateTree, 1000);
:root {
--first-color: #2E6311;
--second-color: #ED404A;
--tree-color: #EC6F2A;
--font-family: sans-serif;
--background-gradient: linear-gradient(180deg, #012349, #00030A 70%, #00030A);
}
body {
margin: 0;
height: 100vh;
background: var(--background-gradient);
font-family: var(--font-family);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
font-size: 1.2em;
font-weight: 300;
}
span {
display: block;
text-shadow: 0 0 5px var(--first-color),
0 0 10px var(--first-color),
0 0 15px var(--first-color),
0 0 20px var(--first-color),
0 0 25px var(--first-color),
0 0 30px var(--first-color);
}
span b {
position: relative;
z-index: 2;
font-weight: 300;
}
#tree span:first-child {
text-shadow: 0 0 5px var(--second-color),
0 0 10px var(--second-color),
0 0 15px var(--second-color),
0 0 20px var(--second-color),
0 0 25px var(--second-color) !important;
}
.tree {
text-align: center;
line-height: 1.5;
white-space: pre;
}
.down {
font-family: "Pacifico", serif;
font-weight: 400;
text-align: center;
max-width: 700px;
line-height: 1.2;
position: relative;
overflow: visible;
padding: 3vh 0;
}
.down:before {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 120%;
height: 120%;
background: radial-gradient(ellipse, #93061A 0%, transparent 100%);
filter: blur(10px);
border-radius: 50%;
z-index: -1;
}
.glow {
text-shadow: 0 0 5px var(--tree-color),
0 0 10px var(--tree-color),
0 0 15px var(--tree-color),
0 0 20px var(--tree-color),
0 0 25px var(--tree-color);
}
.bg_text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 80vh;
color: rgba(32, 67, 107, 0.1);
z-index: -3;
}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Pacifico&display=swap" rel="stylesheet">
<div class="bg_text">2025</div>
<main>
<div class="tree" id="tree"></div>
<div class="tree" id="trunk"></div>
</main>
<h1 class="down">Merry Christmas <br> and <br> Happy New Year</h1>
Анимация надписи: с Новым годом!
Буквы движутся сначала хаотично, затем паркуются на место.
(Серый шаблон надписи) на фоне картинки.
Горизонтальная парковка букв
Разверните снипет на полный экран и кликните по холсту ЛКМ
#text1 {
fill:#860D86;
stroke:white;
stroke-width:2;
}
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<rect width="100%" height="100%" fill="url(#grad)" />
<text x="200 " y="500"
font-size="120" fill="white" stroke-width="2" stroke="white" opacity="0.4">С Новым годом!</text>
<g transform="translate(0)">
<text id="text1" x="200" y="500"
font-size="120">С Новым годом!</text>
<animate xlink:href="#text1"
attributeName="x"
attributeType="XML"
values="200 233 266 299 332 365 400 431 464 497 530 563 596;
100 600 200 365 700 465 465 563 530 398 431 850 900;
200 500 900 950 150 531 300 620 150 266 365 650 900;
332 233 820 300 800 633 200 670 300 850 800 530 266;
464 900 900 900 820 670 430 900 530 600 233 365 100;
332 100 100 100 500 100 800 563 900 700 900 100 100;
200 233 266 299 332 365 400 431 464 497 530 563 596"
dur="5s"
begin="svg1.click"
repeatCount="2" />
<animate xlink:href="#text1"
attributeName="y"
attributeType="XML"
values="500 500 500 500 500 500 500 500 500 500 500 500 500;
100 200 850 100 250 175 750 100 750 720 850 500 50;
100 600 600 250 200 450 50 200 520 550 300 300 750;
500 100 650 650 600 150 550 50 150 550 200 550 400;
800 300 100 750 150 650 75 350 550 700 755 120 800;
800 600 300 150 750 350 700 650 200 250 500 650 100;
500 500 500 500 500 500 500 500 500 500 500 500 500"
dur="4s"
begin="svg1.click"
repeatCount="2" />
</g>
</svg>
Вертикальная парковка букв
#text1 {
fill:#00FF3C;
stroke:white;
stroke-width:2;
}
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<rect width="100%" height="100%" fill="url(#grad)" />
<text x="200 " y="500"
font-size="120" fill="white" stroke-width="2" stroke="white" opacity="0.4">С Новым годом!</text>
<g transform="translate(0)">
<text id="text1" x="200" y="500"
font-size="120">С Новым годом!</text>
<animate xlink:href="#text1"
attributeName="x"
attributeType="XML"
values="200 233 266 299 332 365 400 431 464 497 530 563 596;
100 600 200 365 700 465 465 563 530 398 431 850 900;
200 500 900 950 150 531 300 620 150 266 365 650 900;
332 233 820 300 800 633 200 670 300 850 800 530 266;
464 900 900 900 820 670 430 900 530 600 233 365 100;
332 100 100 100 500 100 800 563 900 700 900 100 100;
200 233 266 299 332 365 400 431 464 497 530 563 596"
dur="4s"
begin="svg1.click"
repeatCount="2" />
<animate xlink:href="#text1"
attributeName="y"
attributeType="XML"
values="500 500 500 500 500 500 500 500 500 500 500 500 500;
100 200 850 100 250 175 750 100 750 720 850 500 50;
100 600 600 250 200 450 50 200 520 550 300 300 750;
500 100 650 650 600 150 550 50 150 550 200 550 400;
800 300 100 750 150 650 75 350 550 700 755 120 800;
800 600 300 150 750 350 700 650 200 250 500 650 100;
500 500 500 500 500 500 500 500 500 500 500 500 500"
dur="5s"
begin="svg1.click"
repeatCount="2" />
</g>
</svg>
Update 18.01.2025 г.
- Glow effect
Достигается комплексным применением svg фильтров к тексту. Пояснения смотрите в комментариях внутри программы.
container {
width:100vw;
height:100vh;
}
text {
font-family: Helvetica, Arial, sansserif;
font-size: 100px;
font-weight: 900;
fill: white;
filter: url(#red-glow);
}
<div class="container">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1680 1050">
<defs>
<filter id="red-glow" filterUnits="userSpaceOnUse"
x="-50%" y="-50%" width="200%" height="200%">
<!-- размыть текст на разных уровнях-->
<feGaussianBlur in="SourceGraphic" stdDeviation="5" result="blur5"/>
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur10"/>
<feGaussianBlur in="SourceGraphic" stdDeviation="20" result="blur20"/>
<feGaussianBlur in="SourceGraphic" stdDeviation="30" result="blur30"/>
<feGaussianBlur in="SourceGraphic" stdDeviation="50" result="blur50"/>
<!-- объединить все размытия, кроме первого -->
<feMerge result="blur-merged">
<feMergeNode in="blur10"/>
<feMergeNode in="blur20"/>
<feMergeNode in="blur30"/>
<feMergeNode in="blur50"/>
</feMerge>
<!-- перекрасить объединенные размытия в циан цвет-->
<feColorMatrix result="cyan-blur" in="blur-merged" type="matrix"
values="0 0 0 0 0
1 0 0 0 0
1 0 0.44 0 0
0 0 0 1 0" />
<feMerge>
<feMergeNode in="cyan-blur"/>
<feMergeNode in="blur5"/>
<feMergeNode in="SourceGraphic"/>
</filter>
</defs>
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<text x="800" y="200" text-anchor="middle" >С Новым 2025 годом!</text>
</svg>
</div>
- Ещё вариант Glow effect:
.container {
width:100vw;
height:100vh;
}
<div class="container">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1680 1050">
<svg>
<filter id="neon">
<feFlood flood-color="rgb(255,255,128)" flood-opacity="0.5" in="SourceGraphic" />
<feComposite operator="in" in2="SourceGraphic" />
<feGaussianBlur stdDeviation="10" />
<feComponentTransfer result="glow1">
<feFuncA type="linear" slope="4" intercept="0" />
</feComponentTransfer>
<feMerge>
<feMergeNode in="glow1" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<text text-anchor="middle" font-size="100" font-family="sans-serif" x="50%" y="200" fill="yellow" filter="url(#neon)">С Новым 2025 годом!</text>
</svg>
</div>
- 'Flood-Color' - это цвет свечения.
stdDeviation
- приблизительный размер, более высокие значения означают меньшую интенсивностьslope
усиливает свечение и противодействует разбавлению размытия по Гауссу. flood-opacity` делает то же самое, но имеет верхний предел 1- если вы хотите получить свечение перед буквами, измените порядок с
<feMergeNode>
s - если вы хотите наложить несколько слоев свечения, как в примере на
codepen
, повторите примитивы фильтра, кроме последнего<feMerge>
, и добавьте их результат в том порядке, в котором вы хотите, чтобы они<feMerge>
Источник ответа:@ccprog немного доработан.
- Вертикальная парковка букв + glow эффект
#text1 {
fill:yellow;
stroke:white;
stroke-width:2;
}
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<filter id="neon">
<feFlood flood-color="#B22222" flood-opacity="0.5" in="SourceGraphic" />
<feComposite operator="in" in2="SourceGraphic" />
<feGaussianBlur stdDeviation="10" />
<feComponentTransfer result="glow1">
<feFuncA type="linear" slope="4" intercept="0" />
</feComponentTransfer>
<feMerge>
<feMergeNode in="glow1" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Подложка - фоновый текст -->
<text x="200 " y="500"
font-size="150" fill="white" stroke-width="2" stroke="white" opacity="0.4">С Новым годом!</text>
<g>
<text id="text1" font-size="150" x="200" y="500" fill="green" filter="url(#neon)">С Новым годом!</text>
<animate xlink:href="#text1"
attributeName="x"
attributeType="XML"
values="200 233 266 299 332 365 400 431 464 497 530 563 596;
100 600 200 365 700 465 465 563 530 398 431 850 900;
200 500 900 950 150 531 300 620 150 266 365 650 900;
332 233 820 300 800 633 200 670 300 850 800 530 266;
464 900 900 900 820 670 430 900 530 600 233 365 100;
332 100 100 100 500 100 800 563 900 700 900 100 100;
200 233 266 299 332 365 400 431 464 497 530 563 596"
dur="4s"
begin="svg1.click"
repeatCount="2" />
<animate xlink:href="#text1"
attributeName="y"
attributeType="XML"
values="500 500 500 500 500 500 500 500 500 500 500 500 500;
100 200 850 100 250 175 750 100 750 720 850 500 50;
100 600 600 250 200 450 50 200 520 550 300 300 750;
500 100 650 650 600 150 550 50 150 550 200 550 400;
800 300 100 750 150 650 75 350 550 700 755 120 800;
800 600 300 150 750 350 700 650 200 250 500 650 100;
500 500 500 500 500 500 500 500 500 500 500 500 500"
dur="5s"
begin="svg1.click"
repeatCount="2" />
</g>
</svg>
Это не конкурсный ответ, а скорее попытка оказать помощь новичкам, которые захотят окунуться в этот чудесный мир - анимации.
Для начала можно взять готовые заготовки из раздела:
Дополнительные материалы
в шапке конкурсного топика.
- Берем к примеру заготовку: Символ 2025 года + фон заставка
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<!-- Фон -->
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Змея - символ 2025 года -->
<image id="snake" x="250" y="350" transform="scale(2)" xlink:href="https://i.sstatic.net/QkvLYcnZ.png"/>
</svg>
- Немного поиграем с перемещением, увеличением объекта относительно фона с помощью команды - animateTransform
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<!-- Фон с ёлочкой -->
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Символ 2025 года Змея -->
<image id="zmeya" x="75" xlink:href=" https://i.sstatic.net/pB6og8Sf.png">
<!-- команда анимации перемещения объекта -->
<animateTransform attributeName="transform" type="translate " values="175 725; 850 725; 175 725" dur="16s" begin="0.5s" repeatCount="5" fill="freeze" />
<!-- команда анимации увеличения, уменьшения объекта -->
<animateTransform attributeName="transform" type="scale " values="1;2;1" dur="8s" begin="0.5s" additive="sum" repeatCount="5" fill="freeze" />
</image>
</svg>
Нюанс : атрибут additive="sum"
необходим для одновременной работы двух анимаций: перемещение, увеличение
update 12.01.2025
- Появление объекта.
Используется анимация атрибута opacity
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<!-- Фон с ёлочкой -->
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Дед мороз -->
<image id="Ded_Moroz" x="100" y="725" xlink:href="https://i.sstatic.net/TYaVo.png" width="30%" height="30%" opacity="0">
<!-- Анимация появления объекта -->
<animate id="op1" attributeName="opacity" values="0; 1" dur="4s" begin="svg1.click" repeatCount="1" fill="freeze" restart="whenNotActive" />
</image>
</svg>
атрибут restart="whenNotActive"
не позволяет повторный запуск до окончания полного выполнения анимации.
begin="svg1.click"
- условия запуска анимации (клик по холсту svg)
Необходимо привыкнуть всегда присваивать командам анимации уникальные идентификаторы id=""
С помощью которых выстраивается сценарий и логика анимаций: какая анимация идет за первой анимацией, одновременный запуск нескольких действий, задержка, закольцевание и т.д
- Появление + движение объекта
Движение объекта - реализуется изменением координаты, в данном примере "x"
begin="op1.end"
- запуск анимации движения после окончания анимации появления.
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<!-- Фон с ёлочкой -->
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Дед мороз -->
<image id="Ded_Moroz" x="100" y="725" xlink:href="https://i.sstatic.net/TYaVo.png" width="30%" height="30%" opacity="0">
<!-- Анимация появления объекта -->
<animate id="op1" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация движения объекта -->
<animate id="Go" attributeName="x" values="100; 600" dur="4s" begin="op1.end" repeatCount="1" fill="freeze" restart="whenNotActive" />
</image>
</svg>
- Одновременная анимация двух персонажей
Сценарий:
- После клика появляются персонажи Деда Мороза и Снегурочки
- Оба персонажа двигаются навстречу друг другу
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<!-- Фон с ёлочкой -->
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Дед мороз -->
<image id="Ded_Moroz" x="100" y="700" xlink:href="https://i.sstatic.net/TYaVo.png" width="30%" height="30%" opacity="0">
<!-- Анимация появления Деда -->
<animate id="op1" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация движения Деда -->
<animate id="Go" attributeName="x" values="100; 600" dur="4s" begin="op1.end" repeatCount="1" fill="freeze" restart="whenNotActive" />
</image>
<!-- Снегурочка -->
<image id="Girl" x="1150" y="725" xlink:href="https://i.sstatic.net/RDght.png" width="30%" height="30%" opacity="0">
<!-- Анимация появления Снегурочки -->
<animate id="op1_Girl" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация движения снегурочки -->
<animate id="GO_girl" attributeName="x" values="1150;700" dur="4s" begin="op1_Girl.end" repeatCount="1" fill="freeze" />
</image>
</svg>
- Движение навстречу и расхождение персонажей
Для этого нужно добавить в существующую анимацию несколько цифр в атрибут values
Было: values="1150;700
Стало: values="1150;700;700;1150"
повторение цифры 700 обеспечивает паузу в месте встречи
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<!-- Фон с ёлочкой -->
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Дед мороз -->
<g id="group" >
<image id="Ded_Moroz" x="100" y="700" xlink:href="https://i.sstatic.net/TYaVo.png" width="30%" height="30%" opacity="0">
<!-- Анимация появления Деда -->
<animate id="op1" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация движения Деда -->
<animate id="Go" attributeName="x" values="100; 600;600;100" dur="6s" begin="op1.end" repeatCount="1" fill="freeze" restart="whenNotActive" />
</image>
<!-- Снегурочка -->
<image id="Girl" x="1150" y="725" xlink:href="https://i.sstatic.net/RDght.png" width="30%" height="30%" opacity="0">
<!-- Анимация появления Снегурочки -->
<animate id="op1_Girl" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация движения снегурочки -->
<animate id="GO_girl" attributeName="x" values="1150;700;700;1150" dur="6s" begin="op1_Girl.end" repeatCount="1" fill="freeze" />
</image>
</g>
</svg>
update 13.01.2025
- Анимация зайца с гитарой
перемещение по вертикали и горизонтали
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<!-- Фон с ёлочкой -->
<image xlink:href="https://i.sstatic.net/PBRad.jpg" height="100%" width="100%"/>
<!-- Заяц -->
<image id="zayka" x="300" y="750" xlink:href="https://i.sstatic.net/jtM0Q2iF.png" opacity="0">
<!-- Анимация появления зайца -->
<animate id="op1_zayka" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Перемещение зайки по горизонтали -->
<animate id="Go_zayka" attributeName="x" values="300;375;450;525;600;600;675;750;825;900;1025;1100" dur="6s" begin="op1_zayka.end" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Перемещение по вертикали -->
<animate id="Go_zayka_y" attributeName="y" values="750;800;750;800;750;800;750;800;750;800;750;800;" dur="6s" begin="op1_zayka.end" repeatCount="1" fill="freeze" restart="whenNotActive" />
</image>
</svg>
update 14.01.2025
Дрон + фон
.drone .body {
fill: #050423;
stroke:grey;
stroke-width:0.25;
}
.wing {
fill: #000;
transform-origin: center center;
transform-box: fill-box;
}
.drone.animate .wing {
animation: wing 5s linear forwards infinite;
}
@keyframes wing {
100% {
transform: rotateY(7200deg);
}
}
<svg class="drone animate" height="40vh" viewBox="-3 -3 60 20" >
<defs>
<radialGradient id="Lg" fx="50%" fy="50%" >
<stop offset="5%" stop-color="yellow" />
<stop offset="100%" stop-color="red" />
</radialGradient>
<radialGradient id="Lg2" fx="50%" fy="50%" >
<stop offset="5%" stop-color="gold" />
<stop offset="100%" stop-color="green" >
</radialGradient>
</defs>
<g>
<g class="wing left">
<path d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/> </g>
<g class="wing right">
<path d="M48,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S48.6,2,48,2z"/>
<path d="M43,2c-0.6,0-8-0.4-8-1s7.4-1,8-1s1,0.4,1,1S43.6,2,43,2z"/>
</g>
<!-- Верхний фонарь -->
<ellipse opacity="0.2" cx="28" cy="2.5" rx="1" ry="2" fill="url(#Lg2)">
<animate id="op_dron3" attributeName="opacity" begin="op_dron1.end" dur="0.5s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
<g class="body">
<path d="M45,0.5C45,0.2,45.2,0,45.5,0S46,0.2,46,0.5V4c0.6,0,1,0.4,1,1v1h0.5C48.3,6,49,6.7,49,7.5S48.3,9,47.5,9H37v0.9
c0,0.7-0.4,1.4-1,1.7l-3.6,2.1c-0.3,0.2-0.7,0.3-1,0.3h-6.9c-0.4,0-0.7-0.1-1-0.3L20,11.6c-0.6-0.4-1-1-1-1.7V9H8.5
C7.7,9,7,8.3,7,7.5S7.7,6,8.5,6H9V5c0-0.6,0.4-1,1-1V0.5C10,0.2,10.2,0,10.5,0C10.8,0,11,0.2,11,0.5V4c0.6,0,1,0.4,1,1v1h7l0,0
c0.1-0.6,0.4-1.2,1-1.6l3.6-2.1c0.3-0.2,0.7-0.3,1-0.3h6.9c0.4,0,0.7,0.1,1,0.3L36,4.4C36.6,4.8,37,5.3,37,6l7,0V5
c0-0.6,0.4-1,1-1V0.5z"/>
</g>
<!-- Сигнальные фонари, камеры -->
<ellipse opacity="0.2" cx="25" cy="12" rx="1.4" ry="1.4" fill="url(#Lg)">
<animate id="op_dron1" attributeName="opacity" begin="0s;op_dron2.end" dur="1s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
<ellipse opacity="0.2" cx="31" cy="12" rx="1.4" ry="1.4" fill="url(#Lg)">
<animate id="op_dron2" attributeName="opacity" begin="op_dron1.end" dur="1s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
</g>
</svg>
Или так:
.drone .body {
fill: #050423;
stroke:grey;
stroke-width:0.25;
}
.wing {
fill: #000;
transform-origin: center center;
transform-box: fill-box;
}
.drone.animate .wing {
animation: wing 5s linear forwards infinite;
}
@keyframes wing {
100% {
transform: rotateY(7200deg);
}
}
<svg class="drone animate" height="40vh" viewBox="-3 -3 60 20" >
<defs>
<radialGradient id="Lg" fx="50%" fy="50%" >
<stop offset="5%" stop-color="yellow" />
<stop offset="100%" stop-color="green" />
</radialGradient>
<radialGradient id="Lg2" fx="50%" fy="50%" >
<stop offset="5%" stop-color="gold" />
<stop offset="100%" stop-color="red" >
</radialGradient>
</defs>
<g>
<g class="wing left">
<path d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/> </g>
<g class="wing right">
<path d="M48,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S48.6,2,48,2z"/>
<path d="M43,2c-0.6,0-8-0.4-8-1s7.4-1,8-1s1,0.4,1,1S43.6,2,43,2z"/>
</g>
<!-- Верхний фонарь -->
<ellipse opacity="0.2" cx="28" cy="2.5" rx="1" ry="2" fill="url(#Lg2)">
<animate id="op_dron3" attributeName="opacity" begin="op_dron1.end" dur="0.5s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
<g class="body">
<path d="M45,0.5C45,0.2,45.2,0,45.5,0S46,0.2,46,0.5V4c0.6,0,1,0.4,1,1v1h0.5C48.3,6,49,6.7,49,7.5S48.3,9,47.5,9H37v0.9
c0,0.7-0.4,1.4-1,1.7l-3.6,2.1c-0.3,0.2-0.7,0.3-1,0.3h-6.9c-0.4,0-0.7-0.1-1-0.3L20,11.6c-0.6-0.4-1-1-1-1.7V9H8.5
C7.7,9,7,8.3,7,7.5S7.7,6,8.5,6H9V5c0-0.6,0.4-1,1-1V0.5C10,0.2,10.2,0,10.5,0C10.8,0,11,0.2,11,0.5V4c0.6,0,1,0.4,1,1v1h7l0,0
c0.1-0.6,0.4-1.2,1-1.6l3.6-2.1c0.3-0.2,0.7-0.3,1-0.3h6.9c0.4,0,0.7,0.1,1,0.3L36,4.4C36.6,4.8,37,5.3,37,6l7,0V5
c0-0.6,0.4-1,1-1V0.5z"/>
</g>
<!-- Сигнальные фонари, камеры -->
<ellipse opacity="0.2" cx="25" cy="12" rx="1.4" ry="1.4" fill="url(#Lg)">
<animate id="op_dron1" attributeName="opacity" begin="0s;op_dron2.end" dur="1s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
<ellipse opacity="0.2" cx="31" cy="12" rx="1.4" ry="1.4" fill="url(#Lg)">
<animate id="op_dron2" attributeName="opacity" begin="op_dron1.end" dur="1s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
</g>
</svg>
Ответ на конкурсный вопрос:
Новогодняя ёлочка: ёлочные игрушки, гирлянды
Сделал ёлку в стиле одной игры, но SO ни дал запихать её не только в сниппет, но даже в тело ответа (максимально 30к символов, а кода точно больше ?).
По этому будет просто ссылка на Сodepen.
codepen.io/de-minov/pen/KwPymyB
# SO, ну это не серьёзно..
Не рассчитывал на участие, но сделать хотелось.
Ранее делал костёр из одной игры, вот по этому такой стиль.
codepen.io/de-minov/pen/VYZLWZq
# ?
В новогодней анимации использован трек группы "Верасы - Белый снег" (Завируха)
Пояснения даны в подготовительном посте
Анимация начинается после клика по холсту SVG
Сценарий анимации:
- Девочка смотрит сквозь замерзшее стекло.
- Растапливает изморозь своим дыханием на окне и видит
- Ёлку на лесной полянке вокруг которой летает дрон.
- Появляются Дед Мороз и танцующая Снегурочка.
- Заяц с гитарой, снеговик.
- Анимация надписи "С Новым 2025 Годом!"
- Анимация разноцветной закраски звезды на ёлке и самой ёлки.
- Все вместе поют и пляшут :-)
let snowmax = 80,
snowcolor = new Array("#aaaacc", "#ddddff", "#ccccdd", "#f3f3f3", "#f0ffff"),
snowtype = new Array("Arial Black", "Arial Narrow", "Times", "Comic Sans MS"),
snowletter = "*",
sinkspeed = 1.5,
snowmaxsize = 30,
snowminsize = 4,
snow = new Array(),
marginbottom,
marginright,
timer,
i_snow = 0,
x_mv = new Array(),
crds = new Array(),
lftrght = new Array();
function randommaker(range) {
rand = Math.floor(range * Math.random());
return rand;
}
function initsnow() {
marginbottom = window.innerHeight;
marginright = window.innerWidth;
let snowsizerange = snowmaxsize - snowminsize;
for (i = 0; i <= snowmax; i++) {
crds[i] = 0;
lftrght[i] = Math.random() * 15;
x_mv[i] = 0.03 + Math.random() / 10;
snow[i] = document.getElementById("s" + i);
snow[i].style.fontFamily = snowtype[randommaker(snowtype.length)];
snow[i].size = randommaker(snowsizerange) + snowminsize;
snow[i].fontSize = snow[i].size;
snow[i].style.color = snowcolor[randommaker(snowcolor.length)];
snow[i].sink = sinkspeed * snow[i].size / 5;
snow[i].posx = randommaker(marginright - snow[i].size);
snow[i].posy = randommaker(
2 * marginbottom - marginbottom - 2 * snow[i].size
);
snow[i].style.left = snow[i].posx;
snow[i].style.top = snow[i].posy;
}
movesnow();
}
function movesnow() {
for (i = 0; i <= snowmax; i++) {
crds[i] += x_mv[i];
snow[i].posy += snow[i].sink;
snow[i].style.left = snow[i].posx + lftrght[i] * Math.sin(crds[i]) + "px";
snow[i].style.top = snow[i].posy + "px";
if (
snow[i].posy >= marginbottom - 2 * snow[i].size ||
parseInt(snow[i].style.left) > marginright - 3 * lftrght[i]
) {
snow[i].posx = randommaker(marginright - snow[i].size);
snow[i].posy = 0;
}
}
let timer = setTimeout("movesnow()", 50);
}
for (i = 0; i <= snowmax; i++) {
document.write(
"<span id='s" +
i +
"'style='position: absolute; top: -" +
snowmaxsize +
"'>" +
snowletter +
"</span>"
);
}
initsnow();
window.addEventListener('resize', ()=> initsnow())
.container{
width:100vw;
height:100vh;
}
.body {
fill: #170A41;
stroke:white;
stroke-width:0.5;
}
.wing {
fill: white;
transform-origin: center center;
transform-box: fill-box;
}
.wing {
animation: wing 5s linear forwards infinite;
}
@keyframes wing {
100% {
transform: rotateY(7200deg);
}
}
@keyframes wing {
100% {
transform: rotateY(7200deg);
}
}
<div class="container">
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<defs>
<mask id="msk1" x="0" y="0" width="400" height="400" >
<rect fill="white" x="0" y="0" width="100%" height="100%" />
<circle cx="820" cy="450" r="1" fill="black" stroke-width="70" stroke="yellow" >
<animate id="no_Princess" attributeName="r" begin="svg1.click" values="1;400;400;1200" dur="7s" restart="whenNotActive" fill="freeze" />
</circle>
</mask>
<circle cx="700" cy="400" r="1" fill="black" stroke-width="70" stroke="yellow" >
<animate id="no_Princess" attributeName="r" begin="svg1.click" values="1;350;350;1200" dur="7s" restart="whenNotActive" fill="freeze" />
</circle>
</mask>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
<!-- Для дрона -->
<radialGradient id="Lg" fx="50%" fy="50%" >
<stop offset="5%" stop-color="yellow" />
<stop offset="100%" stop-color="green" />
</radialGradient>
<radialGradient id="Lg2" fx="50%" fy="50%" >
<stop offset="5%" stop-color="gold" />
<stop offset="100%" stop-color="red" >
</radialGradient>
<!-- Дрон -->
<g id="drone" >
<g class="wing left">
<path d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/> </g>
<g class="wing right">
<path d="M48,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S48.6,2,48,2z"/>
<path d="M43,2c-0.6,0-8-0.4-8-1s7.4-1,8-1s1,0.4,1,1S43.6,2,43,2z"/>
</g>
<!-- Верхний фонарь -->
<ellipse opacity="0.2" cx="28" cy="2.5" rx="2" ry="4" fill="url(#Lg2)">
<animate id="op_dron3" attributeName="opacity" begin="op_dron1.end" dur="0.5s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
<g class="body">
<path d="M45,0.5C45,0.2,45.2,0,45.5,0S46,0.2,46,0.5V4c0.6,0,1,0.4,1,1v1h0.5C48.3,6,49,6.7,49,7.5S48.3,9,47.5,9H37v0.9
c0,0.7-0.4,1.4-1,1.7l-3.6,2.1c-0.3,0.2-0.7,0.3-1,0.3h-6.9c-0.4,0-0.7-0.1-1-0.3L20,11.6c-0.6-0.4-1-1-1-1.7V9H8.5
C7.7,9,7,8.3,7,7.5S7.7,6,8.5,6H9V5c0-0.6,0.4-1,1-1V0.5C10,0.2,10.2,0,10.5,0C10.8,0,11,0.2,11,0.5V4c0.6,0,1,0.4,1,1v1h7l0,0
c0.1-0.6,0.4-1.2,1-1.6l3.6-2.1c0.3-0.2,0.7-0.3,1-0.3h6.9c0.4,0,0.7,0.1,1,0.3L36,4.4C36.6,4.8,37,5.3,37,6l7,0V5
c0-0.6,0.4-1,1-1V0.5z"/>
</g>
<!-- Сигнальные фонари, камеры -->
<ellipse opacity="0.2" cx="25" cy="12" rx="1.4" ry="1.4" fill="url(#Lg)">
<animate id="op_dron1" attributeName="opacity" begin="0s;op_dron2.end" dur="1s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
<ellipse opacity="0.2" cx="31" cy="12" rx="1.4" ry="1.4" fill="url(#Lg)">
<animate id="op_dron2" attributeName="opacity" begin="op_dron1.end" dur="1s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
<animateTransform id="dron2" attributeName="transform" type="scale" begin="svg1.click+1s" dur="30s" values="1;2;2.5;1;2;2;2;3.5;3.5;2;1;1;1" repeatCount="indefinite" additive="sum" fill="freeze" restart="whenNotActive" />
<animateTransform id="dron2_tr" attributeName="transform" type="translate" begin="svg1.click+1s" dur="20s" values="10 10;100 100;200 200;720 100;10 10" additive="sum" repeatCount="indefinite" restart="whenNotActive" />
</g>
<!-- Для звезды на ёлке -->
<filter id="glow" filterUnits="userSpaceOnUse"
x="-50%" y="-50%" width="300%" height="300%">
<feGaussianBlur in="SourceGraphic" stdDeviation="25" result="blur5"/>
<feGaussianBlur in="SourceGraphic" stdDeviation="30" result="blur10"/>
<feGaussianBlur in="SourceGraphic" stdDeviation="40" result="blur20"/>
<feGaussianBlur in="SourceGraphic" stdDeviation="50" result="blur30"/>
<feGaussianBlur in="SourceGraphic" stdDeviation="70" result="blur50"/>
<feMerge result="blur-merged">
<feMergeNode in="blur10"/>
<feMergeNode in="blur20"/>
<feMergeNode in="blur30"/>
<feMergeNode in="blur50"/>
</feMerge>
<feColorMatrix result="yellow-blur" in="blur-merged" type="matrix"
values="0 0 0 0 0
0 1 0 0 0
0 0 0 0 0
0 0 0 0.7 0" />
<feMerge>
<feMergeNode in="yellow-blur"/>
<feMergeNode in="blur5"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<!-- Маска для ёлки -->
<mask id="msk2">
<rect fill="white" width="100%" height="100%"/>
<path fill="#9939CD" d="m832.5 54.2c-25 19.3-14.5 57.9-13.8 93.8 0.2 11.8-8 22.2-12.5 33.1-2.3 5.7-7.5 17-7.5 17 0 0-8.4 18.5-12 28.1-5.5 15-12.7 29.7-14.5 45.6-1 9.1 3.7 18.2 2.5 27.3-1.7 12.3-11.3 22.5-13.1 34.8-1.1 7.5 1.6 15.1 1.5 22.7-0.1 8.4-2.2 25-2.2 25 0 0-0.6 8.1-2.8 11.4-3.6 5.5-12.9 6-15.6 12-2.2 4.9 1.4 10.7 1.1 16.1-0.5 10-7.2 19.7-5.3 29.5 1 5.1 6.3 8.2 8.3 13.1 1.5 3.6-2.4 15.9-6.7 23.9-2.7 5.2-9.3 4.9-10 9.5-1.4 8.4 12 22.5 12 22.5l-8.9 17.8-4.4 30 1.7 30 9.5 10c1 20.7-2.8 6-8.9 11.1-6.3 6.1 2.1 17.9-0.8 26.1-1.7 4.7-9.2 11.7-9.2 11.7 0 0-5.5 11-4.4 16.7 1.1 5.5 8.9 7.9 10 13.3 1.4 7.1-4 14-5.6 21.1-1 4.8-3.3 9.6-2.5 14.5 0.7 4.1 6 6.9 5.8 11.1-0.2 6.5-8.5 10.4-10 16.7-2.4 9.9 1.1 20.4 1.9 30.6 0.4 4.3 0.5 8.6 1.4 12.8 1.4 7 3 14.1 6.1 20.6 2.7 5.5 4.7 13.4 10.6 15 7 1.9 12.8-8.2 20-8.9 14.8-1.4 29.1 6 43.4 10 8.2 2.3 18.7 2 24.1 7.9 10.5 11.5 10.1 15.7 18 17.4 7.7 1.7 21.5 3.3 28.6-1 7.2-4.3 10-12.8 15.3-17 8.3-6.6 14-3.5 20.7-6.3 6.6-2.7 12.1-7.9 18.9-10 6.4-2 13.3-1.9 20-2.2 7-0.4 15.3 4 21.1 0 5.9-4 4.8-13.5 7.8-20 2.5-5.5 6.5-10.4 8.3-16.1 1.3-4.1 0.5-8.7 1.7-12.8 1.7-5.9 6.7-10.7 7.8-16.7 2-10.6-0.8-21.6-2.2-32.3-0.9-6.4-4.2-12.5-3.9-18.9 0.3-5.8 2.4-11.5 5-16.7 1.8-3.7 6.8-5.9 7.2-10 1.2-10.4-4-22.5-12.2-28.9-4.6-3.6-14.9 2.6-17.2-2.8-5.6-13 23.5-20.9 23.9-35 0.3-8.6-13.3-22.2-13.3-22.2l-5-60.1c0 0-1.6-8.9-1.1-13.3 0.6-5.8 6-11 5-16.7-0.9-4.8-8.8-6.8-8.9-11.7-0.1-6.1 10.2-8.9 10.6-15 0.5-7.8-7.4-13.7-11.1-20.6-4.1-7.6-9.4-14.7-12.2-22.8-1.4-3.9-3.2 0.5-2.2-12.2 0.1-9.5-14.8-18.5-10-26.7 2.5-4.2 11.7 1.8 14.5-2.2 14.2-21.2-16.9-49-17.8-74.5-0.2-4.5 4.3-9.3 2.2-13.3-1.9-3.7-8-2.8-11.1-5.6-3-2.7-5.5-6.2-6.7-10-1.5-5 0-10.4 0-15.6 0-4.4 1.2-9.1 0-13.3-1.4-4.6-5-8.3-7.8-12.2-1.1-1.5-3.1-2.6-3.3-4.4-0.6-4.8 3.9-8.8 5.6-13.3 1.2-3.3 3.9-6.5 3.3-10-0.9-5.5-4.3-12.8-9.8-13.3-1.9-0.2-2.3 4.2-4.2 4-8-1.1-10.4-12.9-12.6-20.7-3.6-26.5-14.5-23.1-15.4-35.2-1.3-25.9 11.6-67.9-9.4-89-8.7-8.8-27.1-11.6-36.9-4z">
<!-- Анимация цветов маски -->
<animate
id="Three_fire"
attributeName="fill"
dur="1.5s"
begin="svg1.click+30s;Three_pause.end"
values=" #CD9AE9;white;white;#CD9AE9"
fill="freeze"
repeatCount="10" />
<!-- Пауза анимации цветов маски -->
<animate
id="Three_pause"
attributeName="fill"
dur="1s"
begin="Three_fire.end"
values=" white;white"
fill="freeze"
repeatCount="1" />
</path>
</mask>
</defs>
<g id="svg1" onclick='play()' >
<use xlink:href="#drone" viewBox="-3 -3 60 20" width="100px" height="100px" transform="scale(4)"/>
<!-- Фон с ёлочкой -->
<image id="img1" mask="url(#msk2)" xlink:href="https://i.sstatic.net/PBRad.jpg" width="100%" height="100%" opacity="1" />
<!-- Звезда на ёлке -->
<path id="star_Full" fill="#E4F6A3" filter="url(#glow)" opacity="0" d="M580.2 76.2 837.2 71.3 774.7 5.7 845.1 62.7 850.1 8c0 0 6.8 54.2 6 54.7-4.3 2.8 70.9-57.5 70.9-57.5L862.8 71.2 1131.2 76.2 864.4 81.8 982.3 203C960.8 189.7 856.8 91.3 856.7 91.2L849.8 194.2 845.7 91.1 714.3 203.7 832.8 82.5Z">
<!-- Анимация opacity звезды -->
<animate
id="an_star"
attributeName="opacity"
dur="2.5s"
begin="svg1.click+25s;pause_star.end"
values="1;1;0"
fill="freeze"
repeatCount="5" />
<!-- Пауза анимация opacity звезды -->
<animate
id="pause_star"
attributeName="opacity"
dur="1.5s"
begin="an_star.end"
values="0;0"
fill="freeze"
repeatCount="1" />
<!-- Замена цвета у звезды -->
<animate
id="fill_change_star"
attributeName="fill"
dur="11s"
begin="svg1.click;pause_star.end"
values="#CDE7FB;red;#B34EE9;#15C14E"
fill="freeze"
repeatCount="1" />
</path>
<image id="Princess" xlink:href="https://i.sstatic.net/u50yb.jpg" width="100%" height="100%" mask="url(#msk1)" >
</image>
<!-- Анимация снеговика -->
<image id="Snowman" x="1700" y="1400" transform="scale(0.5)" xlink:href="https://i.sstatic.net/mbefD.png" opacity="0" >
<!-- Снеговик появляется -->
<animate
id="Snowman_Vis"
attributeName="opacity"
begin="svg1.click+22s;Snowman_Pause.end"
dur="1.5s"
values="0;1"
repeatCount="1"
fill="freeze" />
<!-- Анимация движения снеговика -->
<animate
id="Snowman_TR"
attributeName="x"
values="1700;2000;1700;2000;1700"
dur="22s"
begin="Snowman_Vis.end"
keyTimes="0;0.2;0.6;0.75;1"
repeatCount="5" />
<animate
id="Snowman_Hide"
attributeName="opacity"
begin="Snowman_TR.end+0.5s"
dur="1s"
values="1;0"
repeatCount="1"
fill="freeze" />
<animate
id="Snowman_Pause"
attributeName="opacity"
begin="Snowman_Hide.end+0.5s"
dur="10s"
values="0;0"
repeatCount="1"
fill="freeze" />
</image>
<!-- Заяц -->
<image id="zayka" x="300" y="750" xlink:href="https://i.sstatic.net/jtM0Q2iF.png" opacity="0">
<!-- Анимация появления зайца -->
<animate id="op1_zayka" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click+17s" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Перемещение зайки по горизонтали -->
<animate id="Go_zayka" attributeName="x" values="300;375;450;525;600;600;675;750;825;900;1025;1100" dur="6s" begin="op1_zayka.end" repeatCount="10" fill="freeze" restart="whenNotActive" />
<!-- Перемещение по вертикали -->
<animate id="Go_zayka_y" attributeName="y" values="750;800;750;800;750;800;750;800;750;800;750;800;" dur="6s" begin="op1_zayka.end" repeatCount="10" fill="freeze" restart="whenNotActive" />
</image>
<!-- Дед мороз -->
<image id="Ded_Moroz" x="100" y="700" xlink:href="https://i.sstatic.net/TYaVo.png" width="30%" height="30%" opacity="0">
<!-- Анимация появления Деда -->
<animate id="op1" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click+7s" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация движения Деда -->
<animate id="Go" attributeName="x" values="100;600;600;100;100" dur="12s" begin="op1.end" repeatCount="10" fill="freeze" restart="whenNotActive" />
</image>
<!-- Снегурочка -->
<image id="Girl" x="1150" y="725" xlink:href="https://i.sstatic.net/RDght.png" width="30%" height="30%" opacity="0">
<!-- Анимация появления Снегурочки -->
<animate id="op1_Girl" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click+7s" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация движения снегурочки -->
<animate id="GO_girl" attributeName="x" values="1150;700;700;1150;1150" dur="12s" begin="op1_Girl.end" repeatCount="10" fill="freeze" />
</image>
</g>
<text id="text1" x="220" y="200" fill="#B34EE9" stroke="white"
font-size="120" filter="url(#shadow)" opacity="0"> С Новым 2025 годом!
<!-- Анимация появления текста -->
<animate id="op1_text" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click+12s" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация текста -->
<animate id="GoY_text" attributeName="y" values="120;400;400;120;120" dur="12s" begin="op1_text.end" repeatCount="10" fill="freeze" restart="whenNotActive" />
</text>
<use viewBox="-3 -3 60 20" width="30vw" height="30vh" xlink:href="#drone" />
</svg>
<script>
var zodiac = new Audio();
zodiac.src = 'https://svg-art.ru/files/via-verasy-belyjj-sneg.mp3';
function play() {
zodiac.play();
}
</script>
</div>
#Вариант выполнения предыдущего сценария.
Значительно переработана сцена танца Деда Мороза и Снегурочки.
Пытался придать движениям разнообразия и может быть, где-то реалистичности. Взаимодействия многочисленных анимаций CSS и SVG довольна сложная штука (они не любят работать вместе).
Много интересных идей осталось за бортом. Надеюсь их воплотить позже.
Update 27.01.2025
- Доработан дрон: фонари, кабина, свечение
- Доработано мерцание звезд
- Изменена анимация "С Новым 2025 годом!"
- Доработан танец Деда Мороза и Снегурочки
let snowmax = 40,
snowcolor = new Array("#aaaacc", "#ddddff", "#ccccdd", "#f3f3f3", "#f0ffff"),
snowtype = new Array("Arial Black", "Arial Narrow", "Times", "Comic Sans MS"),
snowletter = "*",
sinkspeed = 0.5,
snowmaxsize = 30,
snowminsize = 8,
snow = new Array(),
marginbottom,
marginright,
timer,
i_snow = 0,
x_mv = new Array(),
crds = new Array(),
lftrght = new Array();
function randommaker(range) {
rand = Math.floor(range * Math.random());
return rand;
}
function initsnow() {
marginbottom = window.innerHeight;
marginright = window.innerWidth;
let snowsizerange = snowmaxsize - snowminsize;
for (i = 0; i <= snowmax; i++) {
crds[i] = 0;
lftrght[i] = Math.random() * 15;
x_mv[i] = 0.03 + Math.random() / 10;
snow[i] = document.getElementById("s" + i);
snow[i].style.fontFamily = snowtype[randommaker(snowtype.length)];
snow[i].size = randommaker(snowsizerange) + snowminsize;
snow[i].fontSize = snow[i].size;
snow[i].style.color = snowcolor[randommaker(snowcolor.length)];
snow[i].sink = sinkspeed * snow[i].size / 5;
snow[i].posx = randommaker(marginright - snow[i].size);
snow[i].posy = randommaker(
2 * marginbottom - marginbottom - 2 * snow[i].size
);
snow[i].style.left = snow[i].posx;
snow[i].style.top = snow[i].posy;
}
movesnow();
}
function movesnow() {
for (i = 0; i <= snowmax; i++) {
crds[i] += x_mv[i];
snow[i].posy += snow[i].sink;
snow[i].style.left = snow[i].posx + lftrght[i] * Math.sin(crds[i]) + "px";
snow[i].style.top = snow[i].posy + "px";
if (
snow[i].posy >= marginbottom - 2 * snow[i].size ||
parseInt(snow[i].style.left) > marginright - 3 * lftrght[i]
) {
snow[i].posx = randommaker(marginright - snow[i].size);
snow[i].posy = 0;
}
}
let timer = setTimeout("movesnow()", 50);
}
for (i = 0; i <= snowmax; i++) {
document.write(
"<span id='s" +
i +
"'style='position: absolute; top: -" +
snowmaxsize +
"'>" +
snowletter +
"</span>"
);
}
initsnow();
window.addEventListener('resize', ()=> initsnow())
.container{
width:80vw;
height:80vh;
}
.body {
fill: #170A41;
stroke:white;
stroke-width:0.5;
}
.wing {
fill: white;
transform-origin: center center;
transform-box: fill-box;
}
.wing {
animation: wing 5s linear forwards infinite;
}
@keyframes wing {
100% {
transform: rotateY(7200deg);
}
}
body {
perspective: 1000px;
}
#Girl {
transform-box:fill-box;
transform-origin: center center;
animation: rotate1 3s linear 12s 4, translate-back2 2s linear 34s forwards, translate-center 2s linear 44s forwards ;
}
@keyframes translate-back2 {
100% { transform: translate3d(500px, 60px, 10px);}
}
@keyframes translate-center {
100% { transform: translate3d(100px, 60px, 10px);}
}
@keyframes rotate1 {
0% {transform: rotate3d(0,1,0,0deg);}
15% {transform: rotate3d(0,1,0,90deg);}
50% {transform: rotate3d(0,1,0,-180deg);}
75% {transform: rotate3d(0,1,0,270deg);}
100% {transform: rotate3d(0,1,0,360deg);}
}
#Ded_Moroz {
transform-box:fill-box;
transform-origin: center center;
animation: skew1 3s linear 14s 4, translate-back1 2s linear 34s forwards ; ;
}
@keyframes skew1 {
0% {transform: skew(0deg, 0deg);}
25% {transform: rotate3d(0,1,0,20deg) skew(-3deg, 3deg);}
50% {transform: skew(5deg, 0deg);}
75% {transform: rotate3d(0,1,0,-20deg) skew(-3deg, 3deg);}
100% {transform: skew(0deg, 0deg);}
}
@keyframes translate-back1 {
100% { transform: translate3d(-450px, 60px, 10px);}
}
#D_G {
ransform-box:fill-box;
transform-origin: center center;
animation: translate1 12s linear 12s 2 ;
animation: rotate2 11s linear 10s 2;
}
@keyframes translate1 {
0% {transform: translate3d(0px, 0px, 10px);}
25% {transform: translate3d(400px, 50px, 10px);}
50% { translate3d(-200px, 50px, 10px);}
75% { translate3d(-200px, 50px, 50px);}
100% { translate3d(-200px, 10px, 10px);}
}
@keyframes rotate2 {
0% {transform: rotate3d(0,1,0,0deg) skew(-3deg, 3deg);}
15% {transform: rotate3d(0,1,0,90deg) skew(0deg, 3deg);}
50% {transform: rotate3d(0,1,0,-180deg) skew(-3deg, 0deg);}
75% {transform: rotate3d(0,1,0,270deg) skew(3deg, 3deg);}
100% {transform: rotate3d(0,1,0,360deg) skew(-3deg, 3deg);}
}
.star {
fill:cyan;
opacity:0;
animation:op_star 3.5s ease-out 15s infinite;
}
@keyframes op_star {
0%{opacity:0;}
50%{opacity:1;}
100%{opacity:0;}
}
.star1 {
fill:cyan;
opacity:0;
animation:op_star 2.5s 1.5s ease-out 20s infinite;
}
@keyframes op_star1 {
0%{opacity:0.2;}
50%{opacity:1;}
100%{opacity:0.2;}
}
<div class="container">
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 1680 1050" preserveAspectRatio="xMinYMin meet" >
<defs>
<!-- Маска для заставки -->
<mask id="msk1" x="0" y="0" width="400" height="400" >
<rect fill="white" x="0" y="0" width="100%" height="100%" />
<circle cx="800" cy="500" r="1" fill="black" stroke-width="70" stroke="yellow" >
<animate id="no_Princess" attributeName="r" begin="svg1.click" values="1;350;350;1200" dur="7s" restart="whenNotActive" fill="freeze" />
</circle>
</mask>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
<!-- Для дрона -->
<radialGradient id="Lg" fx="50%" fy="50%" >
<stop offset="5%" stop-color="yellow" />
<stop offset="100%" stop-color="green" />
</radialGradient>
<radialGradient id="Lg2" fx="50%" fy="50%" >
<stop offset="5%" stop-color="gold" />
<stop offset="100%" stop-color="red" >
</radialGradient>
<filter id="filter_Dron" color-interpolation-filters="linearRGB" filterUnits="objectBoundingBox" primitiveUnits="userSpaceOnUse">
<feGaussianBlur stdDeviation="3 3.5" x="0%" y="-3%" width="140%" height="140%" in="SourceGraphic" edgeMode="wrap" result="blur"/>
</filter>
<!-- Дрон -->
<g id="drone" >
<!-- Тень свечение дрона -->
<Circle cx="28" cy="12" r="12" fill="cyan" opacity="0.2" filter="url(#filter_Dron)" />
<g class="wing left">
<path d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/> </g>
<g class="wing right">
<path d="M48,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S48.6,2,48,2z"/>
<path d="M43,2c-0.6,0-8-0.4-8-1s7.4-1,8-1s1,0.4,1,1S43.6,2,43,2z"/>
</g>
<!-- Верхний фонарь -->
<ellipse opacity="0.2" cx="28" cy="2.5" rx="1.4" ry="2.4" fill="url(#Lg2)">
<animate id="op_dron3" attributeName="opacity" begin="op_dron1.end" dur="0.5s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
<g class="body">
<path d="M45,0.5C45,0.2,45.2,0,45.5,0S46,0.2,46,0.5V4c0.6,0,1,0.4,1,1v1h0.5C48.3,6,49,6.7,49,7.5S48.3,9,47.5,9H37v0.9
c0,0.7-0.4,1.4-1,1.7l-3.6,2.1c-0.3,0.2-0.7,0.3-1,0.3h-6.9c-0.4,0-0.7-0.1-1-0.3L20,11.6c-0.6-0.4-1-1-1-1.7V9H8.5
C7.7,9,7,8.3,7,7.5S7.7,6,8.5,6H9V5c0-0.6,0.4-1,1-1V0.5C10,0.2,10.2,0,10.5,0C10.8,0,11,0.2,11,0.5V4c0.6,0,1,0.4,1,1v1h7l0,0
c0.1-0.6,0.4-1.2,1-1.6l3.6-2.1c0.3-0.2,0.7-0.3,1-0.3h6.9c0.4,0,0.7,0.1,1,0.3L36,4.4C36.6,4.8,37,5.3,37,6l7,0V5
c0-0.6,0.4-1,1-1V0.5z"/>
<line x1="17" y1="6" x2="37" y2="6"/>
<line x1="28" y1="6" x2="28" y2="2"/>
</g>
<!-- Сигнальные фонари, камеры -->
<ellipse opacity="0.2" cx="25" cy="12" rx="1.4" ry="1.4" fill="url(#Lg)">
<animate id="op_dron1" attributeName="opacity" begin="0s;op_dron2.end" dur="1s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
<ellipse opacity="0.2" cx="31" cy="12" rx="1.4" ry="1.4" fill="url(#Lg)">
<animate id="op_dron2" attributeName="opacity" begin="op_dron1.end" dur="1s" values="0.1;1;1;0" repeatCount="1" restart="whenNotActive" />
</ellipse>
<animateTransform id="dron2" attributeName="transform" type="scale" begin="svg1.click+6s" dur="30s" values="1;3;2.5;1;2;2;2;3.0;3.5;2;1;1;1" repeatCount="indefinite" additive="sum" fill="freeze" restart="whenNotActive" />
<animateTransform id="dron2_tr" attributeName="transform" type="translate" begin="svg1.click+8s" dur="20s" values="10 10;100 100;200 200;620 100;400 400;600 50;10 10" additive="sum" repeatCount="indefinite" restart="whenNotActive" />
</g>
<radialGradient id="grad_bl" cx="20%" cy="20%" r="30%" fx="30%" fy="30%">
<stop stop-color="white" offset="20%"/>
<stop stop-color="#31BCE5" offset="90%"/>
</radialGradient>
</defs>
<use xlink:href="#drone" viewBox="-3 -3 60 20" width="100px" height="100px" transform="scale(4)"/>
<g id="svg1" onclick='play()' >
<!-- Фон с ёлочкой -->
<image id="img1" xlink:href="https://i.sstatic.net/PBRad.jpg" width="100%" height="100%" opacity="1" />
<!-- Девочка у замерзшего окна -->
<image id="Princess" xlink:href="https://i.sstatic.net/u50yb.jpg" width="100%" height="100%" mask="url(#msk1)" >
</image>
<!-- Размещение звезд -->
<g>
<path class="star" transform="translate(400 -100) scale(0.5)" d="m280 446c0 0-1 7-3 11-1 3-3 6-6 8-3 2-6 3-9 4-2 1-6 3-6 3 0 0 4 1 6 2 3 1 5 1 8 3 2 2 4 4 6 6 1 2 2 5 3 7 1 2 2 7 2 7 0 0 1-5 2-8 1-3 2-6 4-8 2-2 5-4 7-5 4-2 14-4 14-4 0 0-5-1-8-2-3-1-5-2-8-4-3-2-5-5-6-8-2-4-2-5-4-12zM166 315" />
<path class="star1" transform="translate(400 -100) scale(0.5)" d="m166 315c0 0-1 5-3 8-1 2-2 5-4 6-3 2-10 4-10 4 0 0 5 1 8 3 2 1 4 2 5 4 1 2 3 3 3 5 1 2 1 5 1 5 0 0 1-5 2-7 1-2 2-3 3-4 1-1 3-2 5-3 2-1 7-2 7-2 0 0-3-1-5-2-2-1-4-1-6-3-2-2-3-4-4-6-1-2-3-7-3-7z" />
<path class="star" transform="translate(400 -100) scale(0.5)" d="m1715 288c-2 5-3 9-5 12-2 4-5 7-8 10-3 2-7 3-11 4-3 1-8 2-8 2 0 0 6 1 9 2 4 1 8 2 11 5 3 2 6 6 8 9 3 5 5 15 5 15 0 0 2-11 5-15 2-3 5-6 8-8 3-2 7-3 11-5 2-1 7-2 7-2 0 0-5-2-8-3-3-1-6-1-9-3-3-2-6-5-8-8-3-4-3-9-6-14z" />
<path class="star1" transform="translate(400 -100) scale(1.5)" d="m1557 61c0 0-1 4-2 6-1 2-2 3-3 4-2 2-4 2-6 3-1 1-4 1-4 1 0 0 4 2 6 3 2 1 3 2 5 4 1 2 2 3 3 5 1 1 2 4 2 4 0 0 1-4 2-5 1-2 2-3 4-5 2-1 4-2 5-3 1-1 4-2 4-2 0 0-3-1-5-2-2-1-4-2-5-4-1-1-2-3-3-5-1-1-2-4-2-4z" />
<path class="star" transform="translate(100 0) scale(0.4)" d="m2380 375c0 0-2 7-3 10-1 4-3 7-5 10-2 3-6 4-9 6-3 2-10 3-10 3 0 0 6 2 9 3 4 2 8 3 11 6 3 3 4 8 6 12 1 3 2 8 2 8 0 0 2-6 3-9 1-3 3-7 5-10 2-3 5-5 9-6 4-2 12-4 12-4 0 0-6-2-8-3-2-1-5-2-7-3-2-1-4-3-6-6-2-2-2-5-3-7-1-3-4-10-4-10z" />
<path class="star" transform="translate(0 100) scale(0.5)" d="m2473 233c0 0-1 4-3 6-1 2-2 3-4 5-2 2-3 3-5 4-1 1-4 1-4 1 0 0 4 2 6 3 2 1 4 2 5 4 1 2 2 4 3 6 1 2 2 5 2 5 0 0 1-4 2-6 1-2 2-4 3-5 1-1 3-2 4-3 2-1 7-3 7-3 0 0-5-2-8-3-2-1-3-2-4-4-1-1-1-3-2-5 0-1-1-3-1-3z" />
<path class="star1" transform="translate(-200 0) scale(0.5)" d="m2269 59c0 0-2 1-3 2-2 1-3 3-5 4-2 1-5 1-7 1-2 0-6 0-6 0 0 0 3 3 5 5 1 2 2 3 2 5 1 3 0 5 0 8 0 1 0 3 0 3 0 0 4-3 6-5 1-1 3-2 4-2 2 0 4 0 6 0 2 0 6 1 6 1 0 0-3-3-4-4-1-2-3-3-4-6-1-2 0-4 0-6 0-2 1-5 1-5z" />
<path class="star" transform="translate(0 -100) scale(0.5)" d="m1477 596c0 0-1 3-2 5-1 2-2 4-3 5-2 2-5 3-8 5-1 1-4 1-4 1 0 0 4 1 5 1 2 1 4 2 6 3 2 2 3 4 4 7 1 2 2 5 2 5 0 0 1-4 2-6 1-2 2-3 4-5 1-1 3-2 5-3 2-1 5-2 5-2 0 0-3-2-5-3-2-1-3-2-5-3-2-2-3-4-4-6-1-1-2-4-2-4z" />
<path class="star1" transform="translate(25 200) scale(0.5)" d="m830 136c0 0-1 8-2 11-1 2-2 4-4 5-1 1-3 2-4 3-2 1-6 2-6 2 0 0 4 2 6 3 2 1 4 2 5 4 1 1 2 3 3 5 1 2 2 6 2 6 0 0 1-5 2-7 1-1 2-3 3-4 2-1 4-2 5-3 2-1 6-3 6-3 0 0-4-1-6-2-2-1-3-2-4-3-1-1-2-3-3-4-1-3-2-11-2-11" />
<path class="star" transform="translate(325 200) scale(0.5)" stroke="white" d="m280 446c0 0-1 7-3 11-1 3-3 6-6 8-3 2-6 3-9 4-2 1-6 3-6 3 0 0 4 1 6 2 3 1 5 1 8 3 2 2 4 4 6 6 1 2 2 5 3 7 1 2 2 7 2 7 0 0 1-5 2-8 1-3 2-6 4-8 2-2 5-4 7-5 4-2 14-4 14-4 0 0-5-1-8-2-3-1-5-2-8-4-3-2-5-5-6-8-2-4-2-5-4-12zM166 315" />
<path class="star1" transform="translate(925 100) scale(0.5)" stroke="white" d="m280 446c0 0-1 7-3 11-1 3-3 6-6 8-3 2-6 3-9 4-2 1-6 3-6 3 0 0 4 1 6 2 3 1 5 1 8 3 2 2 4 4 6 6 1 2 2 5 3 7 1 2 2 7 2 7 0 0 1-5 2-8 1-3 2-6 4-8 2-2 5-4 7-5 4-2 14-4 14-4 0 0-5-1-8-2-3-1-5-2-8-4-3-2-5-5-6-8-2-4-2-5-4-12zM166 315" />
</g>
<!-- Звезда на ёлке -->
<path id="star_Full" fill="#E4F6A3" filter="url(#glow)" opacity="0" d="M580.2 76.2 837.2 71.3 774.7 5.7 845.1 62.7 850.1 8c0 0 6.8 54.2 6 54.7-4.3 2.8 70.9-57.5 70.9-57.5L862.8 71.2 1131.2 76.2 864.4 81.8 982.3 203C960.8 189.7 856.8 91.3 856.7 91.2L849.8 194.2 845.7 91.1 714.3 203.7 832.8 82.5Z">
<!-- Анимация opacity звезды -->
<animate
id="an_star"
attributeName="opacity"
dur="2.5s"
begin="svg1.click+25s;pause_star.end"
values="1;1;0"
fill="freeze"
repeatCount="5" />
<!-- Пауза анимация opacity звезды -->
<animate
id="pause_star"
attributeName="opacity"
dur="1.5s"
begin="an_star.end"
values="1;0"
fill="freeze"
repeatCount="1" />
<!-- Замена цвета у звезды -->
<animate
id="fill_change_star"
attributeName="fill"
dur="11s"
begin="svg1.click;pause_star.end"
values="#CDE7FB;red;#B34EE9;#15C14E"
fill="freeze"
repeatCount="1" />
</path>
<!-- Анимация снеговика -->
<image id="Snowman" x="1700" y="1400" transform="scale(0.5)" xlink:href="https://i.sstatic.net/mbefD.png" opacity="0" >
<!-- Снеговик появляется -->
<animate
id="Snowman_Vis"
attributeName="opacity"
begin="svg1.click+22s;Snowman_Pause.end"
dur="1.5s"
values="0;1"
repeatCount="1"
fill="freeze" />
<!-- Анимация движения снеговика -->
<animate
id="Snowman_TR"
attributeName="x"
values="1700;2000;1700;2000;1700"
dur="22s"
begin="Snowman_Vis.end"
keyTimes="0;0.2;0.6;0.75;1"
repeatCount="5" />
<animate
id="Snowman_Hide"
attributeName="opacity"
begin="Snowman_TR.end+0.5s"
dur="1s"
values="1;0"
repeatCount="1"
fill="freeze" />
<animate
id="Snowman_Pause"
attributeName="opacity"
begin="Snowman_Hide.end+0.5s"
dur="10s"
values="0;0"
repeatCount="1"
fill="freeze" />
</image>
<!-- Заяц -->
<image id="zayka" x="300" y="750" xlink:href="https://i.sstatic.net/jtM0Q2iF.png" opacity="0">
<!-- Анимация появления зайца -->
<animate id="op1_zayka" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click+124s" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Перемещение зайки по горизонтали -->
<animate id="Go_zayka" attributeName="x" values="300;375;450;525;600;600;675;750;825;900;1025;1100" dur="6s" begin="op1_zayka.end" repeatCount="indefinity" fill="freeze" restart="whenNotActive" />
<!-- Перемещение по вертикали -->
<animate id="Go_zayka_y" attributeName="y" values="750;800;750;800;750;800;750;800;750;800;750;800;" dur="6s" begin="op1_zayka.end" repeatCount="indefinity" fill="freeze" restart="whenNotActive" />
</image>
<g id="D_G">
<!-- Дед мороз -->
<image id="Ded_Moroz" x="100" y="700" xlink:href="https://i.sstatic.net/TYaVo.png" width="30%" height="30%" opacity="0">
<!-- Анимация появления Деда -->
<animate id="op1" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click+7s" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация движения Деда -->
<animate id="Go" attributeName="x" values="100;600;600" dur="6s" begin="op1.end" repeatCount="1" fill="freeze" restart="whenNotActive" />
</image>
<!-- Снегурочка -->
<image id="Girl" x="1150" y="725" xlink:href="https://i.sstatic.net/RDght.png" width="30%" height="30%" opacity="0">
<!-- Анимация появления Снегурочки -->
<animate id="op1_Girl" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click+7s" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация движения снегурочки -->
<animate id="GO_girl" attributeName="x" values="1150;700;700" dur="6s" begin="op1_Girl.end" repeatCount="1" fill="freeze" />
</image>
</g>
<text id="text1" x="220" y="200" fill="#B34EE9" stroke="white"
font-size="120" filter="url(#shadow)" opacity="0"> С Новым 2025 годом!
<!-- Анимация появления текста -->
<animate id="op1_text" attributeName="opacity" values="0; 1" dur="2s" begin="svg1.click+12s" repeatCount="1" fill="freeze" restart="whenNotActive" />
<!-- Анимация текста -->
<animate id="GoY_text" attributeName="y" values="200;400;400;200;200" dur="10s" begin="op1_text.end" repeatCount="2" fill="freeze" restart="whenNotActive" />
<animate id="GoX_text" attributeName="x" values="220;800;800;1700" dur="4s" begin="GoY_text.end" repeatCount="1" fill="freeze" restart="whenNotActive" />
</text>
<use viewBox="-3 -3 60 20" width="30vw" height="30vh" xlink:href="#drone" />
</svg>
<script>
var zodiac = new Audio();
zodiac.src = 'https://svg-art.ru/files/via-verasy-belyjj-sneg.mp3';
function play() {
zodiac.play();
}
</script>
</div>