Erlo

前端笔记之Canvas

2019-04-18 18:02:28 发布   514 浏览  
页面报错/反馈
收藏 点赞

一、Canvas基本使用

CanvasHTML5的画布,Canvas算是“不务正业”的面向对象大总结,将面向对象玩极致。

算法为王!就是说canvas你不会,但是算法好,不怕写业务,不怕代码量,只要稍微学学API就能出活。

Canvas这里是HTML5新标签,直接要了flash的命。

 

1.1 Canvas简介

MDNCanvas在线手册:

https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API

了解:

是一个可以使用脚本(通常为JavaScript)来绘制图形的 HTML 元素.它可以用于绘制图表、制作图片构图或者制作简单的(以及不那么简单的)动画. 右边的图片展示了一些  的实现示例

历史:

 最早由Apple引入WebKit,用于Mac OS X Dashboard,随后被各个浏览器实现。如今,所有主流的浏览器都支持它。

Mozilla 程序从 Gecko 1.8 (Firefox 1.5) 开始支持 。它首先是由 Apple 引入的,用于 OS X Dashboard SafariInternet Explorer IE9开始支持 ,更旧版本的IE可以引入 Google  Explorer Canvas 项目中的脚本来获得支持。ChromeOpera 9+ 也支持 

Canvas兼容到IE9


1.2 Canvas入门

canvasHTML5中比较特殊的双标签,可以在body中放:

html>
head>
    meta charset="UTF-8" />
    title>Documenttitle>
    style type="text/css">
        canvas{border:1px solid #000;}
    style>
head>
body>
    canvas width="600" height="400">canvas>
body>
html>

不能将widthheightCSS中设置,否则画布的像素的会被缩放,画面质量粗糙了。

 

元素可以像任何一个普通的图像一样(有marginborderbackground等等属性)被设计。然而,这些样式不会影响在canvas中的实际图像。

 

画布没什么用,所有操作都要在“上下文”中进行,这里的上下文是环境的意思,不是面向对象中的this

Canvas的本质就是用js来画画,所有的绘画函数,都是ctx的方法。

 

 

canvas马上开始面对一堆API

 

Canvas的坐标系和绝对定位的坐标系是一样的。

 


二、Canvas绘制形状

2.1绘制形状路径

Canvas中有两种东西:

l stroke路径【笔触】,也叫描边,就是形状的轮廓

l fill填充,就是里面的颜色

//得到画布标签
var canvas = document.querySelector('canvas');
//使用上下文,得到一个2D画布
var ctx = canvas.getContext("2d");
//画画
ctx.beginPath();     //声明要开始绘制路径
ctx.moveTo(100,100); //移动到绘制点,将“画笔”移动到100,100的位置
ctx.lineTo(250,250); //划线
ctx.lineTo(500,250); //划线
ctx.lineWidth = 10;  //线的粗细
ctx.strokeStyle = "red"; //线的颜色
ctx.fillStyle = "blue"; //准备填充的颜色
ctx.closePath();     //闭合路径(自动补全)
ctx.stroke();        //显示线(绘制线),可以绘制的路径显示出来
ctx.fill();          //填充颜色

只有矩形有快捷方法,比如想绘制多边形,都要用以上这些组合。

 


2.2绘制矩形

ctx.fillRect(x,y,w,h);    //绘制填充矩形
ctx.strokeRect(x,y,w,h);   //绘制路径矩形

 

绘制调色板:

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext("2d");
for (var i = 0;i ){
   for (var j = 0;j ){
       ctx.fillStyle = 'rgba('+ Math.floor(255-42.5 * i) +','+ Math.floor(255-42.5 * j) +', 200)';
       ctx.fillRect(i * 25, j * 25, 25, 25);
   }
}

记住一句话:Canvas是不可逆,绘制的元素一旦上了屏幕,是无法针对它再次操作。


2.3绘制弧度

ctx.arc(圆心x, 圆心y, 半径, 开始的弧度, 结束的弧度, 是否逆时针);

ctx.beginPath();  //开始绘制路径
// ctx.arc(100, 100, 60, 0, 6.28, false);
ctx.arc(100, 100, 60, 0, Math.PI * 2, false);
ctx.stroke(); //显示路径线

切一个圆,让切下来的弧边长等于圆的半径,此时弧对应的角度是57.3度左右,此时角度是固定的。

 

正方向是正右方

canvas中所有涉及角度的坐标系有两点注意的:

l 0弧度的方向是正右方向。

 

弧度的顺时针和逆时针:

ctx.arc(100,100,60, 0, 3, false); //绘制圆弧

ctx.arc(100,100,60, 0, 1, true); //绘制圆弧

 

绘制圆形:

ctx.arc(100,100,60, 0, Math.PI * 2, false);
ctx.arc(100,100,60, 0, 6.28, false);
ctx.arc(100, 100, 60, 0, -6.28, true);

注意:xy坐标是到圆心的位置,而且圆的大小是半径,后面绘制的形状会覆盖前面的形状。

 

绘制笑脸

绘制笑脸


三、使用图片

3.1图片基本使用

canvas中不可能所有形状都自己画,一定是设计师给我们素材,然后使用。

canvas中使用图片的方法:注意,必须等img完全加载后才能呈递图片。

ctx.drawImage();

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext("2d");
//创建一个img标签
var image = new Image()
//设置图片的路径
image.src = "images/baby1.jpg";
//当图片成功加载,就画图(上屏幕)
image.onload = function(){
   //显示图片的API
   ctx.drawImage(image, 100, 100); //表示x和y坐标
}

3.2使用切片

如果2个数字参数,此时表示左上角位置的xy坐标:

ctx.drawImage(img,100,100);
ctx.drawImage(img图片对象,画布X,画布Y);

如果4个数字参数,此时表示x、y、w、h:
ctx.drawImage(img图片对象, 画布X,画布Y,图片W,图片H);

如果8个数字参数,此时表示:
ctx.drawImage(img,切片X,切片Y,切片W,切片H,画布X,画布Y,图片W,图片H);

//创建一个img标签
var image = new Image()
//设置图片的路径
image.src = "images/baby1.jpg";
//当图片成功加载,就画图(上屏幕)
image.onload = function(){
   //显示图片的API
   // ctx.drawImage(image, 100, 100); //表示x和y坐标
   // ctx.drawImage(image, 100, 100, 150, 150); //表示x和y坐标
   // ctx.drawImage(img,切片X,切片Y,切片W,切片H,画布X,画布Y,图片W,图片H);
   ctx.drawImage(image, 108, 200, 145, 120, 100, 100, 145, 120);
}

图片APIhttps://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Using_images

 


3.3简易的图片加载器

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext("2d");
var R = {
   "0":"images/d1.jpg",
   "1":"images/d2.jpg",
   "2":"images/d3.jpg"
}
var arr = [];
for(var k in R){
   arr[k] = new Image(); //创建img对象
   arr[k].src = R[k];    //设置图片地址
   // 当图片成功加载,就画图(上屏幕)
   arr[k].onload = function(){
       ctx.drawImage(arr[k], 50, 50)
   }
}

3.4显示GIF动态图

 HTML代码:

img id="testImg" src="xxx.gif" width="224" height="126">
p>input type="button" id="testBtn" value="停止">p>

if ('getContext' in document.createElement('canvas')) {
    HTMLImageElement.prototype.play = function() {
        if (this.storeCanvas) {
            // 移除存储的canvas
            this.storeCanvas.parentElement.removeChild(this.storeCanvas);
            this.storeCanvas = null;
            // 透明度还原
            image.style.opacity = '';
        }
        if (this.storeUrl) {
            this.src = this.storeUrl;    
        }
    };
    HTMLImageElement.prototype.stop = function() {
        var canvas = document.createElement('canvas');
        // 尺寸
        var width = this.width, height = this.height;
        if (width && height) {
            // 存储之前的地址
            if (!this.storeUrl) {
                this.storeUrl = this.src;
            }
            // canvas大小
            canvas.width = width;
            canvas.height = height;
            // 绘制图片帧(第一帧)
            canvas.getContext('2d').drawImage(this, 0, 0, width, height);
            // 重置当前图片
            try {
                this.src = canvas.toDataURL("image/gif");
            } catch(e) {
                // 跨域
                this.removeAttribute('src');
                // 载入canvas元素
                canvas.style.position = 'absolute';
                // 前面插入图片
                this.parentElement.insertBefore(canvas, this);
                // 隐藏原图
                this.style.opacity = '0';
                // 存储canvas
                this.storeCanvas = canvas;
            }
        }
    };
}

var image = document.getElementById("testImg"), 
    button = document.getElementById("testBtn");
    
if (image && button) {
    button.onclick = function() {
        if (this.value == '停止') {
            image.stop();
            this.value = '播放';
        } else {
            image.play();
            this.value = '停止';
        }
    };
}
JavaScript代码

3.5游戏图片资源加载器

//得到画布
var canvas = document.querySelector("canvas");
// 使用上下文,得到一个2D的画布
var ctx = canvas.getContext("2d");
//资源文件
var R = {
   "d1" : "images/d1.jpg",
   "d2" : "images/d2.jpg",
   "d3" : "images/d3.jpg"
}
//遍历这个对象,将他们的地址变为真实图片地址
var count = 0; //已成功加载的图片个数
var length = Object.keys(R).length; //所有图片的总数
for(var k in R){
   //创建image对象
   var image = new Image();
   //设置src图片路径
   image.src = R[k];
   //将R里面的资源文件,变为真正的图片对象
   R[k] = image;
   //当image加载成功后,显示图片在画布上
   image.onload = function(){
       count++; //当某张图片加载成功,给计数器+1
       ctx.clearRect(0,0,600,600)
       //绘制文本,提升用户体验,提示加载的进度
       //填充文字API
       ctx.textAlign = "center";
       ctx.font = "30px 微软雅黑";
       ctx.fillText("正在加载图片:" + count + "/" + length, canvas.width / 2,50)
       //当加载完毕,开始游戏
       if(count == length){
           //开始游戏的回调函数
           ctx.clearRect(0,0,600,600)
           start();
       }
   }
}
// 开始游戏的函数
function start(){
   ctx.drawImage(R["d1"],100,100);
   ctx.drawImage(R["d2"],0,100);
   ctx.drawImage(R["d3"],300,200);
}
游戏图片加载器

四、画布的变形

4.1 translate移动变形

translate()移动画布,rotate()旋转画布。

canvas中不能只移动某一个对象,移动的都是整个画布。

canvas中不能只旋转某一个对象,旋转的都是整个画布。

但是可以用save()restore()来巧妙设置,实现让某一个元素进行移动和旋转。

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext("2d");
ctx.translate(100, 100); //将画布移动,坐标系就发生变化了
ctx.fillRect(100, 100, 100, 100); //相对于移动后的坐标系开始画画

 

移动变形、移动的是整个画布、而不是某个元素,在ctx.translate()之后绘制的语句都将被影响。

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext("2d");
ctx.translate(100, 100); //将画布移动,坐标系就发生变化了
ctx.fillRect(100, 100, 100, 100); //相对于移动后的坐标系开始画画
ctx.beginPath();
ctx.arc(100,100, 100, 0, 6.28, false);
ctx.fillStyle = 'skyblue';
ctx.fill();


4.2 save()保存和restore()恢复

ctx.save()表示保存上下文的物理性质,ctx.restore()表示恢复最近一次的保存。

save表示保存sava函数之前的状态,restore表示获取save保存的状态。

&l
登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认