人工智能应用探索

关于

以 p5.js 动画为例,关于生成式AI使用的一些细节

May 5, 2023

引言

这个网站大部分文字、代码(包含HTML、CSS、和 JavaScript)和全部图片内容由AI生成,那么在目前的发展阶段使用AI创作的过程是什么样的呢?下面我们以首页的 p5.js 动画为例, 详细描述一下它的创作过程。

p5.js 简介

在开始创作之前,我们需要先简单了解一下什么是 p5.js 。

在官方网站 p5js.org 上的介绍如下:

p5.js 是个 JavaScript 创意编程程式库,其专注在让编程更易于使用及更加广泛的包容艺术家、设计师、教育家、初学者以及任何其他人!p5.js 是个免费及开源的软件因为我们相信所有人都应该能自由使用软件及用于学习软件的工具。

p5.js 使用绘图的比喻并有一副完整的绘画功能。除此之外,您也不单限于您的绘图画布。您可以将您整个浏览器页面当作您的绘图,这包括了 HTML5 物件如文字、输入框、视屏、摄像头及音频。

可以看出,这个官网大概率是机翻的 : ),但简单来说, p5.js 是一种用来绘制图形的编程语言, 同时由于它基于计算机编程语言的特性,它很适合被用于制作可视化数据,数据艺术等。

开始创作

现在我们来明确一下这次创作的需求,我们想得到一个动态的,类似数据艺术的, 由许多短线组成的像波浪一样的3D动画。

以下我们开始使用ChatGPT进行创作, 由于目前ChatGPT的中文对话能力相比于英文来说相对薄弱, 以下对话为英文输入后翻译成中文,首先将我们的需求说明:

Can you create the code of a data art in p5js that moves like a 3d wave?

你可以用 p5js 语言生成一个动起来像3D波浪一样的代码吗?

ChatGPT给出如下回答:

Certainly! Here's an example code for creating a 3D wave animation in p5js:

当然可以!这里是创造3D波浪动画的一个 p5js 代码示例:
	
	let wave = [];
	let numPoints = 50;
	let amplitude = 200;
	let frequency = 0.05;
	let phase = 0;
	let angle = 0;
	let speed = 0.1;

	function setup() {
	  createCanvas(windowWidth, windowHeight, WEBGL);
	  colorMode(HSB, 360, 100, 100, 1);
	  for (let i = 0; i < numPoints; i++) {
		wave[i] = 0;
	  }
	}

	function draw() {
	  background(0);
	  noStroke();
	  rotateX(PI / 3);
	  translate(-width / 2, -height / 2, 0);
	  angle += speed;
	  let x = angle;
	  for (let i = 0; i < numPoints; i++) {
		wave[i] = sin(x) * amplitude;
		x += frequency;
	  }
	  fill(150, 100, 100);
	  beginShape();
	  for (let i = 0; i < numPoints; i++) {
		vertex(i * width / numPoints, wave[i], 0);
	  }
	  vertex(width, height, 0);
	  vertex(0, height, 0);
	  endShape(CLOSE);
	  fill(200, 100, 100);
	  beginShape();
	  for (let i = 0; i < numPoints; i++) {
		vertex(i * width / numPoints, wave[i], 0);
	  }
	  vertex(width, height, 0);
	  vertex(0, height, 0);
	  endShape(CLOSE);
	}
	
	
In this code, we start by defining an array called 'wave' that will hold the y-coordinates of our points. We then set the number of points, the amplitude, frequency, phase, and angle of our wave.
In the 'setup' function, we create a canvas with the 'WEBGL' renderer, set the color mode to HSB, and initialize our 'wave' array to all zeroes.

In the 'draw' function, we first set the background to black, turn off stroke, and rotate the canvas using the 'rotateX' function to give the wave a 3D appearance. We then translate the canvas to the center of the screen.

Next, we calculate the y-coordinates of each point in our wave by iterating through our 'wave' array and using the 'sin' function to calculate the y-coordinate based on the current x-coordinate. We then update the x-coordinate by adding the frequency to it.

We then draw two shapes using 'beginShape', 'vertex', and 'endShape'. The first shape is filled with a reddish color and the second shape is filled with a bluish color. These shapes represent the crest and trough of our wave.

Finally, we update the angle of our wave by adding the 'speed' to it, which causes the wave to animate and move over time.


在这段代码中,我们首先定义了一个名为wave的数组,它将保存我们的点的y坐标。然后,我们设置了点的数量、振幅、频率、相位和角度。

在setup函数中,我们使用WEBGL渲染器创建了一个画布,将颜色模式设置为HSB,并将我们的波形数组初始化为所有零。

在draw函数中,我们首先将背景设置为黑色,关闭描边,并使用rotateX函数旋转画布,以使波形具有3D外观。然后,我们将画布平移到屏幕中心。

接下来,我们通过迭代我们的波形数组并使用sin函数来计算基于当前x坐标的y坐标来计算我们波形中每个点的y坐标。然后,我们通过添加频率来更新x坐标。

然后,我们使用beginShape、vertex和endShape绘制了两个形状。第一个形状填充了红色,第二个形状填充了蓝色。这些形状代表了我们波形的顶峰和谷底。

最后,我们通过添加速度来更新波浪的角度,从而导致波浪随时间动画和移动。

可以看到,在这个答案中,ChatGPT在给出代码之后,还解释了一下这个代码的工作原理,但因为我们这次想让ChatGPT完全独立完成这个创作,这个解释对我们用处不大,在之后的回答中,这些解释也将被省略。

我们直接把它给出的代码复制到 p5.js 的官方编辑器之后,得到了这个动画:

这虽然是个波浪,但完全不是我们想要的样子,所以我们直接向 ChatGPT 指出:

This is a 2d animation, I want an array of short lines that looks like it is moving in 3d.

这是个2D的动画,我想要看起来像是在3D空间移动的一个由很多短线组成的阵列。

以下是ChatGPT这次给出的回答, 代码和解释将被省略:

Sure, here's an example code for creating an array of short lines that looks like it's moving in 3D using p5js:

当然, 这里是创造由一个阵列的短线组成,看起来像在3D运动的示例代码:

这次 ChatGPT 给出的答案明显更加接近我们想要的效果,但仍然存在两个问题,一是线太长,二是整个图案只在画面中间,而我们想要它充满画面。

我们继续向ChatGPT指出:

Can you make the lines shorter and fill the canvas?

你可以把线变短并且充满整个画面吗?

它给出的答案是:

Sure, here's an updated code that makes the lines shorter and fills the entire canvas:

当然,这里是把线变短并且充满整个画布的更新后的代码:

这次看起来线不但没有变短,反而变得更长了,而且更加集中在画面中间了,我们直接指出这个明显的错误:

That doesn't fill up the canvas.

这并没有填满整个画布.

ChatGPT似乎认识到了这个错误:

I apologize for the mistake in my previous response. Here's an updated code that should fill the entire canvas:

我对前面回答中的错误表示抱歉。这里是更新后的代码,应该能将画布填满:

并没有什么区别,我们再对要求稍微明确一点:

Make the lines very short and fill the canvas with array of them in both x and y directions.

把线变得很短,并且用一个在x和y方向上都有的阵列来填满画布。

这次它给出了这样的答案:

Sure! Here's an updated code that makes the lines very short and fills the entire canvas with an array of them in both x and y directions:

当然!这里是把线变得很短并用x和y方向上的阵列填满画布的更新后的代码:

这个线更长了,越来越偏离我们给出的要求了。这里我们必须要更加明确一下要求了:

The lines are very long, I want short lines, no more than 10px.

这线太长了,我要短线,不超过10像素的。

ChatGPT 有一次似乎认识到了错误:

Sorry about that! Here's an updated code that makes the lines shorter, no more than 10px:

十分抱歉!这里是更新后把线变短,不超过10像素的代码:

这次只有上面和左边有线了,似乎完全忘记了前面的要求:

Use more lines to fill the canvas.

用更多的线把画布填满。

这里省略一次回答,因为并没有什么区别。

在我再一次告诉它只有上面和左边有线时,它终于将线铺满了屏幕,但由于代码中计算太多,整个动画运行时非常卡,我告诉它动画很卡后,他减少了线的数量,但依然卡,这里就不放这两个动画了。

在这里我决定换一个说法,看会不会得到不同的结果:

Not exactly what i wanted, I want an array of individual short lines that rotate in a pattern and look like they are forming a 3d wave.

并不完全是我想要的,我想要由一个个在旋转的短线组成的阵列,看起来像组合成了一个3d的波浪。

它再次道歉:

I apologize for the confusion. Here is an updated code that creates an array of short lines that rotate in a pattern and look like they are forming a 3D wave:

我对造成的困惑表示抱歉。这里是由一个个在旋转的短线组成的阵列,看起来像组合成了一个3d的波浪的更新后的代码:

至此ChatGPT终于生成了与我们要求接近的动画

之后我再次要求它做了几次颜色和动画速度上的改动,包括增加不同颜色,调整变色速度,使动画更加平滑等,最终便得到了首页上的动画:

网站应用

在对动画满意之后,我们需要将动画放到网站首页作为背景,我们继续向它询问:

How do I make this a background of an html page?

我如何将这个作为一个HTML网页的背景?

它给出了这样的回答:

To use the p5.js sketch as the background of an HTML page, you can do the following:

你可以通过以下这几步将这个 p5.js 绘画作为一个HTML页面的背景:

1. In your HTML file, add a div element with an id attribute that matches the name of your p5.js sketch:

1. 在你的HTML文件中加入一个id为你的 p5.js 绘画名称的 div 元素:

<div id="mySketch"> </div>
2. In your p5.js sketch file, remove the createCanvas() function and replace it with a setup() function that creates a canvas and appends it to the div element using the parent() function:

2. 在你的 p5.js 文件中,删除createCanvas()函数,并用一个setup()函数替换它,该函数创建一个画布,并使用parent()函数将它附加到div元素上:
function setup() {
  let canvas = createCanvas(windowWidth, windowHeight, WEBGL);
  canvas.parent('mySketch');
  // ...
}


This will create a canvas with the same size as the window and append it to the div element with the id "mySketch".

这将创建一个与窗口大小相同的画布,并将其附加到id为“mySketch”的div元素上。

3. In your HTML file, include the p5.js library and your sketch file using script tags:

在你的HTML文件中,使用script标签包含p5.js库和你的草图文件:
 <script src="https://cdnjs.cloudflare.com/ ajax/libs/p5.js/1.4.0/p5.min.js"></script>
<script src="sketch.js"></script>
Make sure to replace "sketch.js" with the name of your p5.js sketch file.

务必将“sketch.js”替换为你的 p5.js 文件名。

4. Finally, add some CSS to style the div element and the canvas:

最后,加上一些CSS来设置div元素和画布的样式:
html, body {
	  margin: 0;
	  padding: 0;
	}

	#mySketch {
	  position: fixed;
	  top: 0;
	  left: 0;
	  z-index: -1;
	}

	canvas {
	  display: block;
	}


This will position the div element at the top-left corner of the page and set its z-index to -1 to make it appear behind the other content. The canvas element will be set to display: block to remove any default padding and margins.

Once you have these steps set up, you should be able to see your p5.js sketch as the background of your HTML page.

这将把div元素定位在页面的左上角,并将其z-index设置为-1,使其出现在其他内容的后面。画布元素将被设置为display: block,以去除任何默认的填充和边距。

一旦你完成了这些步骤,你应该能够看到你的p5.js草图作为你的HTML页面的背景。

根据这些详细的步骤,我们很容易地将这些代码应用到了我们的文件中,也达到了我们最终想要的效果。

最后我们当然要稍微表扬一下ChatGPT并表示感谢:

Works great, thanks!

成功了,谢谢!
You're welcome! I'm glad I could help. If you have any more questions or need further assistance, feel free to ask!

你太客气了!我很高兴能帮助你。如果你还有其他问题或需要进一步的帮助,请随时问!