https://blog.csdn.net/lecepin/article/details/53536445
思路:增加每個像素點的寬度 減少數組個數。 用另外一個數組去維護每個點的唯一。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#c1 {
background: #ccc;
}
</style>
</head>
<body>
<canvas id="c1"></canvas>
<script>
var canvas = document.getElementById('c1');
var ctx = canvas.getContext('2d');
//畫布屬性
var mW = canvas.width = screen.width;
var mH = canvas.height = 300;
var lineWidth = 3;
var speed = 1; //波浪速度,數越大速度越快
var speedx = 0.05; //波浪速度,數越大速度越快
var yOffset = 0; //波浪x偏移量
var xOffset = 0; //波浪x偏移量
//Sin 曲線屬性
var sX = 0;
var sY = mH / 2;
var axisLength = mW; //軸長
var waveWidth = 0.011 ; //波浪寬度,數越小越寬
var waveHeight = 70; //波浪高度,數越大越高
ctx.lineWidth = lineWidth;
//畫sin 曲線函數
var drawSin = function(yOffset,xOffset){
ctx.save();
var points=[]; //用於存放繪製Sin曲線的點
ctx.beginPath();
//在整個軸長上取點
for(var x = sX; x < sX + axisLength; x += 20 / axisLength){
//此處座標(x,y)的取點,依靠公式 “振幅高*sin(x*振幅寬 + 振幅偏移量)”
// var y = -Math.sin((sX + x) * waveWidth);
var y = -Math.sin((sX + x) * waveWidth+xOffset);
points.push([x, sY + y * waveHeight]);
ctx.lineTo(x, sY + y * waveHeight+yOffset);
}
//封閉路徑
ctx.lineTo(axisLength, mH);
ctx.lineTo(sX, mH);
ctx.lineTo(points[0][0],points[0][1]);
ctx.stroke();
ctx.restore();
};
drawSin(yOffset,xOffset);
var render = function(){
ctx.clearRect(0, 0, mW, mH);
drawSin(yOffset,xOffset);
// drawSin(xOffset2);
// drawSin(20);
yOffset += speed; //形成動態效果
xOffset += speedx; //形成動態效果
if(yOffset > waveHeight ){
speed = -1;
}
if(yOffset < -waveHeight){
speed = 1;
}
requestAnimationFrame(render);
}
render();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#c1 {
background: #ccc;
}
</style>
</head>
<body>
<canvas id="c1"></canvas>
<script>
var canvas = document.getElementById('c1');
var ctx = canvas.getContext('2d');
//畫布屬性
var mW = canvas.width = screen.width;
var mH = canvas.height = 300;
var lineWidth = 3;
var speed = 1; //波浪速度,數越大速度越快
var speedx = 0.05; //波浪速度,數越大速度越快
var yOffset = 0; //波浪x偏移量
var xOffset = 0; //波浪x偏移量
//Sin 曲線屬性
var sX = 0;
var sY = mH / 2;
var axisLength = mW; //軸長
var waveWidth = 0.011 ; //波浪寬度,數越小越寬
var waveHeight = 70; //波浪高度,數越大越高
ctx.lineWidth = lineWidth;
var points=[];
//畫sin 曲線函數
var drawSin = function(yOffset,xOffset){
ctx.save();
//用於存放繪製Sin曲線的點
ctx.beginPath();
//在整個軸長上取點
for(var x = sX; x < sX + axisLength; x += 2000 / axisLength){
//此處座標(x,y)的取點,依靠公式 “振幅高*sin(x*振幅寬 + 振幅偏移量)”
// var y = -Math.sin((sX + x) * waveWidth);
var y = -Math.sin((sX + x) * waveWidth);
points.push([x, sY + y * waveHeight]);
// ctx.lineTo(x, sY + y * waveHeight);
}
//封閉路徑
ctx.lineTo(axisLength, mH);
ctx.lineTo(sX, mH);
ctx.lineTo(points[0][0],points[0][1]);
ctx.stroke();
ctx.restore();
};
drawSin();
drawWave = function(){
ctx.save();
ctx.beginPath();
for(var i=0;i<points.length;i++){
let point = points[i];
let x = point[0];
let y = point[1];
ctx.lineTo(x,y)
}
ctx.stroke();
}
var len = points.length;
// drawWave();
drawPoint = function(x,y){
ctx.fillRect(x,y,10,10)
// ctx.lineTo(x,y)
// ctx.stroke();
}
var j = 0;
var render = function(){
if(j >= len) {
ctx.clearRect(0, 0, mW, mH);
j =0;
}
var pop = points[j++]
drawPoint(pop[0],pop[1]);
requestAnimationFrame(render);
}
render()
</script>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>canvas高級貝塞爾曲線運動動畫</title>
</head>
<body>
<script type="text/javascript ">
window.addEventListener('load',eventWindowLoaded,false);
function eventWindowLoaded(){
canvasApp();
}
function canvasApp(){
var pointImage = new Image();
pointImage.src="point.jpg";
function drawScreen(){
//首先填充canvas的背景
context.fillStyle = '#eee'
context.fillRect(0,0,theCanvas.width,theCanvas.height);
//邊框
context.strokeStyle = '#eee'
context.strokeRect(1,1,theCanvas.width,theCanvas.height);
//在這裏解釋下貝塞爾曲線,看網頁底部的那個點擊成Canvas三次貝塞爾曲線操作實例!你就會發現一個曲線是由4個點組成的,在下面有註釋
var t = ball.t;
var cx = 3*(p1.x-p0.x);
var bx = 3*(p2.x-p1.x)-cx;
var ax = p3.x-p0.x-cx-bx;
var cy = 3*(p1.y-p0.y);
var by = 3*(p2.y-p1.y)-cy;
var ay = p3.y-p0.y-cy-by;
var xt = ax*(t*t*t)+bx*(t*t)+cx*t+p0.x;
var yt = ay*(t*t*t)+by*(t*t)+cy*t+p0.y;
//這裏的xt和yt貝塞爾曲線的公式,這裏涉及到一門叫做計算機圖形學的學科(大學裏面有上,我也最近一直在上)
// 0 <= t <= 1這是一個T....學過圖形學的應該知道比如一根直線他的起始座標軸的位置(0,0)然後有DDA算法計算斜率,他也是一樣,具體的公式網上還是都有的,我的語言組織也不是很好-_-//
ball.t +=ball.speed;
if(ball.t>1){
ball.t=1;
}
//繪製點
context.font = "10px sans ";
context.fillStyle = "#ff0000 ";
context.beginPath();
context.arc(p0.x,p0.y,8,0,Math.PI*2,true);
context.closePath();
context.fill();
context.fillStyle = "#fff";
context.fillText("0",p0.x-2,p0.y+2);
//
points.push({x:xt,y:yt});
for(var i =0;i<points.length;i++){
context.drawImage(pointImage,points[i].x,points[i].y,5,5);
}
//繪製圖片重點!!!!圖片,定位context.drawImage(img,x,y,width,height);也就是繪製那個點後的小點的軌跡
context.closePath();
context.fillStyle="#000000 ";
context.beginPath();
context.arc(xt,yt,5,0,Math.PI*2,true);
context.closePath();
context.fill();
}
var p0={x:60,y:10};//起始點
var p1={x:70,y:200};//1號點
var p2={x:125,y:295};//2號點
var p3={x:350,y:350};//3號點
var ball={x:0,y:0,speed:.01,t:0};
var points=new Array();
//這裏的起始點和3號點,我取得的名字比較通俗一下,實際上應該稱爲端點。因爲必須要經過的
//1號點和2號點雖然可以刪除但是他控制着弧線的路徑,我們就叫他控制點
theCanvas = document.getElementById('canvas')
context = theCanvas.getContext("2d")
setInterval(drawScreen,33);
}
</script>
<canvas id="canvas" width="800 " height="800 ">
你的瀏覽器無法使用canvas
小白童鞋;你的支持是我最大的快樂!!
</canvas>
</body>
</html>