<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<title>sin_cos</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body>
<canvas id="drawing_canvas"></canvas>
<script src="//cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>
<script src="js/main.js"></script>
</body>
xxxxxxxxxx
html, body {
width: 100%;
height: 100%;
overflow: hidden;
}
body {
background-color: #222;
margin: 0;
}
#drawing_canvas {
background-color: #aaa;
position: absolute;
margin: auto;
width: 1024px;
height: 480px;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
xxxxxxxxxx
const TWO_PI = Math.PI * 2;
const HALF_PI = Math.PI * 0.5;
var viewWidth = 1024;
var viewHeight = 480;
var drawingCanvas, ctx;
var speed = 60;
var timeStep = (1/speed);
var time = 0;
var radius = 100;
var points = [];
initDrawingCanvas();
initGUI();
function initGUI() {
var gui = new dat.GUI();
gui.add(window, "radius", 20, 100);
gui.add(window, "speed", 1, 120).onChange(function() {
timeStep = (1 / (121 - speed));
});
}
function initDrawingCanvas() {
drawingCanvas = document.getElementById("drawing_canvas");
drawingCanvas.width = viewWidth;
drawingCanvas.height = viewHeight;
ctx = drawingCanvas.getContext('2d');
}
function draw() {
// update points
var x = -Math.sin(time) * radius + 120;
var y = Math.cos(time) * radius + 120;
points.unshift({x:x, y:y});
if (points.length > 4096) points.pop();
ctx.lineWidth = 2;
ctx.lineCap = "round";
clear();
drawBackground();
drawProjectionLines(x, y);
// draw line from circle center to [x, y]
ctx.strokeStyle = "#fff";
drawLine(120, 120, x, y);
// draw little circles at intersections
ctx.fillStyle = "#fff";
drawCircleFill(x, y, 5);
ctx.fillStyle = "#f0f";
drawCircleFill(240, y, 5);
ctx.fillStyle = "#0ff";
drawCircleFill(x, 240, 5);
drawCircleFill(240, 480 - x, 5);
// draw the waves
drawSinWave();
drawCosWave();
// next frame
time += timeStep;
requestAnimationFrame(draw);
}
function clear() {
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, viewWidth, viewHeight);
}
function drawBackground() {
var dividerCount = Math.ceil((viewWidth - 240) / (radius * Math.PI)) * 2,
dividerX;
// top graph
ctx.strokeStyle = '#333';
drawLine(120, 120 - radius, viewWidth, 120 - radius);
drawLine(0, 120, viewWidth, 120);
drawLine(120, 120 + radius, viewWidth, 120 + radius);
// bottom graph
drawLine(240, 360 - radius, viewWidth, 360 - radius);
drawLine(240, 360, viewWidth, 360);
drawLine(240, 360 + radius, viewWidth, 360 + radius);
drawLine(120 - radius, 120, 120 - radius, 240);
drawLine(120, 0, 120, 240);
drawLine(120 + radius, 120, 120 + radius, 240);
// arcs
drawArc(240, 240, 120 - radius, HALF_PI, Math.PI);
drawArc(240, 240, 120, HALF_PI, Math.PI);
drawArc(240, 240, 120 + radius, HALF_PI, Math.PI);
// vertical dividers
for (var i = 0; i < dividerCount; i++) {
dividerX = 240 + radius * HALF_PI * i;
dividerX += radius * (time % HALF_PI);
drawLine(dividerX, 0, dividerX, 480);
}
// circle and axis
ctx.strokeStyle = '#777';
drawLine(240, 0, 240, viewHeight);
drawLine(0, 240, viewWidth, 240);
drawCircleStroke(120, 120, radius);
}
function drawProjectionLines(x, y) {
// draw lines connecting the circle and waves
ctx.setLineDash([5]);
ctx.strokeStyle = '#f0f';
drawLine(x, y, 240, y);
ctx.strokeStyle = '#0ff';
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, 240);
ctx.arcTo(x, 480 - x, 240, 480 - x, 240 - x);
ctx.stroke();
ctx.setLineDash([]);
}
function drawSinWave() {
ctx.strokeStyle = "#f0f";
ctx.beginPath();
for (var i = 0; i < points.length; i++) {
ctx.lineTo(i * timeStep * (radius) + 240, points[i].y);
}
ctx.stroke();
}
function drawCosWave() {
ctx.strokeStyle = "#0ff";
ctx.beginPath();
for (var j = 0; j < points.length; j++) {
ctx.lineTo(240 + j * timeStep * radius, -points[j].x + 480);
}
ctx.stroke();
}
function drawLine(x1, y1, x2, y2) {
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function drawCircleFill(x, y, r) {
ctx.beginPath();
ctx.arc(x, y, r, 0, TWO_PI);
ctx.fill();
}
function drawCircleStroke(x, y, r) {
ctx.beginPath();
ctx.arc(x, y, r, 0, TWO_PI);
ctx.stroke();
}
function drawArc(x, y, r, s, e) {
ctx.beginPath();
ctx.arc(x, y, r, s, e);
ctx.stroke();
}
requestAnimationFrame(draw);