第三课:P5.js创意编程入门
闪电编程,助你闪电入门!⚡️⚡️⚡️
本节课的大纲:
- javascript语言关键概念回顾
- 本地编程环境配置
- p5.js基本代码结构
- 元素:坐标、形状、颜色
- 动画:旋转、平移、鼠标事件
- 用p5.js做的第一个CodeArt作品
本节课学完后能收获什么:
- 安装好本地环境并用其创建p5.js项目
- 掌握最基本的p5.js “武器库”:形状、颜色、动画
- 建立“坐标”和“函数”的概念并实操。
- 完成一幅简单的数字艺术作品。
课前准备:
-
在线代码编辑环境:闪电编程班练习区
-
p5.js官方API文档-参考查阅用: (p5js.org/zh-Hans/ref…)
课前复习:JavaScript语言关键概念
抽查:变量 函数、参数如何定义? 如何使用?
参考: 闪电编程入门课-第二课
第一部分、搭建你的创意画板:p5.js环境配置
在开始创作之前,我们需要准备好我们的“画板”和“画笔”。p5.js 提供了两种非常便捷的开发方式,你可以根据自己的喜好选择其一。
方案一:在线画板 —— p5.js Web Editor (打开即用)
这是最简单、最快速的入门方式,无需在你的电脑上安装任何软件。
- 打开浏览器,访问 p5.js Web Editor。
- 你会看到一个清晰的界面,主要分为三个部分:左侧是代码编辑器,你将在这里编写代码;右侧是预览窗口,实时展示你的代码生成的可视化结果;底部是控制台,用于显示信息或错误。
- 你可以直接在编辑器中开始编写代码,点击顶部的“Play”按钮即可运行。
方案二:本地画室 —— Trae + p5.js
为什么需要本地开发环境?
在线编辑器虽然方便,但有时需要离线工作,或需要使用本地资源(如图片、音频)。
如果要将项目文件保存在本地,并使用更专业的代码编辑器,VSCode是绝大多数程序员的选择。
但在AI时代,我们推荐使用 Trae,由字节跳动出品,一个免费的带AI助手的VSCode。
环境配置步骤(带大家操作)
- 安装 Trae:前往 Trae CN 官网 下载并安装。 国际版地址:TRAE - The Real AI Engineer
下载完成后,打开Trae:
- 安装 Live Server 插件:在 Trae的扩展商店中搜索并安装 "Live Server" 插件。它能帮你创建一个本地服务器,并实现代码保存后浏览器自动刷新。
-
创建项目文件:
- 创建一个项目文件夹,例如
p5-art。 - 在文件夹中创建三个文件:
index.html,style.css,sketch.js。
- 创建一个项目文件夹,例如
动手练习:搭建你的本地“数字画室”
让我们通过本地方式,把画室搭建起来。
练习目标: 创建一个能运行p5.js代码的基本HTML页面。
步骤:
-
编写
index.html文件:将以下代码复制到你的
index.html文件中。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- 引入 p5.js 核心库 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/p5.js"></script>
<!-- (可选) 引入 p5.js 音频库 -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/addons/p5.sound.min.js"></script> -->
<meta charset="utf-8" />
</head>
<body>
<main>
</main>
<!-- 引入你自己的 sketch 文件 -->
<script src="sketch.js"></script>
</body>
</html>
代码解读:
HTML代码用于搭建并呈现我们网页的基本框架结构,这段HTML代码做了两件重要的事:
- 通过
<script>标签从一个公共CDN(内容分发网络)地址加载了p5.js的核心库。这意味着我们的“画板工具箱”已经准备好了。——引入资源 - 加载了我们自己的
sketch.js文件,这是我们即将开始创作的地方。——写核心p5代码的地方。
-
编写
style.css文件(可选):将以下代码复制到
style.css,它可以让我们的画布居中显示,看起来更舒服。body { margin: 0; padding: 0; height: 100%; display: flex; justify-content: center; align-items: center; background-color: #222; /* 给页面一个深色背景,突出画布 */ } -
编写
sketch.js文件(初始代码):现在,在
sketch.js文件里写下我们第一行“魔法咒语”。
function setup() {
createCanvas(400, 400); // 创建一个400x400像素的画布
}
function draw() {
background(220); // 设置背景颜色
text("你好! P5.js !",100,100)
}
- 运行!:在
index.html文件上右键,选择 "Open with Live Server",浏览器就会自动打开并运行你的作品。
- 修改js代码后,按ctrl+s保存,浏览器会自动刷新页面。
第二部分、p5.js 的魔法咒语:基本结构
p5.js是个JavaScript的创意编程程式库,其专注在让编程更易于使用及更加广泛的包容艺术家、设计师、教育家、初学者以及任何人!
小白解释版:
JavaScript是一门编程语言,p5.js就是在这门语言上的咒语库(多种法术张口就用,力量强大。Harry Potter里的索命咒: 阿瓦达啃大瓜!)
可以点击p5.js 官网寻找更多信息
2.1 认识代码结构
来看一个最基础的p5.js代码结构:
每个 p5.js 项目(我们称之为 "sketch")都会有两个核心函数进行构建:setup() 和 draw()。你可以把它们想象成一位画家创作的两个阶段。
setup()函数:
setup()函数就像是画画前的准备工作:把画布置于画架,挤好颜料,选好画笔。这个过程只发生一次。
draw()函数:
draw()函数则是持续不断的绘画动作:一笔一笔地将颜料涂上画布。这个过程会循环往复,默认每秒重复约60次,从而形成动画。
程序执行流程:
- 首先执行setup()函数一次
- 然后持续执行draw()函数内的代码,直到程序停止。
示例练习:颜色变换小动画
我们在 setup 函数中创建“画布”,在 draw 函数中让画布“动画化”。
将下面的代码复制到js文件中:
function setup() {
createCanvas(200, 200); // <- 创建画布
}
function draw() {
background(220); // <- 设置背景色
}
上面的代码创建了一个 200x200 的画布,背景色为灰色。呈现效果:
你可能会奇怪,我们明明添加了 draw 函数,并且它会每秒画60次,为什么画布没有任何动画?
好问题!因为我们的 draw 函数每一次重绘后都是相同的,它始终将背景色设置为 220 这个灰阶值(后文会介绍颜色)。既然每一次都是相同的,那么我们也就看不出任何动画过程了。
修改: 改变draw 函数内的代码,让背景色随着帧数量而变化:
function draw() {
background(frameCount % 255); // <- 随着帧数量而变化灰阶值
text("帧数: " + frameCount, 100, 100); //显示当前帧数
}
观察: 出现了什么样的效果?
-
动态变化的关键:
frameCount % 255frameCount:系统内置的变量,代表程序从运行开始时到当前的 “总帧数”(默认每秒 60 帧,随时间递增)。%(取模运算符):计算frameCount除以 255 后的余数。由于余数范围始终是 0-254(当frameCount为 255 时,余数为 0;256 时余数为 1,以此类推),相当于把 “持续递增的帧数” 限定在 0-254 的区间内。
-
最终效果
随着程序运行,background()的参数会从 0(黑)→1→2→…→254(接近白)→0(黑)循环变化,画布背景会呈现 “从黑逐渐变浅、到接近白后瞬间回到黑、再重新变浅” 的周期性灰阶渐变效果
2.2 引入文本和图片
文本
创建文本的方法叫 text()。
语法如下:
text(str, x, y)
str: 文本x和y是文本基线左侧的坐标
使用 textSize() 方法可以修改文字的字号
textSize(100)
text('雷猴', 20, 100)
图片
一般把图片和视频等资源加载写在 preload() 里。
-
我们使用
loadImage()方法加载图片。——(从网络链接或本地拿过来) -
使用
image()方法渲染图片。——(渲染到画面上)
注意:加载和渲染是分开2步操作的!
示例代码
let img = null
function preload() {
img = loadImage('https://p3-passport.byteimg.com/img/user-avatar/848d36b5efa8e055ab080bff4f27e669~180x180.awebp') // 加载图片
}
function setup() {
createCanvas(180, 180) // 创建画布
}
function draw() {
image(img, 0, 0) // 渲染图片
}
2.3 p5.js的注释
在代码中添加注释是一个好习惯,注释是对你接下来这部分代码的功能说明和解释。
在p5.js中,使用//来添加单行注释,
使用/* */来添加多行注释。
// 这是一个单行注释
/*
这是一个多行注释
可以跨越多行
*/
动手练习 :改变世界
尝试修改你的代码,
- 在setup()中,使用
createCanvas()函数,将画布变得更像一个宽屏电影(600x400像素) - 在draw()中,使用
text()函数写下: “你好,我的第一个p5世界!”. 文字大小设置为50. - 修改
background()函数,把背景色从灰色变成你喜欢的任何颜色(例如,天空蓝)。 - 尝试: 修改
createCanvas()函数的参数,创建一个铺满你浏览器窗口的画布。p5.js为此提供了两个便捷的内置变量:windowWidth和windowHeight。
示例代码
function setup() {
// 练习:将画布尺寸改为 600 宽, 400 高
createCanvas(600, 400);
// createCanvas(windowWidth, windowHeight);
}
function draw() {
// 练习:使用 RGB 值将背景设置为天蓝色
// 提示:天蓝色的 RGB 值大约是 (135, 206, 235)
background(135, 206, 235);
textSize(50)
text('你好,我的第一个p5世界!', 20, 100)
}
三、p5.js的基本形状和颜色
P5.js的坐标系统
在 P5.js 中画画,首先要懂 “画布上的位置”—— 坐标系统。
类比:就像手机屏幕,左上角是 “起点”(0,0),向右 x 坐标变大,向下 y 坐标变大(和数学坐标系不同,记好这个区别!)。
示例:
- 画布左上角:(0, 0);
- 400x400 画布的中心:(200, 200);
- 画布右下角:(400, 400)。
左侧的是笛卡尔座标系,0,0 位于中间。而右图计算机图形学中的座标系 0,0 位于左上角。所以你会发现我们上面的代码中,并没有负数座标值。
3.1 常用基本图形
P5.js 提供了现成的 “画笔工具”,能直接画点、线、矩形、圆形等,核心函数如下:
| 图形 | 函数语法 | 说明 |
|---|---|---|
| 点 | point(x, y) | (x,y) 是点的坐标 |
| 线 | line(x1,y1, x2,y2) | 从 (x1,y1) 到 (x2,y2) 的直线 |
| 矩形 | rect(x,y, w,h) | 左上角 (x,y),宽 w,高 h |
| 圆形 / 椭圆 | ellipse(x,y, w,h) | 中心 (x,y),宽 w,高 h(w=h 时是圆形) |
| 三角形 | triangle(x1,y1, x2,y2, x3,y3) | 三个顶点的坐标 |
| 弧线 | arc(x,y, w,h, start, end) | 中心 (x,y),宽 w 高 h,从 start 到 end 弧度 |
练习
在练习区里面试试自己画矩形、椭圆、线和点,代码如下:
function setup() {
createCanvas(200, 200);
}
function draw() {
point(81, 70); // <- 绘制一个点,座标 81, 70
line(90, 150, 80, 160); // <- 绘制一条线,起点座标 90, 150,终点座标 80, 160
rect(100, 100, 20, 100); // <- 绘制一个矩形,座标 100, 100,宽 20,高 100
ellipse(100, 70, 60, 60); // <- 绘制一个椭圆,座标 100, 70,宽 60,高 60
ellipse(81, 70, 16, 32); // <- 绘制一个椭圆,座标 81, 70,宽 16,高 32
}
3.2 p5.js的色彩体系
3.2.1 颜色如何控制
设置色彩:
background(r, g, b): 设置背景色。fill(r, g, b): 设置图形的填充色。stroke(r, g, b): 设置图形的描边(轮廓)色。
取消:
noFill(): 取消填充。noStroke(): 取消描边。strokeWeight(数值):设置边框粗细;
注意: fill() 和 stroke() 的设置会一直生效,直到你再次调用它们来改变颜色。这就像画画时,除非你换一支画笔,否则会一直使用当前画笔的颜色。
案例练习
试试下面的代码会出现什么颜色:
function draw() {
background(220);
fill(255, 0, 0); // 红色填充
stroke(0, 0, 255); // 蓝色描边
strokeWeight(5); // 描边粗细5像素
ellipse(200, 200, 100, 100);
fill(0, 255, 0, 127); // 绿色+半透明(第4个参数是透明度0~255)
noStroke(); // 关闭描边
rect(250, 250, 80, 80);
}
3.2.2 不同颜色模式
p5 提供了多种颜色表示方式,包括 RGB、HSB、CSS颜色名、hex十六进制颜色等。
代码:
颜色默认用 RGB(红、绿、蓝)模式表示,每个值的范围是 0 到 255。
function setup() {
createCanvas(260, 100);
}
function draw() {
background(200); // <- 单个数字参数,作为灰阶
noStroke(); // 无描边
fill(255, 0, 0); // <- RGB 颜色,红色
circle(30, 50, 40);
}
HSB 色相(H)、饱和度(S)、亮度(B)颜色模式:
colorMode(HSB); // <- 改为 HSB 颜色模式
fill(50, 55, 100); // <- HSB 颜色,黄色
circle(80, 50, 40);
其它颜色模式:
fill("green"); // <- CSS 颜色,绿色
circle(180, 50, 40);
fill("#4A58DF"); // <- Hex 颜色,蓝色
circle(230, 50, 40);
我们首先设置了颜色模式和背景色,然后连续创建了五个不同颜色的圆,它们的颜色使用方法各不相同。
fill 函数调用以后的所有图形都会具有这个颜色,直到下一个 fill 函数调用。这就是为什么我们要先调用 fill 再调用 circle。
当 background、fill 等函数的颜色参数存在第四个值时,它表示 Alpha,代表透明度。
关于HSB
在 HSB 模式中,颜色由如下三种值组成:
-
H(hue)代表色相:在0~360°的标准色轮上,色相是按位置度量的。在通常的使用中,色相是由颜色名称标识的,比如红、绿或橙色。黑色和白色无色相。
-
S(saturation)表示饱和度:表示色彩的纯度,为0时为灰色。白、黑和其他灰色色彩都没有饱和度的。在最大饱和度时,每一色相具有最纯的色光。取值范围0~100%。数值越大,颜色中的灰色越少,颜色越鲜艳,呈现一种从灰度到纯色的变化。
-
B(brightness)表示亮度:其作用是控制色彩的明暗变化。它同样使用了 0% 至 100% 的取值范围。数值越小,色彩越暗,越接近于黑色;数值越大,色彩越亮,越接近于白色。
3.2.3 案例:画一幅小风景
结合图形和颜色,画一幅包含太阳、山、树的风景:
function setup() {
createCanvas(600, 400);
colorMode(HSB, 360, 100, 100); // 用HSB模式调色
}
function draw() {
// 背景(从浅蓝到深蓝的渐变效果:每帧改背景色,配合循环产生渐变)
background(frameCount % 360, 30, 100);
// frameCount:当前循环次数,%360让色相在0-360循环
// 太阳(右上角橙色圆形)
fill(45, 100, 100); // 色相45=橙色
noStroke();
ellipse(500, 100, 80, 80);
// 山(两个三角形)
fill(120, 50, 70); // 色相120=绿色
triangle(0, 400, 300, 150, 600, 400); // 大山顶点
triangle(100, 400, 300, 250, 500, 400); // 小山顶点
// 树(矩形树干+圆形树冠)
// 树干
fill(30, 80, 40); // 色相30=棕色
rect(100, 320, 20, 80);
// 树冠
fill(120, 80, 60);
ellipse(110, 300, 60, 60);
ellipse(80, 280, 60, 60);
ellipse(140, 280, 60, 60);
}
3.2.4 动手练习:个性化风景
练习目标
修改案例代码,添加1种新图形(如云朵、房子、河流),并调整颜色搭配。
练习提示
- 云朵:用多个白色椭圆叠加(ellipse());
- 房子:矩形 + 三角形屋顶(rect()+triangle());
- 河流:蓝色矩形加圆角(rect()后用rectMode(CENTER)调整锚点);
- 可切换回 RGB 模式试试不同调色效果。
参考代码(带云朵和房子)
function setup() {
createCanvas(600, 400);
colorMode(RGB); // 切换回RGB模式
}
function draw() {
// 背景(固定天空蓝)
background(135, 206, 235);
// 云朵(多个白色椭圆)
fill(255);
noStroke();
ellipse(200, 100, 60, 40);
ellipse(230, 100, 70, 45);
ellipse(260, 100, 60, 40);
ellipse(180, 110, 50, 35);
ellipse(270, 110, 50, 35);
// 太阳
fill(255, 204, 0);
ellipse(500, 100, 80, 80);
// 山
fill(34, 139, 34);
triangle(0, 400, 300, 150, 600, 400);
fill(46, 139, 87);
triangle(100, 400, 300, 250, 500, 400);
// 房子
// 屋顶
fill(139, 69, 19);
triangle(400, 280, 480, 280, 440, 230);
// 房身
fill(255, 248, 220);
rect(400, 280, 80, 100);
// 窗户
fill(173, 216, 230);
rect(415, 300, 20, 20);
rect(445, 300, 20, 20);
// 树
fill(139, 69, 19);
rect(100, 320, 20, 80);
fill(34, 139, 34);
ellipse(110, 300, 60, 60);
ellipse(80, 280, 60, 60);
ellipse(140, 280, 60, 60);
}
四、 赋予生命:p5.js的动画与交互
4.1 动画的原理:draw()每一帧与变量
什么是动画? 动画的原理是通过快速连续地绘制画面,使人类大脑产生运动的错觉。就像早期的电影和动画一样,每秒展示24-60帧画面,就能让我们看到连续的运动。
p5.js中的动画实现:
draw()函数每秒执行多次(默认60次)- 在
draw()中使用变量(如frameCount)来控制图形的位置、大小或颜色,实现变化效果
如何做到“略有不同”呢?答案是变量。
让我们来看一个最简单的动画:一个向右移动的圆。
let x = 0; // 定义一个变量x,表示圆的水平位置
function setup() {
createCanvas(600, 400);
}
function draw() {
background(220); // 每帧都重绘背景,清除上一帧的圆
ellipse(x, 200, 50, 50); // 在(x, 200)位置画圆
x = x + 2; // 关键!每一帧都让x的值增加1
// 当圆移动到画布外时,让它回到起点
if (x > width) { // 'width'是p5.js内置变量,代表画布宽度
x = 0;
}
}
在这个例子里,x 的值在 draw() 的每一次循环中都会改变为x + 2,导致圆的位置也随之改变,从而形成了动画。
4.2 鼠标交互:让作品 “活” 起来
P5.js 自带鼠标相关的变量和函数,能轻松实现 “跟随鼠标”、“点击变色” 等交互效果。
4.2.1 鼠标相关的变量
p5.js 提供了一些非常有用的系统变量,它们会随着程序的运行而自动更新。其中最常用的就是鼠标坐标:
mouseX: 当前鼠标指针的水平位置 (x坐标)。mouseY: 当前鼠标指针的垂直位置 (y坐标)。mouseIsPressed: 一个布尔值(true或false),如果鼠标被按下,它就是true。
因为 draw() 函数在不断循环,我们可以在每一帧都使用 mouseX 和 mouseY 来绘制图形,这样图形的位置就会实时跟随你的鼠标移动。
案例:鼠标跟随的彩色圆圈
function setup() {
createCanvas(600, 600);
// 如果我们把背景放在setup里,这样画出的笔迹就不会被清除了。
// background(220);
}
function draw() {
background(220);
fill(random(255), random(255), random(255));
// 按下鼠标会变色
if (mouseIsPressed) {
fill(255, 0, 0);
}
ellipse(mouseX, mouseY, 50, 50);
}
效果: 当鼠标在画布上移动时,会显示一个彩色的圆形,位置与鼠标位置一致。按住鼠标,圆形变色。
4.2.2 鼠标键盘的事件函数
除了跟踪鼠标位置,我们还可以响应用户的具体操作,比如点击鼠标或按下键盘。在P5.js中也内置了相关的 事件函数 来实现。
常用事件函数:
这些函数会在特定事件发生时自动被p5.js调用,你只需要定义它们即可。
-
mousePressed(): 当鼠标被按下时,这个函数里的代码会执行一次。 -
mouseMoved(): 当鼠标在画布上移动时(无论是否按下)执行。 -
mouseDragged(): 当鼠标按住并拖动时执行。 -
keyPressed(): 当任意键盘按键被按下时执行。
使用方式案例:
let brushColor; // 用一个变量来存储画笔颜色
function setup() {
createCanvas(windowWidth, windowHeight); // 画布铺满浏览器窗口
background(0); // 黑色背景
brushColor = color(255, 0, 0); // 初始画笔颜色为红色
}
function draw() {
}
//鼠标移动时,函数被触发
function mouseMoved() {
fill(brushColor);
// 在鼠标位置绘制一个直径为30的圆
circle(mouseX, mouseY, 30);
}
// 当鼠标被点击时,这个函数会被触发
function mousePressed() {
// 生成一个随机颜色
brushColor = color(random(255), random(255), random(255));
}
//按下键盘时,触发
function keyPressed() {
stroke(0,0,255)
//是否可以加入if判断,使得当特定的键被按下才会响应?
}
控制动画播放和暂停的两个函数:
loop():让draw()函数恢复循环执行,类比 “动画播放按钮”;
noLoop():让draw()函数停止循环执行(只执行 1 次),类比 “动画暂停按钮”;
五、项目练习:创世纪——你的互动星空
现在,是时候将本节课所学的一切融会贯通,创造一个完整的、具有艺术感的互动作品了。
这个项目将模拟一个可以由你亲手创造和互动的宇宙星空。
5.1 项目目标
创造一个名为“创世纪”的互动艺术作品,它具备以下特征:
- 动态的宇宙背景: 背景颜色会像深空星云一样缓慢变化。
- 随机的初始星辰: 程序开始时,会自动生成一片随机分布的星星。
- 追随鼠标的彗星: 一道由光点组成的“彗星”或“星尘”会跟随着你的鼠标轨迹。
- 点击创生新星: 每当你在画布上点击鼠标,就会在那个位置“诞生”一颗新的、闪亮的星星。
5.2 步骤分解与代码实现
让我们一步步来构建这个小宇宙。
完整代码结构预览:
let stars = []; // 用一个数组来存储所有星星的信息
function setup() {
createCanvas(windowWidth, windowHeight);
// ... 初始化代码 ...
}
function draw() {
// ... 绘制背景和动画 ...
}
function mousePressed() {
// ... 处理鼠标点击事件 ...
}
Step 1: 搭建夜空背景
在 draw() 函数中,我们将用 background() 创造一个缓慢变化的背景。我们可以使用 frameCount 这个p5.js内置变量,它记录了程序已经运行的总帧数。
// 在 draw() 函数中
function draw() {
// 使用 sin 函数创造一个在 0-100 之间平滑变化的蓝色调
// frameCount * 0.01 控制了颜色变化的速度
let bgColor = map(sin(frameCount * 0.01), -1, 1, 0, 100);
background(0, 10, bgColor);
// ... 后续代码将在这里添加 ...
}
Step 2: 播撒初始星辰
我们需要在程序开始时就创建一些星星。最好的地方是在 setup() 函数中。我们可以用一个 for 循环来完成这件事。为了让星星可以被管理(比如之后让它们闪烁),我们最好用一个数组 stars 来存储它们的位置。
let stars = []; // 在文件顶部定义数组
const starCount = 500; // 定义星星的数量
function setup() {
createCanvas(windowWidth, windowHeight);
// 在 setup 中生成初始的星星
for (let i = 0; i < starCount; i++) {
stars.push({
x: random(width), // 在画布宽度范围内随机一个x坐标
y: random(height), // 在画布高度范围内随机一个y坐标
size: random(1, 3), // 随机大小
brightness: random(150, 255) // 随机亮度
});
}
}
// 然后在 draw() 函数中把它们画出来
function draw() {
// ... 背景代码 ...
// 遍历星星数组,并绘制每一颗星星
stroke(255); // 星星用白色描边
for (let star of stars) {
strokeWeight(star.size);
point(star.x, star.y);
}
// ... 后续代码 ...
}
Step 3: 绘制追随鼠标的彗星
我们利用 mouseX, mouseY 以及 pmouseX, pmouseY 来创造拖尾效果。
// 在 draw() 函数的末尾添加
function draw() {
// ... 背景和星星的代码 ...
// 绘制彗星尾巴
stroke(255, 255, 200, 150); // 淡黄色,半透明
strokeWeight(4);
line(mouseX, mouseY, pmouseX, pmouseY); // 连接当前帧和上一帧的鼠标位置
}
Step 4: 点击诞生新星
我们将使用 mousePressed() 事件函数。当用户点击时,我们向 stars 数组中添加一颗新的星星。这颗新星会更大、更亮,像一颗刚刚爆发的超新星。
// 在文件底部添加 mousePressed 函数
function mousePressed() {
// 当鼠标点击时,在鼠标位置添加一颗明亮的大星星
stars.push({
x: mouseX,
y: mouseY,
size: random(5, 8), // 更大尺寸
brightness: 255 // 最亮
});
}
5.3 完整参考代码
将所有部分整合起来,你的 sketch.js 应该是这样的:
// sketch.js - 互动星空项目
let stars = [];
const starCount = 500;
function setup() {
createCanvas(windowWidth, windowHeight);
// 生成初始的静态星星
for (let i = 0; i < starCount; i++) {
stars.push({
x: random(width),
y: random(height),
size: random(1, 3)
});
}
}
function draw() {
// 1. 绘制缓慢变化的背景
let bgColor = map(sin(frameCount * 0.01), -1, 1, 10, 70);
background(0, 5, bgColor);
// 2. 绘制所有星星
for (let star of stars) {
// 让星星闪烁
let brightness = random(150, 255);
stroke(brightness); // 随机亮度
strokeWeight(star.size);
point(star.x, star.y);
}
// 3. 绘制跟随鼠标的彗星
stroke(255, 255, 200, 150);
strokeWeight(4);
line(mouseX, mouseY, pmouseX, pmouseY);
}
// 4. 当鼠标点击时,诞生一颗新星
function mousePressed() {
stars.push({
x: mouseX,
y: mouseY,
size: random(4, 7) // 新诞生的星星更大
});
}
六、课程总结
今天,我们一起走过了从零到一的创意编程旅程。我们:
- 搭建了p5.js的本地开发环境。
- 理解了p5.js的核心结构
setup()和draw()。 - 学会了如何使用函数绘制基础图形和控制颜色。
- 掌握了通过鼠标和系统变量实现动画与交互的核心方法。
- 最终,我们亲手创造了一个动态的、可交互的“互动星空”艺术作品。
创意编程展望
今天的课程只是一个开始。p5.js的世界远比我们今天探索的要广阔和深邃。
p5.js官方资源:
- 官方文档:p5.js官网
- 官方示例库:p5.js Examples
- 官方教程:p5.js Tutorials
代码对于艺术家而言,不是一堆冰冷的逻辑,而是我们手中又一种全新的、充满无限可能的媒介。
永远记住:
不要畏惧代码,它和画笔、颜料一样,最终服务于我们的思想、情感和创意的表达。
不要害怕犯错,每一个bug都是一次学习的机会。
七、课后作业:简单彩虹画笔
作业概述:
- 作业名称:简单彩虹画笔
- 难度等级: ⭐⭐(简单)
- 预计完成时间: 30-45分钟
- 涉及知识点:p5.js图形创建、鼠标交互、颜色变化、键盘控制
作业目标:
创建一个简单的彩虹画笔,移动鼠标可以画出彩虹色的线条,按空格键可以清除画布重新开始。
详细实现步骤:
第一步:创建基础画布
目标: 建立最基础的P5.js项目
步骤说明:
- 创建setup()函数,设置画布大小
- 创建draw()函数,设置背景色
- 使用HSB颜色模式,更容易创造彩虹效果
参考代码:
function setup() {
// 创建600x400的画布
createCanvas(600, 400);
// 设置白色背景
background(255);
// 使用HSB颜色模式,彩虹色更容易实现
colorMode(HSB);
}
function draw() {
// 暂时什么都不做
}
验证点:
- 画布是否正确显示?
- 背景是否为白色?
第二步:实现鼠标画线
目标: 鼠标移动时画出线条
步骤说明:
- 在draw()函数中添加画线代码
- 使用line()函数连接鼠标位置
- 设置线条的颜色和粗细
参考代码:
function setup() {
createCanvas(600, 400);
background(255);
colorMode(HSB);
}
function draw() {
// 设置线条颜色为蓝色
stroke(240, 80, 90);
// 设置线条粗细
strokeWeight(5);
// 从上一位置到当前位置画线
line(pmouseX, pmouseY, mouseX, mouseY);
}
验证点:
- 移动鼠标是否能画出线条?
- 线条是否为蓝色?
- 线条粗细是否合适?
第三步:添加彩虹效果
目标: 让线条颜色随时间变化,产生彩虹效果
步骤说明:
- 使用frameCount变量获取当前帧数
- 用帧数计算颜色值
- 颜色在0-360之间循环变化
参考代码:
function setup() {
createCanvas(600, 400);
background(255);
colorMode(HSB);
}
function draw() {
// 计算彩虹色(0-360循环)
let rainbowColor = frameCount % 360;
// 设置线条颜色
stroke(rainbowColor, 80, 90);
// 设置线条粗细
strokeWeight(5);
// 画线
line(pmouseX, pmouseY, mouseX, mouseY);
}
验证点:
- 线条颜色是否随时间变化?
- 是否能看到彩虹色效果?
- 颜色变化是否流畅?
第四步:添加清除功能
目标: 按空格键清除画布
步骤说明:
- 添加keyPressed()函数
- 检测空格键是否被按下
- 按下时重新填充背景色
参考代码:
function setup() {
createCanvas(600, 400);
background(255);
colorMode(HSB);
}
function draw() {
// 计算彩虹色
let rainbowColor = frameCount % 360;
// 设置线条颜色和粗细
stroke(rainbowColor, 80, 90);
strokeWeight(5);
// 画线
line(pmouseX, pmouseY, mouseX, mouseY);
}
// 添加键盘事件
function keyPressed() {
// 如果按下空格键
if (key === ' ') {
// 清除画布(重新填充白色背景)
background(255);
}
}
验证点:
- 按空格键是否能清除画布?
- 清除后是否能重新绘画?
- 彩虹效果是否仍然存在?
第五步:添加操作提示
目标: 在画布上显示操作说明
步骤说明:
- 在draw()函数中添加文字显示
- 显示简单的操作提示
- 设置文字样式
参考代码:
function setup() {
createCanvas(600, 400);
background(255);
colorMode(HSB);
}
function draw() {
// 计算彩虹色
let rainbowColor = frameCount % 360;
// 设置线条颜色和粗细
stroke(rainbowColor, 80, 90);
strokeWeight(5);
// 画线
line(pmouseX, pmouseY, mouseX, mouseY);
// 显示操作提示
fill(0); // 黑色文字
noStroke(); // 文字无边框
textAlign(LEFT); // 左对齐
textSize(16); // 字体大小
text("移动鼠标绘画,按空格键清除", 10, 30);
}
function keyPressed() {
if (key === ' ') {
background(255);
}
}
验证点:
- 是否显示操作提示?
- 文字是否清晰可读?
- 提示是否影响绘画效果?
第六步:优化绘画效果
目标: 让绘画效果更好看
步骤说明:
- 增加线条粗细
- 调整颜色饱和度和亮度
- 添加简单的淡出效果
参考代码:
function setup() {
createCanvas(600, 400);
background(255);
colorMode(HSB);
}
function draw() {
// 添加轻微淡出效果,让线条更柔和
background(255, 255, 255, 10);
// 计算彩虹色
let rainbowColor = frameCount % 360;
// 设置线条颜色和粗细
stroke(rainbowColor, 90, 90); // 更鲜艳的颜色
strokeWeight(8); // 更粗的线条
// 画线
line(pmouseX, pmouseY, mouseX, mouseY);
// 显示操作提示
fill(0);
noStroke();
textAlign(LEFT);
textSize(16);
text("移动鼠标绘画,按空格键清除", 10, 30);
}
function keyPressed() {
if (key === ' ') {
background(255);
}
}
验证点:
- 线条是否更粗更鲜艳?
- 是否有轻微的淡出效果?
- 整体效果是否更好看?
完整参考代码
function setup() {
// 创建画布
createCanvas(600, 400);
// 设置白色背景
background(255);
// 使用HSB颜色模式
colorMode(HSB);
}
function draw() {
// 添加轻微淡出效果
background(255, 255, 255, 10);
// 计算彩虹色(0-360循环)
let rainbowColor = frameCount % 360;
// 设置线条颜色(高饱和度,高亮度)
stroke(rainbowColor, 90, 90);
// 设置线条粗细
strokeWeight(8);
// 画彩虹线
line(pmouseX, pmouseY, mouseX, mouseY);
// 显示操作提示
fill(0);
noStroke();
textAlign(LEFT);
textSize(16);
text("移动鼠标绘画,按空格键清除", 10, 30);
}
// 键盘事件
function keyPressed() {
// 按空格键清除画布
if (key === ' ') {
background(255);
}
}
提交要求
- 完整的P5.js代码文件
- 一张你的彩虹画笔作品截图
- 简单的一句话感想