<html>
<head>
<meta charset="utf8" />
<title>三角函数图形</title>
<style type="text/css">
body {
background-color:black;
}
#canvas {
position:absolute;
top:%;
left:%;
margin:-px -px;
border:px dashed #171717;
}
</style>
</head>
<body>
<canvas id="canvas" width="800px" height="300px">您的浏览器不支持canvas</canvas>
<script type="text/javascript">
//判断是否支持canvaas
function isSupportCanvas(canvas) {
return !!(canvas.getContext && canvas.getContext("2d"));
}
//requestAnimationFrame会自动使用最优的帧率进行渲染
function setupRAF() {
window.lastTime = ;
//兼容各个浏览器,Internet Explorer11、Google Chrome(Microsoft Edge)、Mozilla Firefox、Opera
var vendors = ["ms", "moz", "webkit", "o"];
for(var i=; i<vendors.length; i++) {
window.requestAnimationFrame = window[vendors[i] + "RequestAnimationFrame"];
window.cancelAnimationFrame = window[vendors[i] + "CancelAnimationFrame"] || window[vendors[i] + "CancelRequestAnimationFrame"];
//测试浏览器支持哪一张
if(window.requestAnimationFrame) {
console.log(vendors[i] + "requestAnimationFrame");
}
if(window[vendors[i] + "CancelAnimationFrame"]) {
console.log(vendors[i] + "CancelAnimationFrame");
}
if(window[vendors[i] + "CancelRequestAnimationFrame"]) {
console.log(vendors[i] + "CancelRequestAnimationFrame");
}
}
//回退机制
if(!window.requestAnimationFrame) {
window.requestAnimationFrame = function(callback, element) {
var currentTime = new Date().getTime();
var timeToCall = Math.max(, -(currentTime-window.lastTime));
var callTime = currentTime + timeToCall;
var id = window.setTimeout(function() {
callback(callTime);
}, timeToCall);
window.lastTime = callTime;
return id;
};
}
//回退机制
if(!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
}
}
}
var CanvasController = function(canvas) {
var ctx = canvas.getContext("2d");
ctx.lineWidth = ;
var i = ;
var step = ;
var unitX =
var unitY = canvas.height * ;
function update() {
i += step;
i %= ;
}
//渲染坐标
function rendeRcoordinate() {
var color = "white";
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.textBaseline = "top";
ctx.font = "normal 8pt Arial"
ctx.beginPath();
var halfCanvasHeight = * canvas.height;
var topUnit = halfCanvasHeight - unitY;
var bottomUnit = halfCanvasHeight + unitY;
ctx.moveTo(, topUnit);
ctx.lineTo(canvas.width, topUnit);
ctx.moveTo(, halfCanvasHeight);
ctx.lineTo(canvas.width, halfCanvasHeight);
ctx.moveTo(, bottomUnit);
ctx.lineTo(canvas.width, bottomUnit);
ctx.stroke();
var doubleUnitX = * unitX;
var zero = unitX - i;
while(zero < ) {
zero += doubleUnitX;
}
ctx.beginPath();
for(var a = zero; a < canvas.width; a += doubleUnitX) {
ctx.moveTo(a, );
ctx.lineTo(a, canvas.height);
ctx.fillText("(0,0)", a, halfCanvasHeight);
}
ctx.stroke();
}
//绘制x=sin(a),y=cos(a)的函数
function renderXSinYCos() {
var color = "yellow";
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
ctx.font = "normal 2pt Arial"
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.beginPath();
var zeroX = * canvas.width;
var zeroY = * canvas.height;
for(var x = ; x < canvas.width; x++) {
var a = (x + i) / * Math.PI;
var curX = Math.sin(a) * unitX + zeroX;
var curY = Math.cos(a) * unitY + zeroY;
if(x == ) {
ctx.moveTo(curX, curY);
} else {
ctx.lineTo(curX, curY);
}
}
ctx.stroke();
var text = "x=sin(a)\ny=cos(a)";
var textArr = text.split("\n");
for(var index = textArr.length - , y = zeroY; index >= ; index--, y -= ) {
ctx.fillText(textArr[index], zeroX, y);
}
}
//渲染三角函数
function render(trigonometricFunction, color) {
ctx.strokeStyle = color;
ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.font = "bold 18pt Calibri";
ctx.beginPath();
var isLastInRange = false;
for(var x = ; x < canvas.width; x++) {
var a = (x + i) / * Math.PI;
var y = trigonometricFunction(a);
//tan值有可能是无穷大或无穷小(由于这里是用角度换算的,所以一般不会取到无穷的情况)
if(isFinite(y)) {
y = y * unitY + * canvas.height;
if(isLastInRange) {
if(y < || y > canvas.height) {
isLastInRange = false;
} else {
ctx.lineTo(x, y);
}
} else {
if(!(y < || y > canvas.height)) {
isLastInRange = true;
ctx.moveTo(x, y);
}
}
if(x == ) {
ctx.fillStyle = color;
var funcName = trigonometricFunction.toString();
var reg = /function\s*(\w*)/i;
var matches = reg.exec(funcName);
ctx.fillText(matches[], , y);
}
} else {
isLastInRange = false;
break;
}
}
ctx.stroke();
}
this.init = function() {
function loop() {
requestAnimationFrame(loop, canvas);
ctx.clearRect(, , canvas.width, canvas.height);
update();
rendeRcoordinate();
renderXSinYCos();
render(Math.sin, "red");
render(Math.cos, "green");
render(Math.tan, "blue");
}
loop();
}
}
function init() {
var canvas = document.getElementById("canvas");
if(!isSupportCanvas(canvas)) {
return;
}
setupRAF();
var canvasController = new CanvasController(canvas);
canvasController.init();
}
init();
</script>
</body>
</html>

注意:在绘制曲线时,例如波浪等看似很像正弦(余弦)函数,基本都是使用贝塞尔曲线。