Canvas基础


title: Canvas基础
date: 2016-11-09
tags: HTML5


0x00 Canvas

使用 Canvas 元素必须为其设置宽度和高度属性,指定可以绘制区域的大小。如果不添加任何样式或者不绘制任何图形,那么是看不到该元素的。

但是若是通过 CSS 样式来为其设置宽高属性的话,如果 CSS 的尺寸与 canvas 初始比例(canvas 默认初始宽度 300 px 高度 150 px)不一致,它会出现扭曲。

创建 Canvas 元素,并通过 canvas.getContext() 方法获取其 2D 上下文。

// HTML 
<canvas id="myCanvas" width="400" height="400">A drawing of something.</canvas>

// JS
var drawing = $("#myCanvas")

if(drawing.getContext){
    // 确定浏览器是否支持 <canvas>
    var context = canvas.getContext("2d")
    // more code
}

如上,如果需要在画布上绘图,那么首先便需要获得绘图上下文。

然后,使用 canvas.toDataURL() 方法便可以获取在 <canvas> 元素上绘制的图像,它只接受一个参数,即是我们要指定图像的 MIME 类型。

if(drawing.getContext()){
    var imgURL = drawing.toDataURL("image/png");
    // 获取图像的数据 URL

0x01 2D 上下文

使用 2D 上下文可以绘制简单的 2D 图形,比如矩形,弧线和路径。其两种基本绘图操作是填充(fillStyle)描边(strokeStyle)


使用 strokeRect() 和 fillRect() 绘制矩形

可以使用 fillStyle() 属性来为通过 fillRect() 绘制的矩形填充颜色;使用 strokeStyle() 属性来为 strokeRect() 方绘制的矩形描边

var drawing = $("#myCanvas")


if(drawing.getContext){
    // 检测浏览器是支持 canvas
    
    var context1 = drawing.getContext("2d");    
    // 获得 2d 上下文
    
    context1.fillStyle = "red"
    context1.fillRect(40,20,50,50)
    // 绘制一个矩形并填充 红色

    context1.strokeStyle = "blue"   
    context1.strokeRect(10,10,50,50)
    // 绘制一个矩形并描边为 蓝色

}

此外,可以使用 clearRect() 方法来清除指定区域。


0x02 绘制路径

一切形状的原始基础都是路径。在 Cavans 创建一个形状的首先需要的是创建新路径(beginPath()),再通过绘图命令(比如mouvTo()等)在路径中绘制,然后关闭路径(clostPath()),最后填充颜色(fill())或描边(stroke())。

调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合。

moveTo()

设置笔触相对于画布左上角开始的起点位置,即是路径的起始点。

lineTo()

直线路径。

描边三角形
var drawing = $("#myCanvas")
if(drawing.getContext){
    // 检测浏览器是支持 canvas
    var context = drawing.getContext("2d"); 
    // 获得 2d 上下文
    context.beginPath()
        context.strokeStyle = "green"
        context.moveTo(50,200)
        context.lineTo(200,100)
        context.lineTo(100,50)
        context.closePath()
        context.stroke()
    // 描边三角形
}
描边三角形
描边填充三角形
var drawing = document.querySelector("#drawing")
if(drawing.getContext){
    //是否支持 canvas
context = drawing.getContext("2d")
// 获得 2d 上下文
context.beginPath()
// 开始绘画
context.fillStyle = "#333"
// 填充色为 #333
context.strokeStyle = "deeppink"
// 描边颜色为 deeppink
context.lineWidth = "20"
// 线框为 20 px
context.moveTo(150,150)
// 起始触点 (150,150)
context.lineTo(150,300)
context.lineTo(300,225)
// 绘制一个三角形
context.closePath()
// 闭合路劲
context.stroke()
// 描边
context.fill()
// 填充
}
描边填充三角形

arc() arcTo()

arc(x,y,radius,startAngle,endAngle,clockwise)

画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。

arc() 函数中的角度单位是弧度,不是度数。角度与弧度的js表达式:radians=(Math.PI/180)*degrees。

描边圆形
for(var i=0;i<6;i++){
    for(var j=0;j<6;j++){
        context.strokeStyle ='rgb(0,' + Math.floor(255-42.5*i) + ',' + Math.floor(255-42.5*j) + ')'
        context.beginPath()
        context.arc(50+60*i,50+60*j,30,0,Math.PI/180*360)
        context.stroke()
    }
}

源自 MDN 官网。

描边填充圆形

描边填充圆形,并使用 globalAlpha 设置其透明度为 0.3

context.beginPath()
context.strokeStyle = "deeppink"        
context.fillStyle ="#333"
context.globalAlpha = "0.3"
context.lineWidth = "20"
context.arc(450,300,100,0,Math.PI/180*300)
context.closePath()
context.stroke()
context.fill()
描边填充圆形

0x03 渐变

Canvas 支持的渐变效果包括线性(createLinearGradient())和径向(createRadialGradient())渐变,并使用addColorStop() 为其指定渐变颜色。

strokeStylefillStyle 属性都可以接 canvasGradient 对象。

渐变颜色 addColorStop()

addColorStop(position,color) 中第一参数 position 表示颜色出现在渐变中的相对位置。

线性渐变 createLinearGradient()

createLinearGradient(x1,y1,x2,y2),其所接收的四个参数,分别代表渐变的起点和终点。

context.beginPath()
var lineGradient1 = context.createLinearGradient(100,200,100,400)
lineGradient1.addColorStop(0.5,"green")
lineGradient1.addColorStop(1,"red")
context.strokeStyle = lineGradient1
context.lineWidth = "20"
context.moveTo(100,200)
context.lineTo(100,400)
context.closePath()
context.stroke()
linearGradient
径向渐变 createRadialGradient()

createRadialGradient(x1,y1,r1,x2,y2,r2) 方法接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。

// 创建渐变
var radGrad = context.createRadialGradient(0,150,40,0,140,90)
radGrad.addColorStop(0,'#00C9FF')
radGrad.addColorStop(0.8,'#00B5E2')
radGrad.addColorStop(1,'rgba(0,201,255,0)')

// 画图形
context.fillStyle = radGrad
context.fillRect(0,0,150,150)
radialGradient

0x04 绘制文本

文本样式

  • font:这个字符串使用和 CSS 属性相同的语法. 默认的字体是 10px sans-serif
  • textAlign:文本对齐方式,可选值:start,end,left,right,center
  • textBaseline: 基线对齐方式,可选值:top,middle,bottom
fillText(text,x,y,[,maxWidth])

在指定的(x,y)位置填充指定的文本,绘制的最大宽度(可选).

strokeText(text,x,y,[,maxWidth])

在指定的(x,y)位置绘制空心文本,绘制的最大宽度(可选).

var linGrad = context.createLinearGradient(50,50,400,200)
linGrad.addColorStop(0.2,"red")
linGrad.addColorStop(0.7,"deeppink")
// 设置渐变
var str = "to be or not to be "
context.beginPath()
context.font = "60px 宋体"
// 设置文字格式 必需
context.textAlign = "left"
// 设置文字对齐方式 必需
context.textBaseline = "middle"
// 设置文字基线 必需
context.shadowColor = "#333" 
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.shadowBlur = 10;
context.closePath()
// 闭合路径
context.fillStyle = linGrad
// 设置 fillStyle
context.strokeStyle = linGrad
// 设置 strokeStyle 
context.fillText(str,50,50,400)
// 填充文字
context.strokeText(str,50,100,400)
// 描边文字
console.log(context.measureText(str))//width:570

measureText() 方法,将返回一个 [TextMetrics
]对象的宽度、所在像素,这些体现文本特性的属性。


0x05 Using Images

canvas 强大的特性还以使我们对图像进行操作处理。

当然,在对图像进行操作之间必然要引入图像资源,canvas 支持多种不同的图像资源引入方式,这里只了解常用的两种方式:使用 Image 对象或 <img> 标签 和 引用同一页面中的另一画布作为图像资源.

drawImage(source,x,y)

图像资源,以及在画布中的起始位置

drawImage(source,x,y,width,height)

图像资源,在画布中的起始位置,并以指定的宽度和高度显示在画布中。以次实现图像的缩放效果。

var isImage = new Image;
isImage.src = "Koala.jpg"
isImage.onload = function(){
  // do drawingImage statement
  context.drawImage(isImage,60,60,400,400)
  //五个参数时,代表图片在画布中显示的起始点和图片显示的宽高
}
五个参数
drawImage(source, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

当使用九个参数时,便是需要对图像进行切片处理了。其中sx,sy,sWidth,sHeight 规定要在图像源中取得的切片位置和切片大小;dx,dy,dWidht,dHeight 表示该切片在画布中显示的起始位置
和大小。

var isImage = new Image;
isImage.src = "Koala.jpg"
isImage.onload = function(){
    context.drawImage(isImage,300,300,400,300,100,100,200,200)
}
九个参数

createPattern()

我们可使用 createPattern() 方法来规定图像显示的方式,none,repeat,repeat-x,repeat-y

var isImage = new Image;
isImage.src = "Koala.jpg"
isImage.onload = function(){
    //图片是否平铺
    var imgs = context.createPattern(isImage,"repeat-x")
    context.fillStyle = imgs
    context.fillRect(0,0,700,500)
}

0x06 画布裁切 clip()

var isImage = new Image;
isImage.src = "Koala.jpg"
isImage.onload = function(){
    context.drawImage(isImage,0,0,400,400)
}
//画布裁切 clip()
context.arc(230,230,170,0,Math.PI/180*360)
context.closePath()
context.clip()
画布裁切

0x07 画布方法

save() 和 restore()

save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。

context.beginPath()
context.fillRect(50,50,150,150)
// 使用默认设置绘制一个矩形
context.save()
// 保存默认配置下的绘画状态
context.fillStyle = "deeppink"
// 设置一个新的绘画状态
context.fillRect(65,65,120,120)
// 使用新的绘制状态绘制一个矩形
context.restore()
// 恢复到默认绘制状态
context.fillRect(80,80,90,90)
// 同样,使用默认状态绘制一个矩形

restore() 恢复的是离它最近的 save() 之上 所保存的状态。

translate()

transltae(x,y) 方法用 移动 canvas 原点。

context.fillRect(50,50,100,100)
context.translate(100,100)
context.fillRect(50,50,100,100)
translate
scale(x,y)

scale(x,y) 缩放,其所接收的两个参数分别代表在 x 的缩放因子和在 y 轴的缩放因子。

context.scale(1.5,1.5)
context.fillRect(50,50,100,100)
context.translate(150,150)
context.scale(0.5,0.5)
context.fillRect(50,50,100,100)
rotate()

rotate(angle) 只接受一个参数,即旋转的角度,它是顺时针方向的,与 arc() 同样是以 弧度 为单位的值。

context.rotate(Math.PI/180*deg)

scale 也好,translate,rotate() 也好,所有的样式和变形命令都应该写在填充和描边命令之前。


0x08 画一个五角星

var r = 200
context.translate(200,200)
context.beginPath()
context.moveTo(r,0)
for(var i=0;i<9;i++){
    context.rotate(Math.PI/180*36)
    if(i%2 == 0){
        context.lineTo(r/(Math.cos(Math.PI/180*36)*2)*0.7,0)
    }else{
        context.lineTo(r,0)
    }
}
context.closePath()
context.fill()
}
五角星
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 一:canvas简介 1.1什么是canvas? ①:canvas是HTML5提供的一种新标签 ②:HTML5 ...
    GreenHand1阅读 4,658评论 2 32
  • 一、基础介绍和画直线 大多数现代浏览器都是支持Canvas的,比如 Firefox, safari, chrome...
    空谷悠阅读 814评论 0 1
  • 一、图形的组合方式 globalAlpha是一个介于0和1之间的值(包括0和1),用于指定所有绘制的透明度。默认值...
    空谷悠阅读 1,248评论 0 0
  • 标签:canvas 简单示例 入门知识作者: 张耀国 ( IgorZhang )E-mail: igorzhang...
    IgorZhang阅读 2,760评论 4 7
  • 女孩子读书的意义到底是什么? 大概是晚一点在柴米油盐的琐碎里,内心比身体更先老去。 1。 同学A是我的初中同学,细...
    心有猛虎焉知祸福阅读 473评论 6 7