课程大纲/Lesson 06
FunctionParameters & Return

Noise Wave Field · 噪声波浪场

把多层噪声波浪拆成职责清晰的函数,观察封装如何让复杂绘制更容易阅读、修改与复用。

01

识别适合封装的重复代码与独立任务。

02

用参数把变化的数据传入函数。

03

用返回值把计算结果交回调用位置。

04

让 draw() 只保留清晰的执行流程。

核心概念
functionparameterreturnsingle responsibilitynoise()

两段代码绘制的是同一种多层波浪。区别不在效果,而在代码是否把“组织层级、绘制单层、选择颜色、创建渐变”分成可以单独理解的任务。

封装前:所有步骤挤在 draw() 里

循环、颜色、渐变、噪声采样和形状绘制彼此嵌套;修改一个环节时,需要重新读完整段代码。

function draw() {
  background(palette[0]);

  for (let layer = 0; layer <= WAVE_COUNT; layer++) {
    let y = layer * layerStep;
    let colors = [palette[layer % 5], palette[(layer + 2) % 5]];
    let gradient = drawingContext.createLinearGradient(0, 0, width, 0);
    gradient.addColorStop(0, colors[0]);
    gradient.addColorStop(1, colors[1]);

    push();
    translate(0, y);
    drawingContext.fillStyle = gradient;
    beginShape();
    for (let x = 0; x <= width; x += X_STEP) {
      let waveY = map(noise(x * 0.004, layer * 0.12, t), 0, 1, -76, 76);
      vertex(x, waveY);
    }
    vertex(width, height - y);
    vertex(0, height - y);
    endShape(CLOSE);
    pop();
  }
}

封装后:主流程像一张任务清单

draw() 负责安排顺序;每个函数只处理一个问题,函数名直接说明这一步在做什么。

function draw() {
  drawWaveField();
  noiseOffset += VELOCITY;
}

function drawWaveField() {
  const palette = PALETTES[paletteIndex];
  const layerStep = height / WAVE_COUNT;
  background(palette[0]);

  for (let layer = 0; layer <= WAVE_COUNT; layer++) {
    const y = layer * layerStep;
    const colors = getLayerColors(palette, layer);
    drawWaveLayer(y, layer, colors);
  }
}

function getLayerColors(palette, layer) {
  const start = layer % palette.length;
  const end = (layer + 2) % palette.length;
  return [palette[start], palette[end]];
}
drawWaveField()

组织所有波浪层,决定何时调用其他函数。

getLayerColors(palette, layer)

接收调色板与层号,通过 return 交回两种颜色。

drawWaveLayer(y, layer, colors)

接收位置、层号与颜色,只负责画出一层波浪。

先找职责,再写函数

不要为了缩短代码而随意拆分。这里的四个任务可以独立描述:组织波浪场、绘制单层、挑选颜色、创建渐变,因此适合成为四个函数。

参数负责输入

drawWaveLayer(y, layer, colors) 不把位置和颜色写死。同一套绘制步骤接收不同参数,就能复用到每一层。

return 负责输出

getLayerColors() 完成颜色计算后返回数组;调用者不需要知道索引如何计算,只接收结果。

封装不是隐藏一切

常量仍集中放在文件顶部,让波浪数量、振幅与速度容易调整;函数内部只保留完成自身任务所需的细节。

扩展挑战

继续沿着单一职责拆分,并观察参数如何扩大函数的复用范围。

  • 为 drawWaveLayer() 增加振幅参数
  • 写一个返回随机调色板的函数
  • 封装暂停与继续动画的交互
实时运行 · 点击画布切换配色;按 R 生成新的波浪形态
sketch.js打开源码
正在载入源码…

函数名表达意图

阅读主流程时,先理解程序在做什么,再按需进入函数查看怎么做。

参数创造复用

把变化的部分作为参数传入,同一个函数就能处理多层不同波浪。

返回值连接函数

一个函数产生结果,另一个函数使用结果,小模块由此组合成完整画面。