canvas
Posted Ling201509
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了canvas相关的知识,希望对你有一定的参考价值。
canvas
canvas只能在标签中定义宽高
canvas跟其它标签一样,也可以定义样式,但需要注意的是:canvas的默认宽高为300px* 150px,在css中为canvas定义宽高,实际上定义的是canvas的显示的大小,但针对canvas来说还包括里面的绘制的图像的分辨率的大小。所以在css中定义高宽canvas中绘制的图形可能会变形。因此,我们可以使用以下方式指定大小:
// 在标签中指定
<canvas class="mycanvas" width="500" height="500">土鳖!你的浏览器out啦!</canvas>
// -->标签中的内容是当浏览器不支持canvas时的后备信息。
// 在js中通过画布对象属性的方式指定
var drawing = document.querySelector(‘.mycanvas‘);
drawing.width = 500;
drawing.height = 500;
canvas对象的属性和方法:
- width;
- height;
- getContext(); 获取canvas对象
canvas中的绘图是一种基于状态的绘图,也就是说我们需要先设置绘图的状态,在调用函数做一个具体的绘制。
一、基本用法
要在画布上绘图,首先要先获取绘图上下文,取得绘图上下文对象的引用。调用getContext()方法,传入上下文的名字。如下:
var drawing = document.querySelector(‘.mycanvas‘);
// 检测浏览器是否支持<canvas>
if(drawing.getContext) {
var context = drawing.getContext(‘2d‘); //获取绘图上下文
}
if(drawing.getContext(‘2d‘)) {} // 不能这样写,这样写不支持canvas的浏览器会报错!!!
检测getContext()方法是否存在这一步很有必要。因为有些浏览器会为HTML规范之外的元素创建默认的HTML元素对象,并且可以引用它,但这个对象并没有getContext()方法。
使用toDataURL()方法,可以导出在< canvas >元素上绘制的图像。这个参数接受一个参数,即图像的MIME类型格式,而且适合用于创建图像的任何上下文。默认情况下,浏览器会将图像编码为 PNG 格式(除非另行指定)。Firefox 和 Opera 也支持基于”image/jpeg” 参数的 JPEG 编码格式。
var drawing = document.querySelector(‘.mycanvas‘);
if(drawing.getContext) {
// 获取图像的数据URL
var imgURL = drawing.toDataURL(‘image/png‘);
// 显示图像
var image = document.createElement(‘img‘);
image.src = imgURL;
document.body.appendChild(image);
}
如果绘制到画布上的图像源自不同的域, toDataURL() 方法会抛出错误。
二、2D上下文
1、填充和描边
- fillStyle属性;填充
- strokeStyle属性;描边 属性值可以使字符串、渐变对象或模式对象。
2、绘制矩形
矩形是唯一一种可以直接在2D上下文中绘制的形状。
- fillRect(x, y, width, height); 绘制填充指定颜色的矩形,填充颜色通过fillStyle属性指定。
strokeRect(x, y, width, height); 绘制指定颜色的描边矩形,描边颜色通过strokeStyle属性指定。
- lineWidth属性; 线条宽度,值可以是任何整数。
- lineCap属性; 控制线条末端的形状,值可以是:平头(’butt’)、圆头(’round’)、方头(’square’)。
- lineJoin属性; 控制线条相交的方式,值可以是:圆交(’round’)、斜交(’bevel’)、斜接(’miter’)。
clearRect(x, y, width, height); 清除画布上的指定区域。
参数单位都是像素。
var drawing = document.querySelector(‘#mycanvas‘);
if(drawing.getContext) {
var context = drawing.getContext(‘2d‘);
context.fillStyle = ‘red‘;
context.fillRect(10, 10, 100,100);
context.strokeStyle = ‘green‘;
context.strokeRect(60, 60, 100, 100);
context.clearRect(70, 70, 30, 30);
}
3、绘制路径
创建路径:
- beginPath(); 开辟新的路径
- closePath(); 闭合路径
- moveTo(x, y);
lineTo(x, y); 从上一点开始绘制一条直线,直到(x, y)为止。
rect(x, y, width, height); 绘制矩形路径
arc(x, y, radius, startAngle, endAngle, counterclockwise); 绘制弧线。 (圆心x, 圆心y, 半径, 开始角度, 结束角度, 是否按逆时针方向计算)
- arcTo(x1, y1, x2, y2, radius); 绘制弧线
- bezierCurveTo(c1x, c1y, c2x, c2y, x, y); 贝塞尔曲线。从上一点开始绘制一条曲线,到(x, y)为止,并且以(c1x, c1y)和(c2x, c2y)为控制点。
- quadraticCurveTo(cx, cy, x, y); 从上一点开始绘制一条二次曲线,到(x, y)为止,并且以(cx, cy)作为控制点。
绘制图形:
- fill(); 填充路径
- stroke(); 描边路径
clip(); 创建一个剪切区域
isPointInPath(x, y);用于在路径被关闭之前确定画布上的某一点是否位于路径上
4、绘制文本
- fillText(str, x, y, maxWidth); 绘制填充文本
strokeText(str, x, y, maxWidth); 绘制描边文本
font; 文本样式、大小及字体
- textAlign; 文本对齐方式:
- start 默认。文本在指定的位置开始。
- end 文本在指定的位置结束。
- center 文本的中心被放置在指定的位置。
- left 文本左对齐。
- right 文本右对齐。
- textBaseline; 文本的基线:
- alphabetic 默认。文本基线是普通的字母基线。
- top 文本基线是 em 方框的顶端。
- hanging 文本基线是悬挂基线。
- middle 文本基线是 em 方框的正中。
- ideographic 文本基线是表意基线。
- bottom 文本基线是 em 方框的底端。
计算文本大小:
由于绘制文本比较复杂,特别是需要把文本控制在某一区域中的时候,2D上下文提供了辅助确定文本大小的方法measureText(str); 返回TextMetrice对象。返回的对象目前只有一个width属性,但将来还会增加更多度量属性。
var fontSize = 100;
context.font = fontSize + ‘px Arial‘;
while(context.measureText(‘Hello world!‘).width > 140) {
fontSize--;
context.font = fontSize + ‘px Arial‘;
}
context.fillText(‘Hello world!‘, 100, 100);
context.fillText(‘Font size is ‘ + fontSize + ‘px‘, 100, 120);
fillText()和strokeText()方法都可以接受第四个参数(maxWidth),也就是文本的最大像素宽度。提供的这个参数后,如果传入的字符串大于最大宽度,则绘制的文本字符的高度正确,但宽度会收缩以适应最大宽度。不过,这个可选的参数尚未得到所有浏览器支持。
5、变换
为绘制上下文应用变换,会导致使用不同的变换矩阵应用处理,从而产生不同的结果。
- rotate(angle); 围绕原点旋转。
- scale(scaleX, scaleY); 缩放图像,在x方向乘以scaleX,在y方向乘以scaleY。scaleX和scaleY的默认值都是1.0。
- translate(x, y); 重置原点。
- transform(m1_1, m1_2, m2_1, m2_2, dx, dy); 修改变换矩阵。
setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy); 将变换矩阵重置为默认状态,然后在调用transform()。
save(); 保存当前上下文状态。 注意:save()方法保存的只是对绘图上下文的设置和变换,不会保存绘图上下文的内容。
- restore(); 返回上一级保存的上下文状态。
6、绘制图像
- drawImage();
根据期望的最终结果不同,调用这个方法时,可以使用三种不同的参数组合。
1、传入一个html< img >元素,以及绘制该图像的起点(x,y坐标)。如下:
// 取得图像
var img = document.images[0];
// 将图像绘制到上下文中
context.drawImage(img, 100, 100);
绘制到画布上的图像与原始大小一样。
2、绘制指定大小的图像。如果想要改变绘制后的图像的大小,可以再多穿如两个参数,分别表示目标宽度和目标高度。通过这种方式来缩放图像并不影响上下文的变换矩阵。如下:
var img = document.images[0];
context.drawImage(img, 100, 100, 30, 30); // 绘制大小为30*30的图像
3、将图像中的某个区域绘制到上下文中。
drawImage()方法的这种调用方式总共需要出入9个参数:
(img, 源图像x, 源图像y, 源图像width, 源图像height, 目标图像x, 目标图像y, 目标图像width, 目标图像height)。
context.drawImage(img, 500, 0, 500, 500, 0, 0, 500, 500);
原始图像的起点为(500, 0),宽和高都是500px。最终绘制到上下文中的图像的起点是(0, 0),而大小变成了500*500px
除了给drawImage()方法传入HTML< img >元素外,还可以传入另一个< canvas >元素作为其第一个参数。这样就可以把另一个画布内容会知道当前画布上。
结合使用drawImage()和其他方法,可以对图像进行各种基本操作。操作结果可以通过toDataURL()方法获得。不过,图像不能来自其他域。如果图像来自其他域,调用toDataURL()会抛出一个错误。例如,位于www.aaa.com上的页面绘制的图像来自于www,bbb,com,当前上下文就会被认为’不干净’,因而会抛出错误。[注意:toDataURL()是< canvas >对象的方法,而不是上下文对象的方法。]
7、阴影
- shadowColor; 阴影颜色
- shadowOffsetX; 形状或路径x轴偏移量
- shadowOffsetY; y轴偏移量
- shadowBlur; 模糊像素。默认0,即不模糊。
这些属性都可以通过context对象修改。只要在绘制之前为它们设置适当的值,就能自动产生阴影。
不同浏览器对阴影的支持有一些差异。
8、渐变
- createLinearGradient(起点x, 起点y, 终点x, 终点y);创建线性渐变。【基于起点的x, y坐标以及宽度和高度值创建渐变对象。】
- createRadialGradient(x1, y1, radius1, x2, y2, radius2);6个参数,分别对应着两个圆的圆心和半径。
- addColorStop(色标位置, CSS颜色值);
渐变有CanvasGradient实例演示,创建一个新的线性渐变,可以调用createLinearGradient()方法。 调用这个方法后,它就会创建一个指定大小的渐变,并返回CanvasGradient对象的实例。创建渐变对象后,下一步就是使用addColorStop()方法来指定色标【色标位置是一个0(开始的颜色)到1(结束的颜色)之间的位数字】。然后把fillStyle或strokeStyle设置为这个对象,从而使用渐变来绘制或描边。
// 1、创建渐变对象
var gradient = context.createLinearGradient(110, 110, 310, 310);
// 2、指定色标
gradient.addColorStop(0, ‘red‘);
gradient.addColorStop(0.5, ‘yellow‘);
gradient.addColorStop(1, ‘blue‘);
// 3、将渐变对象赋给fillStyle或strokeStyle
context.fillStyle = gradient;
context.fillRect(110, 110, 200, 200);
createLinearGradient()基于起点的x, y坐标以及宽度和高度值创建渐变对象,因此我们可以在fillRect()中使用相同的坐标(起点x, 起点y)。如下:
function createLinearGradient(context, x, y, width, height) {
return context.createLinearGradient(x, y, x + width, y + height);
}
var gradient = createLinearGradient(context, 110, 110, 200, 200);
gradient.addColorStop(0, ‘red‘);
gradient.addColorStop(0.5, ‘yellow‘);
gradient.addColorStop(1, ‘blue‘);
context.fillStyle = gradient;
context.fillRect(110, 110, 200, 200);
径向渐变: 可以把径向渐变想象成一个长圆桶,而createRadialGradient()方法的这6个参数定义的就是这个桶的原型开口的位置。
9、模式
模式其实就是重复的图像,可以用来填充或描边图形。
- createPattern(img, str)方法。接收2个参数:一个HTML< img >元素和一个表示如何重复图像的字符串(与CSS的background-repeat属性值相同)。
var img = document.images[0];
pattern = context.createPattern(img, ‘repeat‘);
// context.fillStyle = pattern;
// context.fillRect(100, 100, 300, 300);
context.strokeStyle = pattern;
context.lineWidth = 20;
context.strokeRect(100, 100, 300, 300);
模式与渐变一样,都是从画布的原点(0, 0)开始的。将填充样式(fillStyle)设置为模式对象,只表示在某个特性的区域显示重复的图像,而不是要从某个位置开始绘制重复的图像。
10、使用图像数据
- getImageData(x, y, width, height); 获取图像数据
- putImageData(x, y, width, height); 回写图像数据并显示结果
2D上下文的一个明显的长处就是,可以通过getImageData()取得原始图像数据。这个方法接受4各参数:要取得其数据的画面区域的x和y坐标以及该区域的像素宽度和高度。
var imgData = context.getImageData(10, 5, 50, 50);
这里返回的对象是ImageData的实例。每个ImageData对象都有三个属性:width、height和data。其中data属性是一个数组,保存着图像总每一个像素的数据。在data数组中,每一个像素用4个元素来保存,分别表示红、绿、蓝和透明度值。因此,第一个像素的数据就保存在数组的第0到第3个元素中。
通过修改图像数据,可以像下面这样创建一个简单的灰阶过滤器。如下:
if(drawing.getContext) {
var context = drawing.getContext(‘2d‘);
var img = document.images[0];
var imageData, data, i, len, average, red, green, blue, alpha;
// 绘制原始图像
context.drawImage(img, 0, 0);
// 取得图像数据
imageData = context.getImageData(0, 0, img.width, img.height);
data = imageData.data;
for(i = 0,len = data.length; i < len; i+=4) {
red = data[i];
green = data[i+1];
blue = data[i+2];
alpha = data[i+3];
// 求得rgb平均值
average = Math.floor((red + green + blue) /3 + 10);
// 设置颜色值,透明度不变
data[i] = average;
data[i+1] = average;
data[i+2] = average;
}
// 回写图像数据并显示结果
imageData.data = data;
context.putImageData(imageData, 0, 0);
}
通过操作原始像素值不仅能实现灰阶过滤,还能实现其他功能。
11、合成
- globalAlpha; 指定所有绘制的透明度。(值介于0~1之间,包括0和1)
- globalCompositionOperation; 表示后绘制的图形怎样与先绘制的图形结合。
可能的字符串值: - source-over(默认值); 后绘制的图形位于先绘制的图形上方。
- source-in; 后绘制的图形与之前的图形重叠的部分可见。
- source-out; 后绘制的图形与之前的图形不重叠的部分可见。
- source-atop; 后绘制的图形与之前的图形重叠的部分可见,但先绘制的图形不受影响。
- destination-over; 后绘制的图形位于先绘制的图形下方。
- destination-in;
- destination-out;
- destination-atop; 后绘制的图形位于先绘制的图形的下方,在两者不重叠的地方,先绘制的图形变透明。
- lighter; 后绘制的图形与先绘制的图形重叠部分的值相加,使该部分变亮。
- copy; 后绘制的图形完全替代与之重叠
- 的先绘制图形。
- xor; 后绘制的图形与先绘制的图形重叠的部分执行“异步”操作。
三、WebGL
WebGL是针对Canvas的3D上下文。与其他Web技术不同,WebGL并不是W3C制定的标准,而是有Khronos Group制定的。
Khtonos Group也设计了其他图形处理API,比如OpenGL ES 2.0。
…此处省略…
四、context绘图上下文对象的canvas属性
canvas属性; 返回当前绘图上下文对象所属的canvas对象
以上是关于canvas的主要内容,如果未能解决你的问题,请参考以下文章
Android UICanvas 画布 ⑨ ( Canvas 绘图坐标系平移实例 )
Android UICanvas 画布 ⑧ ( Canvas 绘图坐标系 2x2 矩阵 | Canvas 绘图坐标系 3x3 操作矩阵 )