HTML5 标签 canvas

370 阅读3分钟

canvas

默认是300x150大小,可以在标签上直接设置宽高

<canvas id="myCanvas" height=500 width=500></canvas>

js获取canvas画布

var canvas = document.getElementById("myCanvas");

定义画笔

var ctx = canvas.getContext("2d");//画3d传webgl

通常3d的动画才会开启CPU加速,所以2d的图片我们也可以设置,translateZ,或者rotate来欺骗浏览器,获取CPU加速

moveTo

ctx.moveTo(100, 100);

定位画笔的初始位置

lineTo

ctx.lineTo(200, 200);

直线

一个简单的三角形,推荐最后一步用closePath()

ctx.moveTo(100, 100);        
ctx.lineTo(200, 200);        
ctx.lineTo(100, 300);        
ctx.lineWidth = 10;//线的中间是基准线        
ctx.strokeStyle = "red";        
ctx.closePath();

ctx.stroke();//描边

ctx.fill();//填充,收尾点连接,填充内部

画笔的方法就相当于构图,这两个方法才是将构图显示在画布上,而且所有的fill和stroke都是作用在所有的子路径上的,也就是说如果你没有开启一个新的路径(beginPath),那么相同的方法就会被覆盖

ctx.beginPath()

开启一个新的路径,最好每个canvas前都加这句

ctx.clearRect(0, 0, w, h);

清除画布,矩形形式

ctx.beginPath();        
ctx.rect(100, 100, 200, 100);
//矩形,左上角(100, 100)开始,左200,高100,还有strokeRect() 和 fillRect() 方法,
//且这两个方法自带beginPath功能        
ctx.stroke();        
//清除画布        
var h = canvas.height,            
w = canvas.width;        
ctx.clearRect(0, 0, w, h);        
//ctx.clearRect(100, 100, 80, 80);

一个方块下落的demo

function animate(y) {            
    ctx.beginPath();//注意没有beginPath的时候,变成柱状了            
    ctx.rect(50, y, 50, 50);            
    ctx.fill();
        //    ctx.fillRect(50, y, 50, 50);                   
}        
var timer = setInterval(function () {            
    ctx.clearRect(0, 0, w, h);            
    animate(y);            
    y += 10            
    if(y >= 460) {                
        animate(450)                
        clearInterval(timer);            
    }        
}, 100)

注意如果你用rect的话,要小心如果没有beginPath的话,你将得到一个柱状的长方形,这是因为clearRect只会清除stroke/fill这种画在画布上的图片,而你画笔的轨迹是不会清除的,所以每一个定时器都会stroke,最后得到的就是一个大的长方形。此外,注意如果下一次小方块运动到画布外的时候,我采取的是直接定位的方式,直接定位到画布底端。

ctx.arc(圆心x,圆心y,r, 起始弧度,末端弧度,顺逆时针)

ctx.arc(50, 50, 40, Math.PI/180*0, Math.PI/180*270, 0);//圆心,半径,弧度,0顺1逆        
ctx.stroke();


//这是一个扇形        
ctx.moveTo(100, 200);        
ctx.lineTo(200, 200);        
ctx.arc(100, 200, 100, Math.PI/180 * 0, Math.PI/180 * 300, 1);        
ctx.lineTo(100, 200);        
ctx.stroke()        
ctx.moveTo(100, 240)        
ctx.arcTo(350, 240, 350, 400, 50);        
ctx.stroke();

0度在数学上笛卡尔坐标系x的正半轴上,角度的大小是顺时针绕x轴一圈0~360,采用弧度制,所以Math.PI/180*X来写入想要的大小

贝塞尔曲线

ctx.moveTo(200, 200);       
ctx.quadraticCurveTo(300, 100, 500, 500);  //二次贝塞尔曲线     
ctx.bezierCurveTo(300, 100,400, 400, 500, 500);   //三次贝塞尔曲线    
ctx.stroke(); 

画布内坐标系的改变

默认是一左上角为(0,0)点,但我们也可以改变,例如:

ctx.translate(200, 200);//平移坐标系    

ctx.scale(2, 0.5)//缩放X轴和Y轴

ctx.rotate(Math.PI/180 * 30);//旋转整个画布,(0,0)为圆心,正为顺时针,负为逆时针 

有时根据需要我们要来回切换坐标系,save方法可以保存坐标系,restore可以回到save保存的坐标系(但只能同时保存一种坐标系,所以我们通常保存原始坐标系,为了方便我们切换),比如下面这个例子:

ctx.save();//保存当前视图状态,只能保存一种状态    
ctx.rotate(Math.PI/180 * 30);//旋转整个画布,30rad    
ctx.rect(100, 100, 50, 50);    
ctx.restore();//回到save的状态    
ctx.rect(400, 400, 50, 50);    
ctx.fill();