
目录
绘制图像_缩放图像
绘制图像_图像切片
Canvas状态的保存和恢复
图形变形_平移
图形变形_旋转
图形变形_缩放
图形变形_变形
裁切路径
动画_时钟
动画_运动的小球
引入外部SVG
绘制图像_缩放图像

ctx.drawImage(img, x, y, width, height)
         img :图像数据,可以是 <img> 元素,也可以是 <canvas> 元素
         x :在目标 canvas 里放置图像的左上角的横坐标
         y :在目标 canvas 里放置图像的左上角的纵坐标
         width :图像在画布上的宽度
         height :图像在画布上的高度
  

       function draw(imgUrl, x, y) {
            // 定义img
            var img = new Image()
            img.src = imgUrl
            // 图片加载完后绘制图像
            img.onload = function () {
                // 绘制图像
                ctx.drawImage(img, x, y, 200, 200)
           }
       }
        // 通过遍历绘制九张图片铺满画布
        for (var i = 0; i < 3; i++) {
            for (var j = 0; j < 3; j++) {
                draw('./assets/4.jpg', i * 200, j * 200)
           }
       }
绘制图像_图像切片

 ctx.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
         img :图像数据,可以是 <img> 元素,也可以是 <canvas> 元素·
         sx :图像源被切的开始位置的横坐标
         sy :图像源被切的开始位置的纵坐标 
        sWidth :图像源被切的宽度
         sHeight :图像源被切的高度
         dx :图像在画布的开始位置的横坐标
         dy :图像在画布的开始位置的纵坐标
         dWidth :图像在画布的宽度
         dHeight :图像在画布的高度
第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。
剩余的8个参数前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。

        //   定义图片
        var img = new Image()
        img.src = './assets/2.jpg'
        // 图片加载完成后绘制图像
        img.onload = function () {
            // 绘制图像
            // 从源图片(50,50)的位置开始切片,切片大小为50*50
            //切片在画布上的起始位置为(100,100),切片在画布上最终画出 //来的大小为200*200
            ctx.drawImage(img, 50, 50, 50,50, 100, 100, 200, 200)
       }
         //绘制矩形
        ctx.lineWidth = 30
        ctx.strokeStyle = 'yellow'
        ctx.strokeRect(100, 100, 200, 200)
Canvas状态的保存和恢复

1、 ctx.save() :将画布的当前状态保存起来,相当于在内存之中产生一个样式快照
 一个绘画状态包括:
         1.1、当前的一些样式: strokeStyle , fillStyle , lineWidth , lineCap , lineJoin ,lineDashOffset ,         shadowOffsetX , shadowOffsetY , shadowBlur , shadowColor , 
         font , textAlign , textBaseline 等
         1.2、当前应用的变形(即移动,旋转和缩放)
        1.3、当前的裁切路径(clipping path)
 2、ctx.restore() :将画布的样式恢复到之前保存的快照

        ctx.fillRect(0, 0, 300, 300)//绘制矩形
        ctx.save()//保存当前状态
        ctx.fillStyle = 'green'//设置填充色
        ctx.fillRect(30, 30, 240,240)//绘制矩形
        ctx.save()//保存当前状态
        ctx.fillStyle='#fff'//设置填充色
        ctx.fillRect(60,60,180,180)//绘制矩形
        ctx.restore()//恢复上一个状态
        ctx.fillRect(90,90,120,120)
        ctx.restore()//恢复上上一个状态
        ctx.fillRect(120,120,60,60)
图形变形_平移

 ctx.translate(x, y)
x :是左右偏移量, x>0 ,向右平移, x<0 ,向左平移
y :是上下偏移量, y>0 ,向下平移, y<0 ,向上平移


     for (var i = 0; i < 2; i++) {
            for (var j = 0; j < 2; j++) {
                ctx.restore()//恢复上一次状态
                ctx.save()//保存上一次状态
                //产生平移
                ctx.translate(50 * i + 10, 50 * j + 10)
                //设置填充颜色
                ctx.fillStyle = ['red', 'green'][j]
                //绘制小矩形
                ctx.fillRect(0, 0, 25, 25)
           }
       }图形变形_旋转

 ctx.rotate(angle) :以 原点为中心 旋转 坐标系
         angle :旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。

        // 平移
        ctx.translate(100, 100)
        for (var i = 1; i < 7; i++) {
            // 旋转坐标系
            ctx.rotate((Math.PI*2)/6)
            // 绘制圆形
            ctx.beginPath()
            ctx.fillStyle = 'red'
            ctx.arc(0, 30, 5, 0, Math.PI * 2)
            ctx.fill()
       }
图形变形_缩放

 ctx.scale(x,y) :用于缩放图像。
         x : x 轴方向的缩放因子
         y : y 轴方向的缩放因子
 默认情况下,一个单位就是一个像素,缩放因子可以缩放单位,比如缩放因子 0.5 表示将大小缩小为原来的50%,缩放因子 10 表示放大十倍。
 如果缩放因子为1,就表示图像没有任何缩放。
 如果为-1,则表示方向翻转。 ctx.scale(-1, 1) 为水平翻转, ctx.scale(1, -1) 表示垂直翻转。


        ctx.translate(100, 100)//平移
        ctx.save()//保存当前状态
        // 绘制第一个矩形
        ctx.fillStyle = 'green'
        ctx.fillRect(0, 20, 100, 100)
        //绘制X轴所在的一条直线
        ctx.beginPath()
        ctx.moveTo(0,0)
        ctx.lineTo(500,0)
        ctx.stroke()
        
        // 绘制第二个矩形
        ctx.scale(0.5, 0.5)//缩放网格
        ctx.fillStyle = 'yellow'
        ctx.fillRect(0, 40, 100, 100)
        
        ctx.restore()//恢复之前的状态
        ctx.scale(1, -1)//垂直方向翻转
        // 绘制第一个矩形
        ctx.fillStyle = 'green'
        ctx.fillRect(0, 20, 100, 100)
        // 绘制第二个矩形
        ctx.scale(0.5, 0.5)//缩放网格
        ctx.fillStyle = 'yellow'
        ctx.fillRect(0, 40, 100, 100)
图形变形_变形

1、 ctx.transform(a, b, c, d, e, f) :接受变换矩阵的六个元素作为参数,完成缩放、平移和倾斜等变形。
         a :x轴方向缩放
         b :x轴方向倾斜
         c :y轴方向倾斜
         d :y轴方向缩放
         e :x轴方向平移
         f :y轴方向平移
 2、默认状态: transform(1,0,0,1,0,0)
变换矩阵: a c e
[ b d f ]
0 0 1
点 (x,y) 经过矩阵变换后得到 (x',y')
 1 、x' = ax + cy + e;
  2 、y' = bx + dy + f;
ctx.setTransform(a, b, c, d, e, f) :重置并创建新的变换矩阵
ctx.resetTransform() :重置当前变形为单位矩阵,它和调用以下语句是一样的:
ctx.setTransform(1, 0, 0, 1, 0, 0);
  

        ctx.fillRect(0, 0, 100, 100);//绘制参考矩形
        ctx.fillStyle='green'
        // ctx1.transform(0.5, 0, 0, 0.5, 0, 0);//缩放
        // ctx1.transform(1, 0, 0, 1, 50, 50);//平移
        // ctx1.transform(1, 1, 0, 1, 0, 0);//倾斜
        ctx.transform(0.5, 1, 0, 0.5, 50, 50);//综合变形
        ctx.fillRect(0, 100, 100, 100);//绘制变形后的矩形
        ctx.setTransform(0.5, 0, 0, 0.5, 0, 0);//重置并创建新的变化矩阵
        ctx.fillRect(0, 400, 100, 100);//绘制重置并创建新变形后的矩形
裁切路径

 ctx.clip() :将构建的路径转换为裁剪路径,裁切路径确定好之后,再绘制图形,裁切路径内的图形可以显示,裁切路径外的图形不显示。
 默认情况下,canvas 有一个与它自身一样大的裁切路径(也就是没有裁切效果)。
提示:
裁切路径也属于canvas状态

        var ctx = document.getElementById('canvas').getContext('2d')
        ctx.save()//保存状态
        ctx.fillRect(0, 0, 200, 200)//绘制一个跟画布一样大小的黑色矩形
        ctx.arc(100, 100, 50, 0, 2 * Math.PI)//定义个圆形的路径
        ctx.clip()
        // ctx.restore()
        // 绘制一个跟画布一样大小的黄色矩形
        ctx.fillStyle = 'yellow'
        ctx.fillRect(0, 0, 200, 200)动画_时钟

    <canvas width="150" height="150" id="canvas"></canvas>
    <script>
        var ctx = document.getElementById('canvas').getContext('2d')
        ctx.translate(75, 75)//移动原点到画布的正中心
        ctx.rotate(-Math.PI / 2)//逆时针旋转九十度
        ctx.lineCap = 'round'//设置线条末端样式
        ctx.save()
        clock()
        function clock() {
            ctx.clearRect(-75, -75, 150, 150)
            //   绘制一个跟画布一样大小的粉色矩形
            ctx.fillStyle = 'pink'
            ctx.fillRect(-75, -75, 150, 150)
            // 获取当前时间
            var now = new Date()
            // 绘制小时的刻度
            ctx.lineWidth = 3//设置线条宽度
            for (var i = 0; i < 12; i++) {
                ctx.beginPath()
                ctx.rotate(Math.PI / 6)
                ctx.moveTo(68, 0)
                ctx.lineTo(75, 0)
                ctx.stroke()
           }
            // 绘制分钟的刻度
            ctx.lineWidth = 2//设置线条宽度
            for (var i = 0; i < 60; i++) {
                // 如果i除以五的余数不为0,则代表不跟小时的刻度重合,则绘制分钟的刻度
                if (i % 5 != 0) {
                    ctx.beginPath()
                    ctx.moveTo(72, 0)
                    ctx.lineTo(75, 0)
                    ctx.stroke()
               }
                ctx.rotate(Math.PI / 30)
           }
           var hour = now.getHours()
            var min = now.getMinutes()
            var sec = now.getSeconds()
            hour = hour > 12 ? hour - 12 : hour
            console.log(hour)
            console.log(min)
            console.log(sec)
            // 绘制时针
            ctx.restore()
            ctx.save()
            ctx.lineWidth = 5
            ctx.rotate((Math.PI / 6) * (hour + min / 60 + sec / 3600))
            ctx.beginPath()
            ctx.moveTo(-10, 0)
            ctx.lineTo(40, 0)
            ctx.stroke()
            // 绘制分针
            ctx.restore()
            ctx.save()
            ctx.lineWidth = 4
            ctx.rotate((Math.PI / 30) * (min + sec / 60))
            ctx.beginPath()
            ctx.moveTo(-10, 0)
            ctx.lineTo(60, 0)
            ctx.stroke()
         // 绘制秒针
            ctx.restore()
            ctx.save()
            ctx.lineWidth = 3
            ctx.rotate((Math.PI / 30) * (sec))
            ctx.beginPath()
            ctx.moveTo(-10, 0)
            ctx.lineTo(60, 0)
            ctx.strokeStyle = 'red'
            ctx.stroke()
            // 在原点处绘制红色小圆点
            ctx.beginPath()
            ctx.arc(0, 0, 5, 0, 2 * Math.PI)
            ctx.fillStyle = 'red'
            ctx.fill()
            // 在秒针末端绘制小圆圈
            ctx.beginPath()
            ctx.arc(65, 0, 5, 0, 2 * Math.PI)
            ctx.stroke()
            ctx.restore()
       }
        setInterval(function () {
            clock()
        }, 1000)
动画_运动的小球
 

        var c = document.getElementById('canvas')
        var ctx = c.getContext('2d')
        var raf;
        var x = 250//定义小球的圆心的默认横坐标
        var y = 250//定义小球的圆形的默认纵坐标
        var stepX = 5//定义小球每次运动水平方向的偏移矢量
        var stepY = 2//定义小球每次运动垂直方向的偏移矢量
        function draw() {
            // ctx.clearRect(0, 0, 500, 500)
            // 每次绘制前都画一个带点透明的矩形,这样可以产生尾巴的效果
            ctx.fillStyle = 'rgba(255,255,255,0.3)';
            ctx.fillRect(0, 0, 500, 500);
            //根据小球的新的圆心的位置绘制小球
            ctx.beginPath()
            ctx.arc(x, y, 20, 0, 2 * Math.PI)
            ctx.fillStyle = 'red'
            ctx.fill()
            // 判断小球的位置.如果超出
            if (x + 20 >= 500 || x - 20 <= 0) {
                stepX = -stepX;
           }
            if (y + 20 >= 500 || y - 20 <= 0) {
                stepY = -stepY;
           }
            // 改变小球的位移
            x += stepX
            y -= stepY
       }
        function anim() {
            draw()//绘制小球
            //告诉浏览器我要执行一个动画,传递进去的回调函数会在每次重绘之前调用,一般情况下每秒执行60次
            raf = window.requestAnimationFrame(anim)
       }
        anim()
        // 监听鼠标的移动事件,让小球跟着鼠标移动位置
        c.addEventListener('mousemove',function (e) {
          window.cancelAnimationFrame(raf);
            x = e.offsetX;
            y = e.offsetY;
            draw()
       });
        // 点击鼠标,则继续开始动画
        c.addEventListener('click', function (e) {
            anim()
      });
引入外部SVG

 SVG :遵循 XML 标准,用来定义可缩放矢量图形。
  1、引入外部svg文件的方式
       1.1、作为元素的背景图
#con {
            width:100px;
            height: 100px;
            background: url('./test.svg') no-repeat;
       }1.2、使用 img 引入
<img src="test.svg" alt="" >1.3、使用 object 引入
<object data="test.svg" type="image/svg+xml" />

















