角度方向正弦波
angled direction sine wave
我已经能够在水平方向绘制正弦波,如图所示(图像link:https://i.stack.imgur.com/RTpDY.png)和垂直方向。
现在我需要在一个45°角的方向上绘制它
谁能帮帮我!
脚本代码:
var c =document.getElementById("c");
var ctx=c.getContext('2d');
var x=0,y=250,vx=0.05,vy=0.05,a=1;
for(var i=0; i<501;i++){
x += a;
y = Math.floor(500 * (0.5 - 0.15 * Math.sin(vy)));
vy += vx;
// this.ctx.clearRect(0, 0, 500,500);
this.ctx.beginPath();
this.ctx.arc(x, y, 2, 0, Math.PI * 2, true);
this.ctx.closePath();
this.ctx.fillStyle = 'red';
this.ctx.fill();
console.log("x:"+x+"y:"+y+"vy:"+vy);
}
最简单的解决方案是旋转 canvas:
ctx.rotate(45*Math.PI/180);
虽然我假设您需要固定 canvas 方向并且您需要从数学上改变您的绘制方式?在这种情况下,这里有一大堆关于如何在逆时针旋转时绘制正弦波的数学:
沿直线绘制正弦波
下面将绘制一条与直线对齐的正弦波。直线可以是任意方向。
标准设置
波长将以像素为单位。为了使正弦波形成一个完整的周期,您需要将其输入角度旋转 Math.PI * 2
,因此您需要将其转换为与像素波长匹配的值。
const waveLen = 400; // pixels
正弦波的相位是从波的哪一部分开始的,因为波长以像素为单位,相位也是以像素为单位,表示沿波的距离,表示起始角。
const phase = 200; // mid way
波的振幅是波的最大点和最小点在中心线上方和下方的距离。这又是像素
const amplitude = 100;
波也有一个偏移量,虽然在这种情况下不是很重要,但我也会添加它。也以像素为单位
const offset = 0;
标记波浪中心的线有开始和结束坐标
const x1 = 20;
const y1 = 20;
const x2 = 400;
const y2 = 400;
以及一些上下文设置
const lineWidth = 3;
const lineCap = "round";
const lineJoin = "round";
const strokeStyle = "blue";
示例代码
因此,对于执行渲染的代码,我用注释扩展了代码,以便您可以阅读正在发生的事情。下面是一个更好用的版本。
const ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
window.addEventListener("resize", () => {
canvas.width = innerWidth;
canvas.height = innerHeight;
y2 = x2 = innerWidth; // at 45 deg
drawSinWave();
})
const waveLen = 120; // pixels
const phase = 50; // mid way
const amplitude = 25;
const offset = 0;
const x1 = 20;
const y1 = 20;
var x2 = 400; // as vars to let it change to fit resize
var y2 = 400;
function drawSinWave() {
ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.strokeStyle = "blue";
// get the vector form of the line
const vx = x2 - x1;
const vy = y2 - y1;
// Get the length of the line in pixels
const dist = Math.sqrt(vx * vx + vy * vy);
// Make the vector one pixel long to move along the line
const px = vx / dist;
const py = vy / dist;
// We also need a vector to move out from the line (at 90 deg to the ine)
// So rotate the pixel vector 90deg CW
const ax = -py; // a for amplitude vector
const ay = px;
// Begin the path
ctx.beginPath();
// Now loop along every pixel in the line
// We go past the end a bit as floating point errors can cause it to end
// a pixels too early
for (var i = 0; i <= dist + 0.5; i++) {
// fix i if past end
if (i > dist) {
i = dist
} // Carefull dont mess with this ot it will block the page
// Use the distance to get the current angle of the wave
// based on the wave length and phase
const ang = ((i + phase) / waveLen) * Math.PI * 2;
// and at this position get sin
const val = Math.sin(ang);
// Scale to match the amplitude and move to offset
// as the distance from the center of the line
const amp = val * amplitude + offset;
// Get line ceneter at distance i using the pixel vector
var x = x1 + px * i;
var y = y1 + py * i;
// Use the amp vector to move away from the line at 90 degree
x += ax * amp;
y += ay * amp;
// Now add the point
ctx.lineTo(x, y);
}
ctx.stroke();
}
drawSinWave();
canvas {
position: absolute;
top: 0px;
left: 0px;
}
<canvas id=canvas width=4 00 height=4 00></canvas>
作为一个更有用的功能,有一些快捷方式
const ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
window.addEventListener("resize", () => {
canvas.width = innerWidth;
canvas.height = innerHeight;
waveExample.y2 = waveExample.x2 = innerWidth; // at 45 deg
drawSinWave(waveExample);
})
const waveExample = {
waveLen: 100, // pixels
phase: 50, // mid way
amplitude: 35,
offset: 0,
x1: 20,
y1: 20,
x2: 400, // as vars to let it change to fit resize
y2: 400,
lineWidth : 5,
lineCap : "round",
lineJoin : "round",
strokeStyle : "Red",
}
function drawSinWave(wave) {
ctx.lineWidth = wave.lineWidth;
ctx.lineCap = wave.lineCap;
ctx.lineJoin = wave.lineJoin;
ctx.strokeStyle = wave.strokeStyle;
var vx = wave.x2 - wave.x1;
var vy = wave.y2 - wave.y1;
const dist = Math.sqrt(vx * vx + vy * vy);
vx /= dist;
vy /= dist;
ctx.beginPath();
for (var i = 0; i <= dist + 0.5; i++) {
if (i > dist) { i = dist }
const pos = Math.sin(((i + wave.phase) / wave.waveLen) * Math.PI * 2) * wave.amplitude + wave.offset;
ctx.lineTo(
wave.x1 + vx * i - vy * pos,
wave.y1 + vy * i + vx * pos
);
}
ctx.stroke();
}
drawSinWave(waveExample);
canvas {
position: absolute;
top: 0px;
left: 0px;
}
<canvas id=canvas width=4 00 height=4 00></canvas>
我已经能够在水平方向绘制正弦波,如图所示(图像link:https://i.stack.imgur.com/RTpDY.png)和垂直方向。
现在我需要在一个45°角的方向上绘制它 谁能帮帮我!
脚本代码:
var c =document.getElementById("c");
var ctx=c.getContext('2d');
var x=0,y=250,vx=0.05,vy=0.05,a=1;
for(var i=0; i<501;i++){
x += a;
y = Math.floor(500 * (0.5 - 0.15 * Math.sin(vy)));
vy += vx;
// this.ctx.clearRect(0, 0, 500,500);
this.ctx.beginPath();
this.ctx.arc(x, y, 2, 0, Math.PI * 2, true);
this.ctx.closePath();
this.ctx.fillStyle = 'red';
this.ctx.fill();
console.log("x:"+x+"y:"+y+"vy:"+vy);
}
最简单的解决方案是旋转 canvas:
ctx.rotate(45*Math.PI/180);
虽然我假设您需要固定 canvas 方向并且您需要从数学上改变您的绘制方式?在这种情况下,这里有一大堆关于如何在逆时针旋转时绘制正弦波的数学:
沿直线绘制正弦波
下面将绘制一条与直线对齐的正弦波。直线可以是任意方向。
标准设置
波长将以像素为单位。为了使正弦波形成一个完整的周期,您需要将其输入角度旋转 Math.PI * 2
,因此您需要将其转换为与像素波长匹配的值。
const waveLen = 400; // pixels
正弦波的相位是从波的哪一部分开始的,因为波长以像素为单位,相位也是以像素为单位,表示沿波的距离,表示起始角。
const phase = 200; // mid way
波的振幅是波的最大点和最小点在中心线上方和下方的距离。这又是像素
const amplitude = 100;
波也有一个偏移量,虽然在这种情况下不是很重要,但我也会添加它。也以像素为单位
const offset = 0;
标记波浪中心的线有开始和结束坐标
const x1 = 20;
const y1 = 20;
const x2 = 400;
const y2 = 400;
以及一些上下文设置
const lineWidth = 3;
const lineCap = "round";
const lineJoin = "round";
const strokeStyle = "blue";
示例代码
因此,对于执行渲染的代码,我用注释扩展了代码,以便您可以阅读正在发生的事情。下面是一个更好用的版本。
const ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
window.addEventListener("resize", () => {
canvas.width = innerWidth;
canvas.height = innerHeight;
y2 = x2 = innerWidth; // at 45 deg
drawSinWave();
})
const waveLen = 120; // pixels
const phase = 50; // mid way
const amplitude = 25;
const offset = 0;
const x1 = 20;
const y1 = 20;
var x2 = 400; // as vars to let it change to fit resize
var y2 = 400;
function drawSinWave() {
ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.strokeStyle = "blue";
// get the vector form of the line
const vx = x2 - x1;
const vy = y2 - y1;
// Get the length of the line in pixels
const dist = Math.sqrt(vx * vx + vy * vy);
// Make the vector one pixel long to move along the line
const px = vx / dist;
const py = vy / dist;
// We also need a vector to move out from the line (at 90 deg to the ine)
// So rotate the pixel vector 90deg CW
const ax = -py; // a for amplitude vector
const ay = px;
// Begin the path
ctx.beginPath();
// Now loop along every pixel in the line
// We go past the end a bit as floating point errors can cause it to end
// a pixels too early
for (var i = 0; i <= dist + 0.5; i++) {
// fix i if past end
if (i > dist) {
i = dist
} // Carefull dont mess with this ot it will block the page
// Use the distance to get the current angle of the wave
// based on the wave length and phase
const ang = ((i + phase) / waveLen) * Math.PI * 2;
// and at this position get sin
const val = Math.sin(ang);
// Scale to match the amplitude and move to offset
// as the distance from the center of the line
const amp = val * amplitude + offset;
// Get line ceneter at distance i using the pixel vector
var x = x1 + px * i;
var y = y1 + py * i;
// Use the amp vector to move away from the line at 90 degree
x += ax * amp;
y += ay * amp;
// Now add the point
ctx.lineTo(x, y);
}
ctx.stroke();
}
drawSinWave();
canvas {
position: absolute;
top: 0px;
left: 0px;
}
<canvas id=canvas width=4 00 height=4 00></canvas>
作为一个更有用的功能,有一些快捷方式
const ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
window.addEventListener("resize", () => {
canvas.width = innerWidth;
canvas.height = innerHeight;
waveExample.y2 = waveExample.x2 = innerWidth; // at 45 deg
drawSinWave(waveExample);
})
const waveExample = {
waveLen: 100, // pixels
phase: 50, // mid way
amplitude: 35,
offset: 0,
x1: 20,
y1: 20,
x2: 400, // as vars to let it change to fit resize
y2: 400,
lineWidth : 5,
lineCap : "round",
lineJoin : "round",
strokeStyle : "Red",
}
function drawSinWave(wave) {
ctx.lineWidth = wave.lineWidth;
ctx.lineCap = wave.lineCap;
ctx.lineJoin = wave.lineJoin;
ctx.strokeStyle = wave.strokeStyle;
var vx = wave.x2 - wave.x1;
var vy = wave.y2 - wave.y1;
const dist = Math.sqrt(vx * vx + vy * vy);
vx /= dist;
vy /= dist;
ctx.beginPath();
for (var i = 0; i <= dist + 0.5; i++) {
if (i > dist) { i = dist }
const pos = Math.sin(((i + wave.phase) / wave.waveLen) * Math.PI * 2) * wave.amplitude + wave.offset;
ctx.lineTo(
wave.x1 + vx * i - vy * pos,
wave.y1 + vy * i + vx * pos
);
}
ctx.stroke();
}
drawSinWave(waveExample);
canvas {
position: absolute;
top: 0px;
left: 0px;
}
<canvas id=canvas width=4 00 height=4 00></canvas>