<!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>