我的正弦波代码的相位控制有什么问题?

What is wrong with the phase control of my sine wave code?

我创建了一个正弦波绘图 Web 应用程序。这是我的代码:

const canvas = document.getElementById("canvas"),
  amplitude_slider = document.getElementById("amplitude_control"),
  wavelength_slider = document.getElementById("wavelength_control"),
  phase_slider = document.getElementById("phase_control"),
  amplitude_output = document.getElementById("amplitude_value"),
  wavelength_output = document.getElementById("wavelength_value"),
  phase_output = document.getElementById("phase_value"),
  radian_factor = Math.PI / 180;

var width,
  height,
  canvas_middle,
  context,
  amplitude = 20,
  wavelength = 0,
  phase = 0;

function init() {
  width = window.innerWidth - 4; //exclude 4 pixels for the border
  height = window.innerHeight - 4;
  canvas.width = width;
  canvas.height = height / 2;
  canvas_middle = height / 4;
  context = canvas.getContext("2d");
}

function draw() {
  context.clearRect(0, 0, width, height);
  context.beginPath();
  var ampl = amplitude / 100 * canvas_middle;
  context.moveTo(0, canvas_middle + ampl * Math.sin(radian_factor * phase * Math.pow(2, wavelength)));
  for (i = 1; i < width; i++) {
    context.lineTo(i, canvas_middle + ampl * Math.sin(radian_factor * (i + phase) * Math.pow(2, wavelength)));
  }
  context.stroke();
}
init();
draw();
window.addEventListener("resize", () => {
  init();
  draw();
});

amplitude_slider.addEventListener("input", () => {
  amplitude = amplitude_slider.value;
  amplitude_output.innerHTML = amplitude;
  draw();
});
wavelength_slider.addEventListener("input", () => {
  wavelength = wavelength_slider.value;
  wavelength_output.innerHTML = Math.pow(2, wavelength).toFixed(2);
  draw();
});
phase_slider.addEventListener("input", () => {
  phase = phase_slider.value;
  phase_output.innerHTML = phase + "&deg; (" + (radian_factor * phase).toFixed(3) + "rad)";
  draw();
});
* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}

canvas {
  border: 2px solid green;
  width: 100%;
  height: 50%;
}

input {
  width: 100%;
  margin-top: 2em;
  padding: 0 10px 0 10px;
}
<canvas id="canvas"></canvas>
<input type="range" id="amplitude_control" value="20" min="0" max="100" step="0.1"> Amplitude <span id="amplitude_value">20</span><br>
<input type="range" id="wavelength_control" value="0" min="-5" max="5" step="0.01"> Wavelength <span id="wavelength_value">4.00</span><br>
<input type="range" id="phase_control" value="0" min="0" max="360" step="0.1"> Phase <span id="phase_value">0&deg; (0.000 rad)</span>

Amplitude 控制和 Wavelength 控制工作正常,但 Phase 控制。我希望它是这样的:
相位180度
相位90度

但是,它的行为非常奇怪,您可以使用 Phase 滑块亲自查看。我做错了什么?

Temmu 的 评论的帮助下,我解决了我的问题。在我的代码中,问题是 phase_slider.value 返回了 string 类型的值。使用 string 类型值进行计算导致了问题。

我只需要使用 parseInt() 方法或在变量前放置一个 + 符号,将 phase_slider.value 转换为数字.

这是我的代码的更正版本:

const canvas = document.getElementById("canvas"),
  amplitude_slider = document.getElementById("amplitude_control"),
  wavelength_slider = document.getElementById("wavelength_control"),
  phase_slider = document.getElementById("phase_control"),
  amplitude_output = document.getElementById("amplitude_value"),
  wavelength_output = document.getElementById("wavelength_value"),
  phase_output = document.getElementById("phase_value"),
  radian_factor = Math.PI / 180;

var width,
  height,
  canvas_middle,
  context,
  amplitude = 20,
  wavelength = 0,
  phase = 0;

function init() {
  width = window.innerWidth - 4; //exclude 4 pixels for the border
  height = window.innerHeight - 4;
  canvas.width = width;
  canvas.height = height / 2;
  canvas_middle = height / 4;
  context = canvas.getContext("2d");
}

function draw() {
  context.clearRect(0, 0, width, height);
  context.beginPath();
  var ampl = amplitude / 100 * canvas_middle;
  context.moveTo(0, canvas_middle + ampl * Math.sin(radian_factor * phase * Math.pow(2, wavelength)));
  for (i = 1; i < width; i++) {
    context.lineTo(i, canvas_middle + ampl * Math.sin(radian_factor * (i + phase) * Math.pow(2, wavelength)));
  }
  context.stroke();
}
init();
draw();
window.addEventListener("resize", () => {
  init();
  draw();
});

amplitude_slider.addEventListener("input", () => {
  amplitude = amplitude_slider.value;
  amplitude_output.innerHTML = amplitude;
  draw();
});
wavelength_slider.addEventListener("input", () => {
  wavelength = wavelength_slider.value;
  wavelength_output.innerHTML = Math.pow(2, wavelength).toFixed(2);
  draw();
});
phase_slider.addEventListener("input", () => {
  phase = parseInt(phase_slider.value); //This is the corrected line
  phase_output.innerHTML = phase + "&deg; (" + (radian_factor * phase).toFixed(3) + "rad)";
  draw();
});
* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}

canvas {
  border: 2px solid green;
  width: 100%;
  height: 50%;
}

input {
  width: 100%;
  margin-top: 2em;
  padding: 0 10px 0 10px;
}
<canvas id="canvas"></canvas>
<input type="range" id="amplitude_control" value="20" min="0" max="100" step="0.1"> Amplitude <span id="amplitude_value">20</span><br>
<input type="range" id="wavelength_control" value="0" min="-5" max="5" step="0.01"> Wavelength <span id="wavelength_value">4.00</span><br>
<input type="range" id="phase_control" value="0" min="0" max="360" step="0.1"> Phase <span id="phase_value">0&deg; (0.000 rad)</span>