1 Star 1 Fork 0

lisashare / base-canvas

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

canvas

<canvas></canvas>

canvas是一个矩形区域的画布,可以使用脚本javascript在其中绘制图形的HTML元素,是HTML5中新增的元素。 canvas自身并不具备绘制功能,canvas须依靠javascript才能绘制出图形;canvas也提供了多种绘制路径、矩形、圆形、字符以及添加图像的方法; canvas 的默认大小为300像素×150像素(宽×高,像素的单位是px)。

  1. canvas不支持在ie9以下的浏览器中执行
  2. canvas宽高设置问题

如果使用style/js(canvas.style.width/height)设置宽高,等同于把画布进行缩放,可能会使内容模糊

canvas正确设置宽高的方法:(属性单位必须是px)

  • 直接在canvas标签上使用width/height设置
  • canvas.width/height 在js中设置

canvas 主要应用领域

  1. 游戏
  2. 可视化数据
  3. banner广告

context

canvas 的上下文、绘制环境

context对象就是js操作canvas的接口:[canvasElement].getContext('2d')来获取2D绘图上下文

3d:webgl

canvas 基本图形绘制

代码详见demo/canvas.html

  1. 矩形:矩形是一个唯一一个可以直接绘制的形状
    1. 绘制一个填充的矩形fillRect(x,y,w,h)
    2. 绘制一个描边的矩形strokeRect(x,y,w,h)
    3. 清除一个矩形区域clearRect(x,y,w,h)
    // 清除之前的图片轨迹 canvas.width = canvas.width; // 一般不用这种方法
    // 如果通过代码重新设置canvas画布的宽高,那么canvas画布里面的所有的内容都会被清空
    ctx.clearRect(0,0,canvas.width,canvas.height);

了解:非零环绕规则,交叉路径的填充问题,运用“非零环绕规则”,顺逆时针穿插次数决定是否填充。

  1. 线段

注意:绘制的线段会出现跨像素,颜色变浅,占2像素的问题(+.5)

  1. 绘制椭圆&圆弧

    arc(圆心x,圆心y,半径,起始弧度(x,水平方向),结束弧度,绘制方向counterClockWise(默认顺时针[false]);

    弧度->角度:30 * Math.PI/180

    圆形上面的点的坐标的计算公式:x = x0 + Math.cos(rad) * R // x0:起始点;R:距离,注意都是弧度

  2. 绘制文字 canvas处理文本的能力很弱

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

    strokeText()

    font 书写有顺序要求:大小不能写在最后 ctx.font = 'italic 50px blod Arial';

    textBaseline = 'bottom' // 设置字体底线对齐绘制基线 顶线:最高位置;基线:x下边;中线:x中间;底线:最底下位置;

    行高的定义:两行文本基线的距离就是行高。

    textAlign = 'left' // 设置字体对齐的方式

    ctx.measureText(item.title).width; // 获取文字所占宽度

  3. 绘制图片&视频

canvas 绘制图片效率比其他高

视频绘制其实就是一帧一帧的绘制

1. drawImage(image,x,y);
2. drawImage(image,x,y,w,h);
3. 图片切片后绘制:s 原图像 d 绘制画布
drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh);
// 1. 创建图片的dom对象
var img = new Image();
// 只要设置了src属性,当前img对象立即去加载图片
img.src = '../images/what.jpg';
// 等待图片加载完成后,把图片绘制到canvas上
img.onload = function(){ 
// 2. 绘制图片(3类)
    // 2.1 绘制图片默认大小
    ctx.drawImage(img,50,400);
    // 2.2 绘制图片并设置大小(缩放)
    ctx.drawImage(img,50,600,100,100);
    // 2.3 图片切片后绘制
    ctx.drawImage(img,60,50,60,60,200,600,60,60)
}

基于状态的绘图

默认上来就有一个状态

状态里面:当前状态里面的绘制样式

beginPath(); 开启一个新路径,开启新状态的绘图;来启一个新的状态,新状态可以继承之前状态的样式,但是当前状态设置所有的样式,只能作用于当前的状态。

canvas 内容样式设置

  1. 颜色:接受颜色名,16进制数据,rgb值,rgba

    1. fillStyle = color;
    2. strokeStyle = color;
  2. 透明度(整个画布的透明度)(了解) globalAlpha = value[0,1];

  3. 线型设置(了解)

    1. 线宽,设置或返回当前的线条宽度

      lineWidth = value

    2. 两端样式,设置或返回线条的结束端点(线头、线冒)样式

      lineCap = type

      butt:默认值,向线条的每个末端添加平直的边缘; round:圆形,向线条的每个末端添加圆形线冒; square:方形(会增加线的宽度),向仙台哦的每个末端添加方形线冒。

    3. 拼接样式,设置或返回两条线相交时,所创建的拐角类型

      lineJoin = type

      bevel:创建斜角; miter:默认,创建尖角; square round:创建圆角。

    4. miterLimit 设置或返回最大斜接长度

      • 斜接长度指的是在两条线交汇处内角和外角之间的距离。
      • 一般用默认值,10就可以了。除非需要特别长的尖角时,是用此属性。
    5. 绘制贝塞尔曲线(知道有)

    6. 创建两条切线的弧(知道有) 类比css3中的圆角 arcTo

  4. 渐变(了解)

一般不用,都是用图片代替,canvas绘制图片效率更高;线性渐变可以用于矩形、圆形、文字等颜色样式。

线性渐变

var linearGradient = ctx.createLinearGradient(50,850,150,950);
    linearGradient.addColorStop(0,'red')
    linearGradient.addColorStop(.2,'skyblue')
    linearGradient.addColorStop(.7,'green')
    linearGradient.addColorStop(1,'pink');
ctx.fillStyle = linearGradient;
ctx.fillRect(50,850,100,100);

径向渐变 ctx.createRadialGradient(x0,y0,r0,x1,y1,r1); x0:渐变的开始圆的x坐标;x1:渐变的结束圆的x坐标;r0:开始圆的半径

  1. 设置阴影(了解,少用,性能差)

设置png图片的阴影,图片透明部分不会被投影

ctx.fillStyle = 'yellow';
ctx.shadowColor = 'red';    设置或返回用于阴影的颜色
ctx.shadowBlur = 30;    设置或返回用于阴影模糊级别,大于1的正整数,树枝越高,模糊程度越大
ctx.shadowOffsetX = 20; 设置或返回阴影距形状的水平距离
ctx.shadowOffsetY = 20; 设置或返回阴影距形状的垂直距离
ctx.fillRect(50,850,100,100);
  1. 绘制背景图(了解) ctx.createPattern(img,pattern); 在制定的方向内重复制定的元素。 pattern:模式 repeat 默认。该模式在水平和垂直方向重复;repeat-x:该模式只在水平方向重复;repeat-y;no-repeat

canvas 变换(重点)

变换:坐标系变换,与CSS3的2D转换类似

注意:原有内容不会受变换影响

  1. 平移 ctx.translate(x,y)
  2. 转转 ctx.rotate(angle);参数是弧度(PI) 如需将角度转换为弧度,请使用degrees*Math.PI/180公式进行计算。

1弧度=180/π度,1度=π/180弧度

角度A1转换弧度A2:A2=A1*π/180

弧度A2转换角度A1:A1=A2*π/PI

  1. 缩放 ctx.scale(x,y) [0,1]

canvas 保存与恢复(重点)

一般配合位移画布使用。

save() 保存当前画笔的状态,可以把当前绘制环境进行保存到缓存中。

restore() 返回之前保存过的路径状态和属性,获取最近缓存的ctx。

    ctx.fillRect(0,0,100,100);
    ctx.save();
    // ctx.translate(100,100);
    ctx.rotate(30*Math.PI/180);
    ctx.fillStyle = 'tomato';
    ctx.fillRect(0,0,100,100);
    ctx.restore();
    ctx.fillRect(100,0,50,50); 

canvas 动画

原理:是先定义一个初始的状态,然后定义一个定时器,定时器内执行一个方法,记得在这个方法中要对当前的画面清除,然后在这个方法中重新绘制需要变化的效果,由于人眼存在残影,所以,短时间内中断的变化可以看成是连续的变化。

动画其实是由不同的静态画面组成,每一幅静态画面我们叫做一帧(frame),当众多的静态画面按照一定的规则快速运动时,我们的眼睛就会欺骗我们的大脑,从而形成物体运动的假象。

画布保存base64编码内容(重要)

  • 把canvas绘制的内容输出成base64内容

  • 语法:canvas.toDataURL(type, encoderOptions);

  • 例如:canvas.toDataURL('image/jpg', 1);

  • 参数说明:

    • type:设置输出的类型,比如:image/png image/jpeg 等
    • encoderOptions:0~1之间的数字,用于标识输出图片的质量,1表示无损压缩,类型为:image.jpeg 或者 image/webp才起作用。
    var canvas = document.getElementById('#canvas');
    var dataURL = canvas.toDataURL();
    console.log(dataURL);
    var img = document.querySelector('#img-demo'); // 拿到图片的dom对象
    img.src = canvas.toDataURL('image/png'); // 将画布的内容给图片标签显示

画布渲染画布(重要)

  • context.drawImage(img,x,y);
  • img参数也可以是画布,也就是把一个画布整体的渲染到另外一个画布上。
  • 优化性能,提高效率。在内存中批量绘制,一次性绘制到可见画布上。
var canvas1 = document.querySelector('#cavsElem1');
var canvas2 = document.querySelector('#cavsElem2');
var ctx1 = canvas1.getContext('2d');
var ctx2 = canvas2.getContext('2d');
ctx1.fillRect(20,20,40,40); // 在第一个画布上绘制矩形 
ctx2.drawImage(canvas1,10,10); // 将第一个画布整体绘制到第二个画布上

canvas的像素化

我们使用canvas绘制了一个图形,一旦绘制成功了,canvas就像素化了他们。canvas没有能力从画布上再次得到这个图形,也就是说我们没有能力去修改已经在画布上的内容,这个就是canvas比较轻量的原因。flash重的原因之一就是它可以通过对应的api得到已经在“画布”上的内容然后进行绘制。

  1. canvas的动画思想 如果想让canvas图形移动,必须按照 清屏(清除画布)-> 更新变量 -> 重新绘制渲染 的逻辑进行编程。总之就是重新再画一次。

canvas上的画布元素,就像被像素化了,所以不能通过style.left方法进行修改,而是必须重新绘制

代码演示部分

// canvas方法参数智能提示
/* @type {HTMLCanvasElement} */
// 得到画布
var canvas = document.getElementById('canvas')
// 获取2d的画笔对象
var ctx = canvas.getContext('2d')
// 设置颜色
ctx.fillStyle = 'red'
var left = 100
// 动画过程
setInterval(()=>{
// 清除画布;0,0代表从什么位置开始清除;500,600代表清除的宽度和高度
ctx.clearRect(0,0,500,600)
// 更新信号量
left++
// 重新绘制
ctx.fillRect(left,100,100,100)
}, 30)

实际上,动画的生存就是相关静态画面连续播放了,这个就是动画的过程,我们把每一次绘制的静态画面叫做“一帧”,时间的间隔(定时器的间隔)就表示帧的间隔

动画过程在主定时器里面,每一帧都会调用实例的更新和渲染方法。

面向对象

new 内部原理:

第一步:创建一个新的空对象(在内存中开辟一块空间);

第二部:把this指向到这个空对象;

第三部:把空对象的内部原型,指向构造函数的原型对象;

第四部:Cat 函数(函数对象):如果当前构造函数,执行到最后的时候,如果没有return,那么把构造函数中,构造的那个this对象返回给cat实例。

函数对象 Cat(this对象添加属性) ----> Cat.prototype  show()(原型上添加方法) PI 对象的方法都放到原型上去定义(节省内存空间);原型上的属性只能通过原型对象自己去设置。尽量不要在原型中添加属性,公共的属性和常量的值可以放到原型对象中去。
    |                                         ^
    V                                         |
cat = new Cat 实例对象  age  cat.PI = 'abc'  如果实例对象设置一个跟原型对象相同属性的值时,会自动添加一个对象自己的属性。 读取取的是原型的属性

面向对象实现canvas动画

因为canvas不能得到已经绘制的上一屏的对象,所以我们要维持对象的状态。在canvas中我们要使用面向对象的方式来编程,因为我们可以使用面向对象的方式来维持canvas的属性和状态;

var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
function DrawRect(x, y, w, h, color) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.color = color ? color:'red';
}
// 更新方法
DrawRect.prototype.update = function() {
    this.x++;
    if(this.x > canvas.width) this.x = 0
}
// 渲染
DrawRect.prototype.render = function() {
    // 设置颜色
    ctx.fillStyle = this.color
    ctx.fillRect(this.x, this.y, this.w, this.h)
}
// 实例化
var p1 = new DrawRect(0,100,canvas.widht,canvas.height)
setInterval(()=>{
    ctx.clearRect(0,0,canvas.width,canvas.height)
    p1.update()
    p1.render()
}, 30)

// setTimeout(function run() {
//     ctx.clearRect(0,0,canvas.width,canvas.height)
//     p1.update()
//     p1.render()
//     setTimeout(run, 50)
// }, 50)

canvas 库

国产的egret引擎

比较火的3d引擎:threejs

Konva 特点:

  • 小巧、使用方便、适合移动端和pc端
  • 支持丰富的事件处理操作
  • 支持类似jquery的操作方式
  • 开源,可以随意更改
  • 社区更新比较活跃,github托管源码
  • 性能也不错

Konva 的使用快速上手

Konva的整体理念

  • 舞台的概念的引入。整个视图看作是一个舞台stage
  • 舞台中可以绘制很多个层layer:一个舞台可以添加多个层,背景层,动画层,光照层
  • layer下面可以有很多的group
  • group下面可以有矩形、图片、其他形状等

Konva 库的事件

  • 跟jquery的表现一致
  • on绑定事件,off解绑事件

Konva 库的动画系统

  • to动画系统
  • tween动画系统
  • animate帧动画

Konva 库的使用案例

创建一个矩形 Konva.Rect(option);
// Konva使用基本案例
// 第一步:创建舞台
var stage = new Konva.Stage({
    container: 'container', // 需要存放舞台的dom容器
    width: window.innerWidth, // 设置全屏
    height: window.innerWidth
});
// 第二步:创建层
var layer = new Konva.Layer(); // 创建一个层
stage.add(layer); // 把层添加到舞台
// 第三步:创建矩形
var rect = new Konva.Rect({// 创建一个矩形
    x: 100, // 矩形的x坐标,相对其父容器的坐标
    y: 100,
    width: 100,
    height: 100,
    fill: 'gold',
    stroke: 'navy',
    strokeWidth: 4,
    opacity: .2,
    scale: 1.2,
    rotation: 30,  // 旋转的角度,是deg不是弧度
    cornerRadius: 10, // 圆角的大小(像素)
    draggable: true
})
// 第四步:把矩形添加到层上去
layer.add(rect);
// 第五步:把层渲染到舞台上
layer.draw();
Konva 进度条案例

webitcast案例

柱状图

多用百分比设置大小,可以适配

饼状图案例

微信案例

需求:我们app画笔回显字体,字体包不能每个页面都重新引入,太大了,能根据接口按需引入么?

空文件

简介

canvas学习,threejs基础入门学习 展开 收起
JavaScript 等 3 种语言
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
JavaScript
1
https://gitee.com/lisa_zhu2012/base-canvas.git
git@gitee.com:lisa_zhu2012/base-canvas.git
lisa_zhu2012
base-canvas
base-canvas
master

搜索帮助