HTML5标签canvas
1、canvas简介
1、canvas:
* >做游戏:白鹭引擎、trees…;
* >做动画;做动态图表,频谱;画图…
* HTML5不是单纯的html
* canvas本身是一个标签,是一个空白的画布,默认是300*150的宽高
* 本身有宽高的属性,不需要使用CSS去设置,如果非要设置,一定要和canvas的宽高设置相同,不然绘制出来的内容就是变形的
* 如果希望画布上有内容,需要通过JS来绘制->是通过画布的上下文(相当于舞台,舞台上面可以有各种移动,展示出来)进行绘制的2、使用步骤:
* >1.创建一个空白画布
* >2.获得画布的上下文
* >3.绘制准备:设置要绘制的一些样式和内容(画笔的宽,颜色,所需的资源)
* >4.开始绘制3、HTMLCanvasElement的2个属性:
* >width:宽;
* >height:高
* >lineWidth:设置笔画宽度4、HTMLCanvasElement的方法:
* >getContext(inDOMString contextId),可以传2d或者experimental-webgl(图形图像处理)
* >toDataURL():把canvas对象转成url->生成带有绘制内容的一个资源链接地址
* >moveTo(x,y):抬起笔来要落到哪一个位置
* >lineTo(x,y):画线到某个点
* >stroke(不传||path):把画的内容绘制出来:path是2d类型的
* >beginPath():标识,要开始一个路径
* >closePath():标识,要闭合一个路径
* >clearRect():是 Canvas 2D API 设置指定矩形区域内(以 点 (x, y) 为起点,范围是(width, height) )所有像素变成透明,并擦除之前绘制的所有内容的方法。
* >canvas:获得画布的DOM元素;
* >lineCap:设置画笔结束位置的形状(butt:方形,round:圆形,square:线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域。)
* >CanvasRenderingContext2D.createLinearGradient()Canvas 2D API 的方法沿着由参数表示的坐标给出的线创建一个梯度。
* >CanvasRenderingContext2D.createRadialGradient()Canvas 2D API 的方法创建由参数表示的两个圆的坐标给出的径向渐变。此方法返回a CanvasGradient。
* >CanvasRenderingContext2D.arc(x<原点x坐标>,y<原点y坐标>,radius<半径>,startAngle<起始角度>,endAngle<结束角度>,anticlockwise<是否逆时针>):其在中心的路径(X,Y)与半径位置[R开始于由startAngle和在结束endAngle通过在给定的方向上行进逆时针(默认顺时针)。
* >CanvasRenderingContext2D.createLinearGradient()//创建一个渐变对象
* >CanvasRenderingContext2D.strokeText(text,x,y [,maxWidth]);Canvas 2D API 的方法在给定的(x,y)位置上触发给定的文本。如果提供了最大宽度的可选第四个参数,文本将被缩放以适应该宽度。
* >Scale(x,y):放大缩小,不会影响到画布本身,所放的是画布里面的内容(让画布里面的单位进行缩放)
* >Save():保存画布上面之前的样式,即在写save之前的样式,包括(笔画宽度,颜色,变形)
* >Restore():还原的是上一次保存的状态,多次retore也是返回上次保存的内容[1]->1.[1,2]->2,1
* >Translate():平移,以画布的原点为参考。也相当于重新设置原点。
* >Rotate(anglePI/180*角度):旋转,旋转中心点一直是 canvas 的起始点。并没有旋转canvas,旋转的是后续绘制在canvas上的图形。 如果想改变中心点,我们可以通过 translate() 方法移动 canvas 。5、 CanvasGradient :设置canvas里免颜色渐变的类,可以通过设置颜色的方式(fillStyl/strokeStyle)去设置渐变对象
* 方法:
* >addColorStop(offset(0-1),color):这个方法可以多次调用添加渐变的颜色值6、canvas里面的动画:
* >1.通过不断刷新canvas里面的内容,实现动画
* >2.清除上一次canvas里面的内容
2、基本方法使用方法
(function(){ var rectX=0; var rectY=0; var timer; function init(){ //dom操作 HTMLElement //canvas:HTMLCanvasElement var canvasEle=document.querySelector("#box"); canvasEle.width=innerWidth; canvasEle.height=innerHeight; /*获得画布的上下文 * 返回一个 CanvasRenderingContext2D对象:提供了绘制,设置绘制内容的方法属性 * >fillStyle:设置填充的样式(充满) * >storkeStyle:设置绘制内容轮廓的样式 * >fillRect(x,y,w,h):绘制矩形的方法,以填充的方式绘制,原点是画布的左上角 */ var context=canvasEle.getContext("2d"); //设置要绘制的参数 // context.fillStyle="red"; //设置绘制内容轮廓的样式 // context.strokeStyle="yellow"; //距离原点左上角100,边长为50,50()的画布 //context.fillRect(100,100,50,50); context.lineWidth=2; /*context.moveTo(200,100); context.lineTo(400,100); context.moveTo(400,100); context.lineTo(400,200); context.moveTo(400,200); context.lineTo(200,200); context.moveTo(200,200); context.lineTo(200,100); context.stroke();*/ rectX=50; rectY=30; drawRect({ context:context, strokeColor:"white", fillColor:"orange", x:50, y:30, width:100, height:100 }); /*setTimeout(function(){ context.clearRect(0,0,innerWidth,innerHeight); },3000); rectControl(context);*/ } //封装一个画矩形的方法 function drawRect(info){ if(!info){ console.log("必须传参数"); return; } info.context.strokeStyle=info.strokeColor; info.context.fillStyle=info.fillColor; info.context.beginPath();//是 Canvas 2D API 通过清空子路径列表开始一个新路径的方法。 当你想创建一个新的路径时,调用此方法。 info.context.moveTo(info.x,info.y); info.context.lineTo(info.x+info.width,info.y); info.context.lineTo(info.x+info.width,info.y+info.height); info.context.lineTo(info.x,info.y+info.height); // info.context.lineTo(info.x,info.y); info.context.closePath();//是 Canvas 2D API 将笔点返回到当前子路径起始点的方法 info.context.fill();//是 Canvas 2D API 根据当前的填充样式,填充当前或已存在的路径的方法 info.context.stroke(); } function rectControl(context){ document.onkeydown=function(event){//当按下wasd的时候执行不同的动画 var dis=""; // console.log(event); switch(event.keyCode){ case 87: dis="top"; break; case 65: dis="left"; break; case 83: dis="bottom"; break; case 68: dis="right"; break; default: break; } move(context,dis); }; document.onkeyup=function(){ clearInterval(timer); timer=null; } } function move(context,direction){ context.clearRect(1,1,innerWidth,innerHeight);//清除上一帧 var distance=5; switch(direction){ case "left": rectX-=distance; break; case "right": rectX+=distance; break; case "top": rectY-=distance; console.log(rectY) break; case "bottom": rectY+=distance; break; } drawRect({ context:context, strokeColor:"white", fillColor:"orange", x:rectX, y:rectY, width:100, height:100 }); if(timer){return}//自己调用自己,如果有timer,就不要去创建,如果不写,每次都创建,定时器效果会叠加 timer=setInterval(function(){ move(context,direction); },30) } init(); })();
(function(){ function init(){ /*var canvasEle=document.querySelector("#box"); canvasEle.width=innerWidth; canvasEle.height=innerHeight; window.onresize=function(){ cavnasEle.width=innerWidth; canvasEle.height=innerHeight; }; var context=canvasEle.getContext("2d"); var linearGradient=context.createLinearGradient(0,0,innerWidth,innerHeight);//创建线性渐变的方法->CanvasGradient类型的对象 linearGradient.addColorStop(0,"blue"); linearGradient.addColorStop(0.5,"white"); linearGradient.addColorStop(1,"green"); context.fillStyle=linearGradient;//添加颜色渐变 context.strokeStyle=linearGradient; context.font="40px 华文楷体"; context.strokeText("你好",100,100); context.fillText("你好",200,200); // context.fillRect(0,0,innerWidth,innerHeight);*/ } init(); })();
(function(){ var context=document.getElementById("container").getContext("2d"); function scale(){ context.save();//保存上一次canvas里面的状态 context.scale(0.5,1);//先放大缩小才行,放大缩小的是画布里面的内容的像素点,画布本身没有变化 context.fillStyle="red"; context.fillRect(100,100,100,100); context.restore();//还原上次保存的状态 context.save(); context.fillStyle="yellow"; context.fillRect(100,100,50,50) context.restore(); context.fillRect(0,0,50,50) } function test(){ context.save(); context.strokeStyle="green"; context.lineWidth=5; context.moveTo(0,0); context.lineTo(300,50); context.stroke(); context.restore(); context.moveTo(0,100); context.lineTo(300,100); context.stroke(); } function move(){ context.save(); context.translate(200,-100);//沿着x向右移动200px,沿着y向上一定100px,移动的时候是以原点为中心去移动的 context.fillRect(300,300,100,100); context.restore(); context.fillStyle="yellow"; context.fillRect(300,300,50,50); } function rotation(){ context.rotate(2*Math.PI/360*45);//旋转45度 context.fillText("nhao",300,300) context.fillRect(300,300,50,50); } function init(){ scale(); test(); move(); rotation(); } init(); })();
3、canvas具体实例
1.自制画板
》HTML部分
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>painter</title>
<style type="text/css">
*{margin: 0;padding: 0;}
html{overflow: hidden;}
#box{background-color: #242424;}
.toolMenu{position: absolute;}
.openButton{width: 50px;height: 50px;background-color: #ff3c1a;border-radius: 50%;}
.tool{background-color: yellow;}
.tool li{margin-top: 5px;}
a{text-decoration: none;background-color: #bebebe;width: 60px;text-align: center;display: block;}
</style>
</head>
<body>
<div class="toolMenu">
<div class="openButton"></div>
<ul class="tool">
<li>宽度<input type="range"/></li>
<li>颜色<input type="color"/></li>
<li><a class="download" download="photo">下载</a></li>
<li><a class="clear" herf="#">清屏</a></li>
<li><a class="eraser" herf="#">橡皮擦</a></li>
</ul>
</div>
<canvas id="box"></canvas>
<script src="js/painter.js" type="text/javascript" charset="utf-8"></script>
<script src="js/main.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
》painter.js:面向对象写法
(function(){
function Painter(id){
var canvasEle=document.getElementById(id);
canvasEle.width=innerWidth;
canvasEle.height=innerHeight;
this.context=canvasEle.getContext("2d");
// this.context.strokeStyle="white";
this.drawLine();
this.bgcolor=document.defaultView.getComputedStyle(canvasEle, null).backgroundColor;
}
Painter.prototype.drawLine=function(){
var self=this;
self.context.canvas.addEventListener("mousedown",startAction);
self.context.canvas.addEventListener("mouseup",endAction);
function startAction(event){
if(!self.isClear){//如果没有使用橡皮擦就是划线的功能
self.context.beginPath();
self.context.moveTo(event.pageX,event.pageY);
self.context.stroke();
}
self.context.canvas.addEventListener("mousemove",moveAction);
}
function endAction(){
self.isClear=false;//不再使用橡皮擦的功能
self.context.canvas.removeEventListener("mousemove",moveAction);
}
function moveAction(event){
if(self.isClear){//移动的时候清除,-8的原因是要让他移动到中间
self.context.clearRect(event.pageX-8,event.pageY-8,16,16);
return;
}
self.context.lineTo(event.pageX,event.pageY);
self.context.stroke();
}
}
Painter.prototype.setLineWidth=function(width){
this.context.lineWidth=width;
}
Painter.prototype.isRoundLineCap=function(isRound){
this.context.lineCap=isRound?"round":"butt";
}
Painter.prototype.setLineColor=function(color){
this.context.strokeStyle=color;
}
Painter.prototype.save=function(){
return this.context.canvas.toDataURL();//吧绘制的内容保存成一个图片地址
}
Painter.prototype.clear=function(){
this.context.clearRect(0,0,innerWidth,innerHeight);
}
/* Painter.prototype.eraser=function(){
this.setLineColor(this.bgcolor);
this.drawLine();
}*/
Painter.prototype.rubber=function(){
this.isClear=true;
}
window.Painter=Painter;
})();
》main.js调用过程:
(function(){
function init(){
var painter=new Painter("box");
painter.setLineWidth(5);
painter.isRoundLineCap(true);
painter.setLineColor("red");
var toolView=document.querySelector(".tool")
document.querySelector(".openButton").onclick=function(){ toolView.style.display=toolView.style.display==="block"?"none":"block";
}; document.querySelector("input[type=range]").value=painter.context.lineWidth*2;
document.querySelector("input[type=range]").onchange=function(){
painter.setLineWidth(this.value/4);
}; document.querySelector("input[type=color]").value=painter.context.strokeStyle;
document.querySelector("input[type=color]").onchange=function(){
painter.setLineColor(this.value);
};
var download=document.querySelector(".download");
download.onclick=function(){
download.setAttribute("href",painter.save());
};
document.querySelector(".clear").onclick=function(){
painter.clear();
};
var eraser=document.querySelector(".eraser");
/*eraser.onclick=function(){
eraser.innerHTML=eraser.innerHTML==="橡皮擦"?"停止":"橡皮擦";
if(eraser.innerHTML=="停止"){ document.body.style.cursor="url(img/eraser.png),pointer"; painter.eraser(); }else{ document.body.style.cursor=""; painter.setLineColor(document.querySelector("input[type=color]").value) painter.drawLine() }
};*/
eraser.onclick=function(){
painter.rubber();
}
}
init();
})();
2、制作动态柱状图
》使用面向对象直接创建表格
(function(){
/*1.封装表格的背景
*2.绘制带文字小方块
* datas是传过来的需要可视化的数据
*/
function Table(superEle,datas){
this.canvasContext=document.createElement("canvas").getContext("2d");//创建canvas对象
superEle.appendChild(this.canvasContext.canvas);//添加到父元素中
this.width=this.canvasContext.canvas.width=innerWidth;//设置宽
this.height=this.canvasContext.canvas.height=innerHeight;//设置高
this.datas=datas||[];
this.background();
this.addRect();
}
Table.prototype.background=function(){
this.canvasContext.beginPath();
this.canvasContext.strokeStyle="black";
var space=10;
this.canvasContext.strokeRect(space,space,this.width-space*2,this.height-space*2);//绘制矩形,边距留白
var lineHeight=(this.height-space*2)/10;
for(var i=1;i<10;i++){//绘制背景的9根线
this.canvasContext.moveTo(space,space+lineHeight*i);
this.canvasContext.lineTo(this.width-space,space+lineHeight*i);
this.canvasContext.stroke();
}
}
Table.prototype.addRect=function(){
var gradient=this.canvasContext.createLinearGradient(0,0,0,this.height);
gradient.addColorStop(0,"red");
gradient.addColorStop(1,"green");
this.canvasContext.fillStyle=gradient;
//宽度间距
var rectWidth=this.width-10*2;//总宽度
var rectHeight=this.height-10*2;//总高度
var space=rectWidth/this.datas.length/5;
var width=(rectWidth-space*(this.datas.length+1))/this.datas.length;
var max=1000;
var heightScale=rectHeight/max;//计算比例
for (var i=0;i<this.datas.length;i++) {
var height=this.datas[i]*heightScale;
var y=this.height-10-height;//总宽度-边距-小方块宽度
this.canvasContext.fillRect(space+(space+width)*i+10,y,width,height);
}
}
Table.prototype.setDatas=function(datas){
this.datas=datas;
this.canvasContext.clearRect(0,0,innerWidth,innerHeight);//清除上一次的内容然后再新建
this.background();
this.addRect();
}
window.Table=Table;
})();
》调用创建的表格
var table=new Table(document.body,[33,200,500,90,100,800,770,1000,560]);
setInterval(function(){
var datas=[];
for (var i=0;i<10;i++) {
datas.push(Math.random()*1000);//随机创建数组
}
table.setDatas(datas);//将新的数据传入到table中
},1000*Math.random()*4);
3、绘制太极图和调试贝塞尔曲线
》HTML部分
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
html{overflow: hidden;}
*{margin: 0;padding: 0;}
#box{background-color: #242424;}
div{
width: 20px;
height: 20px;
background-color: white;
border-radius: 50%;
position: absolute;
left: 100px;
top: 200px;
text-align: center;
line-height: 20px;
}
</style>
</head>
<body>
<canvas id="box"></canvas>
<div class="startPoint">b</div>
<div class="endPoint">e</div>
<div class="Point1">1</div>
<div class="Point2">2</div>
<script src="js/circle.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
》具体的js代码:
(function(){
var curEle=null;
var startPoint=document.querySelector(".startPoint");
var endPoint=document.querySelector(".endPoint");
var Point1=document.querySelector(".Point1");
var Point2=document.querySelector(".Point2");
var context=null;
function init(){
var canvasEle=document.querySelector("#box");
canvasEle.width=innerWidth;
canvasEle.height=innerHeight;
window.onresize=function(){
canvasEle.width=innerWidth;
canvasEle.height=innerHeight;
};
context=canvasEle.getContext("2d");
context.strokeStyle="white";
context.lineWidth=10;
//x,y,radius,startAngle,endAngle,anticlockwise(默认逆时针)
/*context.beginPath();
context.arc(500,300,200,0,Math.PI*2,true);
context.stroke();
context.beginPath();
context.arc(600,300,100,0,Math.PI,true);
context.stroke();
context.beginPath();
context.arc(400,300,100,0,Math.PI,false);
context.stroke();
context.beginPath();
context.moveTo(300,300);
context.bezierCurveTo(500,400,200,400,600,600);
context.stroke();*/
for(var i=0;i<4;i++){//循环给每个元素添加事件
addEvent([startPoint,endPoint,Point1,Point2][i]);
}
document.ondblclick=function(){ document.removeEventListener("mousemove",move) };
}
function addEvent(ele){ ele.onmousedown=function(){ curEle=this; document.addEventListener("mousemove",move) }; }
function move(event){ curEle.style.left=event.pageX+"px"; curEle.style.top=event.pageY+"px"; context.clearRect(0,0,innerWidth,innerWidth); context.beginPath(); context.moveTo(getLeft(startPoint),getTop(startPoint)); context.bezierCurveTo(getLeft(Point1),getTop(Point1),getLeft(Point2),getTop(Point2),getLeft(endPoint),getTop(endPoint)); context.stroke(); }
function getLeft(ele){ return parseInt(ele.style.left) }
function getTop(ele){ return parseInt(ele.style.top) }
init();
})();