canvas 元素负责在页面中设定一个区域,然后就可以通过 JavaScript 动态地在这个区域中绘制图形。
襄汾网站建设公司成都创新互联,襄汾网站设计制作,有大型网站制作公司丰富经验。已为襄汾数千家提供企业网站建设服务。企业网站搭建\成都外贸网站建设要多少钱,请找那个售后服务好的襄汾做网站的公司定做!
要使用 canvas 元素,必须先设置其 width 和 height 属性,指定可以绘图的区域大小。出现在开始和结束标签中的内容是后备信息,如果浏览器不支持 canvas 元素,就会显示这些信息。
如果不添加任何样式或者不绘制任何图形,在页面中是看不到该元素的。
要在这块画布(canvas)上绘图,需要取得绘图上下文。而取得绘图上下文对象的引用,需要调用getContext() 方法并传入上下文的名字。传入 "2d" ,就可以取得 2D 上下文对象。
使用 toDataURL() 方法,可以导出在 canvas 元素上绘制的图像。这个方法接受一个参数,即图像的 MIME 类型格式,而且适合用于创建图像的任何上下文。
取得画布中的一幅 PNG 格式的图像:
如果绘制到画布上的图像源自不同的域, toDataURL() 方法会抛出错误。
使用 2D 绘图上下文提供的方法,可以绘制简单的 2D 图形,比如矩形、弧线和路径。2D 上下文的坐标开始于 canvas 元素的左上角,原点坐标是(0,0)。
2D 上下文的两种基本绘图操作是填充和描边。填充,就是用指定的样式(颜色、渐变或图像)填充图形;描边,就是只在图形的边缘画线。大多数 2D 上下文操作都会细分为填充和描边两个操作,而操作的结果取决于两个属性: fillStyle 和 strokeStyle 。
这两个属性的值可以是字符串、渐变对象或模式对象,而且它们的默认值都是 "#000000" 。如果为它们指定表示颜色的字符串值,可以使用 CSS 中指定颜色值的任何格式,包括颜色名、十六进制码、rgb 、 rgba 、 hsl 或 hsla 。
与矩形有关的方法包括 fillRect() 、strokeRect() 和 clearRect() 。这三个方法都能接收 4 个参数:矩形的 x 坐标、矩形的 y 坐标、矩形宽度和矩形高度。这些参数的单位都是像素。
fillRect() 方法在画布上绘制的矩形会填充指定的颜色。填充的颜色通过 fillStyle 属性指定:
strokeRect() 方法在画布上绘制的矩形会使用指定的颜色描边。描边颜色通过 strokeStyle 属性指定。
描边线条的宽度由 lineWidth 属性控制,该属性的值可以是任意整数。另外,通过 lineCap 属性可以控制线条末端的形状是平头、圆头还是方头( "butt" 、"round" 或 "square" ),通过 lineJoin 属性可以控制线条相交的方式是圆交、斜交还是斜接( "round" 、 "bevel" 或 "miter" )。
clearRect() 方法用于清除画布上的矩形区域。本质上,这个方法可以把绘制上下文中的某一矩形区域变透明。
通过路径可以创造出复杂的形状和线条。要绘制路径,首先必须调用 beginPath() 方法,表示要开始绘制新路径。然后,再通过调用下列方法来实际地绘制路径。
如果想绘制一条连接到路径起点的线条,可以调用closePath() 。如果路径已经完成,你想用 fillStyle 填充它,可以调用 fill() 方法。另外,还可以调用 stroke() 方法对路径描边,描边使用的是 strokeStyle 。最后还可以调用 clip() ,这个方法可以在路径上创建一个剪切区域。
绘制一个不带数字的时钟表盘:
isPointInPath() 方法接收 x 和 y 坐标作为参数,用于在路径被关闭之前确定画布上的某一点是否位于路径上。
绘制文本主要有两个方法: fillText() 和 strokeText() 。这两个方法都可以接收 4 个参数:要绘制的文本字符串、x 坐标、y 坐标和可选的最大像素宽度。
两个方法都以下列 3 个属性为基础:
fillText() 方法使用fillStyle 属性绘制文本, strokeText() 方法使用 strokeStyle 属性为文本描边。
通过上下文的变换,可以把处理后的图像绘制到画布上。2D 绘制上下文支持各种基本的绘制变换。创建绘制上下文时,会以默认值初始化变换矩阵,在默认的变换矩阵下,所有处理都按描述直接绘制。为绘制上下文应用变换,会导致使用不同的变换矩阵应用处理,从而产生不同的结果。
把原点变换到表盘的中心:
使用 rotate() 方法旋转时钟的表针:
可以调用 save() 方法,调用这个方法后,当时的所有设置都会进入一个栈结构,得以妥善保管。调用 restore() 方法,在保存设置的栈结构中向前返回一级,恢复之前的状态。
save() 方法保存的只是对绘图上下文的设置和变换,不会保存绘图上下文的内容。
可以使用 drawImage()方法把一幅图像绘制到画布上。
以使用三种不同的参数组合。最简单的调用方式是传入一个 HTML img 元素,以及绘制该图像的起点的 x 和 y 坐标。
如果想改变绘制后图像的大小,可以再多传入两个参数,分别表示目标
宽度和目标高度。通过这种方式来缩放图像并不影响上下文的变换矩阵。
绘制出来的图像大小会变成 20×30 像素。
可以选择把图像中的某个区域绘制到上下文中。 drawImage() 方法的这种调用方式总共需要传入 9 个参数:要绘制的图像、源图像的 x 坐标、源图像的 y 坐标、源图像的宽度、源图像的高度、目标图像的 x 坐标、目标图像的 y 坐标、目标图像的宽度、目标图像的高度。这样调用drawImage() 方法可以获得最多的控制。
2D 上下文会根据以下几个属性的值,自动为形状或路径绘制出阴影。
要创建一个新的线性渐变,可以调用 createLinearGradient() 方法。这个方法接收 4 个参数:起点的 x 坐标、起点的 y 坐标、终点的 x 坐标、终点的 y 坐标。调用这个方法后,它就会创建一个指定大小的渐变,并返回
CanvasGradient 对象的实例。
创建了渐变对象后,下一步就是使用 addColorStop() 方法来指定色标。这个方法接收两个参数:色标位置和 CSS 颜色值。色标位置是一个 0(开始的颜色)到 1(结束的颜色)之间的数字。
为了让渐变覆盖整个矩形,而不是仅应用到矩形的一部分,矩形和渐变对
象的坐标必须匹配才行。
要创建径向渐变(或放射渐变),可以使用 createRadialGradient() 方法。这个方法接收 6 个参数,对应着两个圆的圆心和半径。前三个参数指定的是起点圆的原心(x 和 y)及半径,后三个参数指定的是终点圆的原心(x 和 y)及半径。
模式其实就是重复的图像,可以用来填充或描边图形。要创建一个新模式,可以调用createPattern() 方法并传入两个参数:一个 HTML img 元素和一个表示如何重复图像的字符串。其中,第二个参数的值与 CSS 的 background-repeat 属性值相同,包括 "repeat" 、 "repeat-x" 、"repeat-y" 和 "no-repeat" 。
createPattern() 方法的第一个参数也可以是一个 video 元素,或者另一个 canvas 元素。
2D 上下文的一个明显的长处就是,可以通过 getImageData() 取得原始图像数据。这个方法接收4 个参数:要取得其数据的画面区域的 x 和 y 坐标以及该区域的像素宽度和高度。
取得左上角坐标为(10,5)、大小为 50×50 像素的区域的图像数据:
返回的对象是 ImageData 的实例。每个 ImageData 对象都有三个属性: width 、 height 和data 。其中 data 属性是一个数组,保存着图像中每一个像素的数据。
在 data 数组中,每一个像素用4 个元素来保存,分别表示红、绿、蓝和透明度值。
数组中每个元素的值都介于 0 到 255 之间(包括 0 和 255)。
还有两个会应用到 2D 上下文中所有绘制操作的属性: globalAlpha 和 globalCompositionOperation 。其中, globalAlpha 是一个介于 0 和 1 之间的值(包括 0和 1),用于指定所有绘制的透明度。默认值为 0。如果所有后续操作都要基于相同的透明度,就可以先把 globalAlpha 设置为适当
值,然后绘制,最后再把它设置回默认值 0。
第二个属性 globalCompositionOperation 表示后绘制的图形怎样与先绘制的图形结合。
WebGL 是针对 Canvas 的 3D 上下文。
WebGL是从 OpenGL ES 2.0 移植到浏览器中的,而 OpenGL ES 2.0 是游戏开发人员在创建计算机图形图像时经常使用的一种语言。WebGL 支持比 2D 上下文更丰富和更强大的图形图像处理能力。
WebGL 涉及的复杂计算需要提前知道数值的精度,而标准的 JavaScript 数值无法满足需要。为此,WebGL 引入了一个概念,叫类型化数组(typed arrays)。类型化数组也是数组,只不过其元素被设置为特定类型的值。
类型化数组的核心就是一个名为 ArrayBuffer 的类型。每个 ArrayBuffer 对象表示的只是内存中指定的字节数,但不会指定这些字节用于保存什么类型的数据。通过 ArrayBuffer 所能做的,就是为了将来使用而分配一定数量的字节。
创建了 ArrayBuffer 对象后,能够通过该对象获得的信息只有它包含的字节数,方法是访问其byteLength 属性:
使用 ArrayBuffer (数组缓冲器类型)的一种特别的方式就是用它来创建数组缓冲器视图。其中,最常见的视图是 DataView ,通过它可以选择 ArrayBuffer 中一小段字节。为此,可以在创建 DataView实例的时候传入一个 ArrayBuffer 、一个可选的字节偏移量(从该字节开始选择)和一个可选的要选择的字节数。
实例化之后, DataView 对象会把字节偏移量以及字节长度信息分别保存在 byteOffset 和byteLength 属性中。
类型化视图一般也被称为类型化数组,因为它们除了元素必须是某种特定的数据类型外,与常规的数组无异。
类型化数组是 WebGL 项目中执行各种操作的重要基础。
目前,主流浏览器的较新版本大都已经支持 canvas 标签。同样地,这些版本的浏览器基本上也都支持 2D 上下文。但对于 WebGL 而言,目前还只有 Firefox 4+和 Chrome 支持它。
一、.获取上下文对象
var cxt = document.getElementById(‘元素名’).getContect(‘2d’);
IE8或更早的浏览器不支持元素。
二、 drawClock() – 实现画时钟
1. clearRect() 清空给定矩形内的指定像素。
context.clearRect(x,y,width,height);
属性 | 值
-----|------------
x,y | 要清除的矩形左上角点的(x,y)坐标
width,height| 要清除的矩形宽度和高度,单位为像素12345
2.new Date() — 得到系统时间
var sec = now.getSeconds(); var min = now.getMinutes(); var hour = now.getHours(); 123
3.画时钟的形状
cxt.beginPath(); cxt.lineWidth = 10; cxt.strokeStyle = "blue"; cxt.arc(550, 310, 300, 0, 360, false); cxt.closePath(); cxt.stroke(); 123456
beginPath()的作用是canvas的绘制方法,都会以上一次beginPath之后的所有路径为基础进行绘制。
closepath()是关闭路径,而不是结束路径,它会试图从当前路径的终点连一条路径到七、起点,让整个路径闭合起来。
cxt.lineWidth() : 画笔的宽度
cxt.strokeStyle() : 设置或返回用于笔触的颜色、渐变或模式。
属性值:color 指示绘图笔触颜色的 CSS 颜色值。默认值是 #000000。
gradient 用于填充绘图的渐变对象(线性或放射性)
pattern 用于创建 pattern 笔触的 pattern 对象
stroke ()绘制已定义的路径
arc() 方法创建弧/曲线(用于创建圆或部分圆)。如需通过 arc() 来创建圆,请把起始角设置为 0,结束角设置为 2*Math.PI。
context.arc(x,y,r,sAngle,eAngle,counterclockwise);
参数
描述
x 圆的中心的 x 坐标。
y 圆的中心的 y 坐标。
r 圆的半径。
sAngle 起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
eAngle 结束角,以弧度计。
counterclockwise 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。
4)drawScale — 自定义函数画刻度
function drawScale(size, width, color, value, startx, starty, endx, endy){
for(var i = 0; i size; i++){
drawPointer(width, color, value, i, startx, starty, endx, endy);
} } 12345
5. 画时钟刻度依托点
function drawPointer(width, color, value, angle, startx, starty, endx, endy){
cxt.save(); //先保存当前画布
cxt.lineWidth = width; //设置画笔的宽度
cxt.strokeStyle = color; //设置画笔的颜色
cxt.translate(550, 310); //重置异次元空间的原点坐标
cxt.rotate(value * angle * Math.PI / 180); //设置旋转的角度,参数是弧度
cxt.beginPath();
cxt.moveTo(startx, starty);
cxt.lineTo(endx, endy);
cxt.closePath(); //先闭合路径,再画线
cxt.stroke(); //开始画线
cxt.restore(); //将旋转后的线段返回给画布 } 12345678910111213
translate() 方法重新映射画布上的 (0,0) 位置。
-
JS代码如下:
//获取上下文文档对象 var clock = document.getElementById('clock');
var cxt = clock.getContext('2d');
//画指针 function drawPointer(width, color, value, angle, startx, starty, endx, endy){
cxt.save(); //先保存当前画布
cxt.lineWidth = width; //设置画笔的宽度
cxt.strokeStyle = color; //设置画笔的颜色
cxt.translate(550, 310); //重置异次元空间的原点坐标
cxt.rotate(value * angle * Math.PI / 180); //设置旋转的角度,参数是弧度
cxt.beginPath();
cxt.moveTo(startx, starty);
cxt.lineTo(endx, endy);
cxt.closePath(); //先闭合路径,再画线
cxt.stroke(); //开始画线
cxt.restore(); //将旋转后的线段返回给画布 }
//画刻度 function drawScale(size, width, color, value, startx, starty, endx, endy){
for(var i = 0; i size; i++){
drawPointer(width, color, value, i, startx, starty, endx, endy);
}
}
//为表盘的中心填充颜色 function drawFill(){
cxt.save();
cxt.beginPath();
cxt.arc(550, 310, 7, 0, 360, false);
cxt.closePath();
cxt.fillStyle = "red";
cxt.fill();
cxt.restore();
}
//画时钟 function drawClock(){
cxt.clearRect(0, 0, 1350, 620); //清空整个画布
var now = new Date(); //获取系统时间,取出时,分,秒
var sec = now.getSeconds();
var min = now.getMinutes();
var hour = now.getHours();
min += sec / 60;
hour += min / 60;
if(hour 12) hour -= 12;
cxt.beginPath();
cxt.lineWidth = 10;
cxt.strokeStyle = "blue";
cxt.arc(550, 310, 300, 0, 360, false);
cxt.closePath();
cxt.stroke();
drawScale(12, 7, "pink", 30, 0, -280, 0, -260); //画时刻度
drawScale(60, 5, "pink", 6, 0, -280, 0, -270); //画分刻度
drawPointer(7, "purple", hour, 30, 0, 12, 0, -210); //画时针
drawPointer(5, "yellow", min, 6, 0, 15, 0, -240); //画分针
drawPointer(4, "red", sec, 6, 0, 17, 0, -250); //画秒针
//细化秒针,为秒针加箭头
drawPointer(3, "red", sec, 6, -7, -235, 0, -255);
drawPointer(3, "red", sec, 6, 7, -235, 0, -255);
drawFill();
}
drawClock();
setInterval(drawClock, 1000); //setInterval()方法中表示每隔1000ms,就执行drawClock一次 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
!DOCTYPE htmlhtml head meta http-equiv="content-type" content="text/html; charset=utf-8" / style type="text/css" canvas{ border: 1px solid black; background-color: #fff; } /style /head body canvas id="canvas" width="500" height="500" /canvas /body script type = "text/javascript" var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); var CENTROID_RADIUS = 10, CENTROID_STROKE_STYLE = "rgba(0,0,0,0.5)", CENTROID_FILL_STYLE = "rgba(80,190,240,0.6)"; var RING_INNER_RADIUS = 35, RING_OUTER_RADIUS = 55; var ANNOTATION_FILL_STYLE = "rgba(0,0,230,0.9)", ANNOTATION_TEXT_SIZE = 12; var TICK_WIDTH = 10, TICK_LONG_STROKE_STYLE = "rgba(100,140,230,0.9)", TICK_SHORT_STROKE_STYLE = "rgba(100,140,230,0.7)"; var TRACKING_DIAL_STROKING_STYLE = "rgba(100,140,230,0.5)"; var GUIDEWIRE_STROKE_STYLE = "goldenrod", GUIDEWIRE_FILL_STYLE = "rgba(250,250,0,0.6)"; var circle ={ x : canvas.width/2, y : canvas.height/2, radius : 150 }; var SEC_HAND_LONG = circle.radius + RING_OUTER_RADIUS, MIN_HAND_LONG = SEC_HAND_LONG*(2/3), HOUR_HAND_LONG = SEC_HAND_LONG/3; //Functions------------------------------------------------ //绘制仪表中心的小圆 function drawCentroid(){ context.save(); context.beginPath(); context.strokeStyle = CENTROID_STROKE_STYLE; context.fillStyle = CENTROID_FILL_STYLE; context.arc(circle.x,circle.y,CENTROID_RADIUS,0,Math.PI*2,false); context.stroke(); context.fill(); context.restore(); } //利用非零环绕规则,绘制剪纸效果的仪表外框(圆环) function drawRing (){ context.save(); //顺时针绘制外围圆 context.shadowColor = "rgba(0,0,0,0.7)"; context.shadowOffsetX = 3; context.shadowOffsetY = 3; context.shadowBlur = 6; context.strokeStyle = TRACKING_DIAL_STROKING_STYLE; context.beginPath(); context.arc(circle.x,circle.y,circle.radius+RING_OUTER_RADIUS,0,Math.PI*2,false); context.stroke(); //逆时针绘制内圈 context.strokeStyle = "rgba(0,0,0,0.1)"; context.arc(circle.x,circle.y,circle.radius+RING_INNER_RADIUS,0,Math.PI*2,true); context.fillStyle = "rgba(100,140,230,0.1)"; context.fill(); context.stroke(); context.restore(); } //绘制恰好与长刻度线相交的,内部的圆 function drawTickInnerCircle(){ context.save(); context.beginPath(); context.strokeStyle = "rgba(0,0,0,0.1)"; context.arc(circle.x,circle.y,circle.radius + RING_INNER_RADIUS-TICK_WIDTH,0,Math.PI*2,false); context.stroke(); context.restore(); } //绘制仪表刻度(包括长刻度,短刻度) function drawTicks(){ var radius = circle.radius + RING_INNER_RADIUS, ANGLE_MAX = Math.PI*2, ANGLE_DELTA = Math.PI/64, tickWidth; //利用度数做循环 //cnt用于计算数目 for(var angle = 0,cnt = 0; angle ANGLE_MAX; angle = angle + ANGLE_DELTA, cnt++){ drawTick(angle,radius,cnt); } //利用半径与半径与x轴夹角绘制单个刻度 function drawTick(angle,radius,cnt){ var tickWidth; context.save(); if(cnt%4 === 0){ tickWidth = TICK_WIDTH; context.strokeStyle = TICK_LONG_STROKE_STYLE; }else{ tickWidth = TICK_WIDTH/2; context.strokeStyle = TICK_SHORT_STROKE_STYLE; } context.beginPath(); context.moveTo( circle.x+Math.cos(angle)*(radius-tickWidth), circle.y+Math.sin(angle)*(radius-tickWidth) ); context.lineTo( circle.x+Math.cos(angle)*(radius), circle.y+Math.sin(angle)*(radius) ); context.stroke(); context.restore(); } } //绘制表盘文字 function drawAnnotations(){ var radius = circle.radius +RING_INNER_RADIUS; context.save(); context.textAlign = "center"; context.textBaseline = "middle"; context.font = ANNOTATION_TEXT_SIZE + "px Helvetial"; context.fillStyle = ANNOTATION_FILL_STYLE; for(var angle=0; angleMath.PI*2; angle= angle+Math.PI/8 ){ context.beginPath(); context.fillText( (angle*180/Math.PI).toFixed(0), circle.x+Math.cos(angle)*(radius-TICK_WIDTH*2), circle.y+Math.sin(angle)*(radius-TICK_WIDTH*2) ); } context.restore(); } //绘制指针 function drawPointHand(angle,handLong){ var endpt = { x:circle.x+handLong*Math.cos(angle), y:circle.y+handLong*Math.sin(angle) }; context.save(); context.strokeStyle = GUIDEWIRE_STROKE_STYLE; context.fillStyle = GUIDEWIRE_FILL_STYLE; //绘制针柄 context.beginPath(); context.moveTo(circle.x,circle.y); context.lineTo(endpt.x,endpt.y); context.stroke(); //绘制针头(圆) context.beginPath(); context.strokeStyle = TICK_LONG_STROKE_STYLE; context.arc(endpt.x,endpt.y,5,0,Math.PI*2,false); context.stroke(); context.fill(); context.restore(); }//Init----------------------------------------------------- drawCentroid(); drawRing(); drawTicks(); drawTickInnerCircle(); drawAnnotations(); drawPointHand(Math.PI/3,SEC_HAND_LONG); /script/html