В этом руководстве я поделюсь своим опытом работы с 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/