Создайте титры как в звездных войнах с помощью CSS и Javascript

RedDeveloper
26.01.2023 13:19
Создайте титры как в звездных войнах с помощью CSS и Javascript

Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего следующего сайта послужил начальный эпизод "Звездных войн"? 😁

Ответ, конечно же, YAAAAAS! Читать дальше....

Я пробовал много итераций этого (потому что я действительно очень хотел этого). Сначала я попробовал использовать стоковое видео о путешествии через космос, но размер файла был слишком большим, и Google Lighthouse жаловался. Я попробовал сжать видео в формат webm, но он работает только на некоторых устройствах (не на iOS) и выглядит ужасно и пиксельно.

После нескольких часов игры я решил использовать элемент HTML5 canvas и JavaScript для визуализации звезд и ключевые кадры CSS для визуализации 3D-ползущего текста. Что касается шрифта, я скачал имитацию шрифта из "Звездных войн" под названием "Deathstar". Вы можете найти его здесь .

Посмотрите этот рабочий пример .

А теперь о коде:

// stars.js

// Get canvas element by its ID
var field = document.getElementById("field");

// Make sure field canvas exists
var f = (typeof field.getContext === 'function') ? field.getContext("2d") : null;

// Config
var stars = {};
var starIndex = 0;
var numStars = 0;
var acceleration = 1;
var starsToDraw = (field.width * field.height) / 200;

function Star() {
    this.X = field.width / 2;
    this.Y = field.height / 2;

    this.SX = Math.random() * 10 - 5;
    this.SY = Math.random() * 10 - 5;

    var start = 0;

    if (field.width > field.height)
        start = field.width;
    else
        start = field.height;

    this.X += this.SX * start / 10;
    this.Y += this.SY * start / 10;

    this.W = 1;
    this.H = 1;

    this.age = 0;
    this.dies = 500;

    starIndex++;
    stars[starIndex] = this;

    this.ID = starIndex;
    this.C="#ffffff";
}

Star.prototype.Draw = function () {
    if (!f) {
        console.info('Could not load canvas element');
        return;
    }
    this.X += this.SX;
    this.Y += this.SY

    this.SX += this.SX / (50 / acceleration);
    this.SY += this.SY / (50 / acceleration);

    this.age++;

    if (this.age == Math.floor(50 / acceleration) | this.age == Math.floor(150 / acceleration) | this.age == Math.floor(300 / acceleration)) {
        this.W++;
        this.H++;
    }

    if (this.X + this.W < 0 | this.X > field.width |
        this.Y + this.H < 0 | this.Y > field.height) {
        delete stars[this.ID];
        numStars--;
    }

    f.fillStyle = this.C;
    f.fillRect(this.X, this.Y, this.W, this.H);
}

field.width = window.innerWidth;
field.height = window.innerHeight;

function draw() {
    if (!f) {
        console.info('Could not load canvas element');
        return;
    }

    if (field.width != window.innerWidth)
        field.width = window.innerWidth;
    if (field.height != window.innerHeight)
        field.height = window.innerHeight;

    // The alpha value can be adjusted to create a stream effect
    f.fillStyle="rgba(0, 0, 0, 0.6)";

    f.fillRect(0, 0, field.width, field.height);

    for (var i = numStars; i < starsToDraw; i++) {
        new Star();
        numStars++;
    }

    for (var star in stars) {
        stars[star].Draw();
    }
}

// Modify interval to adjust speed
if (f) setInterval(draw, 40);

И CSS:

/* global.css */

body {
    margin: 0;
    padding: 0;
    background-color: black;
}

main {
    width: 100vw;
    height: 100vh;
}

#field {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: -3;
}

#crawl {
    position: fixed;
    top: 0;
    bottom: 0;
    z-index: -2;
    font-family: Deathstar, Verdana, Geneva, Tahoma, sans-serif;
    text-align: center;
    color: white;
    font-size: 4rem;
    perspective: 200px;
}

#crawl p {
    transform: rotateX(20deg);
    animation: starwars 30s ease-in;
    animation-iteration-count: infinite;
    margin: 0 auto;
}

#crawl p span {
    font-size: 150%;
}

#overlay {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: -1;
    background-color: rgba(0, 0, 0, 0.4);
}

@keyframes starwars {
    0% {
        transform: rotateX(20deg) translateY(750px);
    }

    100% {
        transform: rotateX(20deg) translateY(-1500px);
    }
}

@keyframes starwars1200 {
    0% {
        transform: rotateX(20deg) translateY(565px);
    }

    100% {
        transform: rotateX(20deg) translateY(-1500px);
    }
}

@media only screen and (max-width: 1200px) {
    #crawl {
        font-size: 1rem;
    }

    #crawl p {
        animation: starwars1200 30s ease-in;
    }
}

@font-face {
    font-family: 'Deathstar';
    font-style: normal;
    font-weight: 100;
    font-display: swap;
    src: url('https://cdn.designly.biz/fonts/deathstar/death_star-webfont.eot');
    src: local(''),
        url('https://cdn.designly.biz/fonts/deathstar/death_star-webfont.eot?#iefix') format('embedded-opentype'),
        url('https://cdn.designly.biz/fonts/deathstar/death_star-webfont.woff2') format('woff2'),
        url('https://cdn.designly.biz/fonts/deathstar/death_star-webfont.woff') format('woff'),
        url('https://cdn.designly.biz/fonts/deathstar/deathstar.otf') format('opentype'),
        url('https://cdn.designly.biz/fonts/deathstar/death_star-webfont.svg') format('svg');
}

CSS, безусловно, можно было бы доработать, включая дополнительные точки разрыва. Недостатком этого кода является то, что вам придется корректировать CSS, если вы измените длину текста. Но если ваш текст статичен, то это должно работать хорошо.

И последнее, но не менее важное - HTML:

<html lang="en">

<head>
    <meta name="robots" content="index, follow" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=yes" />
    <link rel="stylesheet" href="css/global.css" />
</head>

<body>
    <main>
        <canvas id="field"></canvas>
        <div id="crawl">
            <p>
                <span>Episode IV</span>
                <br /><br />
                A New Hope
                <br /><br />
                It is a period of civil war.
                Rebel spaceships, striking
                from a hidden base, have won
                their first victory against
                the evil Galactic Empire.
                <br /><br />
                During the battle, Rebel
                spies managed to steal secret
                plans to the Empire's
                ultimate weapon, the DEATH
                STAR, an armored space
                station with enough power to
                destroy an entire planet.
                <br /> <br />
                Pursued by the Empire's
                sinister agents, Princess
                Leia races home aboard her
                starship, custodian of the
                stolen plans that can save
                her people and restore
                freedom to the galaxy....
            </p>
        </div>
        <div id="overlay"></div>
    </main>
</body>

<script src="js/stars.js"></script>

</html>

Надеюсь, вы нашли эту статью полезной.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?

20.08.2023 18:21

Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2023-2024 годах? Или это полная лажа?".

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией

20.08.2023 17:46

В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.

Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox

19.08.2023 18:39

Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest

19.08.2023 17:22

В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!

Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️

18.08.2023 20:33

Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий их языку и культуре.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL

14.08.2023 14:49

Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.