canvas
简介
- canvas最早由Apple引入WebKit,用于Mac OS X 的Dashboard,厥后又在Safari和Google Chrome中完成
- 基于gecko 1.8浏览器,比方Firefox 1.5,一样支撑这个元素
- canvas元素是WhatWG Web application 1.0的一部份,也包括于HTML5
- H5的canvas元素运用JavaScript在网页上绘制图象,默许大小是300*150,能够自立设置宽高,不发起设置在style款式中
- 浏览器剖析的时刻是图片,能够掌握每一像素
- canvas不是块级元素,所以居中的时刻须要用display转化一下
- canvas具有多种绘制途径、矩形、圆形、字符以及增加图象的要领
绘制步骤
- 先猎取元素,以后猎取东西,再设置肇端位置,以后绘制途径,末了描边
- 描边历程能够设置线条色彩
再次绘制的时刻会运用之前的款式,背面的款式掩盖前面的
... <style> canvas{ border: 1px solid #ccc; /*不发起在这里设置宽高*/ /*width: 600px; height: 300px;*/ } </style> ... <body> <canvas height="300" width="600"></canvas> <script> //猎取canvas元素 var canvas=document.querySelector('canvas'); //猎取绘制环境(东西) var ctx=canvas.getContext('2d'); //设置肇端画图的位置 ctx.moveTo(100,100); //绘制途径 ctx.lineTo(200,100); //描边 ctx.stroke(); </script> </body>
绘制
基础绘制
- 线默许是1px,黑色。canvas由像素点组成,以坐标的中间绘制。假如是1px的线条,会被坐标中间分红两部份,每部份0.5px,浏览器没法显现0.5px,所以显现成淡色的粗线条。
- 假如线条的宽度是偶数的,就不会有这类状况。不过这类效果平常能够疏忽。
- beginPath示意从新绘制一条线,背面没有设置的款式会因循前边线条的款式
- 手动闭合,会发作缺口效果
- 自动闭合closePath
- 添补fill
- 不管是手动闭合照样自动闭合,或者是不关闭,都不会影响添补效果
- 两头款式用lineCap属性设置,默许是butt,另有round和square值,设置成后两种的时刻,线条会比默许稍长
- 设置moveTo和lineTo,组成拐点,默许款式是miter,另有round和bevel值
- 渐变能够算作,线条中的每一个像素离别设置色彩。那末渐变效果用遍历线条中的每一个像素就能够完成
- 遍历一次,线条的出发点moveTo和lineTo就会发作转变
线条
/*1.猎取canvas元素*/
var canvas = document.querySelector('canvas');
/*2.猎取绘制环境 (猎取绘制东西)*/
/*content内容 context 高低文 */
var ctx = canvas.getContext('2d');
/*3.设置肇端画图的位置*/
ctx.moveTo(100,100);
/*6.设置宽度*/
ctx.lineWidth = 10;
/*4.绘制途径 */
ctx.lineTo(200,100);
/*7. 设置描边的色彩*/
ctx.strokeStyle = 'red';
/*5.描边*/
ctx.stroke();
平行线
/*1.猎取canvas元素*/
var canvas = document.querySelector('canvas');
/*2.猎取绘制环境 (猎取绘制东西)*/
/*content内容 context 高低文 */
var ctx = canvas.getContext('2d');
/*3.设置肇端画图的位置*/
ctx.moveTo(100,100);
/*6.设置宽度*/
ctx.lineWidth = 10;
/*4.绘制途径 */
ctx.lineTo(200,100);
/*7. 设置描边的色彩*/
ctx.strokeStyle = 'red';
/*5.描边*/
ctx.stroke();
/*绿色*/
/*再次绘制的时刻 会运用之前设置的款式 设置的款式末了的会见效*/
/*开启新途径*/
ctx.beginPath();
ctx.moveTo(100,200);
ctx.lineTo(200,200);
ctx.strokeStyle = 'green';
ctx.stroke();
三角形
var canvas = document.querySelector('canvas');
/*猎取画图东西*/
var ctx = canvas.getContext('2d'); /*3d如今还不支撑*//*webgl*/
/*挪动画笔*/
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.lineTo(200,200);
//ctx.lineWidth = 10;
/*自动闭合*/
ctx.closePath();
//ctx.stroke();
//ctx.strokeStyle = 'red';
//ctx.stroke();
/*添补*/
//ctx.fillStyle = 'red';
ctx.fill();
镂空矩形
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
/*1.猎取画布的宽度和高度*/
//var width = canvas.width;
var width = ctx.canvas.width;
var height = ctx.canvas.height;
/*2.假定大容器 200*200*/
/*3.假定小容器 100*100*/
/*4. 盘算肇端位置*/
var x = width/2 - 100;
var y = height/2 -100;
ctx.moveTo(x,y);
ctx.lineTo(x+200,y);
ctx.lineTo(x+200,y+200);
ctx.lineTo(x,y+200);
ctx.lineTo(x,y);
/*第二个方形的方向需如果逆方向*/
var x1 = width/2 - 50;
var y1 = height/2 -50;
ctx.moveTo(x1,y1);
ctx.lineTo(x1,y1+100);
ctx.lineTo(x1+100,y1+100);
ctx.lineTo(x1+100,y1);
ctx.lineTo(x1,y1);
ctx.stroke();
ctx.fill();
线两头
var canvas = document.querySelector('canvas');
/*猎取画图东西*/
var ctx = canvas.getContext('2d'); /*3d如今还不支撑*//*webgl*/
ctx.lineWidth = 10;
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.strokeStyle = 'red';
ctx.lineCap = 'butt';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(100,200);
ctx.lineTo(200,200);
ctx.strokeStyle = 'green';
ctx.lineCap = 'round';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(100,300);
ctx.lineTo(200,300);
ctx.strokeStyle = 'pink';
ctx.lineCap = 'square';
ctx.stroke();
线拐点
var canvas = document.querySelector('canvas');
/*猎取画图东西*/
var ctx = canvas.getContext('2d'); /*3d如今还不支撑*//*webgl*/
ctx.lineWidth = 10;
ctx.moveTo(100,100);
ctx.lineTo(150,150);
ctx.lineTo(200,100);
ctx.strokeStyle = 'red';
ctx.lineJoin = 'miter';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(100,200);
ctx.lineTo(150,250);
ctx.lineTo(200,200);
ctx.strokeStyle = 'green';
ctx.lineJoin = 'round';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(100,300);
ctx.lineTo(150,350);
ctx.lineTo(200,300);
ctx.strokeStyle = 'pink';
ctx.lineJoin = 'bevel';
ctx.stroke();
渐变线
var canvas = document.querySelector('canvas');
/*猎取画图东西*/
var ctx = canvas.getContext('2d'); /*3d如今还不支撑*//*webgl*/
/*1.从左到右*/
/*2.肇端色彩 白色*/
/*3.完毕色彩 赤色*/
ctx.lineWidth = 10;
for (var i = 0; i < 255; i++) {
ctx.beginPath();
ctx.moveTo(99+i,100);
ctx.lineTo(100+i,100);
var g = 255 - i;
var b = 255 - i;
ctx.strokeStyle = 'rgb(255,'+g+','+b+')';
ctx.stroke();
}
虚线
- 用setLineDash设置虚线
- 传入一个数组,数组中的数据顺次示意实点空缺
- 假如传入的是奇数个数据,比方5,10,15,
- 那末示意实点5、空缺10、实点15、空缺5、实点10、空缺15
- 奇数总会转换成偶数个数据
别的虚线另有偏移量,负值示意向右偏移
var canvas = document.querySelector('canvas'); /*猎取画图东西*/ var ctx = canvas.getContext('2d'); /*3d如今还不支撑*//*webgl*/ ctx.moveTo(100,100); ctx.lineTo(500,100); /*绘制虚线的要领*/ /*传数组 设置虚线长度的*/ ctx.setLineDash([5,10]); /*offset示意位移*/ ctx.lineDashOffset=5; /*假如是偶数个数设置 */ /*假如是奇数数个数设置 */ /*猎取的不反复的一段*/ console.log(ctx.getLineDash()); ctx.stroke();
非零绘制准绳
- 从某地区伸出一条线,经由这条线的途径,顺时针方向+1,逆时针方向-1。终究途径值的和是0,则这个地区就不添补。
- S1地区,L1伸出来,与一条线交织,这条线是逆时针,-1
- S2地区,L2伸出来,与两条线交织,两条线都是逆时针,-1+(-1)=-2
- S3地区,L3伸出来,与两条线交织,一条是逆时针,一条是顺时针。-1+(+1)=0
- 非零添补,为零不添补
矩形
- 一切的要领中,前两个参数示意相对于canvas坐标,x和y,后两个参数示意矩形的大小,长和宽
- rect没有本身自力的途径,设置完坐标和大小时刻,还须要手动描边或添补
- strokeRect和fillRect都有本身的途径,能够直接天生矩形,一个标识描边天生,另一个是添补天生
clearRect消灭绘制内容
var canvas=document.querySelector('canvas'); var ctx=canvas.getContext('2d'); ctx.rect(100,100,20,100); ctx.strokeRect(200,100,20,100); ctx.fillRect(300,100,20,100); ctx.clearRect(210,100,20,100); ctx.stroke();
渐变计划
- createLinearGradient前两个参数示意出发点的坐标,后两个参数示意尽头坐标
addColorStop示意色彩的设置,第一个参数示意占有位置,第二个参数是色彩
var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d'); /*渐变的计划*/ var linearGradient = ctx.createLinearGradient(100,150,300,150); /* 0-1 0-100% */ linearGradient.addColorStop(0,'red'); linearGradient.addColorStop(0.5,'blue'); linearGradient.addColorStop(1,'yellow'); ctx.fillStyle = linearGradient; ctx.fillRect(100,100,200,100);
曲线
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
/*1.线都是由点组成*/
var yy = 0;
for (var i = 0; i < 600; i++) {
var x = i;
/*y会跟着公式去盘算*/
//var y = 2*x;
var y = Math.pow(x+2,2);
//var y = Math.sin(x/20)*100 + 300;
ctx.beginPath();
ctx.moveTo(x,yy);
ctx.lineTo(x+1,y);
yy = y;
ctx.stroke();
}
圆弧
- 圆弧绘制arc要领有六个参数
- 前两个参数示意圆心的坐标,第三个参数示意圆弧的半径,第四个参数示意最先的弧度,第五个参数示意完毕的弧度,第六个参数示意绘制方向,默许值是false顺时针
- 一个弧度的长度即是半径的长度,一个周长即是2*π个弧度
- 周长是2Math.PIr,一个角度就是Math.PI/180
顺时针转是正方向,是正值。逆时针转是负方向是负值
var canvas=document.querySelector('canvas'); var ctx=canvas.getContext('2d'); ctx.arc(100,100,60,0,2*Math.PI,false); ctx.stroke();
文本
- 文本设置,font设置字体款式和大小
- strokeText示意字体描边,fillText示意字体添补,这两个要领有四个参数,第一个参数示意要示意出来的文本,第二个和第三个参数示意坐标(文本的左下角),第四个参数示意文本最大宽度,能够不设置
- textAlign示意文本摆布方向的对齐体式格局,有left,right,center,start,end…
- textBaseline示意文本高低的对齐体式格局,有top,middle,bottom,alphabetic(默许值)
- measureText要领猎取文本的宽度
- 文本的对齐都是相对于坐标点来肯定的
假如设定肇端点的坐标是(100,100)那末向右对齐的时刻,文本会出如今(100,100)的左侧,高低体式格局的对齐体式格局同理
var canvas=document.querySelector('canvas'); var ctx=canvas.getContext('2d'); ctx.font = '微软雅黑' ctx.stroke(); ctx.fillText('内容内容',100,100,150);
图片
- 建立一个存在于内存中的图片,有下面两种体式格局
- 文档中建立元素,设定元素的途径等属性
- 运用Img对象new一个图片
- 在IE浏览器中,图片加载以后会有缓存,在onload的时刻图片能够已加载出来了,所以要把猎取图片的语句放在onload以后
canvas中绘制图片有三种体式格局
第一种,三个参数
- 参数一,图片对象。参数二,坐标x。参数三,坐标y。
第二种,五个参数
- 参数一,图片对象。参数二,坐标x。参数三,坐标y。参数四,图片宽。参数五,图片高。
第三种,九个参数
- 参数一,图片对象。参数二,图片x轴定位。参数三,图片y轴定位。参数四,截取图片宽度。参数五,截取图片高度。参数六,绘制x坐标。参数七,绘制y坐标。参数八,绘制图片宽度。参数九,绘制图片高度。
/*img元素也有onload事宜*/ /*document.querySelector('img').onload = function () { console.log('加载完成'); }*/ /*怎样动态建立一个图片元素*/ /*这个元素在内存内里*/ var img = document.createElement('img'); img.src = 'images/01.jpg'; img.onload = function () { console.log(img); } /*运用Image对象*/ var img1 = new Image(); img1.onload = function () { console.log(img1); } img1.src = 'images/01.jpg'; /*补充:兼容问题*/ /*IE onload必须先绑定*/
精灵图
- 从一大张精灵图中截取须要的部份
- 猎取画布的宽高,令图片居中显现
九个参数中,猎取img对象,在图片的(40,195)的位置截取图片,截取图片的大小是40X65,放在画布的(startX,startY)的位置,在画布中显现大小是40X65
var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d'); var img = new Image(); img.onload = function () { var width = ctx.canvas.width; var height = ctx.canvas.height; var startX = width/2-20; var startY = height/2-32.5; /*绘制*/ ctx.drawImage(img,40,195,40,65,startX,startY,40,65); } img.src = 'images/03.png';
帧动画
- 猎取画布大小,猎取人物大小,获得绘制的出发点
- 设置索引值初始值为0,代表行列中的第几个图片
- 绘制图片,在图片(0,0)位置截取图片,截取大小是人物大小,画布中绘制出发点就是之前盘算获得的效果,图片大小是人物大小。
- 设置一个定时器,令index自加,假如index加到3,归零
- 绘制图片之前先消灭之前的图片,消灭的出发点是绘制图片的出发点,消灭局限的大小是人物的大小
绘制新图片,截取位置的x方向长度是索引和人物宽度的乘积,y方向就是末了一行的坐标195,图片截取大小就是人物大小,最先位置就是绘制肇端位置,画布中图片显现大小就是人物大小
var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d'); var img = new Image(); img.onload = function () { /*画布大小*/ var width = ctx.canvas.width; var height = ctx.canvas.height; /*人物大小*/ var perWidth = img.width/4; var perHeight = img.height/4; /*绘制出发点*/ var startX = width/2-perWidth/2; var startY = height/2-perHeight/2; /*绘制*/ /*图片的索引*/ var index = 0; ctx.drawImage(img,0,0,perWidth,perHeight,startX,startY,perWidth,perHeight); setInterval(function () { index ++; if(index > 3){ index = 0; } /*绘制之前消灭之前的图片*/ ctx.clearRect(startX,startY,perWidth,perHeight); ctx.drawImage(img,index*perWidth,195,perWidth,perHeight, startX,startY,perWidth,perHeight); },100); } img.src = 'images/03.png';
转换坐标轴
- CSS中translate 在挪动的是元素
- Canvas中 translate挪动的事坐标轴
- CSS中rotate扭转绕元素中间转,坐标轴方向发作转变
- Canvas中 rotate扭转绕坐标轴原点,坐标轴方向发作转变
- Canvas 中scale x轴的缩放 y轴的缩放 并非元素的缩放
保留和恢复
- 保留和恢复,保留多个系列,先保留的后被拿出,后保留的先被拿出。栈
假如先保留一个赤色宽30,再保留一个绿色宽20,以后恢复的时刻,会先恢复
var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d'); ctx.lineWidth = 30; ctx.strokeStyle = 'red'; ctx.moveTo(100,100); ctx.lineTo(300,100); ctx.stroke(); /*保留一系列款式*/ /*保留多个系列款式*/ /*存储构造是栈 后进先出*/ ctx.save(); ctx.beginPath(); ctx.lineWidth = 20; ctx.strokeStyle = 'green'; ctx.moveTo(100,200); ctx.lineTo(300,200); ctx.stroke(); ctx.save(); ctx.beginPath(); ctx.restore(); ctx.moveTo(100,300); ctx.lineTo(300,300); ctx.stroke(); ctx.beginPath(); ctx.restore(); ctx.moveTo(100,400); ctx.lineTo(300,400); ctx.stroke();
实例
刮刮乐
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.onload = function () {
/*添补计划*/
var pat = ctx.createPattern(img,'no-repeat');
/*图片描边*/
ctx.strokeStyle = pat;
/*设置线的款式*/
ctx.lineWidth = 25;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
var isDown = false;
ctx.canvas.addEventListener('mousedown',function (e) {
/*设置肇端坐标*/
ctx.moveTo(e.clientX,e.clientY);
isDown = true;
})
ctx.canvas.addEventListener('mousemove',function (e) {
if(isDown){
ctx.lineTo(e.clientX,e.clientY);
ctx.stroke();
}
})
ctx.canvas.addEventListener('mouseup',function () {
isDown = false;
})
}
img.src = 'images/05.jpg';
键盘掌握人物挪动
var Per = function () {
this.ctx = document.querySelector('canvas').getContext('2d');
this.width = this.ctx.canvas.width;
this.height = this.ctx.canvas.height;
this.stepSize = 10;
this.index = 0;
}
Per.prototype.init = function () {
var that = this;
that.loadImage(function (img) {
that.perWidth = img.width/4;
that.perHeight = img.height/4;
that.startX = that.width/2-that.perWidth/2;
that.startY = that.height/2-that.perHeight/2;
that.drawPer(img,0,0,0);
that.bindEvent(img);
})
}
/*图片加载*/
Per.prototype.loadImage = function (callback) {
var img = new Image();
img.onload = function () {
/*完成其他营业*/
callback && callback(img);
}
img.src = 'images/04.png';
}
/*事宜绑定*/
Per.prototype.bindEvent = function (img) {
var that = this;
/*按键编码 左上右下 37 38 39 40*/
/* 0 1 2 3*/
var direction = 0;
var stepX = 0;
var stepY = 0;
document.addEventListener('keydown',function (e) {
console.log(e.keyCode);
switch(e.keyCode){
case 37:
/*左*/
stepX --;
direction = 1;
break;
case 38:
/*上*/
stepY --;
direction = 3;
break;
case 39:
/*右*/
stepX ++;
direction = 2;
break;
case 40:
/*下*/
stepY ++;
direction = 0;
break;
}
that.index ++;
/*绘制*/
that.drawPer(img,stepX,stepY,direction);
})
}
/*绘制人物*/
Per.prototype.drawPer = function (img,stepX,stepY,direction) {
/*清空*/
this.ctx.clearRect(0,0,this.width,this.height);
if(this.index > 3){
this.index = 0;
}
/*绘制*/
this.ctx.drawImage(img,this.perWidth*this.index,direction*this.perHeight,
this.perWidth,this.perHeight,
this.startX+(stepX*this.stepSize),this.startY+(stepY*this.stepSize),
this.perWidth,this.perHeight);
}
new Per().init();