1PROMTAI.RU

Мои промты для генерации изображений, музыки и т.д

Статьи

Теги

Вход

Новые записи

Общение

Архивы

Рубрики

С наступающим 2027годом

Скрипт создаёт новогоднюю анимацию в верхней части сайта. Он рисует широкую полосу, которая накрывает страницу сверху и не мешает с ней работать — по ней нельзя кликнуть, и она не перекрывает кнопки или ссылки.

Эта полоса выглядит как ночное небо: сверху оно тёмное и плотное, а ближе к низу становится всё прозрачнее, так что сквозь него спокойно просматривается содержимое сайта. По небу мерцают звёзды — одни горят ярче, другие тише, и это создаёт ощущение живого ночного неба. Между звёздами медленно падает снег: снежинки опускаются вниз, слегка покачиваясь из стороны в сторону, а когда долетают до края, снова появляются наверху, чтобы падать заново.

По этому небу летит упряжка Деда Мороза. Впереди бегут олени — их ноги двигаются, как будто они действительно скачут по воздуху. Позади оленей едет сам Дед Мороз в санях. Сани украшены мигающей гирляндой, которая переливается разными цветами. От рук Деда Мороза к оленям тянутся поводья, и они тоже слегка колышутся в такт движению. Вся упряжка плавно покачивается вверх-вниз, как будто летит по волнам.

Внизу, поверх всей этой картины, постепенно проявляется праздничная надпись с поздравлением — сначала она едва заметна, потом становится всё ярче, пока не загорится полностью золотисто-белым сиянием. Вся анимация длится недолго, а потом исчезает сама: полоса убирается со страницы, и сайт остаётся таким, каким был до неё.

Внутри скрипт устроен так. Сначала он создаёт холст — специальную область, на которой можно рисовать. Этот холст прикрепляется к самому верху страницы и растягивается во всю ширину. Он настроен так, чтобы не перехватывать нажатия мыши и не мешать посетителю пользоваться сайтом. Дальше скрипт каждый кадр заново рисует всю картину: сначала фон, потом звёзды, потом снег, потом упряжку, потом надпись.

Делается это очень часто — много раз в секунду, — чтобы движение выглядело плавным. Упряжка движется слева направо, постепенно пересекая весь экран: сначала появляется у левого края, потом пролетает через середину и уходит за правый край. Когда проходит заданное время, скрипт убирает холст со страницы, и от анимации не остаётся следа. Всё сделано так, чтобы работало легко: объектов на экране немного, фигуры простые, а на телефонах и планшетах картинка автоматически становится меньше, чтобы ничего не тормозило.

Скрипт также защищён от повторного запуска — если его случайно подключить дважды, второй раз он уже не сработает и не будет рисовать две упряжки одновременно.



(function() {
  'use strict';
  if (window.__santaRunning) return;
  window.__santaRunning = true;

  function init() {
    var canvas = document.createElement('canvas');

    var W = window.innerWidth;
    var H = 200;
    var isMobile = W < 700;
    var S = isMobile ? 0.5 : 0.7;

    canvas.width = W;
    canvas.height = H;
    canvas.style.cssText = [
      'position:fixed',
      'top:0',
      'left:0',
      'width:100%',
      'height:200px',
      'pointer-events:none',
      'z-index:9998',
      'display:block'
    ].join(';');
    canvas.setAttribute('aria-hidden', 'true');
    document.body.appendChild(canvas);

    var ctx = canvas.getContext('2d');
    var dpr = Math.min(1.5, window.devicePixelRatio || 1);
    canvas.width = W * dpr;
    canvas.height = H * dpr;
    ctx.scale(dpr, dpr);

    var start = performance.now();
    var TOTAL = 12000;

    // ---------- Звёзды ----------
    var stars = [];
    var starCount = isMobile ? 20 : 35;
    for (var i = 0; i < starCount; i++) {
      stars.push({
        x: Math.random() * W,
        y: Math.random() * H * 0.6,
        r: Math.random() * 1.1 + 0.3,
        phase: Math.random() * Math.PI * 2
      });
    }

    // ---------- Снежинки ----------
    var snowflakes = [];
    var snowCount = isMobile ? 30 : 50;
    for (var j = 0; j < snowCount; j++) {
      snowflakes.push({
        x: Math.random() * W,
        y: Math.random() * H,
        r: Math.random() * 1.6 + 0.6,
        vy: 0.5 + Math.random() * 0.9,
        vx: (Math.random() - 0.5) * 0.4,
        phase: Math.random() * Math.PI * 2
      });
    }

    function drawSky() {
      var sky = ctx.createLinearGradient(0, 0, 0, H);
      sky.addColorStop(0.0, 'rgba(5, 11, 31, 0.85)');
      sky.addColorStop(0.5, 'rgba(13, 26, 61, 0.55)');
      sky.addColorStop(1.0, 'rgba(28, 47, 94, 0.15)');
      ctx.fillStyle = sky;
      ctx.fillRect(0, 0, W, H);
    }

    function drawStars(now) {
      ctx.fillStyle = '#fff';
      for (var i = 0; i < stars.length; i++) {
        var s = stars[i];
        var depth = 1 - s.y / (H * 0.6);
        ctx.globalAlpha = (0.25 + 0.6 * Math.abs(Math.sin(now / 1000 + s.phase))) * (0.4 + 0.6 * depth);
        ctx.beginPath();
        ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
        ctx.fill();
      }
      ctx.globalAlpha = 1;
    }

    function drawSnow(now) {
      ctx.fillStyle = '#fff';
      for (var i = 0; i < snowflakes.length; i++) { var f = snowflakes[i]; f.y += f.vy; f.x += f.vx + Math.sin(now / 900 + f.phase) * 0.3; if (f.y > H + 4) { f.y = -4; f.x = Math.random() * W; }
        if (f.x < -4) f.x = W + 4; if (f.x > W + 4) f.x = -4;
        ctx.globalAlpha = 0.5 + 0.4 * (1 - f.y / H);
        ctx.beginPath();
        ctx.arc(f.x, f.y, f.r, 0, Math.PI * 2);
        ctx.fill();
      }
      ctx.globalAlpha = 1;
    }

    // ---------- Олень (смотрит вправо, бежит вправо) ----------
    function drawDeer(x, y, scale, legPhase) {
      ctx.save();
      ctx.translate(x, y);
      ctx.scale(scale, scale);

      var legSwing = Math.sin(legPhase) * 6;

      // Ноги
      ctx.strokeStyle = '#5a3a1e';
      ctx.lineWidth = 4;
      ctx.lineCap = 'round';
      ctx.beginPath();
      ctx.moveTo(-14, 6); ctx.lineTo(-18 + legSwing, 30);
      ctx.moveTo(-6, 8);  ctx.lineTo(-4 - legSwing, 30);
      ctx.moveTo(12, 8);  ctx.lineTo(16 + legSwing, 30);
      ctx.moveTo(20, 6);  ctx.lineTo(24 - legSwing, 30);
      ctx.stroke();

      // Тело
      ctx.beginPath();
      ctx.fillStyle = '#8b5a2b';
      ctx.ellipse(0, 0, 28, 13, 0, 0, Math.PI * 2);
      ctx.fill();

      // Шея
      ctx.beginPath();
      ctx.moveTo(20, -6);
      ctx.quadraticCurveTo(34, -14, 38, -22);
      ctx.lineTo(46, -18);
      ctx.quadraticCurveTo(38, -6, 26, 4);
      ctx.closePath();
      ctx.fill();

      // Голова
      ctx.beginPath();
      ctx.fillStyle = '#9c6633';
      ctx.ellipse(46, -24, 11, 8, -0.35, 0, Math.PI * 2);
      ctx.fill();

      // Морда
      ctx.beginPath();
      ctx.fillStyle = '#7a4f26';
      ctx.ellipse(55, -26, 6, 4.5, -0.25, 0, Math.PI * 2);
      ctx.fill();

      // Нос
      ctx.beginPath();
      ctx.fillStyle = '#3a2412';
      ctx.arc(59, -27, 2, 0, Math.PI * 2);
      ctx.fill();

      // Глаз
      ctx.beginPath();
      ctx.fillStyle = '#1b1008';
      ctx.arc(49, -26, 1.6, 0, Math.PI * 2);
      ctx.fill();

      // Рога
      ctx.strokeStyle = '#d9c9a3';
      ctx.lineWidth = 2.2;
      ctx.lineCap = 'round';
      ctx.beginPath();
      ctx.moveTo(43, -31);
      ctx.bezierCurveTo(38, -46, 30, -50, 24, -44);
      ctx.moveTo(47, -31);
      ctx.bezierCurveTo(52, -46, 60, -50, 66, -44);
      ctx.moveTo(30, -47); ctx.lineTo(26, -54);
      ctx.moveTo(60, -47); ctx.lineTo(64, -54);
      ctx.stroke();

      // Уздечка
      ctx.strokeStyle = '#c9a44c';
      ctx.lineWidth = 1.4;
      ctx.beginPath();
      ctx.moveTo(52, -28);
      ctx.quadraticCurveTo(50, -20, 44, -16);
      ctx.stroke();

      // Хомут
      ctx.strokeStyle = '#a67c2e';
      ctx.lineWidth = 2.6;
      ctx.beginPath();
      ctx.moveTo(24, -12);
      ctx.quadraticCurveTo(30, -18, 34, -10);
      ctx.stroke();

      ctx.restore();
    }

    // ---------- Сани ----------
    function drawSleigh(x, y, scale, now) {
      ctx.save();
      ctx.translate(x, y);
      ctx.scale(scale, scale);

      ctx.strokeStyle = '#c0c8d0';
      ctx.lineWidth = 3;
      ctx.lineCap = 'round';
      ctx.beginPath();
      ctx.moveTo(-6, 22);
      ctx.quadraticCurveTo(-18, 22, -22, 10);
      ctx.moveTo(-2, 22);
      ctx.lineTo(58, 22);
      ctx.quadraticCurveTo(70, 22, 74, 10);
      ctx.stroke();

      ctx.beginPath();
      ctx.fillStyle = '#b22222';
      ctx.moveTo(0, 6);
      ctx.quadraticCurveTo(28, -8, 58, 6);
      ctx.lineTo(52, 20);
      ctx.quadraticCurveTo(28, 26, 4, 20);
      ctx.closePath();
      ctx.fill();

      ctx.beginPath();
      ctx.fillStyle = '#8b1a1a';
      ctx.moveTo(52, 6);
      ctx.quadraticCurveTo(66, -14, 60, -26);
      ctx.quadraticCurveTo(50, -20, 46, -2);
      ctx.closePath();
      ctx.fill();

      ctx.beginPath();
      ctx.fillStyle = '#8b5a2b';
      ctx.ellipse(34, -4, 12, 10, 0, 0, Math.PI * 2);
      ctx.fill();

      // Гирлянда
      for (var i = 0; i < 8; i++) {
        var p = i / 7;
        var lx = 2 + p * 54;
        var ly = 18 + Math.sin(p * Math.PI) * -4;
        var hue = (i * 45 + now / 15) % 360;
        var alpha = 0.5 + 0.5 * Math.abs(Math.sin(now / 260 + i));
        ctx.beginPath();
        ctx.fillStyle = 'hsla(' + hue + ', 100%, 65%, ' + alpha.toFixed(2) + ')';
        ctx.arc(lx, ly, 1.7, 0, Math.PI * 2);
        ctx.fill();
      }

      ctx.restore();
    }

    // ---------- Дед Мороз ----------
    function drawSanta(x, y, scale, wave) {
      ctx.save();
      ctx.translate(x, y);
      ctx.scale(scale, scale);

      ctx.beginPath();
      ctx.fillStyle = '#d62828';
      ctx.moveTo(-14, -8);
      ctx.quadraticCurveTo(2, -18, 18, -8);
      ctx.lineTo(14, 26);
      ctx.quadraticCurveTo(2, 32, -10, 26);
      ctx.closePath();
      ctx.fill();

      ctx.beginPath();
      ctx.fillStyle = '#fff';
      ctx.moveTo(-10, 24);
      ctx.quadraticCurveTo(2, 32, 14, 24);
      ctx.quadraticCurveTo(4, 30, -10, 24);
      ctx.fill();

      var swing = Math.sin(wave) * 2;
      ctx.beginPath();
      ctx.fillStyle = '#1d3557';
      ctx.arc(-6, swing, 4.5, 0, Math.PI * 2);
      ctx.arc(22, -4 - swing, 4.5, 0, Math.PI * 2);
      ctx.fill();

      ctx.beginPath();
      ctx.fillStyle = '#fff';
      ctx.moveTo(-10, -18);
      ctx.quadraticCurveTo(2, 10, 14, -18);
      ctx.quadraticCurveTo(2, -8, -10, -18);
      ctx.fill();

      ctx.beginPath();
      ctx.fillStyle = '#f7c9a3';
      ctx.ellipse(2, -26, 10, 9, 0, 0, Math.PI * 2);
      ctx.fill();

      ctx.fillStyle = '#1b1008';
      ctx.beginPath();
      ctx.arc(-2, -28, 1.4, 0, Math.PI * 2);
      ctx.arc(6, -28, 1.4, 0, Math.PI * 2);
      ctx.fill();

      ctx.beginPath();
      ctx.fillStyle = '#e07a5f';
      ctx.arc(2, -24, 2, 0, Math.PI * 2);
      ctx.fill();

      ctx.beginPath();
      ctx.fillStyle = '#d62828';
      ctx.moveTo(-8, -34);
      ctx.quadraticCurveTo(2, -50, 12, -34);
      ctx.closePath();
      ctx.fill();

      ctx.beginPath();
      ctx.fillStyle = '#fff';
      ctx.ellipse(2, -34, 11, 3.5, 0, 0, Math.PI * 2);
      ctx.fill();

      ctx.beginPath();
      ctx.arc(2, -48, 4, 0, Math.PI * 2);
      ctx.fill();

      ctx.restore();
    }

    // ---------- Поводья: от Деда Мороза (слева) к оленям (справа) ----------
    function drawReins(santaX, santaY, d1x, d1y, d2x, d2y, wave) {
      var swing = Math.sin(wave) * 2;
      ctx.strokeStyle = '#c9a44c';
      ctx.lineWidth = 1.5;

      // От правой руки Деда Мороза к первому оленю
      ctx.beginPath();
      ctx.moveTo(santaX + 22, santaY - 4 - swing);
      ctx.quadraticCurveTo(
        (santaX + d1x) / 2,
        santaY + 14 + Math.sin(wave / 2) * 2,
        d1x - 26, d1y - 12
      );
      ctx.stroke();

      // От первого оленя ко второму
      ctx.beginPath();
      ctx.moveTo(d1x + 24, d1y - 10);
      ctx.quadraticCurveTo(
        (d1x + d2x) / 2,
        d1y + 10 + Math.sin(wave / 2 + 0.6) * 2,
        d2x - 26, d2y - 12
      );
      ctx.stroke();
    }

    // ---------- Надпись ----------
    function drawText(progress) {
      var alpha = Math.min(1, Math.max(0, (progress - 0.05) / 0.15));
      if (alpha <= 0) return; var fontSize = Math.max(18, Math.min(34, W / 22)); var cx = W / 2; var cy = H * 0.82; ctx.save(); ctx.globalAlpha = alpha; ctx.font = 'bold ' + fontSize + 'px "Segoe UI", Arial, sans-serif'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.lineWidth = 5; ctx.strokeStyle = 'rgba(0,0,0,0.65)'; ctx.strokeText('С Новым 2027 годом!', cx, cy); var grad = ctx.createLinearGradient(cx - 200, 0, cx + 200, 0); grad.addColorStop(0, '#fff2b0'); grad.addColorStop(0.5, '#ffffff'); grad.addColorStop(1, '#ffd166'); ctx.fillStyle = grad; ctx.fillText('С Новым 2027 годом!', cx, cy); ctx.restore(); } function animate(now) { var t = now - start; if (t > TOTAL) {
        if (canvas.parentNode) canvas.parentNode.removeChild(canvas);
        window.__santaRunning = false;
        return;
      }

      var progress = t / TOTAL;

      ctx.clearRect(0, 0, W, H);
      drawSky();
      drawStars(now);

      var gs = 0.55 * S;

      // Едем слева направо. Начинаем за левым краем и уезжаем за правый.
      var travel = -500 * S + (W + 1000 * S) * progress;
      var flyY = H * 0.40 + Math.sin(t / 700) * (10 * S);

      // Сани и Дед Мороз — ПОЗАДИ (слева)
      var santaX  = travel;
      var santaY  = flyY;
      var sleighX = santaX - 10 * S;
      var sleighY = santaY + 14 * S;

      // Олени — ВПЕРЕДИ (справа), везут сани
      var deer1X = santaX + 110 * S;
      var deer1Y = santaY + 18 * S + Math.sin(t / 250) * 2;
      var deer2X = deer1X + 100 * S;
      var deer2Y = santaY + 22 * S + Math.sin(t / 250 + 1.2) * 2;

      var legPhase = t / 80;

      // Порядок отрисовки: дальние → ближние
      // 1) Дальний олень (второй, самый правый, впереди всех)
      drawDeer(deer2X, deer2Y, gs * 0.95, legPhase + 1.1);

      // 2) Ближний олень (первый)
      drawDeer(deer1X, deer1Y, gs, legPhase);

      // 3) Поводья от Деда Мороза к оленям
      drawReins(santaX, santaY, deer1X, deer1Y, deer2X, deer2Y, t / 120);

      // 4) Сани
      drawSleigh(sleighX, sleighY, gs, now);

      // 5) Дед Мороз поверх саней — он сидит в них
      drawSanta(santaX, santaY, gs, t / 120);

      drawText(progress);
      drawSnow(now);

      requestAnimationFrame(animate);
    }

    requestAnimationFrame(animate);

    var resizeTimer;
    window.addEventListener('resize', function() {
      clearTimeout(resizeTimer);
      resizeTimer = setTimeout(function() {
        if (canvas.parentNode) canvas.parentNode.removeChild(canvas);
        window.__santaRunning = false;
        init();
      }, 300);
    });
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})();


Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

🧮 Проверка безопасности
11 + 19 = ?

В Шедевруме


Смотреть все мои промты и картинки

Календарь

Сентябрь 2026
Пн Вт Ср Чт Пт Сб Вс
 123456
78910111213
14151617181920
21222324252627
282930  

Новые комментарии

Контакты