我的正弦波代码的相位控制有什么问题?
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 + "° (" + (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° (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 + "° (" + (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° (0.000 rad)</span>
我创建了一个正弦波绘图 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 + "° (" + (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° (0.000 rad)</span>
Amplitude 控制和 Wavelength 控制工作正常,但 Phase 控制。我希望它是这样的:
但是,它的行为非常奇怪,您可以使用 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 + "° (" + (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° (0.000 rad)</span>