Canvas中可以读入JPG或PNG等图像,而且还可以进行尺寸修改、图像截取等操作。
图像绘制的基本步骤如下:
(1)读取图像文件
(2)在Canvas中进行绘制
图像读取前,首先创建Image对象,在Image对象的src属性中指定图像文件所在路径(URL)后就可以开始读取了。读取结束后,触发onload事件。基本语法下:
var image=new Image();
image.src="图像文件路径";
image.onload=function(){/*图像读取时的处理*/}
使用Canvas上下文中的drawImage()方法将读取后的Image对象绘制在Canvas上,实际上是将Image对象中的图像数据输出到Canvas中。有三种drawImage()方法用于图像的绘制。
(1)直接绘制
context.drawImage(image,dx,dy)
(2)尺寸修改(resize)
context.drawImage(image,dx,dy,dw,dh)
(3)图像截取
context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)
第(1)种方法直接将读取的图像绘制在坐标(dx,dy)处。第(2)种方法按照新的宽度(dw)与高度(dh)将图像绘制在坐标(dx,dy)处。第(3)种方法是将原图像的一部分截取出后再按指定尺寸绘制在Canvas上,从原图像的坐标(sx,sy)开始截取宽(sw)、高(sh)的部分图像,然后绘制在Canvas上的坐标(dx,dy)处,宽度为dw,高度为dh。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>drawImage绘制图像</title>
</head>
<body>
<canvas id="canvas" width="400" height="300"></canvas>
<script type="text/javascript">
var image=new Image();
image.src="https://img.alicdn.com/tps/i4/TB1HQn0BCzqK1RjSZPcSuvTepXa.jpg_1080x1800Q90s50.jpg";
image.onload=function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.fillStyle="#a0a0a0";
ctx.fillRect(0,0,400,300);
//绘制
//ctx.drawImage(image,0,0);
ctx.drawImage(image,0,0,400,300);
//ctx.drawImage(image,440,190,200,200,100,50,200,200);
}
</script>
</body>
</html>
像素处理
Canvas与SVG以及Flash稍有不同,绘制的图形/图像并不能作为对象操作。也就是说明使用stroke()或者fill()方法绘制的图形,既不能移动它也不能删除它。如果想操作绘制的图形/图像,使用SVG或者Flash实现比使用Canvas要好。
imagedata=ctx.getImageData(sx,sy,sw,sh) | 返回以(sx,sy)为左上顶点,宽为sw,高为sh的矩形图像---imagedata对象 |
ctx.putImageData(imagedata,dx,dy) | 将imagedata所表示的图像绘制在顶点坐标为(dx,dy)处 |
简单来说,使用getImageData()方法取出Canvas上图像的像素数据,通过JavaScript加工过这些像素数据后,使用putImageData方法,重新绘制到Canvas中。
ImageData对象是代表图像像素数据的对象。
imagedata.width | 图像数据的宽度 |
imagedata.height | 图像数据的高度 |
imagedata.data | 图像数据(CanvasPixelArray类型) |
在JavaScript中进行像素数据读取,并进行加工与输出时的具体操作是,从imagedata.data中得到CanvasPixelArray类型的对象。此对象是保存像素信息的一元数组。但是与JavaScript的Array对象不同,不可对其进行与通常数组一样的操作。
CanvasPixelArray对象中只定义了 length属性。这个与Array对象的length属性一样,表示返回数组中的元素数目。当需要访问数组中的各个元素时,也与Array对象一样,通过具体的数组下标来访问。
CanvasPixelArray对象数组中到底保存了什么样的数据?我们可以看到此数组,即imagedata.data各元素中全部保存的是0~255间的整数。4个整数表示一个像素,分别表示红色、绿色、蓝色、透明度。即代表RGBA值的4个整数。在imagedata.data数组中,从图像的左上角由右向左顺序保存像素信息,保存完一行,又开始从最左端开始保存,一直到右下端的像素信息为止。因此一元数组imagedata.data中的元素数目为imagedata.width*imagedata.height*4。
关于像素处理功能,Firefox3.6、Safari、Chrome5、Opera10.50以及IE9中都已安装。
像素处理实例:
1、进行图像黑白处理
从本机向网页中拖放一图像文件,图像在浏览器中显示并进行黑白处理。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>像素处理实例</title>
<style type="text/css">
body{font-family:Helvetica, Arial,sans-serif;font-size: 80%;}
#dp{
width: 200px;
min-height: 70px;
border: 1px solid #000000;
background-color: #eeeeee;
padding: 1em;
margin: 2em;
}
#dp img{
margin-left: 1em;
}
</style>
<script type="text/javascript">
(function(){
//拖动区域的div元素
var dp=null;
//FileReader接口对象
var reader=null;
/*
*页面导入时的处理
*/
window.addEventListener("load",function(){
//拖动区域的div元素
dp=document.getElementById("dp");
//设置dragover事件的事件侦听
dp.addEventListener("dragover",function(event){
event.preventDefault();
},false);
//设置drop事件的事件侦听
dp.addEventListener("drop",function(event){
event.preventDefault();
file_droped(event);
},false);
},false);
/*
* 文件被拖入时的处理
*/
function file_droped(event){
//清空显示区域
while(dp.firstChild){
dp.removeChild(dp.firstChild);
}
//插入文件的File接口对象
var file=event.dataTransfer.files[0];
//FileReader接口对象
reader=new FileReader();
//非图像文件画像时报错
if(!/^image/.test(file.type)){
alert("请拖入图像文件。");
}
//导入拖入图像
reader.readAsDataURL(file);
reader.onload=prepare_image;
}
/*
*显示拖入图像文件
*/
function prepare_image(event){
//创建img元素,显示拖入的图像
var image=document.createElement("img");
image.setAttribute("src",reader.result);
dp.appendChild(image);
//img元素中导入图像文档后进行后续处理
image.onload=function(){
//获取图像的尺寸
var w=parseInt(image.width);
var h=parseInt(image.height);
//创建canvas对象、导入图像
var canvas=document.createElement("canvas");
canvas.width=w;
canvas.height=h;
var ctx=canvas.getContext("2d");
ctx.drawImage(image,0,0);
//获取canvas像素数据
var imagedata=ctx.getImageData(0,0,w,h);
//进行黑白转换
convert_image_to_gray_scale(imagedata.data);
//替换canvas中的像素数据
ctx.putImageData(imagedata,0,0);
//显示canvas
dp.appendChild(canvas);
}
}
/*
* 黑白转换函数
--->>一元函数imagedata.data中的元素数目为image.height*image.width*4
*/
function convert_image_to_gray_scale(data){
var len=data.length;
var pixels=len/4;
for(var i=0;i<pixels;i++){
//取出R,G,B值
var r=data[i*4];
var g=data[i*4+1];
var b=data[i*4+2];
//进行黑白变换
var g=parseInt((11*r+16*g+5*b)/32);
//将变换后的像素数据设置到原来数组元素
data[i*4]=g;
data[i*4+1]=g;
data[i*4+2]=g;
}
}
})();
</script>
</head>
<body>
<!--
1、读取图像文件并在浏览器中显示
2、对图像进行黑白处理
-->
<!--
采用将桌面上的文件拖动到浏览器中,要使用HTML5的拖放功能与File API。使用Firefox3.6以后版本进行测试
-->
<div id="dp">
<p>将桌面图像文件拖动到此处</p>
</div>
</body>
</html>
2、折线图制作
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>数据图表</title>
<script type="text/javascript">
window.onload=function(){
//定义图表数据
var uriage=[80,92,104,110,68,50,74,68,98,103,142,27,12,100];
drawChart(uriage);
}
//绘制折线数据图表的函数
function drawChart(data){
//获取上下文
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
//绘制背景
var gradient=context.createLinearGradient(0,0,0,300);
gradient.addColorStop(0,"#a0a0a0");
gradient.addColorStop(0,"#afafaf");
context.fillStyle=gradient;
context.fillRect(0,0,canvas.width,canvas.height);
//计算坐标
var grid_cols=data.length+1;
var grid_rows=4;
var cell_width=canvas.width/grid_cols;
var cell_height=canvas.height/grid_rows;
//绘制背景的方格线
context.beginPath();
for(var row=0;row<=grid_rows;row++){
var y=row*cell_height;
context.moveTo(0,y);
context.lineTo(canvas.width,y);
}
for(var col=0;col<=grid_cols;col++){
var x=col*cell_width;
context.moveTo(x,0);
context.lineTo(x,canvas.height);
}
context.lineWidth=1;
context.strokeStyle="#c0c0c0";
context.stroke();
//获取数据中最大值
var max_y=0;
for(var i=0;i<data.length;i++){
if(data[i]>max_y)
max_y=data[i];
}
//为了能让最大值能容纳在图表内,计算坐标
max_y=max_y*1.1;
//将数据换算为坐标
var points=[];
for(var i=0;i<data.length;i++){
var y=data[i];
var px=cell_width*(i+1);
var py=canvas.height-canvas.height*(y/max_y);
points.push({"x":px,"y":py});
}
//描绘折线
context.beginPath();
context.moveTo(points[0].x,points[0].y);
for(var i=1;i<points.length;i++){
context.lineTo(points[i].x,points[i].y);
}
context.lineWidth=2;
context.strokeStyle="#ee0000";
context.stroke();
//绘制坐标图形
for(var i in points){
var p=points[i];
context.beginPath();
context.arc(p.x,p.y,6,0,2*Math.PI);
context.fillStyle="#ef0000";
context.fill();
}
}
</script>
</head>
<body style="text-align: center;">
<canvas id="canvas" width="500" height="300"></canvas>
</body>
</html>
---------->>《Canvas画布进阶篇------旋转与变形》