PixiJS中如何为路径描边动态设置重复纹理?
PixiJS中如何为路径描边动态设置重复纹理?
嘿,我刚好碰到过类似的2D墙结构需求,你的思路其实已经走对了大半!要实现动态重复纹理的路径描边,核心是在基础纹理设置重复模式的前提下,根据路径的变化实时调整纹理的重复参数,我来给你拆解一下具体步骤:
一、先搞定基础的纹理重复设置
你代码里设置baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT这一步是关键,这是让纹理能重复显示的基础。不过要注意:
- 修改完
wrapMode后必须调用baseTexture.update(),才能让GPU同步这个设置; - 如果遇到纹理重复不生效的情况,检查下纹理尺寸是否是2的幂次(比如256x256)——虽然WebGL 2.0支持非2幂次纹理重复,但旧环境可能有兼容问题,必要时可以开启PixiJS的WebGL 2.0模式。
二、动态调整纹理重复的核心技巧
要让纹理跟着路径长度/形状动态重复,关键是根据路径的实际长度计算纹理的重复次数,而不是固定死重复值。
1. 先获取路径的总长度
PixiJS的Graphics可以通过geometry.totalLength获取路径的总长度,我们可以封装一个工具函数:
function getPathTotalLength(path) { const tempGraphics = new PIXI.Graphics(); tempGraphics.path(path); const totalLength = tempGraphics.geometry.totalLength; tempGraphics.destroy(); // 用完及时销毁临时对象,避免内存泄漏 return totalLength; }
2. 动态计算并更新纹理重复值
假设我们的纹理原始宽度是baseTexture.width,路径总长度是pathLength,那么让纹理刚好铺满路径的重复次数就是pathLength / baseTexture.width。修改texture.repeat后同样要调用texture.update()生效:
// 加载纹理(替换成你的本地纹理路径) const baseTexture = await PIXI.Assets.load('./your-wall-texture.png'); baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT; baseTexture.update(); const texture = new PIXI.Texture(baseTexture); const g = new PIXI.Graphics(); app.stage.addChild(g); // 初始路径绘制 const path = new PIXI.GraphicsPath(); path.moveTo(100, 100); path.lineTo(200, 100); path.arcTo(250, 100, 250, 150, 30); path.lineTo(250, 200); // 初始计算重复值 const initialPathLength = getPathTotalLength(path); const textureWidth = baseTexture.width; texture.repeat.set(initialPathLength / textureWidth, 1); // x方向按路径长度重复,y方向保持1 texture.update(); // 绘制描边 g.path(path); g.stroke({ width: 12, texture: texture });
3. 路径变化时的动态更新
如果你的墙结构需要动态修改(比如拖拽调整墙的长度、修改圆角半径),只需要重新计算路径长度、更新纹理重复值,然后重新绘制即可:
// 举个例子:点击按钮修改路径 document.querySelector('#adjustWallBtn').addEventListener('click', () => { // 重置并创建新路径 path.reset(); path.moveTo(100, 100); path.lineTo(350, 100); // 更长的直线段 path.arcTo(400, 100, 400, 220, 40); // 更大的圆角 path.lineTo(400, 280); // 重新计算路径长度和纹理重复 const newPathLength = getPathTotalLength(path); texture.repeat.set(newPathLength / textureWidth, 1); texture.update(); // 重新绘制图形 g.clear(); g.path(path); g.stroke({ width: 12, texture: texture }); });
三、额外优化小技巧
- 如果想让纹理在描边的垂直方向(也就是墙的厚度方向)也不被拉伸,可以计算描边宽度和纹理高度的比例,设置
texture.repeat.y = strokeWidth / baseTexture.height; - 如果纹理边缘衔接有缝隙,检查纹理的边缘是否有多余的透明像素,或者微调一下重复值(比如加个很小的偏移)。
这样就能实现完全动态的纹理重复路径描边啦,我之前做类似的室内墙结构就是这么处理的,亲测好用~
内容来源于stack exchange




