如何为基于line()函数的嵌套矩形绘制脚本添加连续缩放机制?
嘿,看起来你已经搞定了嵌套矩形的生成,现在要加连续缩放效果对吧?我之前在Processing项目里做过类似的需求,给你几个实用的思路和代码示例参考下~
实现连续缩放的核心思路
连续缩放的关键是基于一个固定/动态中心(比如你定义的randomXPoint、randomYPoint),逐步调整每个嵌套矩形的尺寸和位置,同时借助动画循环(比如Processing的draw()函数)实现平滑过渡。下面给你两种可行的方案:
方案1:基于缩放因子的渐进式缩放
这个思路最直接,适合新手快速上手:每次循环给所有矩形应用统一的缩放因子,同时保持缩放中心不变。
- 先把每个矩形的原始位置、尺寸用类来封装(比零散变量好维护),存入列表
- 在
draw()里动态调整缩放因子,计算每个矩形缩放后的位置和大小 - 用
line()重新绘制所有矩形,控制缩放速度避免太突兀
适配你代码的示例实现
首先定义一个Box类存储矩形数据:
class Box { float x, y, width, height; Box(float x, float y, float w, float h) { this.x = x; this.y = y; this.width = w; this.height = h; } }
然后调整全局变量和核心逻辑:
// 全局变量 ArrayList<Box> boxes = new ArrayList<>(); float scaleFactor = 1.0f; float scaleSpeed = 0.01f; // 缩放速度,数值越小越平滑 boolean isZoomingIn = true; // 控制缩放方向 int randomXPoint; int randomYPoint; public final int WINDOW_OFFSET = 10; void setup() { size(800, 600); // 生成嵌套矩形(这里替换成你自己的生成逻辑) float startX = WINDOW_OFFSET; float startY = WINDOW_OFFSET; float startW = width - 2 * WINDOW_OFFSET; float startH = height - 2 * WINDOW_OFFSET; for (int i = 0; i < 5; i++) { boxes.add(new Box(startX, startY, startW, startH)); startX += 20; startY += 20; startW -= 40; startH -= 40; } // 初始化随机缩放中心 randomXPoint = (int)random(WINDOW_OFFSET, width - WINDOW_OFFSET); randomYPoint = (int)random(WINDOW_OFFSET, height - WINDOW_OFFSET); } void draw() { background(255); // 动态调整缩放因子,到达边界后反转方向 if (isZoomingIn) { scaleFactor += scaleSpeed; if (scaleFactor > 2.0f) isZoomingIn = false; } else { scaleFactor -= scaleSpeed; if (scaleFactor < 0.5f) isZoomingIn = true; } // 遍历所有矩形,计算缩放后位置并绘制 for (Box box : boxes) { // 计算矩形相对于缩放中心的偏移量 float offsetX = box.x - randomXPoint; float offsetY = box.y - randomYPoint; // 应用缩放计算新坐标 float scaledX = randomXPoint + offsetX * scaleFactor; float scaledY = randomYPoint + offsetY * scaleFactor; float scaledW = box.width * scaleFactor; float scaledH = box.height * scaleFactor; // 用line()绘制矩形的四条边 stroke(0); line(scaledX, scaledY, scaledX + scaledW, scaledY); // 上边 line(scaledX + scaledW, scaledY, scaledX + scaledW, scaledY + scaledH); // 右边 line(scaledX + scaledW, scaledY + scaledH, scaledX, scaledY + scaledH); // 下边 line(scaledX, scaledY + scaledH, scaledX, scaledY); // 左边 } }
方案2:基于坐标变换的相机式缩放
如果你的嵌套矩形数量多,或者想要更真实的“镜头放大”效果,用Processing的坐标变换更高效:
- 通过
translate()和scale()实现整体画布缩放,不用单独计算每个矩形的位置 - 注意坐标变换的顺序:先平移到缩放中心,再缩放,最后平移回原位置(Processing的变换是逆序执行的)
核心代码修改(基于方案1的基础)
只需要替换draw()函数即可:
void draw() { background(255); // 调整缩放因子逻辑同方案1 if (isZoomingIn) { scaleFactor += scaleSpeed; if (scaleFactor > 2.0f) isZoomingIn = false; } else { scaleFactor -= scaleSpeed; if (scaleFactor < 0.5f) isZoomingIn = true; } // 启用坐标变换矩阵 pushMatrix(); // 先平移到缩放中心 translate(randomXPoint, randomYPoint); // 应用缩放 scale(scaleFactor); // 平移回原位置,确保缩放围绕中心进行 translate(-randomXPoint, -randomYPoint); // 直接绘制原始矩形,变换会自动应用到所有图形 for (Box box : boxes) { stroke(0); line(box.x, box.y, box.x + box.width, box.y); line(box.x + box.width, box.y, box.x + box.width, box.y + box.height); line(box.x + box.width, box.y + box.height, box.x, box.y + box.height); line(box.x, box.y + box.height, box.x, box.y); } // 恢复原坐标矩阵 popMatrix(); }
额外提示
- 如果想要跟随动态随机点缩放,可以把
randomXPoint和randomYPoint的更新逻辑放到draw()里 - 可以根据需求调整
scaleSpeed和缩放的边界值(比如2.0f和0.5f) - 如果缩放后矩形超出窗口范围,可以添加可见性判断,只绘制在窗口内的部分,提升性能
内容的提问来源于stack exchange,提问作者DivaKill
相关产品推荐
相关产品推荐

