Фон с прыгающими фигурами с помощью холста

Цель этого проекта — сделать классный фон с произвольными фигурами и возможностью настройки.

Демонстрация: https://canvas-shapes-background.netlify.app/

Код: https://github.com/MaurerKrisztian/CanvasShapesBackground

Простой пример использования:


https://codepen.io/maurerkrisztian/pen/rNdGerb

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type='text/javascript' src="https://canvas-shapes-background.netlify.app/bundle.js"></script>
</head>
<body>
<canvas id="myCanvas"></canvas>
<script>
    createShapeCanvas("myCanvas", {
        modelNumbers: 11,
        colors: ['blue', 'red', 'green', 'yellow'],
        backgroundColor: 'black', //'none',
        enabledModels: ['Triangle', 'Circle', 'Rect'],
        minSpeed: 11,
        maxSpeed: 11,
        lineWidth: 3,
        sizeMultiplier: 2,
        startPosition: 'random' //  'middle' | 'random',
        isFullScreen: true,
    })
</script>
</body>
</html>
Вход в полноэкранный режим Выход из полноэкранного режима

Я добавил конфигуратор в демо-версию: https://canvas-shapes-background.netlify.app/.

  • Легко тестировать различные конфигурации и копировать настроенные параметры.

«createShapeCanvas» имеет 2 аргумента

  • идентификатор холста
  • конфигурация

config

  • startPosition: ‘middle’ | ‘random’ начальная позиция модели
  • enabledModels: типы фигур будут генерироваться случайным образом
  • modelNumbers: генерировать это количество моделей из массива «enabledModels»
  • colors: выбрать случайный цвет из этого массива для фигур
  • backgroundColor: цвет фона холста, может быть «none»
  • minSpeed: минимальная скорость фигуры
  • maxSpeed: максимальная скорость фигуры
  • lineWidth: ширина линии границы фигуры
  • sizeMultiplier: умножение сгенерированного размера на это значение
  • isFullScreen: полноэкранный или размер элемента

Как я это сделал?

Я использовал HTML Canvas.

Я хотел, чтобы он был легко расширяемым, поэтому абстрагировал некоторые вещи:

Animator:

  • отвечает за настройку каждого кадра и вызов модели update().

Модель:

  • имеет 2 основные функции:
  • draw() — рисовать фигуру,
  • update()
    • как вести себя, основываясь на текущей позиции x,y и
    • xd, dy aka куда двигаться и как быстро.Если вы запутались, как dx, dy работает, это в основном вектор.Он имеет направление (это будет направление модели) и длину (это будет скорость модели).

Пример модели:

export class CircleModel implements IModel {
    static MODEL_NAME = 'Circle'

    color: string;

    constructor(private x: number, private y: number, private dx: number, private dy: number, private radius: number, private lineWidth: number = Setup.CONFIG.lineWidth) {
        this.color = Utils.pickRandomFromArray<string>(Setup.CONFIG.colors)
    }

    draw(context: CanvasRenderingContext2D) {
        context.lineWidth = this.lineWidth;
        context.beginPath();
        context.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
        context.strokeStyle = this.color;
        context.stroke();
        context.lineWidth = DEFAULT_LINE_WIDTH;
    }


    update(context: CanvasRenderingContext2D) {
        if (this.x > Context.canvasWidth - this.radius || this.x < 0 + this.radius) {
            this.dx = -this.dx;
        }
        if (this.y > Context.canvasHeight - this.radius || this.y < 0 + this.radius) {
            this.dy = -this.dy;
        }

        this.x = this.x + this.dx;
        this.y = this.y + this.dy;

        this.draw(context);
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Я хотел сделать баунс со стороны холста, поэтому

Хорошо знать, где находится сторона холста.

Система координат:

x(0) — левая минимальная позиция, x(canvasWidth) — правая позиция, аналогично с y.

        if (this.x > Context.canvasWidth - this.radius || this.x < 0 + this.radius) {
            this.dx = -this.dx;
        }
Вход в полноэкранный режим Выход из полноэкранного режима

Если текущая позиция (центр круга) больше, чем ширина холста — радиус, измените направление x.

Аналогично с y.

В конце нужно установить новую позицию:

this.x = this.x + this.dx;
this.y = this.y + this.dy;
Войти в полноэкранный режим Выйти из полноэкранного режима

Я создал 3 модели: Cirle, Rect, Triangle.

Но вы можете легко добавить свою модель:

  • создать модель
  • добавить в ModelFactory
    private static createRandomModel() {
        const speed = Utils.generateRandom(Setup.CONFIG.minSpeed, Setup.CONFIG.maxSpeed)
        const randoModelName = Utils.pickRandomFromArray(Setup.CONFIG.enabledModels)
        switch (randoModelName) {
            case CircleModel.MODEL_NAME:
                return this.createRandomCircle(speed)
                break;
            case TriangleModel.MODEL_NAME:
                return this.createRandomTriangle(speed)
                break;
            case RectModel.MODEL_NAME:
                return this.createRandomRect(speed)
                break;
            default:
                throw new Error(`Model not found with name: ${randoModelName}`)
        }
    }
Войти в полноэкранный режим Выйти из полноэкранного режима

Как создать импортируемый скрипт?

Я просто добавил функцию init в окно, поэтому вы можете импортировать скрипт пакета и вызвать эту функцию.

window.createShapeCanvas = createShapeCanvas
Войти в полноэкранный режим Выход из полноэкранного режима

Планы на будущее:

  • добавить больше моделей
  • добавить больше опций конфигурации
  • создать компонент react и опубликовать в npm

Оцените статью
devanswers.ru
Добавить комментарий