
В этом руководстве я поделюсь своим опытом работы с OpenAI GPT-4 для создания интерактивной и увлекательной круговой анимации на основе холста в JavaScript. С помощью GPT-4 мы добавили визуальные эффекты, такие как мигание границ холста и уменьшение размера круга при столкновении с границей. Давайте углубимся в шаги, которые мы предприняли для достижения этого результата.
Шаг 1. Настройте класс Circle с помощью GPT-4. Сначала GPT-4 предоставил мне базовую структуру класса Circle, определяющую свойства и методы, необходимые для наших кругов. Конструктор класса принимает параметры положения (x, y), радиуса, скорости (dx, dy), цвета, скорости роста и силы притяжения.
class Circle {
constructor(x, y, radius, dx, dy, color, growRate, attractionForce) {
this.x = x;
this.y = y;
this.radius = radius;
this.dx = dx;
this.dy = dy;
this.color = color;
this.growRate = 0.05;
this.attractionForce = 0.0001;
this.friction = 0.70;
const arabicLetters = "ABIGAEL";
this.collisionCounter = 0;
this.letter = arabicLetters[Math.floor(random(0, arabicLetters.length))];
}
}
Шаг 2. Внедрите методы рисования и обновления в соответствии с GPT-4. Было предложено добавить в класс Circle два метода: draw() и update(). Метод draw() отвечает за отрисовку круга на холсте, а метод update() обрабатывает движение круга, рост и взаимодействие с другими кругами и границами холста.
draw(ctx) {
const largestCircle = getLargestCircle();
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
if (this === largestCircle) {
ctx.fillStyle = 'rgba(40, 300, 255, 0.8)'; // Shiny blue
// Create a color-changing effect using Math.sin() and Date.now()
const colorShift = (Math.sin(Date.now() * 0.002) + 1) / 2;
const red = 255 * colorShift;
const blue = 255 * (1 - colorShift);
ctx.strokeStyle = `rgba(${red}, 20, ${blue}, 0.8)`; // Flashing between blue and pink
ctx.lineWidth = 5;
} else {
ctx.fillStyle = this.color;
ctx.strokeStyle = this.color;
ctx.lineWidth = 0.5;
}
ctx.fill();
ctx.stroke();
ctx.closePath();
// Draw the letter
ctx.font = `${Math.floor(this.radius * 0.7)}px Arial`;
// Apply the flashing effect to the letter
if (this === largestCircle) {
const colorShift = (Math.sin(Date.now() * 0.002) + 1) / 2;
const red = 255 * colorShift;
const blue = 255 * (1 - colorShift);
ctx.fillStyle = `rgba(${red}, 20, ${blue}, 0.8)`; // Flashing between blue and pink
} else {
ctx.fillStyle = 'white';
}
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(this.letter, this.x, this.y);
}
Шаг 3: Уменьшите размер круга при столкновении с границей с помощью наведения GPT-4. С учетом входных данных GPT-4 мы изменили метод update(), чтобы определять, когда круг сталкивается с границей. При столкновении размер круга уменьшается на 10%.
update(canvas, circles) {
// Collision with borders
let borderCollision = false;
if (this.x + this.radius > canvas.width) {
this.x = canvas.width - this.radius;
this.dx = -this.dx;
borderCollision = true;
} else if (this.x - this.radius < 0) {
this.x = this.radius;
this.dx = -this.dx;
borderCollision = true;
}
if (this.y + this.radius > canvas.height) {
this.y = canvas.height - this.radius;
this.dy = -this.dy;
borderCollision = true;
} else if (this.y - this.radius < 0) {
this.y = this.radius;
this.dy = -this.dy;
borderCollision = true;
}
if (borderCollision) {
this.radius *= 0.9;
}
let isConnected = false;
const largestCircle = getLargestCircle();
if (this !== largestCircle) {
const dx = largestCircle.x - this.x;
const dy = largestCircle.y - this.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance > largestCircle.radius + this.radius) {
const forceX = dx * this.attractionForce * 2;
const forceY = dy * this.attractionForce * 2;
this.dx += forceX;
this.dy += forceY;
}
} else {
// Make the largest circle run away from the rest of the circles
for (const circle of circles) {
if (circle === this) continue;
const dx = this.x - circle.x;
const dy = this.y - circle.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.radius + circle.radius + 100) {
const forceX = dx * this.attractionForce * 4;
const forceY = dy * this.attractionForce * 4;
this.dx += forceX;
this.dy += forceY;
}
}
}
// Collision with other circles
for (const circle of circles) {
if (circle === this) continue;
const dx = this.x - circle.x;
const dy = this.y - circle.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.radius + circle.radius) {
this.dx = -this.dx;
this.dy = -this.dy;
// Reduce circle size by 10%
this.radius *= 0.99;
circle.radius *= 0.99;
// Increment the collisionCounter for both circles
this.collisionCounter++;
circle.collisionCounter++;
}
// Draw a line between circles when they're close
if (distance < 100) {
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(circle.x, circle.y);
ctx.strokeStyle = this.color;
ctx.lineWidth = 0.5;
ctx.stroke();
ctx.closePath();
// Apply attraction force
const forceX = (circle.x - this.x) * this.attractionForce;
const forceY = (circle.y - this.y) * this.attractionForce;
this.dx += forceX;
this.dy += forceY;
circle.dx -= forceX;
circle.dy -= forceY;
isConnected = true;
}
}
if (!isConnected) {
this.dx *= this.friction;
this.dy *= this.friction;
}
// Grow the circle slowly
this.radius += this.growRate;
this.x += this.dx;
this.y += this.dy;
}
}
Шаг 4. Заставьте границу холста мигать при изменении самого большого круга GPT-4 рекомендует создать визуальный эффект, при котором граница холста мигает желтым цветом каждый раз, когда самый большой круг перемещается в новый круг. Мы добавили переменную previousLargestCircle для отслеживания предыдущего самого большого круга и обновили ее в функции animate(). Если текущий самый большой круг отличается от предыдущего, мы вызвали функцию flashBorder(), чтобы граница мигала желтым цветом.
let previousLargestCircle = null;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (const circle of circles) {
circle.draw(ctx);
circle.update(canvas, circles);
}
const currentLargestCircle = getLargestCircle();
if (previousLargestCircle !== currentLargestCircle) {
previousLargestCircle = currentLargestCircle;
flashBorder();
}
updateCollisionList(); // Update the list of circles and their collision counts
requestAnimationFrame(animate);
}
function flashBorder() {
const borderFlashDuration = 500; // milliseconds
canvas.style.border = '5px solid yellow';
setTimeout(() => {
canvas.style.border = '5px solid green';
}, borderFlashDuration);
}
Шаг 5: Отобразите список столкновений, вдохновленный GPT-4 GPT-4 предложил отображать список кругов и их соответствующие проценты столкновений, чтобы предоставить пользователям дополнительную информацию. Мы добавили функцию updateCollisionList() для обновления списка кругов и количества их столкновений, а также элемент HTML для отображения этого списка.
function updateCollisionList() {
const collisionList = document.getElementById("collisionList");
collisionList.innerHTML = "";
// Calculate the total number of collisions
const totalCollisions = circles.reduce((total, circle) => total + circle.collisionCounter, 0);
for (const circle of circles) {
const listItem = document.createElement("li");
// Calculate the percentage of collisions for the current circle
const collisionPercentage = totalCollisions === 0 ? 0 : ((circle.collisionCounter / totalCollisions) * 100).toFixed(2);
listItem.textContent = `Circle ${circles.indexOf(circle) + 1}: ${collisionPercentage}%`;
collisionList.appendChild(listItem);
}
}
Шаг 6: Я добавил элемент HTML для отображения списка кругов и количества их сговоров в процентах от общего количества всех сговоров. Я также добавил кнопку отдыха, чтобы сбросить анимацию при нажатии.
const circleListContainer = document.createElement("div");
circleListContainer.innerHTML = `
<h3>Collision List</h3>
<ul id="collisionList"></ul>
`;
document.body.appendChild(circleListContainer);
function resetAnimation() {
circles.length = 0;
createCircles(30);
}
const resetButton = document.getElementById('resetButton');
resetButton.addEventListener('click', resetAnimation);
Наконец, я объявил количество кругов на холсте и доработал код с помощью animate() для запуска анимации.
createCircles(10); animate();
Я развернул код в Vercel, что было несложно настроить (позже я напишу о своем опыте работы с Vercel).
Вывод: в сотрудничестве с GPT-4 мы успешно создали интерактивную и привлекательную круговую анимацию на основе холста. Усовершенствования включают мигание границ холста при изменении самого большого круга, уменьшение размера круга при столкновении с границей и список, отображающий процент столкновения каждого круга. Эти улучшения делают анимацию более интерактивной и динамичной, обеспечивая пользователям приятный опыт. Помощь GPT-4 в этом проекте была неоценимой, продемонстрировав потенциал ИИ в управлении и улучшении процесса кодирования.
Посетите веб-сайт круговой анимации на основе холста по адресу: https://animation-wheat.vercel.app/