Web绘图可以实现的效果:
(1)实时走势图
(2)统计图
(3)在线画图板
(4)网页游戏(2D、3D)
目前可以使用Web绘图技术:
(1)Canvas绘图:2D位图绘图技术
(2)SVG绘图:2D矢量图绘图技术
(3)WebGL绘图:2D/3D绘图技术,还不是H5标准技术
Canvas绘图技术
HTML5新提供的一种2D位图绘图技术。
<canvas width="500" height="400">
您的浏览器不支持canvas标签
</canvas>
canvas 标签默认是一个300*150px的 inline-block。注意:画布的宽和高不能用CSS来声明!
使用“画笔(绘图上下文对象)”来在画布上绘图(JS实现):
var ctx = canvas.getContext('2d') //画笔对象
画笔对象的常用成员:
(1)绘制矩形
(2)绘制文本
(3)绘制路径
(4)绘制图像
1、使用Canvas进行绘图——绘制矩形
说明:矩形的定位点在自己的左上角
ctx.lineWidth = 1 描边的线宽
ctx.strokeStyle = '#000' 描边样式
ctx.fillStyle = '#000' 填充样式
ctx.strokeRect(x, y, w, h) 描边一个矩形
ctx.fillRect(x, y, w, h) 填充一个矩形
ctx.clearRect(x, y, w, h) 清除一个矩形范围内的所有内容
2、使用Canvas进行绘图——绘制文本
说明:一段文字的定位点默认在文本基线的最左侧
ctx.textBaseline = "alphabetic" 文件基线
ctx. font ="12px sans-serif" 文本大小和字体
ctx.strokeText( txt, x, y ) 描边一段文本
ctx.fillText( txt, x, y ) 填充一段文本
ctx.measureText(txt).width 基于当前字体设置,测量指定的文本宽度
3、使用Canvas绘制图形 —— 矩形
定位点:矩形左上角
ctx.lineWidth = 1
ctx.strokeStyle = '#000'
ctx.fillStyle = '#000'
ctx.strokeRect(x, y, w, h)
ctx.fillRect(x, y, w, h)
ctx.clearRect(x, y, w, h)
4、使用Canvas绘制图形 —— 文本
定位点:在文本基线的最左侧
ctx.textBaseline = 'alphabetic'
ctx.font = '12px sans-serif'
ctx.fillText(txt, x, y)
ctx.strokeText(txt, x, y)
ctx.measureText(txt).width
5、使用渐变对象绘制图形
1)创建渐变对象必须指定用在画布上的起点和终点坐标:
var g = ctx.createLinearGradient(x1,y1,x2,y2);
2)为渐变对象添加两个以上的颜色点
g.addColorStop( offset, color );
3)绘制图形时应用渐变对象
ctx.fillStyle = g;
ctx.strokeStyle = g;
6、使用Canvas绘制图形 —— 绘制路径(Path)
提示:Canvas中的路径概念与PS中的钢笔工具的含义一样的。可以绘制任意的直线、折线、曲线。路径本身是不可见的,有三个用途:描边、填充、裁剪
ctx.beginPath( ) 开始一条新路径
ctx.closePath( ) 闭合路径(自动连接终点和起点)
ctx.moveTo(x, y) 移动到指定点
ctx.lineTo(x, y) 到指定点绘制直线
ctx.arc(x, y, r, startAngle, endAngle) 绘制圆拱路径
ctx.ellipse(x, y, rx, ry, startAngle, endAngle) 绘制椭圆拱路径
ctx.bezierCurveTo(....) 绘制贝塞尔曲线
ctx.stroke( ) 对当前路径进行描边
ctx.fill( ) 对当前路径进行填充
ctx.clip( ) 对当前路径进行裁切
7、使用Canvas绘制图形 —— 绘制图像
提示:图像的定位点在自己的左上角。必须等待服务器端的图片下载完成,才能开始绘制图像!
var img = new Image();
img.src = 'x.png'; //浏览器会立即异步请求该图片
img.onload = function(){ //图片加载完成事件
ctx.drawImage(img, x, y) //原始大小绘制图像
ctx.drawImage(img, x, y, w, h) //绘制拉伸后的图像
}
案例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>绘制飞机</title>
<style>
canvas{
background:#efefef;
}
</style>
</head>
<body>
<canvas id="can1" width="500px" height="500px"></canvas>
<canvas id="can2" width="500px" height="500px"></canvas>
<canvas id="can3" width="500px" height="500px"></canvas>
</body>
<script>
var ctx1=can1.getContext('2d');
ctx1.lineWidth=5;
ctx1.lineJoin="round";
ctx1.beginPath();
ctx1.arc(250,250,100,Math.PI,3*Math.PI);//3点方向为0度,顺时针转
ctx1.strokeStyle="#999";
ctx1.stroke();
ctx1.strokeStyle="#0f0";
ctx1.fillStyle="#0f0";
var i=0;
var time1=setInterval(function(){
if(i<720){
ctx1.clearRect(200,220,100,60);
i+=36;
ctx1.beginPath();
ctx1.arc(250,250,100,Math.PI,(1+i/360)*Math.PI);
ctx1.stroke();
var txt=i*10/72+"%";
ctx1.textBaseline="top";
ctx1.font="60px SimHei";
var twid=ctx1.measureText(txt).width;
ctx1.fillText(txt,250-twid/2,220);
}else
clearInterval(time1);
},200);
ctx1.strokeStyle="";
</script>
<script>
var ctx2=can2.getContext('2d');
ctx2.lineWidth=5;
ctx2.lineJoin="round";
var x= 1,y= 7,mi= 0,mj=0;
setInterval(function(){
ctx2.clearRect(0,0,500,500);
x=x==1?0:1;
y=y==7?8:7;
path(mi,mj,x,y);
},200);
function path(i,j,x,y){
ctx2.beginPath();
ctx2.arc(250+i,250+j,100,x*Math.PI/4,y*Math.PI/4);//3点方向为0度,顺时针转
ctx2.lineTo(250+i,250+j);
ctx2.closePath();//闭合
ctx2.stroke();
ctx2.beginPath();
ctx2.arc(250+i,200+j,25,0,2*Math.PI);
ctx2.fillStyle="#0f0";
ctx2.fill();
ctx2.beginPath();
ctx2.arc(262+i,200+j,8,0,2*Math.PI);
ctx2.fillStyle="#fff";
ctx2.fill();
ctx2.beginPath();
ctx2.arc(250+i,188+j,5,0,2*Math.PI);
ctx2.fillStyle="#fff";
ctx2.fill();
}
//移动事件 37 38 39 40
window.onkeydown=function(e){
// e.preventDefault();
//console.log(e.keyCode);
switch (e.keyCode){
case 37: e.preventDefault();mi-=10;break;
case 38: e.preventDefault();mj-=10;break;
case 39: e.preventDefault();mi+=10;break;
case 40: e.preventDefault();mj+=10;break;
}
}
</script>
<script>
var ctx3=can3.getContext('2d');
var img1=new Image();
img1.src="img/p3.png";
img1.onload=function(){
/*ctx3.translate(50,25);
ctx3.drawImage(img1,0-50,0-25,100,50);
ctx3.drawImage(img1,400-50,0-25,100,50);
ctx3.drawImage(img1,0-50,450-25,100,50);*/
var i=1;
setInterval(function(){
i++;
(i==36)&&(i=1);
//飞机1
ctx3.translate(50,25);//平移
ctx3.rotate(10*i*Math.PI/180);//旋转
ctx3.drawImage(img1,-50,-25,100,50);//绘图
ctx3.rotate(-10*i*Math.PI/180);//复位
ctx3.translate(-50,-25);//复位
//飞机2
ctx3.drawImage(img1,400,0,100,50);//绘图
//飞机3
ctx3.translate(50,475);//平移
ctx3.rotate(10*i*Math.PI/180);//旋转
ctx3.drawImage(img1,-50,-25,100,50);//绘图
ctx3.rotate(-10*i*Math.PI/180);//复位
ctx3.translate(-50,-475);//复位
//飞机4
ctx3.save();//保存画笔当前状态
ctx3.translate(250,50);//平移
ctx3.rotate(10*i*Math.PI/180);//旋转
ctx3.drawImage(img1,-50,-25,100,50);//绘图
ctx3.restore();//复位画笔之前的状态
//飞机5,测试封装函数
fly(ctx3,img1,250,200,i*10,100,50);
},100);
}
//封装小飞机旋转
function fly(obj,img,x,y,i,wid,hei){
//x,x:坐标 i:一次旋转的度数 wid,hei:图片绘画的宽高
obj.save();//保存画笔当前状态
obj.translate(x,y);//平移
obj.rotate(i*Math.PI/180);//旋转
obj.drawImage(img,-wid/2,-hei/2,wid,hei);//绘图
obj.restore();//复位画笔之前的状态
}
</script>
</html>
图形/图像的变形问题
Canvas绘图中一般不使用CSS的变形属性——CSS变形只能用于HTML元素-Canvas技术中只有一个<canvas>。
若只针对某个图形/图像做变形,需要使用画笔的变形相关方法:
ctx.rotate( deg ) 旋转画笔,所绘的图形图像都会旋转
ctx.scale( x, y ) 缩放
ctx.translate( x, y ) 平移整个画布的原点到一个新的点
ctx.save() 保存画笔的当前变形状态
ctx.restore() 恢复最近一次保存的画笔的所有状态
注意:
(1)画笔旋转默认的轴点是画布的原点(0,0),而不是图形/图像的定位点
(2)画笔的旋转有累加效果
(3)可以通过ctx.translate()修改画布原点的位置,一旦修改,所有点的坐标值全部改变
第三方提供的绘制统计图的工具
(1)Chart.js
(2)FusionCharts
(3)EChart.js
(4)HighCharts