思索 p5.js 的最佳实践
思索 p5.js 的最佳实践
本文写于 2020 年 12 月 18 日
p5.js 是一个 JavaScript 库,用于为艺术家、设计师提供更容易上手的创意编程。
它有着完整的一套基于 Canvas 的作画功能,并且你可以把整个浏览器都当成你的“画布”——利用 p5.dom.js
可以很方便地与其他 HTML 元素进行交互;利用 p5.sound.js
可以很简单的对声音进行分析与处理。
官网推荐用法
在官网的例子中,推荐使用 <script>
标签引入的方法:
<html>
<head>
<!-- ...... -->
<script src="path/to/your/p5.js"></script>
</head>
<body>
<script>
function setup() {
createCanvas(300, 500);
}
function draw() {}
</script>
</body>
</html>
这样是让所有的变量、函数都暴露在全局之下,所以我们可以直接使用 setup
, draw
函数进行操作。
但这对于新手来说,这样的做法存在一个致命问题:没有代码提示。并且也不符合我们现代 Web 开发的习惯——模块化。
在动画复杂的情况下,代码会越来越多、越来越邋遢,直到成为一座“屎山”!!!
所以这让我不由得思考起了 p5.js 的最佳实践究竟该如何。
关于最佳实践的思考
p5.js 拥有多个生命周期函数:
- 用于预加载数据的
preload
函数; - 在最开始执行,并且只执行一次的
setup
函数; - 一秒执行大概 20 多次的
draw
函数; - 鼠标左键点击时触发的
mousePressed
函数; - ……
p5 画图的根本其实就是在不同生命周期里对数据进行操作,然后将数据具体转化为图像。
所以按照 MVC 的思想:view = render(data)
,我们应该拒绝在这些钩子函数中「直接」操作数据——将动画抽象成为独立的 Service(服务),操作数据交给 Service 自己的方法,我们只需要在 draw
函数中对 Service 内的数据进行绘制即可。
这样讲可能大家还不太明白,那么 talk is cheap, show me the code 吧!
运用 OOP 与 SOA 解耦项目
接下来我们通过一个例子看看如何对项目进行解耦。
要求:了解面向对象的编程。
目标:制作一个漫天繁星。
step1 创建 Star 类
第一步我们需要一个 Star 类。
class 星星 {
x坐标 = 0;
y坐标 = 0;
透明度 = 0;
随机放置星星() {
// 随机 x y 坐标值
}
闪烁() {
// 操作透明度
}
}
step2 创建 Service
然后再为所有的星星闪烁制作一个服务,这个服务用来管理所有的星星(服务其实就是一个 class
)。
class 星星服务 {
星星们 = [];
get 星星的位置() {
this.星星们.处理一下((星星) => {
返回 {
x: 星星的x坐标,
y: y坐标,
opacity: 透明度,
}
})
}
创建星星们() {
重复 100 次:this.星星们.增加(new 星星());
}
}
step3 写入 p5
let 星星服务实例;
function preload() {
星星服务实例 = new 星星服务class();
}
function setup() {
星星服务实例.创建星星们();
}
function draw() {
background(0);
if (星星服务实例.星星们 的 长度 > 0) {
星星服务实例.星星的位置.遍历((星星) => {
fill(255, 星星.透明度);
ellipse(星星.x, 星星.y, 半径, 半径);
})
}
}
目前动画比较简单,还看不出来该方案有什么优势。但是一旦动画更加复杂,该方案对原来写法的解耦的优越性将会是毋庸置疑的。
我们仅仅需要的是在不同的生命周期函数中调用服务的方法,然后在 draw
函数中拿到数据后进行绘图!
ts-p5 以及环境搭建
我封装了一个库,可以提供比较好的 p5 代码补全:https://github.com/AerospaceXu/ts-p5。
考虑到使用 p5 的初学者较多,还是说一下如何搭建一个前端项目吧。
完整版本会写在最后一节,这里只提供可运行的步骤。
官网下载 Node.js,一路默认选项安装;
下载 VSCode,他为我们提供了完善的代码提示支持;
新建项目文件夹,命名;
将文件夹拖入 VSCode;
点击 VSCode 菜单栏的“终端”或是“Terminal”选项,选择新建终端;
终端内输入:
npm config set registry https://registry.npm.taobao.org && npm init -y && npm i ts-p5 && npm i -D parcel-bundler
;此时文件夹内出现了
package.json
与package-lock.json
文件,打开前者;在第一行大括号的末尾回车,输入:
{ // 在这里回车
"scripts": {
"start": "./node_modules/.bin/parcel ./src/index.html --no-cache",
"build": "./node_modules/.bin/parcel build ./src/index.html --no-cache -d build"
},
// ......
新建 src 文件夹,让你的目录看起来是这样:
- 你的文件夹名称
- node_modules
- package.json
- package-lock.json
- src
- index.html
- style.css
- main.js
只需要在 index.html 中引入 main.js 和 style.css;
在 index.html 中写入以下代码:
<body>
<div id="sketch"></div> <script src="./main.js"></script>
</body>
在 main.js 中写入以下代码:
import { sketchCreator } from 'ts-p5';
import { getWindowSize } from 'ts-p5/utils'; sketchCreator(
{
preload: function () {},
setup: function (p) {
const { width, height } = getWindowSize();
p.createCanvas(width, height);
p.background(0);
},
draw: function (p) {
p.background(0);
p.noStroke();
},
mousePressed: function (p) {
console.log(p.mouseX);
console.log(p.mouseY);
},
},
document.querySelector('#sketch')
);
然后在终端输入 npm run start
,待显示
Server running at http://localhost:1234
Built in xxxx.
之后,方可打开浏览器输入刚刚输出的网址。
观察到一片漆黑,就完成了。
之后如果需要使用到 p5 的函数或者是变量,输入 p.
就会自动弹出代码提示了(不要忘记在函数参数传入 p 哦)。
为代码添加提示完整版(初学者向)
为了给 p5 增加代码提示,我们不可以使用官网推荐的方式。需要利用 TypeScript 进行模块化的项目构建(会的同学,或者不需要代码提示的同学可以直接跳过这一节)。
这里需要安装一下 Node.js,直接官网下载即可。
以下步骤仅限 Linux 与 MacOS 平台,Windows 不保证可以这么操作!!!
step1 初始化项目
新建一个文件夹,将文件夹拖入 VSCode 打开,切换至英文输入法,同时按下 control + ~
就可以开启终端。
在终端输入 npm config set registry https://registry.npm.taobao.org && npm init -y && npm i p5 && npm i -D typescript @types/p5 parcel-bundler && ./node_modules/.bin/tsc --init
请初学者直接复制粘贴并且回车,不要尝试自己输入。
这时候可以发现我们的文件夹里出现了几个文件,并且他们全都不需要你去关心。
- 你的文件夹名称
- node_modules
- tsconfig.json
- package.json
- package-lock.json
打开 package.json 文件,应该长这样:
{
"name": "你的文件夹名称",
.....
}
step2 创建启动脚本
我们在第二行插入一些东西(一样请直接复制,不要尝试自己打):
{
"scripts": {
"start": "./node_modules/.bin/parcel ./src/index.html --no-cache",
"build": "./node_modules/.bin/parcel build ./src/index.html --no-cache -d build"
},
"name": "你的文件夹名称",
.....
}
step3 创建 HTML 文件
接着我们建立 src 文件夹,并在其中新建我们的 HTML / CSS 文件:
- 你的文件夹名称
- node_modules
- tsconfig.json
- package.json
- package-lock.json
- src
- index.html
- style.css
src 是之后我们唯一需要关注的文件夹。
step4 启动项目
照常的写你的代码,和之前没有任何区别。然后随便在 HTML 中输入一些标签和字符,在终端中输入:npm run start
并等待一会儿,待显示出
Server running at http://localhost:1234
Built in xxxx.
之后,方可打开浏览器,输入他输出的网址。
此时显示了你刚刚在 HTML 中写的文字即是成功了。
step5 创建 TypeScript 文件
首先在 src 中创建 main.ts 文件,并在 html 中引入。
- src
- index.html
- style.css
- main.ts
因为 p5 的特殊性质,所以无法在 js 文件中提供完整的代码提示,必须使用 typescript。
step6 书写 p5
翻看 p5 的源代码我们发现,p5 本身是一个构造函数,接受两个参数,第一个是一个函数,函数接受一个参数,我们可以通过这个参数实现代码提示:
// main.ts
import P5 from 'p5';
const sketch = (p: P5) => {
p.setup = () => {
p.background(0);
};
p.draw = () => {
p.background(0);
p.fill(255);
p.ellipse(0, 0, 25, 25);
};
};
p5 的第二个参数是一个 HTML 元素,意思是我们可以将画布放到这个元素中去。
// index.html
<body>
<div id="app"></div>
<script src="./main.ts"></script>
</body>
这时候我们就可以使用 new P5(sketch, document.querySelector('#app'));
来挂载画布了。
(完)
思索 p5.js 的最佳实践的更多相关文章
- JS编程最佳实践
最近花了一周时间把<编写可维护的js> 阅读了一遍, 现将全书提到的JS编程最佳实践总结如下, 已追来者! 1.return 之后不可直接换行, 否则会导致ASI(自动分号插入机制)会在r ...
- Atitit.angular.js 使用最佳实践 原理与常见问题解决与列表显示案例 attilax总结
Atitit.angular.js 使用最佳实践 原理与常见问题解决与列表显示案例 attilax总结 1. 本文范围 1 2. Angular的优点 1 2.1. 双向数据绑定 1 2.2. dsl ...
- vue.js+boostrap最佳实践
一.为什么要写这篇文章 最近忙里偷闲学了一下vue.js,同时也复习了一下boostrap,发现这两种东西如果同时运用到一起,可以发挥很强大的作用,boostrap优雅的样式和丰富的组件使得页面开发变 ...
- require.js 最佳实践【转】
https://www.cnblogs.com/digdeep/p/4607131.html require.js是一个js库,相关的基础知识,前面转载了两篇博文:Javascript模块化编程(re ...
- require.js 最佳实践
require.js是一个js库,相关的基础知识,前面转载了两篇博文:Javascript模块化编程(require.js), Javascript模块化工具require.js教程,RequireJ ...
- Atitit. js mvc 总结(2)----angular 跟 Knockout o99 最佳实践
Atitit. js mvc 总结(2)----angular 跟 Knockout o99 最佳实践 1. 框架 angular 跟Knockout 1 2. 2. 简单的列表绑定:Knockou ...
- 《.NET最佳实践》与Ext JS/Touch的团队开发
概述 持续集成 编码规范 测试 小结 概述 有不少开发人员都问过我,Ext JS/Touch是否支持团队开发?对于这个问题,我可以毫不犹豫的回答:支持.原因是在Sencha官网博客中客户示例中,有不少 ...
- Vue.js最佳实践
Vue.js最佳实践 第一招:化繁为简的Watchers 场景还原: created(){ this.fetchPostList() }, watch: { searchInputValue(){ t ...
- 十个书写Node.js REST API的最佳实践(上)
收录待用,修改转载已取得腾讯云授权 原文:10 Best Practices for Writing Node.js REST APIs 我们会通过本文介绍下书写Node.js REST API的最佳 ...
随机推荐
- @Required 注解 ?
这个注解表明 bean 的属性必须在配置的时候设置,通过一个 bean 定义的显式的 属性值或通过自动装配,若@Required 注解的 bean 属性未被设置,容器将抛出 BeanInitializ ...
- 为什么HTTP/3要基于UDP?可靠吗?
目录 前言 为什么转用UDP? HTTP/3解决了那些问题? 队头阻塞问题 QPACK编码 Header 参考 推荐阅读: 计算机网络汇总 HTTP/3竟然是基于UDP的!开始我也很疑惑,UDP传输不 ...
- 顺利通过EMC实验(14)
- 小程序完整对接 pingpp支付
小程序完整对接 pingpp支付 有几个先要条件: 小程序需要企业认证且开通支付功能,个人认证是无法使用支付功能的(小程序微信支付官网) pingpp 本身接入的企业服务器(即商户服务器)并不强制要求 ...
- Android普通工具类获取Context
在普通工具类中定义一个构造方法,类成员context,用于接收传过来的context 在activity中定义: 将context传过去. 在工具类中也可以使用SharePreferences,get ...
- RedisDesktopManager 连接不上远程 Redis
1.首先确保远程redis-server已经启用: 2.连接不到可能的原因: redis3.2以上版本默认开启保护模式,不允许外网访问,需要修改redis.conf文件 3.redis.conf文件需 ...
- CCF201503-2数字排序
问题描述 给定n个整数,请统计出每个整数出现的次数,按出现次数从多到少的顺序输出. 输入格式 输入的第一行包含一个整数n,表示给定数字的个数. 第二行包含n个整数,相邻的整数之间用一个空格分隔,表示所 ...
- k8s,coredns内部测试node节点上的pod的calico是否正常的一个小技巧
最近由于master整个挂掉,导致相关一些基础服务瘫掉,修复中测试有些节点网络又出现不通的情况正常的启动相关一些服务后,测试一些节点,比较费劲,还有进入pod,以及还有可能涉及命名空间操作这里可以这样 ...
- 解决一次calico异常情况,pod之间访问pod ip不通
k8s 集群采用二进制安装,cni网络插件用calico通讯问题描述:发现有些pod不是很正常例如: ht13.node正常系统采样 [root@ht6 ~]# cat /etc/redhat-rel ...
- springboot读取配置文件赋值给静态变量
1.实现InitializingBean接口,重写afterPropertiesSet方法,将@Value赋值给成员变量的属性赋值给静态变量,示例如下: /** * @Classname FileUt ...