canvas基础:canvas的属性、方法以及基本运用 您所在的位置:网站首页 canva的中文意思 canvas基础:canvas的属性、方法以及基本运用

canvas基础:canvas的属性、方法以及基本运用

2023-08-13 03:14| 来源: 网络整理| 查看: 265

一、canvas元素的属性

属性描述默认值widthcanvas元素绘图表面的宽度。在默认情况下,浏览器会将canvas元素的大小设定成与绘图表面大小一致。然而,如果在css中覆写了元素的大小,那么浏览器则会将绘图表面进行缩放,使之符合元素尺寸300heightcanvas元素绘图表面的高度。浏览器可能会将绘图表面缩放至与元素相同的尺寸。具体请参照对width的描述。150

注:按照规范,不能给数值加px后缀。

二、canvas元素的方法

属性描述getContext()返回与该canvas元素相关的绘图环境对象。每个canvas元素均有一个这样的环境对象,而且每个环境对象均与一个canvas元素相关联toDataURL(type,quality)返回一个数据地址(data URL),你可以将它设定为ing元素的src属性值。第一个参数制定了图像的类型,例如image/jpeg或者image/png,如果不指定,则默认使用image/png。第二个参数必须是0~01.0之间的double值,他表示JPEG图像的显示质量。注:quality越大,图片的质量越高。且只适用于image/jpeg类型的图片,image/png类型都是以高质量图片得形式展示。toBlob(callback,type,args……)

创建一个用于表示canvas元素图像文件的Blob,第一个参数是一个回调函数,浏览器会以一个指向blob的引用为参数,去调用该回调函数。第二个参数以“image/png”这样的形式来制定图像类型。如果不指定,则默认使用“image/png”。最后一个参数是介于0.0~1.0之间的值,表示JPEG图片的质量。将来可可能会加入其它一些用于精确调控图像属性的参数。

用一个例子对toDataURL做一个介绍:

canvas .imgContent{ height:auto; } .imgContent img{ width:300px; height: 150px; float:left; margin-right:20px; } 该浏览器不支持canvas! var myCanvas = document.getElementById('canvas'); var context = myCanvas.getContext('2d'); context.font="38px Arial"; context.fillStyle="blue"; context.strokeStyle="green"; context.textAlign = 'center'; context.textBaseline = 'bottom'; context.fillText('Hello,canvas!',myCanvas.width/2, myCanvas.height/2) context.strokeText('Hello,canvas!',myCanvas.width/2+20, myCanvas.height/2+50) var fullQuality = canvas.toDataURL("image/jpeg", 1.0); var mediumQuality = canvas.toDataURL("image/jpeg", 0.5); var lowQuality = canvas.toDataURL("image/jpeg", 0.1); document.getElementById('img1').setAttribute("src",fullQuality); document.getElementById('img2').setAttribute("src",mediumQuality); document.getElementById('img3').setAttribute("src",lowQuality);

得到的三张quality分别为1.0,0.5,0.1的jpeg图片,质量如下:

三、canvas的绘图环境

1.2d绘图环境

以下是2d绘图环境的全部属性,后续章节会具体介绍。

属性简介canvas指向该环境所属的canvas对象。该属性最常见的用途是通过它来获取canvas的高度和宽度,分别调用context.canvas.width和context.canvas.height即可fillStyle制定该绘图环境在后续的图像填充操作中所使用的颜色、渐变色或图案font设定在调用绘图环境对应的fillText()或strokeText()方法时,所使用的字型,eg:context.font = 'bold 35px Arial';globalAlpha全局透明度设定,它可以取0(完全透明)~1.0(完全不透明)之间的值,浏览器会将每个元素的alpha值与该值相乘,在绘制图像时也是如此globalCompsiteOperation该值决定了浏览器将某个物体绘制在其他物体之上时,所采用的绘制方式。后续详细介绍有效值。lineCap该值告诉浏览器如何绘制线的端点。可取值:butt、round、square。默认值是butt。lineWidth该值决定了再canvas之中绘制线段的屏幕像素宽度。它必须是个非负、非无穷的double值。默认值是1.0。lineJoin告诉浏览器在两条线段相交时如何绘制焦点。可取值:bevel、round、miter。默认值是miter。miterLimit告诉浏览器如何绘制miter形式的线段焦点。shadowBlur该值决定了浏览器如何延伸阴影效果。值越高,阴影效果延伸得就越远。盖值不是指阴影的像素长度,而是代表高斯模糊方程式中的参数值,他必须是一个非负且非无穷量的double值,默认值是0。shadowColor该值告诉浏览器使用何种颜色来绘制阴影。通常采用半透明色的色作为该属性的值,以便让后面的背景颜色能显示出来。shadowOffsetX以像素为单位,指定了阴影效果的水平方向偏移量shadowOffsetY以像素为单位,指定了阴影效果的垂直方向偏移量strokeStyle

指定了对路径进行描边时所采用的绘制风格。该值可被设定为某个颜色、渐变色或图案。

textAlign决定了fillText()或strokeText()方法进行绘制时,所画文本的水平对齐方式textBaseline决定了fillText()或strokeText()方法进行绘制时,所画文本的垂直对齐方式

2.3d绘图环境WebGL

      非常酷炫的功能,这里暂且不做介绍。

四、Canvas状态的保存和恢复

       绘图环境的save()方法会将当前的绘图环境压入堆栈顶部。对应的restore()方法则会从堆栈顶部弹出一组状态信息,并据此恢复当前绘图环境的各个状态。这意味着我们可以嵌套式的调用save()/restore()方法。

方法描述save()

将当前canvas的状态推送到一个保存canvas装套的堆栈顶部。canvas状态包括了当前的坐标变换信息、剪辑区域以及所有canvas绘制环境对象的属性,包括strokeStyle、fillStyle与globalCompsiteOperation等。

canvas状态并不包括当前的路径或位图。只能通过beginPath()来重置路径。至于位图,他是canvas本身的一个属性,并不属于绘图环境对象。

注:尽管位图是canvas对象本身的属性,然而也可以通过绘图环境对象来访问它(在环境对象上调用getImageData()方法)

restore()将canvas当前的状态堆栈顶部的条目弹出。原来保存于栈顶部的那一组状态,在弹出之后,就被设置成canvas当前的状态了。在调用save()和restore()方法之间,对canvas状态所进行的修稿,起效果只会持续至restore()方法被调用之前。

eg:

canvas 该浏览器不支持canvas! var myCanvas = document.getElementById('canvas'); var context = myCanvas.getContext('2d'); context.font="25px Arial"; context.fillStyle="blue"; context.strokeStyle="green"; context.fillText('Hello,canvas!',myCanvas.width/3, myCanvas.height/3) context.strokeText('Hello,canvas!',myCanvas.width/3+20, myCanvas.height/3+30) context.save();//保存当前绘制参数,用于下一次绘制 //选择新的颜色来绘制文字 context.fillStyle="red"; context.strokeStyle="yellow"; context.fillText('Hello,canvas2!',myCanvas.width/3+40, myCanvas.height/3+90); context.strokeText('Hello,canvas2!',myCanvas.width/3+60, myCanvas.height/3+110) context.restore();//取出之前的状态,重新绘制文字,不需要再重新定义绘制颜色 context.fillText('Hello,canvas3!',myCanvas.width/3, myCanvas.height/3+150); context.strokeText('Hello,canvas3!',myCanvas.width/3+20, myCanvas.height/3+170)

效果图:

五、canvas画图实践、基本操作练习

1、canvas一些基本操作的简介:

画直线 :moveTo移动到某一点准备状态 ,lineTo线的下一个点坐标, stroke() 绘制信号

//绘制一条由坐标(50,50)至坐标(100,100),再到坐标(50,150)的宽度为10的红色线,这里绘制了两条直线,下一条的起点恰好是上一条的终点 ctx.moveTo(50,50); ctx.lineTo(100,100); ctx.lineTo(50,150); ctx.lineWidth = "10"; ctx.strokeStyle = "red"; ctx.stroke();

画折线:

beginPath()开始全新的绘制, closePath()绘制结束-闭合

填充与绘制的区别: fill(), stroke(), fillStyle ,strokeStyle

ctx.beginPath(); ctx.moveTo(100,50); ctx.lineTo(150,100); ctx.lineTo(100,150); ctx.lineWidth = "2";//默认是1 ctx.strokeStyle="blue"; ctx.closePath();//将折线闭合 ctx.stroke(); ctx.beginPath(); ctx.moveTo(200,50); ctx.lineTo(250,100); ctx.lineTo(150,150); ctx.lineWidth = "2"; ctx.fillStyle="red"; ctx.closePath();//将折线闭合 ctx.fill(); //stroke只画边,与strokeStyle配套使用,fill将整个图形填充,与fillStyle配套使用

画矩形

1、设置填充样式或者边框样式(ctx.fillStyle = "color";或者ctx.strokeStyle = "color";) 2、绘制矩形区域(如果采用fillRect或者strokeRect绘制矩形,可以省略第3步); 3、填充或者加上边框(ctx.fill();或者ctx.stroke();)  

ctx.rect(50,50,100,100); ctx.fillStyle = "green"; ctx.strokeStyle = "red"; ctx.fill(); ctx.stroke();

画圆弧

1、设置填充样式或者边框样式(ctx.fillStyle = "color";或者ctx.strokeStyle = "color";)

2、绘制圆形区域 ctx.arc(x,y,r,startAngle,endAngle,boolean); r代表半径,startAngle,endAngle分别代表开始角度和结束角度,最后一个参数表示true(逆时 针),false(顺时针)

3、填充或者加上边框(ctx.fill();或者ctx.stroke();)

注:1、在绘制圆弧的时候,必须使用ctx.beginPath()开始和ctx.closePath()结束,当然,前提 条件时你要画规则的图形。

//用两个嵌套的圆来绘制一个月亮 ctx.beginPath(); ctx.arc(200,200,80,0,Math.PI*2,false); ctx.fillStyle="yellow"; ctx.fill(); ctx.closePath(); ctx.beginPath(); ctx.arc(160,200,70,0,Math.PI*2,false); ctx.fillStyle="white"; ctx.fill();

 

绘制文字:

ctx.fillStyle = "color";或者ctx.strokeStyle = "color";

ctx.textBaseline = "";设置垂直对齐方式 ctx.textAlign = "";

设置水平对齐方式 ctx.fillText("文本",x,y)(实心字)或者ctx.strokeText("文本",x,y)(字的轮廓);

textBaseLine 文本基线:可取值为alphabetic, top, hanging, middle ,ideographic, bottom。

 textAlign为当前对齐方式:可取取为 start ,end, center ,left ,right。

 绘制贝塞尔曲线:

1、绘制二次样条曲线 :

context.quadraticCurveTo(qcpx,qcpy,qx,qy) :

qcpx:二次样条曲线控制点x坐 标 ,qcpy:二次样条曲线控制点y坐标,qx:二次样条曲线终点x坐标,qy:二次样条曲线终点y坐标。

2、绘制三次样条曲线 :

context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y):

cp1x:第一个控制点x坐标, cp1y:第一个控制点y坐标, cp2x:第二个控制点x坐标,cp2y:第二个控制点 y坐标,x:终点x坐标 ,y:终点y坐标。 该知识点比较复杂,推荐一篇写的比较好的博客:https://www.cnblogs.com/wxydigua/p/4204254.html

 

渐变

线性渐变: var lg= context.createLinearGradient(xStart,yStart,xEnd,yEnd)

                         lg.addColorStop(offset,color);

         xStart:渐变起点的x坐标

         yStart:渐变起点的y坐标

         xEnd:渐变起点的x坐标

         yEnd:渐变起点的y坐标

        offset:设定的颜色离渐变结束点的偏移量(0~1)

        color:绘制时要使用的颜色

var lg=ctx.createLinearGradient(0,0,200,200); lg.addColorStop(0,"red"); lg.addColorStop(0.5,"green"); lg.addColorStop(1,"blue"); ctx.fillStyle = lg; ctx.fillRect(0,0,200,200);

径向渐变: var rg=context.createRadialGradient(xStart,yStart,radiusStart,xEnd,yEnd,radiusEnd)

                          rg.addColorStop(offset,color)

         xStart:发散开始圆心x坐标

         yStart:发散开始圆心y坐标

         radiusStart:发散开始圆的半径

         xEnd:发散 结束圆心的x坐标

         yEnd:发散结束圆心的y坐标

         radiusEnd:发散结束圆的半径

         offset:设定的颜色离渐变结束点的偏移量(0~1)

         color:绘制时要使用的颜色

var grd=ctx.createRadialGradient(300,150,10,300,150,150); grd.addColorStop(0,"red"); grd.addColorStop(0.5,"yellow"); grd.addColorStop(1,"white"); ctx.fillStyle = grd; ctx.fillRect(0,0,600,300); ctx.fill();

 

 

图片背景

运用createPattern方法 :createPattern(image, repetitionStyle)

repetitionStyle可取值:"repeat" - 在各个方向上都对图 像贴图。默认值。 "repeat-x" - 只在 X 方向上贴图。 "repeat-y" - 只在 Y 方向上贴图。 "no-repeat" - 不贴图,只使用它一次。

var backgroundImg = new Image(); backgroundImg.src = "./picture/canvas1.jpg"; backgroundImg.onload = function (){ var bakImg = ctx.createPattern(backgroundImg,"repeat"); ctx.fillStyle = bakImg; ctx.fillRect(0,0,600,300); }

 

图形阴影

ctx.shadowOffsetX :阴影距形状的水平距离

ctx.shadowOffsetY: 阴影距形状的垂直距离

ctx.shadowBlur阴影的模糊级别,值越大则越模糊

ctx.shadowColor = "red",设置阴影颜色

ctx.arc(200,200,50,0,Math.PI*2,false); ctx.fillStyle="red"; ctx.shadowOffsetX = 15; ctx.shadowOffsetY = 15; ctx.shadowBlur = 10; ctx.shadowColor = "gray"; ctx.fill();

图形变形

平移 、缩放 、旋转: ralate, scale ,rotate。原理与css的一致。  

ctx.translate(100,100); ctx.rotate(Math.PI/6); ctx.fillStyle="red"; ctx.fillRect(0,0,150,100);

 

图形组合

 在绘制完成第一个图形之后,加

 context.globalCompositeOperation=type

再接着绘制第二个图形

type:

    source-over(默认值):在原有图形上绘制新图形

    destination-over:在原有图形下绘制新图形

    source-in:显示原有图形和新图形的交集,新图形在上,所以颜色为新图形的颜色

    destination-in:显示原有图形和新图形的交集,原有图形在上,所以颜色为原有图形的颜色

    source-out:只显示新图形非交集部分

    destination-out:只显示原有图形非交集部分,是将交集的部分转化为透明

    source-atop:显示原有图形和交集部分,新图形在上,所以交集部分的颜色为新图形的颜色

    destination-atop:显示新图形和交集部分,新图形在下,所以交集部分的颜色为原有图形的颜 色

     lighter:原有图形和新图形都显示,交集部分做颜色叠加

     xor:重叠飞部分不现实

     copy:只显示新图形  

2、下面进行一些实践练习,我们通过绘制一个时钟来练习canvas。

既然要画时钟,要画圆,我们先要了解一些关于canvas画布的规律,如下图所示:

即以坐标轴的x轴正方向为起点,顺时针方向开始,依次是0度,90度,180度,270度,360度(0度),y轴正方向(270度)也可以说是-90度,此时时钟的0点(12点)就在这个位置。有了这些基本知识,我们可以开始简单绘制一个时钟。

canvas 该浏览器不支持canvas! 电子时钟: var myCanvas = document.getElementById('canvas'); var context = myCanvas.getContext('2d'); var Radius=200,//圆圈的半径 FontSize=20,//字体大小 space=20,//为了让数字里圆圈有一定的距离,要给一个间距 HourLength=80,//时针的长度 MinuteLength=130,//分针的长度 SecondLength=160;//秒针的长度 var eleClockValue=''//电子时钟的时刻 function drawCircle(){//画圆圈 context.beginPath(); context.arc(myCanvas.width/2,myCanvas.height/2,Radius,0,Math.PI*2,true); context.stroke(); } function drawNumbers(){//给时钟画上数字 var numbers=[1,2,3,4,5,6,7,8,9,10,11,12], angle=0; //两个刻度之间相差30°,1,2,3,……,12每一个数字在坐标轴上的位置分别是-60°,-30°,0°,30°,……,270° numbers.forEach(function(number){// angle=Math.PI/6*(number-3);//30°*(number-3) /**myCanvas.width/2+Math.cos(angle)*(Radius+space):数字在画布上的x轴坐标 myCanvas.height/2+Math.sin(angle)*(Radius+space):数字在画布上的y轴坐标 contexasureText(text).width:在画布上输出文本之前,检查字体的宽度 */ numberWidth=contexasureText(number).width; context.fillText(number,myCanvas.width/2+Math.cos(angle)*(Radius+space)-numberWidth/2,myCanvas.height/2+Math.sin(angle)*(Radius+space)+FontSize/3) }) } function drawCenter(){//绘制时钟的圆心 context.beginPath(); context.arc(myCanvas.width/2,myCanvas.height/2,5,0,Math.PI*2,true); context.stroke(); } function drawHand(deg,type){//根据传参在时钟上绘制时针,分针,秒针 var angle=0,length=0; if(type==='hour'){//时针 length=HourLength }else if(type==='minute'){ length=MinuteLength }else{ length=SecondLength } context.moveTo(myCanvas.width/2,myCanvas.height/2); context.lineTo(myCanvas.width/2+Math.cos(deg)*length,myCanvas.height/2+Math.sin(deg)*length); context.stroke(); } function drawHands(){//获取当前系统时间,得到绘制时针,分针,秒针所需的参数 var date= new Date(), hour=date.getHours(), minute = date.getMinutes(), second = date.getSeconds(); hour=hour>12?hour-12:hour; //Math.PI/180等于1度 var deg=Math.PI/180; //两个时刻是30度,被分成5格,每格6度,时钟每走12分钟,时针就走一小格,所以对时针而言,分针每走一分钟,时针就多走1/2度 var hourDeg=Math.PI/6*(hour-3)+minute/2*deg; //分针一小时走完360度,1小时=60分钟,所以每走一分钟就走6度 var minuteDeg=Math.PI/6*(minute/5-3); // 秒针一分钟走完360度,1分钟=60秒,所以每走一秒就走6度 var SecondDeg=Math.PI/6*(second/5-3); drawHand(hourDeg,'hour') drawHand(minuteDeg,'minute') drawHand(SecondDeg,'second') eleClockValue=hour+' : '+minute+' : '+second } function drawClock(){ context.clearRect(0,0,myCanvas.width,myCanvas.height);//每画下一秒的时钟图像之前要把画布清空 drawCircle(); drawNumbers(); drawCenter(); drawHands(); } context.font=FontSize+"px Arial" setInterval(function(){ drawClock(); var eleClock=document.getElementById('eleClock') eleClock.innerHTML=eleClockValue },1000)//1s重绘一次时钟

效果如下图所示:

现在一个可以跑的简陋时钟就绘制完成了,但是是真的丑,一点都体现不出canvas强大的绘画功能。为了体现canvas的强大,贴一个我很早之前画的时钟的代码。canvas的坐标轴中心在画布的左上角,这个方法将坐标系的中心从左上角移到了坐标轴的(200,200)位置,这一步为我们省去了很多复杂的计算,不需要再去自己微调数字和刻度盘在圆圈周围的位置,计算直观了很多。

clock you can't see me! var clock=document.getElementById("clock"); var ctx=clock.getContext('2d'); var width=ctx.canvas.width; var height=ctx.canvas.height; var r=width/3; function circle(){ ctx.save(); ctx.translate(200,200);//将坐标系的中心由左上角挪到坐标(200,200),这样可以省去很多繁琐的计算 ctx.beginPath(); ctx.arc(0,0,r,0,Math.PI*2,false); ctx.lineWidth="5"; ctx.strokeStyle="black"; ctx.stroke(); ctx.closePath(); // ctx.save(); // ctx.restore(); //画数字 var Arr=[3,4,5,6,7,8,9,10,11,12,1,2]; for(var i=0;i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有