标签:cal 渐变 lang function 是你 ros 坐标变换 canvas title
fillText(text, x, y[, maxWidth]) -- 填充方式
strokeText(text, x, y[, maxWidth]) -- 描边方式
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制文字</title>
6 </head>
7 <body>
8 <canvas id="addText" height="70px" width="550px"></canvas>
9 <div>
10 <p>
11 古时候,楚国有一家人,祭完祖宗之后,准备将祭祀用的一壶酒,赏给帮忙办事的人员喝。参加的人很多,这壶酒如果大家都喝是不够的,若是让一个人喝,那能喝得有余。这一壶酒到底怎么分呢?<br>
12 大家都安静下来,这时有人建议:每个人在地上画一条蛇,谁画得快又画得好,就把这壶酒归他喝。大家都认为这个方法好,都同意这样做。于是,在地上画起蛇来。<br>
13 有个人画得很快,一转眼最先画好了,他就端起酒壶要喝酒。但是他回 头看看别人,还都没有画好呢。心里想:他们画得真慢。又想显示自己的本领, 他洋洋得意地说: “你们画得好慢啊!我再给蛇画几只脚也不算晚呢!”于是,他便左手提着酒壶,右手拿了一根树枝,给蛇画起脚来。<br>
14 正在他一边画着脚,一边说话的时候,另外一个人已经画好了。那个人 马上把酒壶从他手里夺过去,说:"你见过蛇吗?蛇是没有脚的,你为什么要给它添上脚呢?所以第一个画好蛇的人不是你,而是我了!"<br>
15 那个人说罢就仰起头来,咕咚咕咚把酒喝下去了。
16 </p>
17 </div>
18
19 <script>
20 window.addEventListener("load", function (){
21 var canvas = document.getElementById(‘addText‘);
22 if (canvas && canvas.getContext) {
23 var context = canvas.getContext("2d");
24 context.fillStyle = "#00f";
25 context.font = "italic 15px sans-serif";
26 /*
27 * textBaseline -- 设置文字相对于起点的位置
28 * 取值包括 top hanging middle alphabetic ideographic(默认值) bottom
29 */
30 context.textBaseline = "bottom";
31 /*
32 * textAlign -- 设置文字的对齐方式
33 * 取值包括 start(默认值) end left right center
34 */
35 context.textAlign = "start";
36 /*
37 * context.fillText(text, x, y[, maxwidth])
38 * 表示以填充的方式描绘文字
39 */
40 context.fillText("(比喻做了多余的事,反而有害无利,徒劳无功。)", 160, 50);
41
42 context.strokeStyle = "#faa"; //设置颜色
43 context.font = "bold 30px sans-serif";
44 /*
45 * context.strokeText(text, x, y[, maxwidth])
46 * 表示已描边的方式绘制文字
47 */
48 context.strokeText("画蛇添足", 30, 50);
49 }
50 }, true);
51 </script>
52 </body>
53 </html>
fillRect(x, y, width, height) -- 实心矩形
strokeRect(x, y, width, height) -- 空心矩形
clearRect(x, y, width, height) -- 清除指定区域的像素
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制矩形</title>
6 <style>
7 canvas{
8 float: left;
9 margin-right: 30px;
10 }
11 </style>
12 </head>
13 <body>
14 <canvas id="rect1" height="250px" width="250px"></canvas>
15
16 <canvas id="rect2" height="250px" width="250px"></canvas>
17
18 <canvas id="rect3" height="250px" width="250px"></canvas>
19
20 <script>
21 window.addEventListener("load", function(){
22 var canvas = document.getElementById(‘rect1‘);
23 if (canvas && canvas.getContext) {
24 var context = canvas.getContext("2d");
25 // context.fillStyle = "#fbb";
26 context.strokeStyle = "#fbb";
27 context.lineWidth = 1;
28 // context.fillRect(25,65,200,120);
29 context.strokeRect(25,65,200,120)
30 }
31 }, true);
32 window.addEventListener("load", function(){
33 var canvas = document.getElementById(‘rect2‘);
34 if (canvas && canvas.getContext) {
35 var context = canvas.getContext("2d");
36 context.fillStyle = "#fbb";
37 context.strokeStyle = "#666";
38 context.lineWidth = 1;
39 /*
40 * context.strokeRect(x, y, width, height) -- 绘制实心矩形
41 * 坐标原点为画布左上角
42 */
43 context.fillRect(25,25,200,200);
44 /*
45 * context.strokeRect(x, y, width, height) -- 绘制空心矩形
46 * 坐标原点为画布左上角
47 */
48 context.strokeRect(25,25,200,200)
49 }
50 }, true);
51 window.addEventListener("load", function(){
52 var canvas = document.getElementById(‘rect3‘);
53 if (canvas && canvas.getContext) {
54 var context = canvas.getContext("2d");
55 context.fillStyle = "#fbb";
56 context.strokeStyle = "#666";
57 context.lineWidth = 1;
58 context.fillRect(65,25,120,200);
59 // context.strokeRect(65,25,120,200);
60 /*
61 * context.clearRect(x, y, width, height) -- 清除指定区域的像素
62 * 坐标原点为画布左上角
63 */
64 context.clearRect(65,65,50,50);
65 }
66 }, true);
67 </script>
68 </body>
69 </html>
步骤:
1、beginPath() -- 创建路径
2、moveTo(x, y) -- 将当前位置移到新目标坐标,并作为要绘制线段的起点坐标
3、lineTo(x, y) -- 线段指定目标坐标(线段终点坐标)
4、stroke() -- 绘制图形边框
5、fill() -- 填充图形(依情况自选)
6、closePath() -- 关闭路径(可选)
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制直线</title>
6 <style>
7 canvas{
8 float: left;
9 margin-right: 30px;
10 }
11 </style>
12 </head>
13 <body>
14 <canvas id="line1" height="200px" width="170px"></canvas>
15
16 <canvas id="line2" height="200px" width="250px"></canvas>
17
18 <canvas id="line3" height="200px" width="250px"></canvas>
19
20 <script>
21 window.addEventListener("load", function(){
22 var canvas = document.getElementById(‘line1‘);
23 if (canvas && canvas.getContext) {
24 var context = canvas.getContext("2d");
25 /*
26 * 绘制直线步骤:
27 * 1、创建路径 -- beginPath()
28 * 2、设置起始点坐标 -- moveTo(x,y)
29 * 3、设置目标点坐标 -- lineTo(x,y)
30 * 4、绘制图形的边框 -- 调用stroke()函数绘制图形,若图形不是一条直线,可选择使用fill()填充
31 * 5、填充 -- fill() 可选,用于可填充图形
32 * 6、关闭路径 -- closePath() 可选
33 */
34 context.beginPath(); //开始创建路径
35 context.lineWidth = 1;
36 context.moveTo(20,100); //起始点坐标
37 context.lineTo(150,100);//目标点坐标
38 context.stroke(); //调用stroke函数绘制直线
39 context.closePath(); //关闭路径
40 }
41 }, true);
42 window.addEventListener("load", function(){
43 var canvas = document.getElementById(‘line2‘);
44 if (canvas && canvas.getContext) {
45 var context = canvas.getContext("2d");
46 context.beginPath(); //开始创建路径
47 context.lineWidth = 1;
48 context.moveTo(160,50); //起始点坐标
49 context.lineTo(50,100); //目标点坐标
50 context.lineTo(160,185);//目标点坐标
51 context.stroke(); //调用stroke函数绘制直线
52 }
53 }, true);
54 window.addEventListener("load", function(){
55 var canvas = document.getElementById(‘line3‘);
56 if (canvas && canvas.getContext) {
57 var context = canvas.getContext("2d");
58 context.beginPath(); //开始创建路径
59 context.lineWidth = 1;
60 context.moveTo(160,50); //起始点坐标
61 context.lineTo(50,100); //目标点坐标
62 context.lineTo(160,185);//目标点坐标
63 context.fill(); //调用fill()函数绘制图形
64 }
65 }, true);
66 </script>
67 </body>
68 </html>
arc(x, y, radius, startAngle, endAngle, anticlockwise)
各参数含义:
x -- 绘制圆形的起点横坐标
y -- 绘制圆形的起点纵坐标
radius -- 绘制圆形半径
startAngle -- 开始角度,取值为 Math.PI * n,Math.PI 表示180度
endAngle -- 结束角度,取值为 Math.PI * n,Math.PI 表示180度
anticlockwise -- 是否按照顺时针方向进行绘制,取值为 true 和 false
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制圆形</title>
6 <style>
7 canvas{
8 float: left;
9 margin-right: 30px;
10 }
11 </style>
12 </head>
13 <body>
14 <canvas id="circle1" height="180" width="190"></canvas>
15
16 <canvas id="circle2" height="180" width="190"></canvas>
17
18 <canvas id="circle3" height="180" width="190"></canvas>
19
20 <canvas id="circle4" height="180" width="190"></canvas>
21
22 <script>
23
24 function GetContext(id){
25 var canvas = document.getElementById(id);
26 if (canvas && canvas.getContext) {
27 var context = canvas.getContext("2d");
28 return context;
29 }
30 }
31
32 window.addEventListener("load", function(){
33 var context = GetContext("circle1");
34 context.beginPath();
35 /*
36 * arc(x,y,radius,startAngle,endAngle,anticlockwise)
37 * x, y 表示绘制圆形起点的横纵坐标
38 * anticlockwise 表示是否按照顺时针方向进行绘制,取值为 true 和 false
39 * Math.PI 表示角度为180度
40 */
41 context.arc(80, 80, 60, Math.PI, Math.PI * 2, true);
42 context.stroke();
43 }, true);
44 window.addEventListener("load", function(){
45 var context = GetContext("circle2");
46 context.beginPath();
47 context.arc(80, 80, 60, 0, Math.PI * 2 / 4, true);
48 context.fill();
49 }, true);
50 window.addEventListener("load", function(){
51 var context = GetContext("circle3");
52 context.beginPath();
53 context.arc(80, 80, 60, Math.PI, (Math.PI * 2 / 4) * 3, false);
54 context.fill();
55 }, true);
56 window.addEventListener("load", function(){
57 var context = GetContext("circle4");
58 context.beginPath();
59 context.arc(80, 80, 60, 0, Math.PI * 2, true);
60 context.stroke();
61 }, true);
62 </script>
63 </body>
64 </html>
创建渐变图形的步骤:
1、创建线性或径向渐变对象
2、为渐变对象设置颜色
3、在上下文对象上为填充样式或描边样式设置渐变
(一)、线性渐变
createLinearGradient(xStart, yStart, xEnd, yEnd) -- 创建渐变对象
addColorStop(offset, color) -- 设置渐变颜色(参数 offset 表示渐变偏移量,取值为 0~1)
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制线性渐变</title>
6 </head>
7 <body>
8 <canvas width="320" height="150" id="canvas"></canvas>
9
10 <div><canvas id="title" height="30"></canvas></div>
11
12 <div><canvas id="context" height="115" width="378"></canvas></div>
13
14 <script>
15
16 function GetContext(id){
17 var canvas = document.getElementById(id);
18 if (canvas && canvas.getContext) {
19 var context = canvas.getContext("2d");
20 return context;
21 }
22 }
23
24 window.addEventListener("load", function(){
25 var ctx = GetContext("canvas");
26 /*
27 * context.createLinearGradient(xStart, yStart, xEnd, yEnd)
28 * 创建渐变对象
29 */
30 var lingrad1 = ctx.createLinearGradient(0, 0, 0, 150);
31 /*
32 * addColorStop(offset, color)
33 * 设置渐变颜色
34 * offset 表示所设定的颜色离开渐变起始点的偏移量,取值为 0-1
35 * 0 表示渐变起始点的偏移量
36 * 1 表示渐变结束点的偏移量
37 */
38 lingrad1.addColorStop(0, ‘#00abeb‘);
39 lingrad1.addColorStop(0.5, ‘#fff‘);
40 lingrad1.addColorStop(0.5, ‘#26c000‘);
41 lingrad1.addColorStop(1, ‘#fff‘);
42
43 var lingrad2 = ctx.createLinearGradient(0, 50, 0, 95);
44 lingrad2.addColorStop(0.5, ‘#000‘);
45 lingrad2.addColorStop(1, ‘rgba(0, 0, 0, 0)‘);
46
47 ctx.fillStyle = lingrad1;
48 ctx.strokeStyle = lingrad2;
49
50 ctx.fillRect(10, 10, 300, 130);
51 ctx.strokeRect(50, 50, 210, 210);
52 });
53
54 window.addEventListener("load", function(){
55 var ctx = GetContext("title");
56 ctx.font = "italic 15px sans-serif";
57 ctx.strokeText("绘制线性渐变", 90, 20);
58 });
59
60 window.addEventListener("load", function(){
61 var ctx = GetContext("context");
62 ctx.font = "italic 15px sans-serif";
63 ctx.fillText("本案例实现线性渐变的功能,主要使用到了 Linear", 15, 20);
64 ctx.fillText("rGradient 对象的 addColorStop()函数、context对象的", 0, 40);
65 ctx.fillText("fillStyle 和 StrokeStyle属性及 fillRect()函数和st", 0, 60);
66 ctx.fillText("rokeRect()函数", 0, 80);
67 });
68 </script>
69 </body>
70 </html>
(二)、径向渐变
createRadialGradient(xStart, yStart, radiusStart, xEnd, yEnd, radiusEnd) -- 创建渐变对象
addColorStop(offset, color) -- 设置渐变颜色(参数 offset 表示渐变偏移量,取值为 0~1)
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制径向渐变</title>
6 </head>
7 <body>
8 <canvas id="canvas" width="500" height="250" style="border: 1px solid #f00;"></canvas>
9
10 <script>
11 window.addEventListener("load", function(){
12 var canvas = document.getElementById(‘canvas‘);
13 var ctx = canvas.getContext("2d");
14
15 /*
16 * context.createRadialGradient(xStart, yStart, radiusStart, xEnd, yEnd, radiusEnd)
17 * 创建径向渐变对象
18 * 参数分别表示 开始圆的圆心横纵坐标,开始圆的半径,结束圆的圆心横纵坐标,结束圆的半径
19 */
20 var g1 = ctx.createRadialGradient(400, 0, 0, 400, 0, 400);
21 g1.addColorStop(0.1, "rgb(255, 255, 0)");
22 g1.addColorStop(0.3, "rgb(0, 255, 255)");
23 g1.addColorStop(0.5, "rgb(255, 0, 255)");
24 ctx.fillStyle = g1;
25 ctx.fillRect(0, 0, 500, 300);
26
27 // var n = 0;
28 var g2 = ctx.createRadialGradient(250, 250, 0, 250, 250, 300);
29 g2.addColorStop(0.1, "rgba(43, 255, 243, 0.3)");
30 g2.addColorStop(0.7, "rgba(255, 255, 0, 0.5)");
31 g2.addColorStop(1, "rgba(0, 0, 255, 0.8)");
32
33 for (var i = 0; i < 10; i++) {
34 ctx.beginPath();
35 ctx.fillStyle = g2;
36 ctx.arc(i * 25, i * 25, i * 10, 0, Math.PI, true);
37 ctx.closePath();
38 ctx.fill();
39 }
40 });
41 </script>
42 </body>
43 </html>
shadowOffsetX -- 阴影水平方向偏移量,默认值为1
shadowOffsetY -- 阴影垂直方向偏移量,默认值为1
shadowBlur -- 阴影模糊范围,取值为 0~10,默认值为1
shadowolor -- 阴影颜色, 默认为全透明黑色
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制阴影</title>
6 </head>
7 <body onload="PicShadow(), TxtShadow()">
8 <canvas width="300" height="220" id="canvas1"></canvas>
9 <canvas width="300" height="220" id="canvas2"></canvas>
10
11 <script>
12 function PicShadow(){
13 var canvas = document.getElementById(‘canvas1‘);
14 var ctx = canvas.getContext("2d");
15 ctx.shadowOffsetX = 15;
16 ctx.shadowOffsetY = 15;
17 ctx.shadowBlur = 10;
18 ctx.shadowColor = "rgba(100, 200, 100, 0.5)";
19 ctx.fillStyle = "#bbf";
20 ctx.arc(150, 100, 80, 0, Math.PI * 2, true);
21 ctx.fill();
22 }
23
24 function TxtShadow(){
25 var canvas = document.getElementById(‘canvas2‘);
26 var ctx = canvas.getContext("2d");
27 ctx.shadowOffsetX = -5;
28 ctx.shadowOffsetY = -5;
29 ctx.shadowBlur = 1;
30 ctx.shadowColor = "rgba(255, 125, 255, 0.5)";
31 ctx.strokeStyle = "#bbf";
32 ctx.font = "italic 25px sans-serif";
33 ctx.strokeText("实现文字和图形阴影", 30, 100);
34 ctx.stroke();
35 }
36 </script>
37 </body>
38 </html>
(一)、保存和回复状态以及输出图像
save() -- 保存
restore() -- 恢复状态
注意: save方法用于临时保存画布坐标系统的状态;
restore方法可以用来恢复save之后设置的状态即回到save之前的状态;
save和restore 方法必须是配对使用的;
restore方法前必须有save方法,不然会报Underflow in restore错误;
restore方法的调用只影响restore之后绘制的内容
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制变形图形1 -- 保存和恢复状态</title>
6 </head>
7 <body>
8 <canvas id="canvas" width="250" height="250" style="margin-left: 100px;"></canvas>
9
10 <script>
11 window.addEventListener("load", function(){
12 var ctx = document.getElementById(‘canvas‘).getContext("2d");
13 ctx.fillStyle = "#fbb";
14 ctx.fillRect(0, 0, 250, 250);
15 ctx.save();
16 ctx.fillStyle = "#00f";
17 ctx.fillRect(15, 15, 220, 220);
18 ctx.save();
19 ctx.fillStyle = "#bbf";
20 ctx.globalAlpha = 0.5;
21 ctx.fillRect(30, 30, 190, 190);
22 ctx.restore();
23 ctx.fillRect(45, 45, 160, 160);
24 ctx.restore();
25 ctx.fillRect(60, 60, 130, 130);
26 /*
27 * save方法用于临时保存画布坐标系统的状态
28 * restore方法可以用来恢复save之后设置的状态即回到save之前的状态
29 * save和restore方法必须是配对使用的
30 * restore方法前必须有save方法,不然会报Underflow in restore错误
31 * restore方法的调用只影响restore之后绘制的内容
32 */
33 });
34 </script>
35 </body>
36 </html>
toDataURL(type) -- 输出图像
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制变形图形2 -- 输出图像</title>
6 </head>
7 <body>
8 <canvas id="canvas" width="260" height="260" style="margin-left: 200px;"></canvas>
9 <input type="button" value="输出图像" onclick="javascript: showImg();">
10 <img id="img1" width="150" height="150">
11
12 <script>
13 function showImg(){
14 /*
15 * canvas.toDataURL(type)
16 * type 表示要输入的数据的MIME类型
17 */
18 var img1 = document.getElementById(‘canvas‘).toDataURL("images/png");
19 document.getElementById(‘img1‘).src = img1;
20 }
21
22 window.addEventListener("load", function(){
23 var canvas = document.getElementById(‘canvas‘);
24 if (canvas && canvas.getContext) {
25 var ctx = canvas.getContext("2d");
26 ctx.fillStyle = "#ffb";
27 ctx.beginPath();
28 ctx.rect(5, 5, 250, 250);
29 ctx.fill();
30 ctx.stroke();
31 ctx.arc(150, 150, 80, 0, Math.PI * 2 / 4, true);
32 ctx.stroke();
33 }
34 });
35 </script>
36 </body>
37 </html>
(二)、坐标变换
translate(x, y) -- 平移
scale(x, y) -- 缩放
rotate(angle) -- 旋转(旋转中心为坐标轴原点)
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制变形图形3 -- 坐标变换</title>
6 </head>
7 <body>
8 <canvas id="canvas" width="360" height="300" style="margin-left: 300px;"></canvas>
9
10 <script>
11
12 window.addEventListener("load", function(){
13 var ctx = document.getElementById(‘canvas‘).getContext("2d");
14 ctx.translate(130, 120);
15 for (var i = 1; i < 7; i++) {
16 ctx.save();
17 ctx.fillStyle = ‘rgba(‘ + (30 * i) + ‘,‘ + (255 - 30 * i) + ‘255, 1)‘;
18 for (var j = 0; j < i * 7; j++) {
19 ctx.translate(1, 1);
20 ctx.rotate(Math.PI * 2 / (i * 7));
21 ctx.beginPath();
22 ctx.scale(1.02, 1.02);
23 ctx.arc(0, i * 12, 5, 0, Math.PI * 2, false);
24 ctx.fill();
25 }
26 ctx.restore();
27 }
28 });
29 /*
30 * 坐标变换函数
31 * translate(x, y) -- x 表示向右移动,y 表示向下移动
32 * scale(x, y) -- x 表示水平方向的放大倍数,y 表示垂直方向的放大倍数,取 0-1 之间的数则为缩小
33 * rotate(angle) -- angle 表示旋转的角度,旋转的中心点是坐标轴的原点,旋转是以顺时针方向进行的,
34 * 若参数设为负值,则表示逆时针
35 */
36 </script>
37 </body>
38 </html>
(三)、矩阵变换
transform(a, b, c, d, e, f)
各参数含义:
a -- 水平缩放
b -- 水平倾斜
c -- 垂直倾斜
d -- 垂直缩放
e -- 水平移动
f -- 垂直移动
实例:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>绘制变形图形4 -- 矩阵变换</title>
6 </head>
7 <body>
8 <canvas id="diagonal" width="300" height="300" style="margin-left: 300px;"></canvas>
9
10 <script>
11
12 window.addEventListener("load", function(){
13 var canvas = document.getElementById(‘diagonal‘);
14 if (canvas && canvas.getContext) {
15 var ctx = canvas.getContext("2d");
16 ctx.transform(1, 0, 0, 1, 150, 150);
17 ctx.beginPath();
18 ctx.fillStyle = "rgba(255, 0, 0, 0.25)";
19 rad = 18 * Math.PI / 90;
20 for (var i = 0; i < 10; i++) {
21 ctx.fillRect(0, 0, 100, 100);
22 // 设置旋转效果
23 ctx.transform(Math.cos(rad), Math.sin(rad), -Math.sin(rad), Math.cos(rad), 0, 0);
24 ctx.closePath();
25 }
26 }
27 });
28 /*
29 * 矩阵变换函数
30 * transform(a, b, c, d, e, f)
31 * 各参数意义
32 * a -- 水平缩放
33 * b -- 水平倾斜
34 * c -- 垂直倾斜
35 * d -- 垂直缩放
36 * e -- 水平移动
37 * f -- 垂直移动
38 * rotate(x, y) 使用 transform(a, b, c, d, e, f) 方法替换如下
39 * ctx.transform(
40 * Math.cos(angle*Math.PI/180),
41 * Math.sin(angle*Math.PI/180),
42 * -Math.sin(angle*Math.PI/180),
43 * Math.cos(angle*Math.PI/180),
44 * 0, 0);
45 * 或 ctx.transform(
46 * -Math.sin(angle*Math.PI/180),
47 * Math.cos(angle*Math.PI/180),
48 * Math.cos(angle*Math.PI/180),
49 * Math.sin(angle*Math.PI/180),
50 * 0, 0);
51 * setTransform(a, b, c, d, e, f) -- 重置矩阵
52 */
53 </script>
54 </body>
55 </html>
标签:cal 渐变 lang function 是你 ros 坐标变换 canvas title
原文地址:http://www.cnblogs.com/xlb-happymoment/p/6809354.html