Skip to content

Commit

Permalink
Добавляет снег 2025 (#1317)
Browse files Browse the repository at this point in the history
  • Loading branch information
solarrust authored Dec 25, 2024
1 parent 0ee87fb commit 87c7cd3
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/includes/blocks/footer.njk
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<legend class="visually-hidden">Тема:</legend>
<span class="footer__theme-toggle-label" aria-hidden="true">Тема:</span>
{% include "blocks/theme-toggle.njk" %}
{% include "blocks/snow-toggle.njk" %}
</fieldset>
<div class="footer__lists">
<ul class="footer__list footer-list footer__list_social font-theme font-theme--code base-list">
Expand Down
1 change: 1 addition & 0 deletions src/includes/blocks/snow-25.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<canvas id="snowCanvas"></canvas>
1 change: 1 addition & 0 deletions src/layouts/base.njk
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
{{ content | safe }}

{% include "blocks/cookie-notification.njk" %}
{% include "blocks/snow-25.njk" %}

<script src="/scripts/index.js" {% if env.isDevEnv %}type="module"{% endif %}></script>
</body>
Expand Down
1 change: 1 addition & 0 deletions src/scripts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ import './modules/person-badges-tooltip.js'
import './modules/answer.js'
import './modules/pwa.js'
import './modules/triggers.js'
import './modules/snow-toggle-25.js'
138 changes: 138 additions & 0 deletions src/scripts/modules/snow-toggle-25.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
window.onload = function () {
class Snowfall {
constructor(canvas) {
this.canvas = canvas
this.context = canvas.getContext('2d')
this.snowCounter = 0
this.speedMultiplier = 0
this.snowflakes = []
this.animationFrameId = null

this.resize()
}

createSnowflake() {
const radius = getRandomInt(1, 10)
return {
xpos: getRandomInt(0, this.canvas.width),
ypos: getRandomInt(-this.canvas.height, 0),
radius: radius,
opacity: radius * 10,
speed: this.speedMultiplier * (radius / 6),
dx: (Math.random() - 0.5) * 2,
}
}

drawSnowflake(flake) {
this.context.beginPath()
this.context.arc(flake.xpos, flake.ypos, flake.radius, 0, Math.PI * 2)
this.context.fillStyle = `hsl(202.33deg 53.09% 84.12% / ${flake.opacity}%)`
this.context.fill()
}

updateSnowflake(flake) {
flake.xpos += flake.dx
flake.ypos += flake.speed

if (flake.ypos - flake.radius > this.canvas.height) {
flake.ypos = getRandomInt(-this.canvas.height, 0)
flake.xpos = getRandomInt(0, this.canvas.width)
}
}

start() {
this.snowCounter = 100
this.speedMultiplier = 1

this.stop()
this.snowflakes = Array.from({ length: this.snowCounter }, () => this.createSnowflake())
this.animate()
}

animate() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
this.snowflakes.forEach((flake) => {
this.updateSnowflake(flake)
this.drawSnowflake(flake)
})
this.animationFrameId = requestAnimationFrame(this.animate.bind(this))
}

stop() {
if (this.animationFrameId) {
cancelAnimationFrame(this.animationFrameId)
this.animationFrameId = null
}

snowfall.snowflakes = []
snowfall.context.clearRect(0, 0, canvas.width, canvas.height)
}

setCounter(newCount) {
this.snowCounter = newCount
this.snowflakes = Array.from({ length: this.snowCounter }, () => this.createSnowflake())
}

resize() {
this.canvas.width = window.innerWidth
this.canvas.height = window.innerHeight
}
}

function debounce(func, wait) {
let timeout
return function (...args) {
clearTimeout(timeout)
timeout = setTimeout(() => func.apply(this, args), wait)
}
}

function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}

function changeSnowAnimation(animationName) {
if (animationName === 'none') {
snowfall.stop()
document.title = pageTitle
} else if (animationName === 'snowfall') {
snowfall.start()
document.title = '❄️ ' + pageTitle
}
}

const canvas = document.getElementById('snowCanvas')
const snowToggle = document.querySelector('.snow-toggle')
const snowfall = new Snowfall(canvas)
const pageTitle = document.title
snowfall.start()
document.title = '❄️ ' + pageTitle
const storageKey = 'snow'

let currentStorage = localStorage.getItem(storageKey)

if (currentStorage) {
snowToggle.querySelector(`.snow-toggle__control[value='${currentStorage}']`).checked = true

changeSnowAnimation(currentStorage)
}

window.addEventListener('storage', () => {
changeSnowAnimation(localStorage.getItem(storageKey))
})

document.querySelectorAll('input[name="snow"]').forEach((radio) => {
radio.addEventListener('change', (event) => {
const value = event.target.value
localStorage.setItem(storageKey, event.target.value)
changeSnowAnimation(value)
})
})

window.addEventListener(
'resize',
debounce(() => {
snowfall.resize()
}, 150),
)
}
8 changes: 8 additions & 0 deletions src/styles/blocks/snow-25.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* stylelint-disable-next-line selector-id-pattern */
#snowCanvas {
position: fixed;
inset: 0;
z-index: 100;
display: block;
pointer-events: none;
}
2 changes: 1 addition & 1 deletion src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
@import url("blocks/footer.css");
@import url("blocks/theme-toggle.css");
@import url("blocks/snow-toggle.css");
@import url("blocks/snow.css");
@import url("blocks/snow-25.css");
@import url("blocks/intro.css");
@import url("blocks/featured-article.css");
@import url("blocks/featured-articles-list.css");
Expand Down

0 comments on commit 87c7cd3

Please sign in to comment.