查看原文
其他

p5.js 光速入门

作者:德育处主任

https://juejin.cn/post/7173451612654927908

本文的目标是一起有序的快速上手 p5.js ,会讲解 p5.js 的基础用法。

本文会涉及到的内容包括:

  • 项目搭建
  • p5.js 基础2D图形
  • 文字
  • 图形样式设置
  • 图片
  • 事件(交互相关的)
  • 基础动画

其中还会讲解部分 p5.js 全局方法。

官方文档很重要,但对于初学者来说可能会有点懵。因为官方文档主要讲解api的用法,第一次接触p5.js的工友可能不是那么容易将各个知识点串联起来。

本文在基于官方案例的基础上,把我觉得入门必学的知识点过一遍,然后串起来搞一个小特效。

要快速学习一个库,尤其是可视化方面的库,最快速的方法是找到一个好教程,然后跟着敲代码,建立自己的 “demo仓库” 。

学习本文内容,你需要有 JavaScript 基础。

什么是p5.js

p5.js 简介

引用官网的话:

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

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

简单来说,p5.js 能让“切图仔”更容易做出具有艺术感的作品(很能整活)。

举个例子,p5.js 很擅长实现下面这种效果。

p5.jsProcessing 往浏览器延伸的一个 canvas库Processing 是使用 Java 编写的,而 Java 对于从事艺术工作的工友来说上手是有点难度的。

浏览器暂时只接受 HTMLCSSJavaScript,如果能将 Processing 直接搬上浏览器运行的话,对于艺术家来说是大大的好事。于是,p5.js 应运而生!

p5.js 第一个测试版在 2014年8月 发布。

更多的故事可在 p5.js 官网中寻找,本文的目标是光速入门 p5.js

找到 p5.js

  • p5.js 官网[1]
  • p5.js github地址[2]
  • p5.js npm地址[3]

快速上手

本文的目标是和各位工友快速上手 p5.js,所以 CDN 的方式引入 p5.js,因为这样非常快!

接下来我们试试在画布创建一个圆形吧~

环境搭建

CDN

<script src="https://cdn.jsdelivr.net/npm/p5@[p5_version]/lib/p5.js"></script>

[p5_version] 改成指定版本号即可,本文使用的版本是 1.5.0 ,所以我是这样引入 1.5.0 版的 p5.js

<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>

查看其他版本可以浏览:https://cdn.jsdelivr.net/npm/p5@1.5.0/

npm

安装

npm i p5 --save

引入

import p5 from 'p5'

在画布创建一个圆形

我使用的开发工具是 vs code,并装了 Live Server 插件[4]。这个插件可以帮我们快速启动一个服务端运行当前页面,并具备热更新的能力。启动完服务,在浏览器运行指定页面后,你代码的每一次保存,浏览器都会自动刷新。

02.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(200, 200) // 创建一个 200 * 200 像素的画布
    background(180, 180, 180) // 画布背景色 background(r, g, b)
  }

  function draw() {
    circle(60, 60, 100) // 画一个圆形
  }
</script>

上面的代码用到几个“奇怪”的方法,逐一讲解一下。

  • setup(): 可以理解为 p5.js 的一个生命周期,创建画布的方法通常写在 setup() 里。
  • draw(): 同样可以理解为 p5.js 的一个生命周期,在这函数里的代码会以 60帧每秒 的速度执行。
  • createCanvas(): 创建画布的方法,这个方法是 p5.js 在全局创建的,传入画布的宽高后,p5.js 会自动在页面的最后插入一个 canvas 元素。
  • background(): 设置背景色,可以分别传入 r、g、b ,该方法也是 p5.js 在全局创建的。
  • circle(): 创建圆形的方法,3个参数分别代表:圆心x坐标、圆心y坐标、直径。

暂时只需大概了解一下怎么画一个圆就行,详细的后面会讲到。

项目代码结构

使用 p5.js ,你可以理解为用这个工具创造一个“有生命”的世界。

  • 创造世界的工作是放在 setup() 函数里的。

  • “有声明” 的意思是这个世界有生物,生物无时无刻都在活动。而活动的过程是放在 draw() 函数里。

setup()draw() 这两个函数非常重要,在前端的世界里,你可以把 setup()draw() 理解为生命周期函数。

启动函数 setup

使用 CDN 的方式开发时,引入 p5.js 后就会在全局创建一些函数和常量。

setup()p5.js 里一个很重要的方法,你可以简单的理解为 setupp5.js 里的一个生命周期函数。在该函数里可以做很多初始化工作,比如创建画布并设置大小、画布背景色等。

setup() 在每个页面都只能出现一次,并且它不能在一开始执行后再次被调用。

更多说明可查看 `setup()说明文档`[5]

绘图 draw

draw()p5.js 里另一个很重要的函数。

draw() 会在 setup() 之后执行,并且会重复的执行。如果想打断 draw() 可以试用 noLoop() 方法。

draw() 每秒执行次数受到 frameRate() 影响,frameRate() 默认每秒60帧。如果需要修改帧率,可以直接传入指定数值,比如 frameRate(20)

如果要做动画,代码可以写在 draw() 里。

更多说明可查看 `draw()说明文档`[6]

2D基础图形

p5.js 可以绘制 2D 和 3D 图形,但在光速入门阶段只会讲解 2D 图形的基础用法。

先从最简单的点线面开始学起~

点 point

点是 p5.js 的基础元素之一,语法如下:

point(x, y, [z])

point() 接收3个参数,其中 xy 是必传参;如果是在 2D 画布里,z 不需要传。

  • x 表示点在 x 轴的坐标
  • y 表示点在 y轴的坐标

点出现在画布的中间

03.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(200, 200)
    background(220, 220, 220)
  }

  function draw() {
    point(100, 100)
  }
</script>

上面的例子中,画布的宽高是200像素,点在 100, 100 的位置,仔细看可以发现点出现在画布的中心。

如果需要画一个更大的点,可以通过 strokeWeight() 方法设置

04.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(200, 200)
    background(220, 220, 220)
  }

  function draw() {
    point(100, 100)
    strokeWeight(10) // 更大的点
  }
</script>

其实 strokeWeight() 方法是用来设置描边粗细的,用在 point 里也完全没问题。

更多说明可查看 `point()说明文档`[7]

线段 line

要画一根线段的语法:

line(x1, y1, [z1], x2, y2, [z2])

注意上面的参数顺序,一定不能写错的。

其中 z1z2 在 2D 情况下是不需要传的,所以语法变成这样:

line(x1, y1, x2, y2)
  • x1y1 代表起点坐标
  • x2y2 代表终点坐标

使用 line() 方法会自动将起点和终点连接起来,形成一根线段。

05.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(200, 200)
    background(220, 220, 220)
  }

  function draw() {
    line(60, 30, 130, 140)
  }
</script>

更多说明可查看 `line()说明文档`[8]

三角形 triangle

三角形的语法是:

triangle(x1, y1, x2, y2, x3, y3)

和前面的 点(point) 和 线段(line) 不同,三角形(triangle) 的所有参数都是必传的。

三角形有3个点,每个点需要用2个坐标(x和y)来描述,所以 triangle() 一共要传入6个参数。

经过前面的 点(point) 和 线段(line) 练习,相信你看到三角形的参数名称就已经知道什么意思了。

确定了3个点的坐标后,triangle() 会使用直线连接这3个点,形成一个三角形。

06.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(200, 200)
    background(220, 220, 220)
  }

  function draw() {
    triangle(100, 30, 40, 140, 160, 140)
  }
</script>

更多说明可查看 `triangle()说明文档`[9]

正方形 square

正方形是特殊的四边形,也可以说是特殊的矩形。

所以先从正方形讲起。

创建正方形用到的方法是 square(),语法如下所示:

square(x, y, s, [tl], [tr], [br], [bl])
  • xy 是正方形左上角的坐标
  • s 是正方形的边长

tltrbrbl 是用来设置正方形的圆角半径,分别是 上左上右下右下左。如果不传这几个参数,正方形的角默认是90°(直角)。

07.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(200, 200)
    background(220, 220, 220)
  }

  function draw() {
    square(10, 10, 80)
  }
</script>

圆角半径

圆角半径参数遵循以下规则:

省略的角半径参数设置为参数列表中先前指定的半径值的值。

意思是,如果只传入1个半径值,那么后面3个圆角半径的值会取左上的圆角半径。

08.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(200, 200)
    background(220, 220, 220)
  }

  function draw() {
    square(10, 10, 80, 10)
  }
</script>

如果是传入2个圆角半径,那第三和第四个圆角半径的值会取第二个的值。

09.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(200, 200)
    background(220, 220, 220)
  }

  function draw() {
    square(10, 10, 80, 10, 30)
  }
</script>

更多说明可查看 `square()说明文档`[10]

矩形 rect

前面了解完 正方形(quad) 如何创建后,学习 矩形(rect) 会觉得非常简单。

p5.js 提供了 rect() 方法绘制矩形,而且会根据参数的数量判断绘制矩形还是绘制正方形。

语法如下:

rect(x, y, w, [h], [tl], [tr], [br], [bl])
  • xy 是矩形左上角坐标位置
  • w 是边长

如果只传3个参数,绘制出来的是正方形(长和宽的值都使用第三个参数)

10.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
   createCanvas(300, 300)
   background(220, 220, 220)
  }

  function draw() {
    rect(10, 10, 60) // 矩形
  }
</script>

如果传4个参数的话,就可以分别设置长和宽了,第3和第4个参数分别是 wy

  • w: x轴方向的长度(宽)
  • h: y轴方向的长度(高)
11.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
   createCanvas(300, 300)
   background(220, 220, 220)
  }

  function draw() {
    rect(10, 10, 60, 100) // 矩形
  }
</script>

后面的4个参数 tltrbrbl 分别设置四个角的圆角半径,不设置的话默认就是90°。用法和正方形一样的,自己动手试试看吧~

更多说明可查看 `rect()说明文档`[11]

四边形 quad

如果需要绘制四边形,使用 quad() 即可。

四边形有4个顶点,1个定点用2个参数表示 xy 坐标。

语法如下:

quad(x1, y1, x2, y2, x3, y3, x4, y4)

需要注意绘制四边形时顶点的绘制顺序

12.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
   createCanvas(300, 300)
   background(220, 220, 220)
  }

  function draw() {
    quad(80, 40, 180, 40, 140, 80, 40, 80) // 四边形
  }
</script>

更多说明可查看 `quad()说明文档`[12]

圆形 circle

圆形是“特殊椭圆”,使用 circle() 方法可以创建圆形。

语法如下:

circle(x, y, d)
  • xy 是圆形的坐标
  • d 是圆的直径
13.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
   createCanvas(300, 300)
   background(220, 220, 220)
  }

  function draw() {
    circle(80, 80, 100) // 圆形
  }
</script>

上面代码的意思:圆心在 (80, 80) 的位置,直径是 100。换算一下半径就是50咯。

更多说明可查看 `circle()说明文档`[13]

椭圆 ellipse

使用 ellipse() 可以创建椭圆,椭圆(ellipse) 的创建方法和 矩形(rect) 其实是有点像的。

ellipse() 方法会根据传入的参数数量判断创建圆形还是创建椭圆。

语法如下:

ellipse(x, y, w, [h])
  • xy 确定了椭圆的圆心
  • w 椭圆在x轴的宽度
  • h 椭圆在y轴的高度

如果只传3个参数,h 会取 w 的值,所以画出来的是正圆形。

如果传4个参数,并且 wh 的值不一样,那画出来就是一个椭圆。

14.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
   createCanvas(300, 300)
   background(220, 220, 220)
  }

  function draw() {
    ellipse(80, 80, 100, 50) // 椭圆
  }
</script>

更多说明可查看 `ellipse()说明文档`[14]

弧状 arc

弧形(arc) 是一个很好玩的方法,你可以用 arc() 画圆形、椭圆、饼图和弧线。

随着功能的增加, arc() 所需的参数也会比圆形和椭圆更多。

先来看看语法:

arc(x, y, w, h, start, stop, [mode], [detail])
  • xy: 圆弧的圆心坐标
  • w : x轴方向的宽度
  • h: y轴方向的高度
  • start: 弧形开始的角度(用弧度定义)
  • stop: 弧形结束的角度(用弧度定义)
  • mode: 定义弧形的画法。可选值:开放式半圆形(OPEN),封闭式半圆形(CHORD),封闭式饼形段(PIE)
  • detail: 指定构成圆弧周长的顶点数量,在 2D 模式下不会用到

我知道有很些工友对弧度制不太熟悉,其实也不需要担心,p5.js 提供了 radians() 方法,可以将角度转成弧度。

接下来我就用角度的方式去画图展示一下 arc() 是如何使用的。

我画4个弧形,分别表示 90°、180° 、270° 和 360°。

15.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
   createCanvas(300, 300)
   background(220, 220, 220)
  }

  function draw() {
    // 左上角的图形,0-90°(角度)
    arc(50, 50, 50, 50, radians(0), radians(90))

    // 右上角的图形,0-180°(角度)
    arc(250, 50, 50, 50, radians(0), radians(180))

    // 左下角的图形,0-270°(角度)
    arc(50, 250, 50, 50, radians(0), radians(270))

    // 右下角的图形,0-360°(角度)
    arc(250, 250, 50, 50, radians(0), radians(360))
  }
</script>

从上面的代码可以看出,0°(角度)是在图形的正右方。

顺便展示一下不同 mode 的效果

16.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
   createCanvas(300, 300)
   background(220, 220, 220)
  }

  function draw() {
    // 左上角的图形,默认
    arc(50, 50, 50, 50, radians(0), radians(270))

    // 右上角的图形,开放式半圆形(OPEN)
    arc(250, 50, 50, 50, radians(0), radians(270), OPEN)

    // 左下角的图形,封闭式半圆形(CHORD)
    arc(50, 250, 50, 50, radians(0), radians(270), CHORD)

    // 右下角的图形,封闭式饼形段(PIE)
    arc(250, 250, 50, 50, radians(0), radians(270), PIE)
  }
</script>

OPENCHORDPIE 这几个常量都不需要我们定义的,p5.js 已经在全局定义好了。

更多说明可查看 `arc()说明文档`[15]

其他图形

除了前面讲到的几个基础图形,p5.js 还提供了贝塞尔曲线、球体、立方体、圆锥等图形元素,甚至还能自定义多边形。

但在光速入门阶段我们只需掌握基础的图形,再加上自己的创意就可以做出很漂亮的作品。

文本

创建文本的方法叫 text()

语法如下:

text(str, x, y, [x2], [y2])
  • str: 文本
  • xy 是文本基线左侧的坐标
  • x2y2 定义文本内容占用的面积,x2 表示宽度,y2 表示高度。
17.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
   createCanvas(300, 300)
   background(220, 220, 220)
  }

  function draw() {
    text('雷猴', 10, 20)
  }
</script>

我们还可以传入 x2y2 参数来控制内容的展示方式。

x2 会影响文本换行方式,y2 控制文本显示的内容。

先说 x2,这个参数是控制文本在 x 轴方向的展示长度,x2 \- x 就可以得出这段文字在 x 轴方向可以展示的长度。

比如一个字符的宽度是 5pxx 设为10,x2 设为20,那么一行就可以展示2个文字。

x2 并不能很好的控制文本长度,它只会判断这行文本里有没有空格,如果出现空格,且超出文本框宽度的内容就会换行。

y2 \- y 得出的长度就是y轴方向可展示的区域。超出这个区域的文本都不会展示出来了。

举个例子

18.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
   createCanvas(300, 300)
   background(220, 220, 220)
  }

  function draw() {
    text(
      'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque et assumenda quibusdam quis, rerum incidunt animi nihil perspiciatis temporibus neque!',
      10,
      20,
      40,
      60
    )
  }
</script>

此时,在 x2y2 的限制下,文本已经无法完全展示出来了。

基础样式

p5.js 提供了几个设置样式的方法,我挑常用的几个来讲讲。

颜色

p5.js 支持多种颜色值,比如 颜色关键字十六进制CSS颜色字符串RGBHSBHSL灰度

关键字 与 十六进制

颜色关键字十六进制CSS颜色字符串 就不多说了,合格的切图仔都懂这个。

  • 关键字: 'red'、'blue' 等
  • 十六进制: #ff0000

需要注意的是 RGBHSBHSL灰度

其中,RGBHSBHSL 都支持传入第4个参数,这个参数表示透明通道。

RGB

RGB 的第4个参数取值范围是 0 ~ 2550 表示完全透明,255 表示完全不透明。

如果不传第4个参数,默认值是 255

我用 background 背景色来举例。

20.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(152, 231, 162) // 设置绿色背景色
  }
</script>

如果此时在 background() 里传入第4个参数就可以改变背景色的不透明度。

比如

21.png
background(152231162100)

HSB 与 HSL

HSBHSL 都是颜色表示的一种方法。

  • HSB: H(Hue) 色相、S(Saturation) 饱和度、B(Brightness) 亮度
  • HSL: H(Hue) 色相、S(Saturation) 饱和度、L(Lightness) 明度

HSBHSL用法 上差不多,但和 RGB 是有区别的。

  1. 使用 HSBHSL 前,要设置颜色模式,告诉 p5.js 要使用哪种颜色模式去渲染。而 RGB 就省略了这步。
  2. HSBHSL 第1个参数取值 0 ~ 360,第2和第3个参数取值是 0 ~ 100。而 RGB 前3个参数的取值都是 0 ~ 255
  3. 在透明度上,HSBHSL 在第4个参数的取值范围是 0 ~ 1 ,而 RGB0 ~ 255

如果要使用 HSB ,就需要使用 colorMode(HSB) 设置一下;HSL 就用 colorMode(HSL) 设置一下。

还是用 background() 举例

22.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    colorMode(HSB) // 设置 HSB 颜色模式
    background(360, 30, 80) // 设置背景色
    // background(360, 30, 80, 0.5) // 背景色,添加透明通道
  }
</script>

灰度

灰度模式的意思是只有 “黑白灰” 三种颜色,而灰色是过渡颜色。

灰度模式是默认的颜色模式,不需要进行特殊设置。

灰度模式的取值范围是 0 ~ 255。0表示黑色,255表示白色,中间的其他值表示不同程度的灰色。

使用 RGB 设置颜色,需要传 3 ~ 4 个参数,而使用灰度模式只需传1个参数。

还是拿 background() 举例

23.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(128) // 设置背景色
  }
</script>

背景色 background()

前面一直使用背景色,相信大家已经对 background() 的用法非常熟悉了。

通常 background() 会在2个地方用到。

一个是写在 setup() 里,在初始化画布时可以设置画布背景色。

还可以写在 draw() 里,每次刷新画布都可以设置画布背景色。写在 draw() 里,画布每次刷新都会重新设置一次背景色。某些情况下是很有用的,比如移动图像时,如果背景色没重新设置一次,那么图形移动后会产生“残留”的现象。这个放在动画章节说。

填充颜色 fill()

创建图像后,图像默认的填充色是白色。

要修改图像填充色,使用 fill() 方法即可。

24.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(200)
  }
  function draw() {
    fill('#f2c0ca') // 设置填充色
    rect(30, 30, 100, 80)
    circle(220, 70, 80)
  }
</script>

需要注意的是,一旦设置了 fill() ,在它后面创建的图形都会使用相同的填充色,正如上面的例子那样。

如果希望后面的图形使用别的颜色,可以再重新调用一遍 fill() 进行设置。

25.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(200)
  }
  function draw() {
    fill('#f2c0ca') // 设置填充色
    rect(30, 30, 100, 80)
    fill('yellow') // 重新设置填充色
    circle(220, 70, 80)
  }
</script>

无填充 noFill()

如果不想设置填充色,可以使用 noFill() 方法。

不填充的情况下,图形内部将会设置成透明,会直接显示在它下层的颜色,如果它下层没有其他元素,则会直接显示背景色。

26.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(200)
  }

  function draw() {
    noFill()
    rect(30, 30, 100, 80)
    circle(220, 70, 80)
  }
</script>

边框颜色 stroke()

p5.js 创建出来的元素默认是有一个黑色边框,如果想要修改边框颜色,可以使用 stroke() 方法。

27.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(200)
  }

  function draw() {
    stroke('red') // 设置边框颜色
    rect(30, 30, 100, 80)
    circle(220, 70, 80)
  }
</script>

fill() 一样,在使用 stroke() 设置完颜色之后的图形都会使用这个边框颜色。如果要再次修改边框颜色,只需再次使用 stroke() 即可。

无边框 noStroke()

如果不希望图形有边框,可以使用 noStroke() 方法。

28.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(200)
  }

  function draw() {
    noStroke() // 无边框
    rect(30, 30, 100, 80)
    circle(220, 70, 80)
  }
</script>

设置边框粗细 strokeWeight()

使用 strokeWeight() 方法可以设置图形边框的粗细。

29.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(200)
  }

  function draw() {
    strokeWeight(10) // 设置边框粗细
    rect(30, 30, 100, 80)
    circle(220, 70, 80)
  }
</script>

修改文字大小 textSize()

使用 textSize() 方法可以修改文字的字号

30.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(200)
  }

  function draw() {
    textSize(100)
    text('雷猴', 20, 100)
  }
</script>

关于文字的样式,前面说到的 fill()stroke()strokeWeight() 方法都可以对文字的填充色、描边等样式进行设置。自己动手试试吧~

图片

在打算将图片加入到画布之前,我们需要了解 preload() 函数。

preload() 函数也是 p5.js 的一个生命周期函数,它会在 setup() 前执行。

preload() 可以强制程序等待,直到 preload() 函数内的资源加载完成或者事件执行完再执行其他代码。

所以一般会把图片和视频等资源加载写在 preload() 里。

了解完 preload() 后,我们就可以使用 loadImage() 方法加载图片,使用 image() 方法渲染图片。

注意:加载和渲染是分开2步操作的!

本例请来的演员是 摸鱼的春哥[16]

Snipaste_2022-12-03_09-15-36.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  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) // 渲染图片
  }
</script>
  • loadImage() 方法传入图片地址
  • image(img, x, y) 方法第一个参数是图片对象。xy 是图片左上角的坐标。

除了可以渲染 jpgpng 外,p5.js 还可以渲染动图gif。


<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  let img = null

  function preload() {
    img = loadImage('https://p3-passport.byteimg.com/img/user-avatar/221976c6804d412aa876fdd5154129ae~180x180.awebp') // 加载 gif
  }

  function setup() {
    240, 150
  }

  function draw() {
    image(img, 0, 0) // 渲染图片
  }
</script>

可以在 setup() 函数里使用 frameRate() 方法设置帧率,这可以影响gif的刷新率。

交互事件

p5.js 提供了很多鼠标和键盘的交互事件,入门阶段我们挑2个来学就行。

交互事件通常写在 draw() 函数里。

鼠标点击 mouseIsPressed

本例使用 mouseIsPressed 判断用户是否点击了鼠标,点击鼠标时画布背景是蓝色,松开鼠标后画布背景是橙色


<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background('orange')
  }

  function draw() {
    if (mouseIsPressed) { // 检测鼠标是否按下
      background('skyblue')
    } else {
      background('orange')
    }
  }
</script>

draw() 函数在页面运行时会一直执行,所以 mouseIsPressed 写在 draw() 里可以被捕捉到。如果用户点击鼠标,且被捕捉到 mouseIsPressed 时,mouseIsPressed 会返回 true

按住键盘 keyIsPressed

keyIsPressed 可以检测用户当前是否按住键盘,如果键盘被按下会返回 true ,否则返回 false


<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background('orange')
  }

  function draw() {
    if (mouseIsPressed) { // 检测键盘是否按下
      background('skyblue')
    } else {
      background('orange')
    }
  }
</script>

动画

动画其实就是在修改元素属性的同时不断刷新画布。

p5.js 里做动画效果其实很简单,只需要在 draw() 里修改元素属性即可。

举个例子:圆形图案跟随鼠标指针移动


<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(100)
  }

  function draw() {
    background(100)
    circle(mouseX, mouseY, 40, 40)
  }
</script>

有没有发现,上面的例子在 draw() 里首先设置背景色,再创建一个新的圆。

如果没重新设置背景色的话,上一帧的圆会保留下来。很多时候保留上一帧的数据会产生不错的艺术作品。

试试把 draw() 里的 background(100) 这句删掉

36.png
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
<script>
  function setup() {
    createCanvas(300, 300)
    background(100)
  }

  function draw() {
    circle(mouseX, mouseY, 40, 40)
  }
</script>

这个也是p5.js官网的例子[17]

到此,相信各位工友已经对 p5.js 有一定的了解了。

参考资料

[1]

p5.js 官网: https://p5js.org/

[2]

p5.js github地址: https://github.com/processing/p5.js

[3]

p5.js npm地址: https://www.npmjs.com/package/p5

[4]

Live Server 插件: https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer

[5]

setup()说明文档: https://p5js.org/zh-Hans/reference/#/p5/setup

[6]

draw()说明文档: https://p5js.org/zh-Hans/reference/#/p5/draw

[7]

point()说明文档: https://p5js.org/zh-Hans/reference/#/p5/point

[8]

line()说明文档: https://p5js.org/zh-Hans/reference/#/p5/line

[9]

triangle()说明文档: https://p5js.org/zh-Hans/reference/#/p5/triangle

[10]

square()说明文档: https://p5js.org/zh-Hans/reference/#/p5/square

[11]

rect()说明文档: https://p5js.org/zh-Hans/reference/#/p5/rect

[12]

quad()说明文档: https://p5js.org/zh-Hans/reference/#/p5/quad

[13]

circle()说明文档: https://p5js.org/zh-Hans/reference/#/p5/circle

[14]

ellipse()说明文档: https://p5js.org/zh-Hans/reference/#/p5/ellipse

[15]

arc()说明文档: https://p5js.org/zh-Hans/reference/#/p5/arc

[16]

https://juejin.cn/user/1714893870865303: https://juejin.cn/user/1714893870865303

[17]

p5.js官网的例子: https://p5js.org/zh-Hans/get-started/

向下滑动查看

推荐阅读  点击标题可跳转

1、大厂为啥都要用Node去写中间层(BFF)呢?

2、纯 JS 实现语雀的划词高亮功能

3、前端人 70% 以上 不了解的迭代器/可迭代对象/生成器

继续滑动看下一个
大前端技术之路
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存