Интервьюер спросил меня, умею ли я рисовать анимацию фейерверка 🎇

внешний интерфейс Canvas
Интервьюер спросил меня, умею ли я рисовать анимацию фейерверка 🎇

Это 6-й день моего участия в Gengwen Challenge.Подробности мероприятия смотрите:Обновить вызов

предисловие

Кривые Безье повсюду в нашем повседневном развитии:

  1. Кривые в svg (поддерживает 2-й, 3-й порядок)
  2. Рисование кривых Безье на холсте
  3. Почти все интерфейсные библиотеки 2D или 3D графики и диаграмм (echarts, d3, three.js) используют кривые Безье.

Поэтому овладение кривой Безье необходимо. Эта статья в основном является практической статьей и не будет вводить знания, связанные с Безье.Если некоторые студенты не очень понимают кривые Безье: вы можете проверить эту мою статью——Глубокое понимание SVG

рисовать кривые Безье

Первым шагом является создание ctx и использование ctx для построения кривой Безье второго порядка для просмотра. Кривая Безье второго порядка имеет 1 контрольную точку, начальную и конечную точки.

const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = '#000';
ctx.moveTo(100,100)
ctx.quadraticCurveTo(180,50, 200,200)
ctx.stroke();

image-20210614151914950.png

Таким образом, мы нарисовали кривую Безье.

Нарисовать анимацию кривой Безье

Кто бы не нарисовал линию? Основное содержание следующей статьи. Сначала представьте себе анимацию, мы должны рисовать кривую шаг за шагом? Но есть ли проблема с тем, что этот ctx отрисовывает все это для нас? Давайте еще раз посмотрим на анимацию процесса реализации кривой Безье второго порядка, чтобы увидеть, есть ли какая-то идея.

20170817110550542.gif

Из рисунка можно проанализировать, что кривая Безье связана с t, а интервал t находится в диапазоне от 0 до 1. Можем ли мы вычислить каждую точку с помощью уравнения кривой Безье второго порядка? Этот термин называетсядискретностьОднако информация об этом результате не является викториной, мы реализуем это в первую очередь.

Сначала посмотрите на следующее уравнение:

v2-4a70bb17e8c6ff69d500a51279ad8168_r.png

Мы моделируем и пишем код следующим образом:

//这个就是二阶贝塞尔曲线方程
function twoBezizer(p0, p1, p2, t) {
  const k = 1 - t
  return k * k * p0 + 2 * (1 - t) * t * p1 + t * t * p2
}

//离散
function drawWithDiscrete(ctx, start, control, end,percent) {
    for ( let t = 0; t <= percent / 100; t += 0.01 ) {
        const x = twoBezizer(start[0], control[0], end[0], t)
        const y = twoBezizer(start[1], control[1], end[1], t)
        ctx.lineTo(x, y)
    }
}

Посмотрим на эффект:

image-20210614154751897.png

Это почти то же самое, что мы нарисовали, поэтому давайте начнем нашу анимацию с requestAnimationFrame и дадим следующий код:

let percent = 0
function animate() {
    ctx.clearRect( 0, 0, 800, 800 );
    ctx.beginPath();
    ctx.moveTo(100,100)
    drawWithDiscrete(ctx,[100,100],[180,50],[200,200],percent)
    ctx.stroke();
    percent = ( percent + 1 ) % 100;
    id =  requestAnimationFrame(animate)
}
animate()

Здесь следует отметить две вещи: я постоянно добавляю 1 и 100 к проценту, поэтому процент будет продолжать изменяться от 1 до 100, хорошо, поэтому мы должны выполнить очистку области перед анимацией, ctx.clearRect( 0 , 0, 800, 800 ); Это будет продолжать цикл от начала до конца. Давайте посмотрим на эффект:

Jun-14-2021 16-47-49.gif

Разве это не выглядит хорошо хахаха 😸.

Нарисуйте кривую Безье, способ анимации 2

Как вы думаете, это конец? Конечно нет, неужели мы не можем нарисовать кривую Безье для определенного t? В настоящее время нет, вот процесс вывода уравнения Бесселя второго порядка:

微信图片_20210615144706.jpg

Любая точка на кривой Безье второго порядка может быть получена тем же соотношением. В любой точке между двумя точками кривая Безье первого порядка фактически удовлетворяется, а кривая Безье первого порядка фактически является линейным изменением. Я даю следующее уравнение

 function oneBezizer(p0,p1,t) {
      return p0 + (p1-p0) * t
  }

Как видно из рисунка, который я нарисовал, мы можем нарисовать кривую Безье за ​​определенный период времени, пока продолжаем искать точку А и точку С.

Я даю следующий код и рендеринг:

function drawWithDiscrete2(ctx, start, control, end,percent) {
    const t = percent/ 100;
    // 求出A点
    const A = [];
    const C = [];
    A[0] = oneBezizer(start[0],control[0],t);
    A[1] = oneBezizer(start[1],control[1],t);
    C[0] = twoBezizer(start[0], control[0], end[0], t)
    C[1] = twoBezizer(start[1], control[1], end[1], t)
    ctx.quadraticCurveTo( 
        A[ 0 ], A [ 1 ],
        C[ 0 ], C[ 1 ]
    );
}

Jun-14-2021 16-47-49.gif

Фейерверк 🎉 Анимация

Выше мы достигли линии Bezier, отправной точкой мы поместили эту кривую Безье в качестве центра круга, а затем найдите разные конечные точки в соответствии с числом. Написать случайный цвет, эффект фейерверков попал прямо на код,

for(let i=0; i<count; i++) {
    const angle = Math.PI * 2 / count * i;
    const x = center[ 0 ] + radius * Math.sin( angle );
    const y = center[ 1 ] + radius * Math.cos( angle );
    ctx.strokeStyle = colors[ i ];
    ctx.beginPath();
    drawWithDiscrete(ctx, center,[180,50],[x,y],percent)
    ctx.stroke();
}

function getRandomColor(colors, count) {
    // 生成随机颜色
    for ( let i = 0; i < count; i++ )  {
        colors.push( 
          'rgb( ' + 
            ( Math.random() * 255 >> 0 ) + ',' +
            ( Math.random() * 255 >> 0 ) + ',' + 
            ( Math.random() * 255 >> 0 ) + 
          ' )'
        );
    }
}

Смотрим анимацию:

端午节快乐.gif

конец

На этом статья заканчивается. Если она показалась вам полезной, поставьте лайк и подпишитесь. Ваша поддержка - самая большая мотивация для меня, чтобы продолжать обновлять. Весь код у меняgithubначальство. Наконец, я желаю всем счастливого Праздника лодок-драконов!