You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:35:49