Это 6-й день моего участия в Gengwen Challenge.Подробности мероприятия смотрите:Обновить вызов
предисловие
Кривые Безье повсюду в нашем повседневном развитии:
- Кривые в svg (поддерживает 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();
Таким образом, мы нарисовали кривую Безье.
Нарисовать анимацию кривой Безье
Кто бы не нарисовал линию? Основное содержание следующей статьи. Сначала представьте себе анимацию, мы должны рисовать кривую шаг за шагом? Но есть ли проблема с тем, что этот ctx отрисовывает все это для нас? Давайте еще раз посмотрим на анимацию процесса реализации кривой Безье второго порядка, чтобы увидеть, есть ли какая-то идея.
Из рисунка можно проанализировать, что кривая Безье связана с t, а интервал t находится в диапазоне от 0 до 1. Можем ли мы вычислить каждую точку с помощью уравнения кривой Безье второго порядка? Этот термин называетсядискретностьОднако информация об этом результате не является викториной, мы реализуем это в первую очередь.
Сначала посмотрите на следующее уравнение:
Мы моделируем и пишем код следующим образом:
//这个就是二阶贝塞尔曲线方程
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)
}
}
Посмотрим на эффект:
Это почти то же самое, что мы нарисовали, поэтому давайте начнем нашу анимацию с 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 ); Это будет продолжать цикл от начала до конца. Давайте посмотрим на эффект:
Разве это не выглядит хорошо хахаха 😸.
Нарисуйте кривую Безье, способ анимации 2
Как вы думаете, это конец? Конечно нет, неужели мы не можем нарисовать кривую Безье для определенного t? В настоящее время нет, вот процесс вывода уравнения Бесселя второго порядка:
Любая точка на кривой Безье второго порядка может быть получена тем же соотношением. В любой точке между двумя точками кривая Безье первого порядка фактически удовлетворяется, а кривая Безье первого порядка фактически является линейным изменением. Я даю следующее уравнение
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 ]
);
}
Фейерверк 🎉 Анимация
Выше мы достигли линии 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 ) +
' )'
);
}
}
Смотрим анимацию:
конец
На этом статья заканчивается. Если она показалась вам полезной, поставьте лайк и подпишитесь. Ваша поддержка - самая большая мотивация для меня, чтобы продолжать обновлять. Весь код у меняgithubначальство. Наконец, я желаю всем счастливого Праздника лодок-драконов!