p5.js中keyPressed事件内调用filter滤镜失效如何解决?
问题根因
滤镜不生效是两个写法错误导致的:
- 你用的是p5.js实例模式初始化,所有p5内置方法、常量都必须绑定在sketch入参的
p对象上调用,你写的全局形式filter(THRESHOLD)在实例模式下根本找不到对应函数和常量,代码直接静默报错没执行。你前面写的p.clear()是对的,滤镜相关调用漏了p.前缀。 POSTERIZE(色调分离)滤镜是必填参数的,需要传入2-255之间的整数指定色阶数,不传参数调用不会有任何效果。
另外你当前的按键判断只匹配大写的T/I/P,如果用户没开大写锁定、按小写按键是触发不了逻辑的,属于附带的体验问题。
修复方法
- 给所有滤镜调用、滤镜常量加上
p.前缀,改成实例模式的调用形式 - 给
POSTERIZE补必填的色阶参数,一般传3-5之间的数值效果比较明显 - 可选优化:把按键值统一转成大写再判断,兼容大小写按键输入;鼠标绘制坐标直接用p5内置的
p.mouseX/p.mouseY,比取事件对象的clientX/clientY更准确,不会因为画布位置偏移画错位置。
修复后完整代码
const sketch = function(p) { let colorPicker; let brushSize = 20; p.setup = function() { p.createCanvas(800, 800); colorPicker = p.createColorPicker('red'); colorPicker.position(0, 0); }; p.keyPressed = function(e) { let key = e.key; if (key === '=') brushSize += brushSize * 0.1; else if (key === '-') brushSize = Math.max(5, brushSize - brushSize * 0.1); // 限制笔刷最小值,避免出现0/负数尺寸 else if (key === 'c') p.clear(); // 修复滤镜调用,统一转大写兼容大小写按键 else if (key.toUpperCase() === 'T') p.filter(p.THRESHOLD); else if (key.toUpperCase() === 'I') p.filter(p.INVERT); else if (key.toUpperCase() === 'P') p.filter(p.POSTERIZE, 3); // 补POSTERIZE必填的色阶参数 } p.mouseDragged = function() { let currentColor = colorPicker.color(); // 补变量声明,避免污染全局作用域 p.fill(currentColor); p.stroke(currentColor); // 用p5内置鼠标坐标,避免画布偏移导致绘制位置错误 p.ellipse(p.mouseX, p.mouseY, brushSize, brushSize) } }; let myp5 = new p5(sketch);
补充说明:
filter方法会直接修改当前画布的像素数据,多次触发会累加滤镜效果,按c清空画布即可重置像素状态。
内容的提问来源于stack exchange,提问作者rose
相关产品推荐
相关产品推荐

