>

canvas api

- 编辑:澳门新葡亰平台游戏 -

canvas api

canvas api

2016/01/11 · HTML5 · Canvas

原文出处: 韩子迟   

Canvas API(画布)用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap)。
使用前,首先需要新建一个canvas网页元素。

最近要准备一次组内分享关于canvas 的一个神奇的应用。

基本骨骼


 

<canvas id="canvas" width=1000 height=1000 style="border: 1px black dotted"></canvas> <script> var ctx = document.getElementById('canvas').getContext('2d'); </script>

1
2
3
4
5
<canvas id="canvas" width=1000 height=1000 style="border: 1px black dotted"></canvas>
 
<script>
  var ctx = document.getElementById('canvas').getContext('2d');
</script>
1
2
3
4
<canvas height="200" id="myCanvas" width="400">
    您的浏览器不支持canvas!
</canvas>
<!-- 如果浏览器不支持这个API,则就会显示canvas标签中间的文字——“您的浏览器不支持canvas!”。 -->

其实我对于canvas学过很多次,但是因为平常不咋用,就总是忘记。

矩形


实心:

// 填充色 (默认为黑色) ctx.fillStyle = 'darkSlateBlue'; // 规定画布左上角坐标为 (0, 0) // 矩形左上角坐标 (0, 0) // 矩形大小 100*100 ctx.fillRect(0, 0, 100, 100);

1
2
3
4
5
6
7
// 填充色 (默认为黑色)
ctx.fillStyle = 'darkSlateBlue';
 
// 规定画布左上角坐标为 (0, 0)
// 矩形左上角坐标 (0, 0)
// 矩形大小 100*100
ctx.fillRect(0, 0, 100, 100);

空心:

// 边框颜色 (默认黑色) ctx.strokeStyle = 'darkSlateBlue'; // 规定画布左上角坐标为 (0, 0) // 矩形左上角坐标 (0, 0) // 矩形大小 100*100 ctx.strokeRect(0, 0, 100, 100);

1
2
3
4
5
6
7
// 边框颜色 (默认黑色)
ctx.strokeStyle = 'darkSlateBlue';
 
// 规定画布左上角坐标为 (0, 0)
// 矩形左上角坐标 (0, 0)
// 矩形大小 100*100
ctx.strokeRect(0, 0, 100, 100);

每个canvas元素都有一个对应的context对象(上下文对象),Canvas API定义在这个context对象上面,所以需要获取这个对象,方法是使用getContext方法。

估计这次分享后 还是忘记,,oudoukaji

圆形


实心:

ctx.fillStyle = 'darkSlateBlue'; ctx.beginPath(); ctx.arc(100, 100, 50, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill();

1
2
3
4
5
6
ctx.fillStyle = 'darkSlateBlue';
 
ctx.beginPath();
ctx.arc(100, 100, 50, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();

空心:

ctx.strokeStyle = 'darkSlateBlue'; ctx.beginPath(); ctx.arc(100, 100, 50, 0, Math.PI * 2, true); ctx.closePath(); ctx.stroke();

1
2
3
4
5
6
ctx.strokeStyle = 'darkSlateBlue';
 
ctx.beginPath();
ctx.arc(100, 100, 50, 0, Math.PI * 2, true);
ctx.closePath();
ctx.stroke();
1
2
3
4
5
var canvas = document.getElementById('myCanvas');
if (canvas.getContext) {
    var ctx = canvas.getContext('2d');
}
// getContext方法指定参数2d,表示该canvas对象用于生成2D图案(即平面图案)。如果参数是3d,就表示用于生成3D图像(即立体图案),这部分实际上单独叫做WebGL API(看博主其他文章)。

线段


ctx.strokeStyle = 'darkSlateBlue'; ctx.beginPath(); ctx.moveTo(100, 100); // 起点 ctx.lineTo(200, 200); ctx.lineTo(300, 100); // ctx.closePath(); ctx.stroke();

1
2
3
4
5
6
7
8
ctx.strokeStyle = 'darkSlateBlue';
 
ctx.beginPath();
ctx.moveTo(100, 100); // 起点
ctx.lineTo(200, 200);
ctx.lineTo(300, 100);
// ctx.closePath();
ctx.stroke();

canvas画布提供了一个用来作图的平面空间,该空间的每个点都有自己的坐标,x表示横坐标,y表示竖坐标。原点(0, 0)位于图像左上角,x轴的正向是原点向右,y轴的正向是原点向下。
绘制路径
beginPath方法表示开始绘制路径,moveTo(x, y)方法设置线段的起点,lineTo(x, y)方法设置线段的终点,stroke方法用来给透明的线段着色。

分享内容来自这里,前端大全微信公众号的一篇文章。讲的是 隐写术,看上去是不是逼格很高。。

图像


动态生成 img:

var img = new Image(); // 一定要等图片载入后(或者已经在缓存中了)才能用 drawImage 方法 img.onload = function() { // 左上角坐标 & 图像大小 ctx.drawImage(img, 0, 0, 100, 56); }; img.src = '0.jpg';

1
2
3
4
5
6
7
8
9
var img = new Image();
 
// 一定要等图片载入后(或者已经在缓存中了)才能用 drawImage 方法
img.onload = function() {
  // 左上角坐标 & 图像大小
  ctx.drawImage(img, 0, 0, 100, 56);
};
 
img.src = '0.jpg';

或者直接从 dom 中取:

var img = document.getElementById('myImg'); ctx.drawImage(img, 0, 0, 100, 56);

1
2
var img = document.getElementById('myImg');
ctx.drawImage(img, 0, 0, 100, 56);
1
2
3
4
5
6
7
ctx.beginPath(); // 开始路径绘制
ctx.moveTo(20, 20); // 设置路径起点,坐标为(20,20)
ctx.lineTo(200, 20); // 绘制一条到(200,20)的直线
ctx.lineWidth = 1.0; // 设置线宽
ctx.strokeStyle = #CC0000; // 设置线的颜色
ctx.stroke(); // 进行线的着色,这时整条线才变得可见
//moveto和lineto方法可以多次使用。最后,还可以使用closePath方法,自动绘制一条当前点到起点的直线,形成一个封闭图形,省却使用一次lineto方法。

canvas 我没有用它写过动画,我日常切图工作的动画难度基本上css3那些就可以搞定。但是他有一个很厉害的地方就是可以获得图片每个像素的信息。就像我觉得svg很牛逼的地方就是 矢量图 不失真。

文字


文字) 的位置设定相对复杂,不像矩形、图像一样有个固定的左上角坐标,也不像圆一样有固定的圆心。文字的位置设置也是一个类似 (x, y) 形式的坐标,这个位置可以是文字的 4 个角,或者中心。

x 部分,蓝线(水平坐标)为 x 坐标所在位置(textAlign 属性):

图片 1

ctx.font = "bold 80px serif" ctx.textAlign = "start"; // 默认值为 start ctx.fillStyle = 'darkSlateBlue'; // 文本内容、坐标 ctx.fillText('hello world', 0, 0);

1
2
3
4
5
6
ctx.font = "bold 80px serif"
ctx.textAlign = "start";  // 默认值为 start
 
ctx.fillStyle = 'darkSlateBlue';
// 文本内容、坐标
ctx.fillText('hello world', 0, 0);

y 部分,蓝线(垂直坐标)为 y 坐标所在位置 (textBaseline 属性):

图片 2

ctx.font = "bold 80px serif" ctx.textAlign = "start"; // 默认值为 start ctx.textBaseline = "hanging"; // 默认值为 alphabetic ctx.fillStyle = 'darkSlateBlue'; // 文本内容、坐标 ctx.fillText('hello world', 0, 0);

1
2
3
4
5
6
7
ctx.font = "bold 80px serif"
ctx.textAlign = "start";  // 默认值为 start
ctx.textBaseline = "hanging"; // 默认值为 alphabetic
 
ctx.fillStyle = 'darkSlateBlue';
// 文本内容、坐标
ctx.fillText('hello world', 0, 0);

所以文字的位置共有 5*6=30 种。

fillText 方法不支持文本断行,即所有文本出现在一行内。所以,如果要生成多行文本,只有调用多次 fillText 方法。

空心的话用 stroke 即可。

绘制矩形
fillRect(x, y, width, height)方法用来绘制矩形,它的四个参数分别为矩形左上角顶点的x坐标、y坐标,以及矩形的宽和高。fillStyle属性用来设置矩形的填充色。

文章写得很仔细 我就不再写了

其他 API


属性:

  • lineWidth:stroke 的线条宽度 ctx.lineWidth = 2

方法:

  • clearRect: 清除某部分(矩形区域)画布 ctx.clearRect(0, 0, 100, 100)
  • measureText: 计算文本对象的宽度
  • translate
  • rotate
1
2
3
4
5
6
ctx.fillStyle = 'yellow';
ctx.fillRect(50, 50, 200, 100);
//strokeRect方法与fillRect类似,用来绘制空心矩形。
ctx.strokeRect(10,10,200,100);
//clearRect方法用来清除某个矩形区域的内容。
ctx.clearRect(100,50,50,50);

但是我想复习一下这些api。

Read More


  • Canvas API (w3cschool)
  • HTML5 Canvas — the Basics (Opera)
  • Canvas API (ruanyifeng)
  • Canvas tutorial (MDN)

    1 赞 3 收藏 评论

图片 3

绘制文本
fillText(string, x, y) 用来绘制文本,它的三个参数分别为文本内容、起点的x坐标、y坐标。使用之前,需用font设置字体、大小、样式(写法类似与CSS的font属性)。与此类似的还有strokeText方法,用来添加空心字。


?

我们在写css样式时 ,如果想实现透明效果,可以用opacity:0.5;但是也会这样 rgba(155,155,155,0.5);这四个值分别代表 红绿蓝及透明度。
通过canvas 可以帮助我们 巧妙地操作这些像素信息。

1
2
3
4
5
6
7
8
9
10
11
// 设置字体
ctx.font = Bold 20px Arial;
// 设置对齐方式
ctx.textAlign = left;
// 设置填充颜色
ctx.fillStyle = #008600;
// 设置字体内容,以及在画布上的位置
ctx.fillText(Hello!, 10, 50);
// 绘制空心字
ctx.strokeText(Hello!, 10, 100);
//fillText方法不支持文本断行,即所有文本出现在一行内。所以,如果要生成多行文本,只有调用多次fillText方法。
  • 第一步,获取canvas的上下文对象
    var ctx = document.getElementById('canvas').getContext('2d');
    通过这个对象ctx,进而可以get/set画布。

    图片 4

    打印出一个初始化的ctx

  • 第二步,获取原始图片信息
    <canvas id="canvas" width="640" height="640"></canvas>
    ctx.drawImage(img, 0, 0,640,580,0,0,640,580);
    orginalData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);

    图片 5

    Paste_Image.png

绘制圆形和扇形
arc方法用来绘制扇形

ctx.drawImage(img, 0, 0,640,580);  

![](https://upload-images.jianshu.io/upload_images/94752-a8070835cfd2f65d.png)

Paste_Image.png


此时发现图像被挤压了,有一个问题
,困扰我好久,图像挤压后,我脑洞打开觉得像素被挤成长方形了,其实是,图像在被挤压后,**丢掉了一部分像素**,这个解释
我觉得 还算合理。  
返回 说这个api的参数。  

![](https://upload-images.jianshu.io/upload_images/94752-23a6782fe95bfc51.png)

w3c



![](https://upload-images.jianshu.io/upload_images/94752-22ed0843bb0cb31f.png)

Paste_Image.png
1
2
3
4
5
6
7
8
9
10
11
12
13
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
//arc方法的x和y参数是圆心坐标,radius是半径,startAngle和endAngle则是扇形的起始角度和终止角度(以弧度表示)//,anticlockwise表示做图时应该逆时针画(true)还是顺时针画(false)
//绘制实心的圆形
ctx.beginPath();
ctx.arc(60, 60, 50, 0, Math.PI*2, true);
ctx.fillStyle = #000000;
ctx.fill();
//绘制空心圆形
ctx.beginPath();
ctx.arc(60, 60, 50, 0, Math.PI*2, true);
ctx.lineWidth = 1.0;
ctx.strokeStyle = #000;
ctx.stroke();

看一眼打印的图像信息。

设置渐变色
createLinearGradient方法用来设置渐变色。

图片 6

1
2
3
4
5
6
var myGradient = ctx.createLinearGradient(0, 0, 0, 160);
myGradient.addColorStop(0, #BABABA);
myGradient.addColorStop(1, #636363);
//createLinearGradient方法的参数是(x1, y1, x2, y2),其中x1和y1是起点坐标,x2和y2是终点坐标。通过不同的坐标值,可以生成从上至下、从左到右的渐变等等
ctx.fillStyle = myGradient;
ctx.fillRect(10,10,200,100);

Paste_Image.png

设置阴影
一系列与阴影相关的方法,可以用来设置阴影。

每四个一组,值得注意的是,我们知道rgba里面最后一个值只要大于1 都是不进行透明度设置的,这里如果默认为255,表示不透明。1表示完全透明,中间为不同程度的透明。其余三个为rgb。

1
2
3
4
5
6
ctx.shadowOffsetX = 10; // 设置水平位移
ctx.shadowOffsetY = 10; // 设置垂直位移
ctx.shadowBlur = 5; // 设置模糊度
ctx.shadowColor = rgba(0,0,0,0.5); // 设置阴影颜色
ctx.fillStyle = #CC0000;
ctx.fillRect(10,10,200,100);
  • 第三步,获取隐藏文案的ImageData信息
    ctx.font = '70px Microsoft Yahei';//这个语法和css语法一致
    ctx.fillText('春风十里不如你', 60, 130);

    图片 7

    filltext语法源自W3c

  • 第四步,处理目标图片的数据,并生成图片
    这样就得到了两组图像数据。因为这个案例是显示纯色的文字在纯色的背景上,所以作者想了一个巧妙的方法,对原来图片上对应到文字的部分的R通道为奇数,其他非文字区域的R通道为偶数。
    ctx.putImageData(originalData, 0, 0);

    图片 8

    Paste_Image.png

  • 第五步,解密图片
    这样当解密图片时 只需要对R通道的数据进行判断,进而附上颜色值。

 

对于文章一开头 举的例子,解密后是一张图片的。估计需要更复杂的算法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//canvas允许将图像文件插入画布,做法是读取图片后,使用drawImage方法在画布内进行重绘。
var img = new Image();
img.src = image.png;
ctx.drawImage(img, 0, 0); // 设置对应的图像对象,以及它在画布上的位置
//由于图像的载入需要时间,drawImage方法只能在图像完全载入后才能调用,因此上面的代码需要改写。
var image = new Image();
image.onload = function() {
    if (image.width != canvas.width)
        canvas.width = image.width;
    if (image.height != canvas.height)
        canvas.height = image.height;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(image, 0, 0);
}
image.src = image.png;
//drawImage()方法接受三个参数,第一个参数是图像文件的DOM元素(即img标签),第二个和第三个参数是图像左上角在//Canvas元素中的坐标,上例中的(0, 0)就表示将图像左上角放置在Canvas元素的左上角。
 
//getImageData方法可以用来读取Canvas的内容,返回一个对象,包含了每个像素的信息。
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
//imageData对象有一个data属性,它的值是一个一维数组。该数组的值,依次是每个像素的红、绿、蓝、alpha通道值,因//此该数组的长度等于 图像的像素宽度 x 图像的像素高度 x 4,每个值的范围是0–255。这个数组不仅可读,而且可写,//因此通过操作这个数组的值,就可以达到操作图像的目的。修改这个数组以后,使用putImageData方法将数组内容重新绘//制在Canvas上。
context.putImageData(imageData, 0, 0);
 
//对图像数据做出修改以后,可以使用toDataURL方法,将Canvas数据重新转化成一般的图像文件形式。
function convertCanvasToImage(canvas) {
  var image = new Image();
  image.src = canvas.toDataURL(image/png);
  return image;
}
 
//save方法用于保存上下文环境,restore方法用于恢复到上一次保存的上下文环境。
ctx.save();
ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
ctx.shadowBlur = 5;
ctx.shadowColor = rgba(0,0,0,0.5);
ctx.fillStyle = #CC0000;
ctx.fillRect(10,10,150,100);
ctx.restore();
ctx.fillStyle = #000000;
ctx.fillRect(180,10,150,100);
//先用save方法,保存了当前设置,然后绘制了一个有阴影的矩形。接着,使用restore方法,恢复了保存前的设置,绘制//了一个没有阴影的矩形
 
//利用JavaScript,可以在canvas元素上很容易地产生动画效果
var posX = 20,
    posY = 100;
setInterval(function() {
    context.fillStyle = black;
    context.fillRect(0,0,canvas.width, canvas.height);
    posX += 1;
    posY += 0.25;
    context.beginPath();
    context.fillStyle = white;
    context.arc(posX, posY, 10, 0, Math.PI*2, true);
    context.closePath();
    context.fill();
}, 30);
//产生一个小圆点,每隔30毫秒就向右下方移动的效果。setInterval函数的一开始,之所以要将画布重新渲染黑色底色,//是为了抹去上一步的小圆点。
//通过设置圆心坐标,可以产生各种运动轨迹。
//先上升后下降。
var vx = 10,
    vy = -10,
    gravity = 1;
setInterval(function() {
    posX += vx;
    posY += vy;
    vy += gravity;
    // ...
});
//x坐标始终增大,表示持续向右运动。y坐标先变小,然后在重力作用下,不断增大,表示先上升后下降。
//小球不断反弹后,逐步趋于静止
var vx = 10,
    vy = -10,
    gravity = 1;
setInterval(function() {
    posX += vx;
    posY += vy;
    if (posY > canvas.height * 0.75) {
          vy *= -0.6;
          vx *= 0.75;
          posY = canvas.height * 0.75;
    }
    vy += gravity;
    // ...
});
//一旦小球的y坐标处于屏幕下方75%的位置,向x轴移动的速度变为原来的75%,而向y轴反弹上一次反弹高度的40%。
 
//通过getImageData方法和putImageData方法,可以处理每个像素,进而操作图像内容。
//假定filter是一个处理像素的函数,那么整个对Canvas的处理流程,可以用下面的代码表示。
if (canvas.width > 0 && canvas.height > 0) {
    var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
    filter(imageData);
    context.putImageData(imageData, 0, 0);
}
 
//以下是几种常见的处理方法。
//灰度图(grayscale)就是取红、绿、蓝三个像素值的算术平均值,这实际上将图像转成了黑白形式。假定d[i]是像素数组中一个象素的红色值,则d[i+1]为绿色值,d[i+2]为蓝色值,d[i+3]就//是alpha通道值。转成灰度的算法,就是将红、绿、蓝三个值相加后除以3,再将结果写回数组。
grayscale = function (pixels) {
    var d = pixels.data;
    for (var i = 0; i < d.length; i += 4) {
      var r = d[i];
      var g = d[i + 1];
      var b = d[i + 2];
      d[i] = d[i + 1] = d[i + 2] = (r+g+b)/3;
    }
    return pixels;
};
 
//复古效果(sepia)则是将红、绿、蓝三个像素,分别取这三个值的某种加权平均值,使得图像有一种古旧的效果。
sepia = function (pixels) {
    var d = pixels.data;
    for (var i = 0; i < d.length; i += 4) {
      var r = d[i];
      var g = d[i + 1];
      var b = d[i + 2];
      d[i]     = (r * 0.393)+(g * 0.769)+(b * 0.189); // red
      d[i + 1] = (r * 0.349)+(g * 0.686)+(b * 0.168); // green
      d[i + 2] = (r * 0.272)+(g * 0.534)+(b * 0.131); // blue
    }
    return pixels;
};
 
//红色蒙版指的是,让图像呈现一种偏红的效果。算法是将红色通道设为红、绿、蓝三个值的平均值,而将绿色通道和蓝色通道都设为0。
red = function (pixels) {
    var d = pixels.data;
    for (var i = 0; i < d.length; i += 4) {
      var r = d[i];
      var g = d[i + 1];
      var b = d[i + 2];
      d[i] = (r+g+b)/3;        // 红色通道取平均值
      d[i + 1] = d[i + 2] = 0; // 绿色通道和蓝色通道都设为0
    }
    return pixels;
};
 
//亮度效果(brightness)是指让图像变得更亮或更暗。算法将红色通道、绿色通道、蓝色通道,同时加上一个正值或负值。
brightness = function (pixels, delta) {
    var d = pixels.data;
    for (var i = 0; i < d.length; i += 4) {
          d[i] += delta;     // red
          d[i + 1] += delta; // green
          d[i + 2] += delta; // blue  
    }
    return pixels;
};
 
//反转效果(invert)是指图片呈现一种色彩颠倒的效果。算法为红、绿、蓝通道都取各自的相反值(255-原值)。
invert = function (pixels) {
    var d = pixels.data;
    for (var i = 0; i < d.length; i += 4) {
        d[i] = 255 - d[i];
        d[i+1] = 255 - d[i + 1];
        d[i+2] = 255 - d[i + 2];
    }
    return pixels;
};

【附加】
image.src = canvas.toDataURL("image/png");
注意:canvas为画布对象,而不是canvas上下文。

图片 9

Paste_Image.png

支持两个参数 ,第一个是转化类型,第二个是压缩规模。
ps:canvas压缩不支持png压缩,如果要对png图片进行压缩需要先toDataURL为jpeg格式,注意的是 绘制画布之前 需要为画布铺上一层底色。否则png透明区域就为黑色啦。

最后将image,apend到dom树中就好了。

  • 【附加】
    上传本地图片
    <input type="file" name="" id="ipt" value="ee" />
    var reader = new FileReader(),
    file = ipt.files[0];
    reader.readAsDataURL(file);
    reader.onload = function(){
    var src = this.result;
    var img = new Image();
    img.src = src;
    cxt.drawImage(img,0,0)
    }
    这是用到的几个文件上传的api
    用到了 FileReader对象,readAsDataURL这个方法会读取文件内容。当读取结束后,该对像的readystate变为done然后将读取结果已URL格式存储在 FileReader对象的result属性上。

本文由前端php发布,转载请注明来源:canvas api