Skip to content

Instantly share code, notes, and snippets.

@otizis
Created March 17, 2017 09:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save otizis/a6ee65a92eac0b7eac09606afc0caf7d to your computer and use it in GitHub Desktop.
Save otizis/a6ee65a92eac0b7eac09606afc0caf7d to your computer and use it in GitHub Desktop.
学习canvas的操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<canvas id="myCanvas" width="600" height="400" style="border: 1px black solid"></canvas>
<script>
function Dot(centerX, centerY, color,startx,starty) {
this.x = centerX;
this.y = centerY;
this.color = color;
this.x2 = centerX + (Math.random() - 0.5)*5;
this.y2 = centerY + (Math.random() - 0.5)*5;
this.frameNum = 0;//示为这个粒子当前在第几帧
this.frameCount = Math.ceil(3000 / 16.66);//表示一共有多少帧,一般来说我们不会直接知道做完这个动画一共有多少帧,所以这里我们是算出来的,parseInt(3000 / 16.66) 中3000表示3000毫秒,也就是整个动画耗时3秒,而16.66是因为按60FPS来算,浏览器对每一帧画面的渲染工作需要1秒 / 60 = 16.66毫秒,算出来之后再做个向上取整,就算出总帧数。
this.startx = startx;
this.starty = starty;
this.delay = Math.random()*this.frameCount
}
function rgb2hex(red, green, blue) {
var rgb = blue | (green << 8) | (red << 16);
return '#' + (0x1000000 + rgb).toString(16).slice(1)
}
// 计算缓动的函数
// t 当前时间
// b 初始值
// c 总位移
// d 总时间
function easeInOutCubic(t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t + b;
return c/2*((t-=2)*t*t + 2) + b;
}
(function() {
var canvas=document.getElementById('myCanvas')
var ctx = null;
if(canvas.getContext){
ctx = canvas.getContext('2d');
}
var winWidth = canvas.width;
var winHeight = canvas.height;
var image = new Image();
var imgW = image.width,
imgH = image.height;
var dotList=[];
var endDotNum = 0;
var rafId=null;
function draw() {
// body..
ctx.clearRect(0, 0, winWidth, winHeight);
var curDot;
var frameNum = 0,frameCount = 0,curX, curY;
var len = dotList.length;
for(var i=0; i< len; i++)
{
curDot = dotList[i];
if(curDot.delay > 0)
{
curDot.delay-=2;
continue;
}
frameNum = curDot.frameNum;
frameCount = curDot.frameCount;
if(frameNum < frameCount){
curx = easeInOutCubic(frameNum,curDot.startx,curDot.x2 - curDot.startx,frameCount);
cury = easeInOutCubic(frameNum,curDot.starty,curDot.y2 - curDot.starty,frameCount);
//设置填充颜色
ctx.fillStyle = curDot.color;
//绘粒子到画布上
ctx.fillRect(curx, cury ,1,1);
curDot.frameNum++;
}else if(frameNum == frameCount){
//设置填充颜色
ctx.fillStyle = curDot.color;
//绘粒子到画布上
ctx.fillRect(curDot.x2, curDot.y2,1,1);
endDotNum++;
curDot.frameNum++;
}else{
//设置填充颜色
ctx.fillStyle = curDot.color;
//绘粒子到画布上
ctx.fillRect(curDot.x2, curDot.y2,1,1);
}
}
if(endDotNum >= len)
{
cancelAnimationFrame(rafId);
float();
return;
}
rafId = requestAnimationFrame(draw);
}
function float(){
// body..
ctx.clearRect(0, 0, winWidth, winHeight);
var curDot;
var frameNum = 0,frameCount = 0,curX, curY;
var len = dotList.length;
for(var i=0; i< len; i++)
{
curDot = dotList[i];
if(curDot.delay > 0)
{
curDot.delay-=2;
continue;
}
frameNum = curDot.frameNum;
frameCount = curDot.frameCount;
if(frameNum < frameCount){
curx = easeInOutCubic(frameNum,curDot.startx,curDot.x2 - curDot.startx,frameCount);
cury = easeInOutCubic(frameNum,curDot.starty,curDot.y2 - curDot.starty,frameCount);
//设置填充颜色
ctx.fillStyle = curDot.color;
//绘粒子到画布上
ctx.fillRect(curx, cury ,1,1);
curDot.frameNum++;
}else if(frameNum == frameCount){
//设置填充颜色
ctx.fillStyle = curDot.color;
//绘粒子到画布上
ctx.fillRect(curDot.x2, curDot.y2,1,1);
curDot.startx = curDot.x2;
curDot.starty = curDot.y2;
curDot.x2 = curDot.x + (Math.random() - 0.5)*20;
curDot.y2 = curDot.y + (Math.random() - 0.5)*20;
curDot.frameNum = 0;
curDot.frameCount = 20;
}
}
rafId = requestAnimationFrame(float);
}
image.onload = function () {
imgW = image.width;
imgH = image.height;
var sx = winWidth/2-imgW/2;
var sy = winHeight/2-imgH/2;
ctx.drawImage(image,sx,sy);
var imgData = ctx.getImageData(sx,sy,imgW,imgH);
console.log(imgData);
var forX = imgData.width;
var forY = imgData.height;
var imageArray = imgData.data;
for(var x=0; x<forX; x+=1) {
for(var y=0; y<forY; y+=1) {
//imgData.data代表的是rgba的值,比如说第一个数字0,代表第一个像素的R值,第二个数字0代表第一个像素的G值,第三第四个0分别代表第一个像素的B值和Alpha值,最后出来第一个像素就是个全透明的颜色,第五个数字就代表第二个像素的R值了。
var i = (y*forX + x) * 4;
//imgData.data[i+3] > 128 表示alpha值不透明
if((imageArray[i]+imageArray[i+1]+imageArray[i+2]+imageArray[i+3] < 900)&&imageArray[i+3] > 128){
var dot = new Dot(
sx + x,
sy + y,
rgb2hex(imageArray[i],imageArray[i+1],imageArray[i+2],imageArray[i+3]),
winWidth*Math.random(),
winHeight*Math.random());
dotList.push(dot);
}
}
}
console.log(dotList.length);
float();
}
image.src = 'bug.png';
})()
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment