<!DOCTYPE html>
<html>
<head>
<title>HTML绘图支持</title>
<meta http-equiv="Content-Type" content="text/html;charset=gbk"/>
</head>
<body>
<!--1、使用canvas元素
HTML新增了一个canvas元素,专门用于绘制图形,但实际上该元素自身并不绘制图形,只至关于一张空画布,要想画图,必须借助JavaScript脚本进行绘制
向<canvas>元素上画图,须要通过三个步骤:
获取<canvas>元素对应的DOM对象,这是一个Canvas对象;
调用Canvas对象的getContext()方法,返回一个CanvasRenderingContext2D对象;
利用CanvasRenderingContext2D对象的方法画图。
--> javascript
<!--2、绘图
1.canvas绘图基础:CanvasRenderingContext2D
HTML5绘图的组件是Canvas对象,可是绘图的核心API是CanvasRenderingContext2D,他提供了一系列的方法和属性供绘制图形使用
2.绘制几何图形
fillRect:填充一个矩形
strokeRect:绘制一个矩形边框
CanvasRenderingContext2D只提供了这两个绘制几何图形的方法,并无提供绘制其余几何图形的方法
-->
<canvas id="mc" width="300" height="300" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('mc');
var ctx=canvas.getContext('2d');
//设置填充颜色
ctx.fillStyle="#f00";
//填充一个矩形
ctx.fillRect(30,20,120,60);
ctx.fillStyle="#ff0";
ctx.fillRect(80,60,120,60); html
//设置线条颜色
ctx.strokeStyle="#00f";
//设置线条宽度
ctx.lineWidth=10;
//绘制矩形边框
ctx.strokeRect(30,130,120,60); java
ctx.strokeStyle="#0ff";
//设置连接点类型
ctx.lineJoin="round";
ctx.strokeRect(80,160,120,60); 算法
ctx.strokeStyle="#f0f";
ctx.lineJoin="bevel";
ctx.strokeRect(130,190,120,60);
</script> 数据库
<!--3.绘制字符串
fillText:填充字符串
strokeText:绘制字符串边框
字体的对齐方式:
textAlign:水平对齐方式
textBaseAlign:垂直对齐方式
-->
<canvas id="zfc" width="400" height="400" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('zfc');
var ctx=canvas.getContext('2d');
ctx.fillStyle='#00f';
ctx.font='italic 50px 隶书';
ctx.textBaseline='top';
ctx.fillText("HTML5",0,0); canvas
ctx.strokeStyle="#f0f";
ctx.font='bold 45px 宋体';
ctx.strokeText("Crazy HTML5",0,50);
</script> 网络
<!--4.设置阴影
shadowBlur:阴影的模糊度
shadowColor:阴影的颜色
shadowOffsetX:阴影在X方向的偏移
shadowOffsetY:阴影在Y方向的偏移
-->
<canvas id="yy" width="500" height="500" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('yy');
var ctx=canvas.getContext('2d');
ctx.shadowBlur=5.6;
ctx.shadowColor='#222';
ctx.shadowOffetX=10;
ctx.shadowOffY=-6;
ctx.fillStyle="#00f";
ctx.font="italic 50px 宋体";
ctx.textBaseline='top';
ctx.fillText("Crazy HTML",0,0); dom
ctx.strokeStyle="#f0f";
ctx.font="bold 45px 宋体";
ctx.strokeText("疯狂Java",0,50); 异步
ctx.fillStyle="#0ff";
ctx.fillRect(20,150,180,80);
ctx.strokeStyle="#ff0";
ctx.lineWidth=8;
ctx.strokeRect(300,150,180,80);
</script> 函数
<!--5.使用路径
为了在Canvas上绘制更加复杂的图形,必须在Canvas上启用路径,借助路径来绘制图形
按以下步骤:
调用CanvasRenderingContext2D的beginPath()方法开始定义路径
调用CanvasRenderingContext2D的各类方法添加子路径
调用CanvasRenderingContext2D的closePath()方法关闭路径
调用CanvasRenderingContext2D的fill()或者stroke()方法来填充路径或者绘制路径边框
CanvasRenderingContext2D提供了以下方法添加子路径:
arc(x,y,radius,startAngle,endAngle,counterclockwise(boolean值,true为逆时针)):添加一段弧
arcTo(x1,y1,x2,y2,radius):添加一段弧,肯定这段圆弧的方式是假设从当前点到P1(x1,y1)绘制一条线条,再从P1(x1,y1)到P2(x2,y2)绘制一条线条,arcTo()则绘制一段同时与上面两条线条相切,且半径为radius的圆弧
bezierCurveTo:贝济埃曲线
lineTo(x,y):添加一段线段
moveTo(x,y):移动到(x,y)
quadraticCurveTo:二次曲线
rect(x,y,width,height):添加一个矩形
-->
<h2>绘制图形</h2>
<canvas id="yx" width="400" height="300" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('yx');
var ctx=canvas.getContext('2d');
for(var i=0;i<10;i++){
//开始定义路径
ctx.beginPath();
//添加一段圆弧
ctx.arc(i*25,i*25,(i+1)*8,0,Math.PI*2,true);
//关闭路径
ctx.closePath();
//设置填充色
ctx.fillStyle='rgba(255,0,255,'+(10-i)*0.1+')';
//填充路径
ctx.fill();
}
</script>
<h2>actTo示例</h2>
<canvas id="at" width="400" height="180" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('at');
var ctx=canvas.getContext('2d');
function createRoundPath(Context,x1,y1,width,height,radius){
ctx.beginPath();
ctx.moveTo(x1+radius,y1);
ctx.lineTo(x1+width-radius,y1);
ctx.arcTo(x1+width,y1,x1+width,y1+radius,radius);
ctx.lineTo(x1+width,y1+height-radius);
ctx.arcTo(x1+width,y1+height,x1+width-radius,y1+height,radius);
ctx.lineTo(x1+radius,y1+height);
ctx.arcTo(x1,y1+height,x1,y1+height-radius,radius);
ctx.lineTo(x1,y1+radius);
ctx.arcTo(x1,y1,x1+radius,y1,radius);
ctx.closePath();
}
ctx.lineWidth=3;
createRoundPath(ctx,30,30,200,100,20);
ctx.stroke();
</script>
<h1>lineTo</h1>
<canvas id="lt" width="400" height="200" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('lt');
var ctx=canvas.getContext('2d');
function createStar(context ,n ,dx,dy,size){
context.beginPath();
var dig=Math.PI/n*4;
for(var i=0;i<n;i++){
var x=Math.sin(i*dig);
var y=Math.cos(i*dig);
context.lineTo(x*size+dx,y*size+dy);
}
context.closePath();
}
//绘制三角形
createStar(ctx,3,60,60,50);
ctx.fillStyle="#f00";
ctx.fill();
//绘制五角形
createStar(ctx,5,160,60,50);
ctx.fillStyle="#0f0";
ctx.fill();
//绘制七角形
createStar(ctx,7,260,60,50);
ctx.fillStyle="#00f";
ctx.fill();
//绘制九角形
createStar(ctx,9,360,60,50);
ctx.fillStyle="#f0f";
ctx.fill();
</script>
<!---6.绘制曲线
bezierCurveTo:贝济埃曲线
quadraticCurveTo:二次曲线
-->
<canvas id="ct" width="400"height="200" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('ct');
var ctx=canvas.getContext('2d');
function createFlower(context,n,dx,dy,size,length){
context.beginPath();
context.moveTo(dx,dy+size);
var dig=2*Math.PI/n;
for(var i=1;i<n+1;i++){
//计算控制点的坐标
var ctrlx=Math.sin((i-0.5)*dig)*length+dx;
var ctrly=Math.cos((i-0.5)*dig)*length+dy;
//计算结束点的坐标
var x=Math.sin(i*dig)*size+dx;
var y=Math.cos(i*dig)*size+dy;
//绘制二次曲线
context.quadraticCurveTo(ctrlx,ctrly,x,y);
}
context.closePath();
}
//绘制5瓣花朵
createFlower(ctx,5,70,100,30,80);
ctx.fillStyle="#f00";
ctx.fill();
//绘制6瓣花朵
createFlower(ctx,6,200,100,30,80);
ctx.fillStyle="#0f0";
ctx.fill();
//绘制7瓣花朵
createFlower(ctx,7,330,100,30,80);
ctx.fillStyle="#f0f";
ctx.fill();
</script>
<!--7.绘制位图
drawImage方法
该方法须要传入Image对象,建立Image对象采用以下方法:
Image img = new Image([width,height]);
img.src = "图片地址";
须要指出的是为Image对象的src属性赋值后,Image对象会去装载指定图片,这种装载是异步的,须要必定的时间开销,为保证图片装载完成以后才去绘制,可用以下代码来绘制:
Image img = new Image([width,height]);
img.src = "图片地址";
img.onload = function(){
//在该函数里绘制
}
--->
<hr/>
<h2>绘制位图</h2>
<canvas id="wt" width="650" height="380" style="border:1px solid black;"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('wt');
var ctx=canvas.getContext('2d');
var img=new Image();
img.src="imgs/1.jpg";
img.onload=function(){
//原始尺寸 参数x,y
ctx.drawImage(img,20,70);
//绘制图片时进行缩放 参数x,y 缩放的 w,h
ctx.drawImage(img,320,10,120,150);
//从原位图挖一块放大3倍绘制在Canvas上
var sd=50;
var sh=65;
ctx.drawImage(img,2,50,sd,sh,460,10,sd*3,sh*3);
}
</script>
<!--3、图形特效处理
1.使用坐标变换
translate:平移坐标系统
scale:缩放坐标系统(水平方向上缩放sx,垂直方向上缩放sy)
totate:旋转坐标系统
还提供了save和restore方法,避免屡次坐标变换后累加结果
须要指出的是save方法保存的绘图状态,不只包括当前系统的坐标状态,还包括填充风格、线条风格等各类绘图状态,可是不包括Canvas上绘制的图形
-->
<h2>坐标变换</h2>
<canvas id="zbhh" width="650" height="380" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('zbhh');
var ctx=canvas.getContext('2d');
ctx.fillStyle='rgba(255,0,0,0.3)';
ctx.translate(100,200);
for(var i=0;i<50;i++){
ctx.translate(50,50);
ctx.scale(0.93,0.93);
ctx.rotate(-Math.PI/10);
ctx.fillRect(0,0,150,75);
}
</script>
<!--2.坐标变换与路径结合使用
雪花飘飘的动态效果:
-->
<h2>雪花飘飘</h2>
<canvas id="show" width="420" height="280" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById("show");
var ctx=canvas.getContext('2d');
setInterval("fall(ctx);",200);
snowPos=[
{x:20,y:4},
{x:60,y:4},
{x:100,y:4},
{x:140,y:4},
{x:180,y:4},
{x:220,y:4},
{x:260,y:4},
{x:300,y:4},
{x:340,y:4},
{x:380,y:4}
];
function createFlower(context,n,dx,dy,size,length){
context.beginPath();
context.moveTo(dx,dy+size);
var dig=2*Math.PI/n;
for(var i=1;i<n+1;i++){
//计算控制点的坐标
var ctrlx=Math.sin((i-0.5)*dig)*length+dx;
var ctrly=Math.cos((i-0.5)*dig)*length+dy;
//计算结束点的坐标
var x=Math.sin(i*dig)*size+dx;
var y=Math.cos(i*dig)*size+dy;
//绘制二次曲线
context.quadraticCurveTo(ctrlx,ctrly,x,y);
}
context.closePath();
}
function fall(context){
context.fillStyle="#000";
context.fillRect(0,0,420,280);
context.fillStyle="#fff";
for(var i=0;i<snowPos.length;i++){
//保存当前绘图状态
context.save();
context.translate(snowPos[i].x,snowPos[i].y);
context.rotate((Math.random()*6-3)*Math.PI/10);
//控制雪花掉落
snowPos[i].y+=Math.random()*8;
if(snowPos[i].y>280){
snowPos[i].y=4;
}
//建立并绘制雪花
createFlower(context,6,0,0,5,8);
context.fill();
//恢复绘图状态
context.restore();
}
}
</script>
<!--3.使用矩阵变换
CanvasRenderingContext2D提供了一种更加通用的坐标变换方法:
transform(m11,m12,m21,m22,dx,dy)这是一个基于矩阵变换的方法,前面三个变换方法均可以经过transform来实现,只是比较复杂
{x,y}----{x*m11+y*m21+dx,x*m12+y*m22+dy}
实现自定义变换---倾斜变换:
对于倾斜变换而言,Y坐标无需变换,只要将X坐标横向移动tan(angle)*Y便可,这就是实现倾斜变换的理论基础
四.控制叠加风格
经过CanvasRenderingContext2D的globalCompositeOperation属性来实现
-->
<p></p>
<h2>叠加风格</h2>
<select style="width:160px;" onChange="draw(this.value);">
<option value="source-over" selected="selected">source-over</option>
<option value="source-in">source-in</option>
<option value="source-out">source-out</option>
<option value="source-atop">source-atop</option>
<option value="destination-over">destination-over</option>
<option value="destination-in">destination-in</option>
<option value="destination-out">destination-out</option>
<option value="destination-atop">destination-atop</option>
<option value="lighter">lighter</option>
<option value="xor">xor</option>
<option value="copy">copy</option>
</select><br/>
<canvas id="dj" width="400" height="200" style="border:1px solid black;"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('dj');
var ctx=canvas.getContext('2d');
var draw=function(coma){
ctx.save();
ctx.clearRect(0,0,400,200);
ctx.fillStyle="#f00";
ctx.fillRect(30,20,160,100);
ctx.globalCompositeOperation=coma;
ctx.fillStyle="#0f0";
ctx.fillRect(120,60,160,100);
ctx.restore();
}
</script>
<!--五.控制填充风格
除了fillStyle,CanvasRenderingContext2D还支持渐变填充(CanvasGradient)和位图填充(CanvasPattern)
1.线性渐变
调用CanvasRenderingContext2D的createLinearGradient方法建立一个线性渐变,返回一个CanvasGradient对象;
调用CanvasGradient对象的addColorStop方法向线性渐变中添加颜色变化;
将CanvasGradient对象赋给CanvasRenderingContext2D的fillStyle或strokeStyle属性。
-->
<canvas id="xj" width="400" height="300" style="border:1px solid black;"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('xj');
var ctx=canvas.getContext('2d');
ctx.clearRect(0,0,400,280);
ctx.save();
ctx.translate(30,20);
//建立线性渐变
var lg=ctx.createLinearGradient(0,0,160,80);
//向线性渐变中添加颜色
lg.addColorStop(0.2,"#f00");
lg.addColorStop(0.5,"#0f0");
lg.addColorStop(0.9,"#00f");
//使用线性渐变做为填充色
ctx.fllStyle=lg;
ctx.fillRect(0,0,160,80);
ctx.restore();
//平移坐标系统
ctx.translate(280,160);
ctx.beginPath();
ctx.arc(0,0,80,0,Math.PI*2,true);
ctx.closePath();
ctx.lineWidth=12;
//再次建立线性渐变
var lg2=ctx.createLinearGradient(-40,-40,80,50);
lg2.addColorStop(0.1,"#ff0");
lg2.addColorStop(0.4,"#0ff");
lg2.addColorStop(0.8,"#f0f");
ctx.strokeStyle=lg2;
ctx.stroke();
</script>
<!--2.圆形渐变
createRadialGradient
-->
<hr/>
<h2>圓形漸變</h2>
<canvas id="yj" width="400" height="280" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('yj');
var ctx=canvas.getContext('2d');
ctx.save();
ctx.translate(30,20);
//建立圆形渐变
var lg=ctx.createRadialGradient(80,40,5,80,40,60);
//向线性渐变中添加颜色
lg.addColorStop(0.2,"#f00");
lg.addColorStop(0.5,"#0f0");
lg.addColorStop(0.9,"#00f");
//使用线性渐变做为填充色
ctx.fillStyle=lg;
ctx.fillRect(0,0,160,80);
ctx.restore();
//平移坐标系统
ctx.translate(280,160);
ctx.beginPath();
ctx.arc(0,0,80,0,Math.PI*2,true);
ctx.closePath();
ctx.lineWidth=12;
//再次建立线性渐变
lg2=ctx.createRadialGradient(0,0,5,0,0,80);
lg2.addColorStop(0.1,"#f00");
lg2.addColorStop(0.4,"#0ff");
lg2.addColorStop(0.8,"#f0f");
ctx.fillStyle=lg2;
ctx.fill();
</script>
<!--3.位图填充
createPattern
-->
<hr/>
<h2>位图填充</h2>
<canvas id="wttc" width="400" height="280" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('wttc');
var ctx=canvas.getContext('2d');
ctx.save();
ctx.translate(30,20);
var img=new Image();
img.src="imgs/1.jpg";
img.onload=function(){
var imgPattern=ctx.createPattern(img,"repeat");
ctx.fillStyle=imgPattern;
ctx.fillRect(0,0,160,100);
ctx.restore();
ctx.translate(280,160);
ctx.beginPath();
ctx.arc(0,0,80,0,Math.PI*2,true);
ctx.closePath();
ctx.lineWidth=12;
ctx.strokeStyle=imgPattern;
ctx.stroke();
}
</script>
<!--6、位图处理
1.位图裁剪
clip这个方法会把位图当前路径裁剪下来:
将要裁剪的部分定义成Canvas路径;
调用CanvasRenderingContext2D的clip方法把路径裁剪下来;
绘制位图---被裁剪部分才会显示。
-->
<h2>位图裁剪</h2>
<canvas id="wtcj" width="400" height="350" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('wtcj');
var ctx=canvas.getContext('2d');
var dig=Math.PI/20;
var count=0;
var img=new Image();
img.src="imgs/1.jpg";
img.onload=function(){
//每隔0.15秒调用一次addRadial函数
setInterval("addRadial()",150);
}
var addRadial=function(){
ctx.save();
ctx.beginPath();
ctx.arc(200,130,200,0,dig*++count,false);
//让圆弧链接到圆形
ctx.lineTo(200,130);
ctx.closePath();
ctx.clip();
//此时绘制的图片只有路径覆盖的部分才会显示出来
ctx.drawImage(img,124,20);
ctx.restore();
}
</script>
<!--2.像素处理
getImageData(int x,int y,int width,int height):该方法获取从Canvas上从(x,y)点开始,宽为width,高为height的图片区域的数据,该方法返回值是一个CanvasPixelArray对象(包含width、height、data属性,data[r1,g1,b1,a1,r2,g2,b2,a2,...,rN,gN,bN,aN],每四个元素肯定一个像素点)
putImageData(CanvasPixelArray data,x,y):把data里的数据放入Canvas中从(x,y)开始的区域,该方法直接改变Canvas上的图像数据
经过以上两种像素处理方法,能够对图片进行各类复杂的处理,例如改变图片透明度、高亮、剪切、复制等;若是配合一些算法理论,甚至能够对图片进行模糊、降噪等复杂的滤波处理。
-->
<h2>像素处理</h2>
<canvas id="xscl" width="400" height="350" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('xscl');
var ctx=canvas.getContext('2d');
var img=new Image();
img.src="imgs/1.jpg";
img.onload=function(){
//带透明度参数的方法绘制图片
drawImage(img,124,20,0.4);
}
var drawImage=function(image,x,y,alpha){
ctx.drawImage(image,x,y);
var imgData=ctx.getImageData(x,y,image.width,image.height);
for(var i=0,len=imgData.data.length;i<len;i+=4){
imgData.data[i+3]=imgData.data[i+3]*alpha;
}
ctx.putImageData(imgData,x,y);
}
</script>
<!--2)高亮画图:
所谓高亮就是把图片像素的R、G、B值都按比例放大
-->
<h2>高亮显示</h2>
<canvas id="xsgl" width="400" height="350" style="border:1px solid black"></canvas>
<script type="text/javascript">
var canvas=document.getElementById('xsgl');
var ctx=canvas.getContext('2d');
var img=new Image();
img.src="imgs/1.jpg";
img.onload=function(){
drawImage(img,124,20,1.6);
}
var drawImage=function(image,x,y,ligth){
ctx.drawImage(image,x,y);
var imgData=ctx.getImageData(x,y,image.width,image.height);
for(var i=0,len=imgData.data.length;i<len;i+=4){
imgData.data[i+0]=imgData.data[i+0]*ligth;
imgData.data[i+1]=imgData.data[i+1]*ligth;
imgData.data[i+2]=imgData.data[i+2]*ligth;
}
ctx.putImageData(imgData,x,y);
}
</script>
<!--7、输出位图
toDataURL(String type):type是MIME字符串
DataURL格式是一种保存二进制文件的方式,咱们既可把图片转换为DataURL格式的字符串,也可把DataURL格式的字符串恢复成原来的文件
-->
<h2>位图输出</h2>
<canvas id="wtsc" width="400" height="280" style="border:1px solid black"></canvas>
<img src="" id="result" alt="图片输出"/>
<script type="text/javascript">
var canvas=document.getElementById('wtsc');
var ctx=canvas.getContext('2d');
ctx.save();
ctx.translate(30,20);
var img=new Image();
img.src="imgs/1.jpg";
img.onload=function(){
//建立位图填充
imgPattern=ctx.createPattern(img,"repeat");
ctx.fillStyle=imgPattern;
ctx.fillRect(0,0,160,80);
ctx.restore();
ctx.translate(280,160);
ctx.beginPath();
ctx.arc(0,0,80,0,Math.PI82,true);
ctx.closePath();
ctx.lineWidth=12;
ctx.strokeStyle=imgPattern;
ctx.stroke();
document.getElementById('result').src=canvas.toDataURL("image/png");
}
</script>
<!--实际上,Canvas能够把图片转换成DataURL格式的字符串,这个字符串既能够经过网络传输,也能够保存到磁盘、数据库中,这样就能够永久保存使用Canvas绘制的图片了--> </body> </html>