canvas入门学习

示例地址
https://liuxianl.com/2021/02/12/%E5%89%8D%E7%AB%AF/canvas/

1.

canvas标签中特殊属性只有width和height
通过document.getElementById(‘canvas的id’)来获取canvas元素

方法、属性描述
getContext()得到画布上下文,上下文有2个,2d的上下文和3d的上下文
fillStyle设置颜色
fillRect()方法,绘制已填色的矩形,默认的填充颜色是黑色

2.

面向对象的画布动画

// 获取画布
var can = document.getElementById("can")
var ctx = can.getContext("2d");
// 绘制方法
function Rect(x, y, w, h, color) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.color = color
}
// 更新方法
Rect.prototype.update = function () {
    this.x++;
}
// 渲染
Rect.prototype.render = function () {
    // 设置颜色
    ctx.fillStyle = this.color;
    // 渲染
    ctx.fillRect(this.x, this.y, this.w, this.h);
}
// 实例化
var r1 = new Rect(100, 100, 50, 50, "#91d5ff")
// 动画过程
setInterval(() => {
    //清屏
    ctx.clearRect(0, 0, can.width, can.height)
    //更新
    r1.update()
    // 渲染
    r1.render()
}, 5)

3.绘制、画线

方法 / 属性描述
fillStyle设置填充颜色
fillRect(x,y,width,height)方法绘制 “已填色” 的矩形。默认的填充颜色是黑色。
strokeStyle设置边框颜色
strokeRect(x,y,width,height)方法绘制矩形边框。默认的填充颜色是黑色。
clearRect(x,y,width,height)清除画布内容
globalAlpha设置透明度 0-1

#3.1 绘制路径

// 创建路径
ctx.beginPath()
// 移动绘制点
ctx.moveTo(100,100)
// 描述行进路径
ctx.lineTo(200,300);
ctx.lineTo(300,230);
ctx.lineTo(440,290);
ctx.lineTo(380,50);
// 封闭路径
ctx.closePath()
// 设置颜色
ctx.strokeStyle="#91d5ff"
// 绘制不规则图形
ctx.stroke()
// 填充不规则图形
ctx.fill()

4.绘制圆弧

arc(x, y, radius, startAngle, endAngle, anticlockwise)
  • x,y 为绘制圆弧所在圆上的圆心坐标。
  • radius 为半径。
  • startAngle 以及 endAngle 参数用弧度定义了开始以及结束的弧度。这些都是以 x 轴为基准。
  • 参数 anticlockwise 为一个布尔值。为 true 时,是逆时针方向,否则顺时针方向。
    注意:arc() 函数中表示角的单位是弧度,不是角度。角度与弧度的 js 表达式:弧度 =(Math.PI/180)* 角度。
// 创建路径
ctx.beginPath();
// 圆周长 2π 2*3.14≈7 2*Math.PI
ctx.arc(200,200,100,0,2*Math.PI,false)
//  ctx.arc(200,200,100,0,0.3,false)
// 绘制
ctx.stroke()

炫彩小球

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        canvas{
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <canvas id="mycanvas" width="800" height="600"></canvas>
    
    <script>
        var can =document.getElementById("mycanvas");
        var ctx =can.getContext("2d");
        
        function Ball(x,y,r) {
            this.x =x;
            this.y =y;
            this.r =r;
            this.color =getRandomColor();
            this.dx =parseInt(Math.random() *10) - 5;
            this.dy =parseInt(Math.random() *10) - 5;
            balArr.push(this)
        }
        Ball.prototype.update =function () {
            this.x +=this.dx
            this.y +=this.dy
            this.r -=0.1
            if (this.r < 0) {
                this.remove()
            }
        }
        Ball.prototype.remove =function () {
            for (let index =0;index < balArr.length;index++) {
                if (balArr[index] ==this) {
                    balArr.splice(index,1)
                }
            }
        }
        Ball.prototype.render =function () {
            ctx.beginPath();
            ctx.arc(this.x,this.y,this.r,0,2 *Math.PI,false)
            ctx.fillStyle =this.color
            ctx.fill()
        }
        can.addEventListener("mousemove",function (event) {new Ball(event.offsetX,event.offsetY,Math.random() *13)
        })
        setInterval(() =>{
            ctx.clearRect(0,0,can.width,can.height)
            for (let index =0;index < balArr.length;index++) {
                balArr[index].update()
                if (balArr[index]) {
                    balArr[index].render()
                }
            }
        },40)
        var balArr =[]
        function getRandomColor() {
            var allType ="0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f"
            var allTypeArr =allType.split(",");var color ="#"
            for (let index =0;index < 6;index++) {
                var random =parseInt(Math.random() *allTypeArr.length);
                color +=allTypeArr[random]
            }
            return color
        }
    </script>
</body>
</html>

小球连线

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        canvas{
            display: block;
        }
    </style>
</head>
<body>
    <canvas id="can" width="800" height="600"></canvas>
    
    <script>
        var ballArr =[]
        var can =document.getElementById("can");var ctx =can.getContext("2d");

        can.width =document.documentElement.clientWidth
        can.height =document.documentElement.clientHeight
        function Ball(x,y,r) {this.x =x
            this.y =y
            this.r =r
            this.color=getRandomColor()
            this.count =0
            this.dx =parseInt(Math.random() *10) - 5
            this.dy =parseInt(Math.random() *10) - 5
            ballArr.push(this)
            this.index = ballArr.length -1
        }
        Ball.prototype.update =function () {
            this.x +=this.dx
            this.y +=this.dy
            if (this.x <=this.r ||this.x >=can.width - this.r) {
                this.dx =-this.dx
                this.count++
                this.color=getRandomColor()
            }
            if (this.y <=this.r ||this.y >=can.height - this.r) {
                this.dy =-this.dy
                this.count++
                this.color=getRandomColor()
            }
            if (this.count >=3) {
                this.remove()
            }
        }
        Ball.prototype.remove =function () {
            for (let index =0;index < ballArr.length;index++) {
                if (ballArr[index] ==this) {
                    ballArr.splice(index,1)
                }  
            }
        }
        Ball.prototype.render =function () {
            ctx.beginPath();
            ctx.globalAlpha =1
            ctx.arc(this.x,this.y,this.r,0,2 *Math.PI,false)
            ctx.fillStyle =this.color
            ctx.fill()
            for (let index = this.index + 1;index < ballArr.length;index++) {
                if (Math.abs(ballArr[index].x - this.x) < 180 && Math.abs(ballArr[index].y - this.y) < 180) {
                    ctx.strokeStyle = getRandomColor()
                    ctx.beginPath();
                    ctx.globalAlpha =10 / Math.sqrt(Math.pow(ballArr[index].x - this.x,2) + Math.pow(ballArr[index].y - this.y,2))
                    ctx.moveTo(this.x,this.y)
                    ctx.lineTo(ballArr[index].x,ballArr[index].y)
                    ctx.closePath()
                    ctx.stroke()
                }
            }
        }
        can.addEventListener("click",function (event) {
            for (let index =0;index < Math.ceil(Math.random() *20);index++) {
                new Ball(event.offsetX,event.offsetY,Math.random() *10 + 10)
            }
        })
        setInterval(function () {
            ctx.clearRect(0,0,can.width,can.height)
            for (let index =0;index < ballArr.length;index++) {
                ballArr[index].update()
                ballArr[index].render()
            }
        },25)
        function getRandomColor() {
            var allType ="0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f"
            var allTypeArr =allType.split(",");var color ="#"
            for (let index =0;index < 6;index++) {
                var random =parseInt(Math.random() *allTypeArr.length);
                color +=allTypeArr[random]
            }
            return color
        }
    </script>
</body>
</html>

线型

方法 / 属性描述
lineCap线开头和结束的形状
lineJoin线交会时的形状,有三种值round,bevel,miter
setLineDash设置虚线的样式

蚂蚁线

let canvas = document.getElementById("mycanvas");
        let ctx = canvas.getContext('2d');
        let offset = 0;

        function draw() {
            ctx.clearRect(0,0, canvas.width, canvas.height);
            ctx.setLineDash([2, 3]);
            ctx.lineDashOffset = -offset;
            ctx.strokeRect(10,10, 100, 100);
        }
        function march() {
            offset++;
            if (offset > 16) {
                offset = 0;
            }
            draw();
            setTimeout(march, 20);
        }

        march();

渐变

方法 / 属性描述
font设置字体大小、字体等
textAlign根据坐标的对齐方式
fillText()(文字,x1,y1)

线型渐变

  let line = ctx.createLinearGradient(100,150,300,160);
        line.addColorStop(0, 'black');
        line.addColorStop(0.5, 'red');
        line.addColorStop(1, 'orange');
        ctx.fillStyle = line;
        ctx.fillRect(100,150,200,10);

镜像渐变

   let gradient = ctx.createRadialGradient(200,300,100,200,300,0);
        gradient.addColorStop(0,"white");
        gradient.addColorStop(.2,"red");
        gradient.addColorStop(.4,"orange");
        gradient.addColorStop(.6,"green");
        gradient.addColorStop(.8,"blue");
        gradient.addColorStop(1,"purple");
        ctx.fillStyle = gradient;
        ctx.fillRect(100,200,200,200);

阴影

方法 / 属性描述
shadowOffsetXX轴偏离像素
shadowOffsetYY轴偏离像素
shadowBlur模糊程度
shadowColor阴影颜色

使用图片

let image = new Image();
image.src = "imgs/test1.png";
image.onload = function(){
    // ctx.drawImage(image, 10, 10, 50, 50);
    ctx.drawImage(image, 0, 0, 10, 10,10, 10, 50, 50);
}
  • 前4个参数表示以图片为坐标的x,y,width,height
  • 后4个参数表示以画布为坐标的x,y,width,height

资源管理器

https://liuxianl.com/demo/
https://liuxianl.com/2021/02/12/%E5%89%8D%E7%AB%AF/canvas/

进度1234567891011,121314

1.
canvas标签中特殊属性只有width和height
通过document.getElementById('canvas的id')来获取canvas元素


2.
面向对象的画布动画
// 获取画布
var can = document.getElementById("can")
var ctx = can.getContext("2d");
// 绘制方法
function Rect(x, y, w, h, color) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.color = color
}
// 更新方法
Rect.prototype.update = function () {
    this.x++;
}
// 渲染
Rect.prototype.render = function () {
    // 设置颜色
    ctx.fillStyle = this.color;
    // 渲染
    ctx.fillRect(this.x, this.y, this.w, this.h);
}
// 实例化
var r1 = new Rect(100, 100, 50, 50, "#91d5ff")
// 动画过程
setInterval(() => {
    //清屏
    ctx.clearRect(0, 0, can.width, can.height)
    //更新
    r1.update()
    // 渲染
    r1.render()
}, 5)

3.绘制、画线
方法 / 属性 描述
fillStyle 设置填充颜色
fillRect(x,y,width,height) 方法绘制 “已填色” 的矩形。默认的填充颜色是黑色。
strokeStyle 设置边框颜色
strokeRect(x,y,width,height) 方法绘制矩形边框。默认的填充颜色是黑色。
clearRect(x,y,width,height) 清除画布内容
globalAlpha 设置透明度 0-1

3.1 绘制路径
JAVASCRIPT
 // 创建路径ctx.beginPath()// 移动绘制点ctx.moveTo(100,100)// 描述行进路径ctx.lineTo(200,300);ctx.lineTo(300,230);ctx.lineTo(440,290);ctx.lineTo(380,50);// 封闭路径ctx.closePath()// 设置颜色ctx.strokeStyle="#91d5ff"// 绘制不规则图形ctx.stroke()// 填充不规则图形ctx.fill()

4.2 绘制圆弧
JAVASCRIPT
1 arc(x, y, radius, startAngle, endAngle, anticlockwise)
x,y 为绘制圆弧所在圆上的圆心坐标。
radius 为半径。
startAngle 以及 endAngle 参数用弧度定义了开始以及结束的弧度。这些都是以 x 轴为基准。
参数 anticlockwise 为一个布尔值。为 true 时,是逆时针方向,否则顺时针方向。
注意:arc() 函数中表示角的单位是弧度,不是角度。角度与弧度的 js 表达式:
弧度 =(Math.PI/180)* 角度。
JAVASCRIPT
1234567 // 创建路径ctx.beginPath();// 圆周长 2π 2*3.14≈7 2*Math.PIctx.arc(200,200,100,0,2*Math.PI,false)//  ctx.arc(200,200,100,0,0.3,false)// 绘制ctx.stroke()


炫彩小球
JAVASCRIPT
 <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title>    <style>        canvas{            border: 1px solid #000;        }    </style></head><body>    <canvas id="mycanvas" width="800" height="600"></canvas>        <script>        var can =document.getElementById("mycanvas");        var ctx =can.getContext("2d");                function Ball(x,y,r) {            this.x =x;            this.y =y;            this.r =r;            this.color =getRandomColor();            this.dx =parseInt(Math.random() *10) - 5;            this.dy =parseInt(Math.random() *10) - 5;            balArr.push(this)        }        Ball.prototype.update =function () {            this.x +=this.dx            this.y +=this.dy            this.r -=0.1            if (this.r < 0) {                this.remove()            }        }        Ball.prototype.remove =function () {            for (let index =0;index < balArr.length;index++) {                if (balArr[index] ==this) {                    balArr.splice(index,1)                }            }        }        Ball.prototype.render =function () {            ctx.beginPath();            ctx.arc(this.x,this.y,this.r,0,2 *Math.PI,false)            ctx.fillStyle =this.color            ctx.fill()        }        can.addEventListener("mousemove",function (event) {new Ball(event.offsetX,event.offsetY,Math.random() *13)        })        setInterval(() =>{            ctx.clearRect(0,0,can.width,can.height)            for (let index =0;index < balArr.length;index++) {                balArr[index].update()                if (balArr[index]) {                    balArr[index].render()                }            }        },40)        var balArr =[]        function getRandomColor() {            var allType ="0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f"            var allTypeArr =allType.split(",");var color ="#"            for (let index =0;index < 6;index++) {                var random =parseInt(Math.random() *allTypeArr.length);                color +=allTypeArr[random]            }            return color        }    </script></body></html>

小球连线
JAVASCRIPT
 <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title>    <style>        *{            margin: 0;            padding: 0;        }        canvas{            display: block;        }    </style></head><body>    <canvas id="can" width="800" height="600"></canvas>        <script>        var ballArr =[]        var can =document.getElementById("can");var ctx =can.getContext("2d");        can.width =document.documentElement.clientWidth        can.height =document.documentElement.clientHeight        function Ball(x,y,r) {this.x =x            this.y =y            this.r =r            this.color=getRandomColor()            this.count =0            this.dx =parseInt(Math.random() *10) - 5            this.dy =parseInt(Math.random() *10) - 5            ballArr.push(this)            this.index = ballArr.length -1        }        Ball.prototype.update =function () {            this.x +=this.dx            this.y +=this.dy            if (this.x <=this.r ||this.x >=can.width - this.r) {                this.dx =-this.dx                this.count++                this.color=getRandomColor()            }            if (this.y <=this.r ||this.y >=can.height - this.r) {                this.dy =-this.dy                this.count++                this.color=getRandomColor()            }            if (this.count >=3) {                this.remove()            }        }        Ball.prototype.remove =function () {            for (let index =0;index < ballArr.length;index++) {                if (ballArr[index] ==this) {                    ballArr.splice(index,1)                }              }        }        Ball.prototype.render =function () {            ctx.beginPath();            ctx.globalAlpha =1            ctx.arc(this.x,this.y,this.r,0,2 *Math.PI,false)            ctx.fillStyle =this.color            ctx.fill()            for (let index = this.index + 1;index < ballArr.length;index++) {                if (Math.abs(ballArr[index].x - this.x) < 180 && Math.abs(ballArr[index].y - this.y) < 180) {                    ctx.strokeStyle = getRandomColor()                    ctx.beginPath();                    ctx.globalAlpha =10 / Math.sqrt(Math.pow(ballArr[index].x - this.x,2) + Math.pow(ballArr[index].y - this.y,2))                    ctx.moveTo(this.x,this.y)                    ctx.lineTo(ballArr[index].x,ballArr[index].y)                    ctx.closePath()                    ctx.stroke()                }            }        }        can.addEventListener("click",function (event) {            for (let index =0;index < Math.ceil(Math.random() *20);index++) {                new Ball(event.offsetX,event.offsetY,Math.random() *10 + 10)            }        })        setInterval(function () {            ctx.clearRect(0,0,can.width,can.height)            for (let index =0;index < ballArr.length;index++) {                ballArr[index].update()                ballArr[index].render()            }        },25)        function getRandomColor() {            var allType ="0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f"            var allTypeArr =allType.split(",");var color ="#"            for (let index =0;index < 6;index++) {                var random =parseInt(Math.random() *allTypeArr.length);                color +=allTypeArr[random]            }            return color        }    </script></body></html>


5.线型
方法 / 属性 描述
lineCap 线开头和结束的形状
lineJoin 线交会时的形状,有三种值round,bevel,miter
setLineDash 设置虚线的样式

5.1 蚂蚁线
JS
let canvas = document.getElementById("mycanvas");        let ctx = canvas.getContext('2d');        let offset = 0;        function draw() {            ctx.clearRect(0,0, canvas.width, canvas.height);            ctx.setLineDash([2, 3]);            ctx.lineDashOffset = -offset;            ctx.strokeRect(10,10, 100, 100);        }        function march() {            offset++;            if (offset > 16) {                offset = 0;            }            draw();            setTimeout(march, 20);        }        march();


5.渐变
方法 / 属性 描述
font 设置字体大小、字体等
textAlign 根据坐标的对齐方式
fillText() (文字,x1,y1)

线型渐变
        let line = ctx.createLinearGradient(100,150,300,160);
        line.addColorStop(0, 'black');
        line.addColorStop(0.5, 'red');
        line.addColorStop(1, 'orange');
        ctx.fillStyle = line;
        ctx.fillRect(100,150,200,10);


镜像渐变
        let gradient = ctx.createRadialGradient(200,300,100,200,300,0);
        gradient.addColorStop(0,"white");
        gradient.addColorStop(.2,"red");
        gradient.addColorStop(.4,"orange");
        gradient.addColorStop(.6,"green");
        gradient.addColorStop(.8,"blue");
        gradient.addColorStop(1,"purple");
        ctx.fillStyle = gradient;
        ctx.fillRect(100,200,200,200);


6.阴影
方法 / 属性 描述
shadowOffsetX X轴偏离像素
shadowOffsetY Y轴偏离像素
shadowBlur 模糊程度
shadowColor 阴影颜色

7.使用图片
let image = new Image();
image.src = "imgs/test1.png";
image.onload = function(){
    // ctx.drawImage(image, 10, 10, 50, 50);
    ctx.drawImage(image, 0, 0, 10, 10,10, 10, 50, 50);
}4个参数表示以图片为坐标的x,y,width,height
后4个参数表示以画布为坐标的x,y,width,height

8.资源管理器
<canvas id="mycanvas" width="600" height="400"></canvas>
    <script>
        function Game(){
            this.dom = document.querySelector("canvas");
            this.ctx = this.dom.getContext("2d");

            let image = new Image();
            this.R = {
                'test1': "./imgs/test1.png",
                'test2': "./imgs/test2.png",
                'test3': "./imgs/test3.png",
                'test4': "./imgs/test4.png",
                'test5': "./imgs/test5.png",
            }
            let allAmount = Object.keys(this.R).length;
            let count = 0;
            
            for(k in this.R){
                let src = this.R[k];
                this.R[k] = new Image();
                this.R[k].src = src;

                let self = this;
                this.R[k].onload = function(){
                    count++;
                    self.ctx.clearRect(0,0,600,400);
                    self.ctx.font = "16px Arial";
                    self.ctx.fillText("图片已加载:"+count+"/"+allAmount,10,50);
                    if(count == allAmount){
                        self.start();
                    }
                }
            }
        }

        Game.prototype.start = function(){
            this.ctx.drawImage(this.R["test1"],200,200,100,100);
        }

        new Game();
    </script>


9.变形

属性/方法 
translate 和css的translate一样,空间平移
rotate 参数为旋转角度
scale 缩放(宽度缩放比,高度缩放比)>0 0~1为缩小,>1为放大
transform(a, b, c, d, e, f) a (m11)水平方向的缩放b(m12)竖直方向的倾斜偏移c(m21)水平方向的倾斜偏移d(m22)竖直方向的缩放e(dx)水平方向的移动f(dy)竖直方向的移动

10.滚动的车轮案例
    <canvas id="mycanvas" width="1200" height="500"></canvas>

    <script>
        var canvs = document.getElementById("mycanvas");
        var ctx = canvs.getContext('2d');

        let img = new Image();
        img.src = "imgs/车轮.png";
        img.onload = function(){
            let deg = 0;
            let x = 200;
            setInterval(function(){
                ctx.clearRect(0, 0, canvs.width, canvs.height);
                x+=2;
                deg += 0.08;
                ctx.save();
                ctx.translate(x, 200);
                ctx.rotate(deg);
                ctx.drawImage(img, -200/2, -200/2);  
                ctx.restore();
            },50);
        }   
   </script>





11.合成
属性/方法 描述
source-in 取重合的部分
source-over 之后的压盖前面的
source-out 取不重合的部分
source-atop 取之前的部分+重合的部分
destination-in 之前的在上层,取重合的部分
destination-atop 重合部分之前的在上层+之后的画布
destination-over 之后的将被压盖
lighter 重合的部分颜色会累加
copy 只显示之后的部分
xor 重合部分为透明
multiply 重合部分像素乘以底层像素
screen 重合部分像素被倒转,相乘,再倒转,结果是一幅更明亮的图片。
overlay 重合部分multiply和screen的结合,原本暗的地方更暗,原本亮的地方更亮。
darken 保留两个图层中最暗的像素。
lighten 保留两个图层中最亮的像素。
color-dodge 将底层除以顶层的反置。
color-burn 将底层除以顶层的反置。
hard-light 屏幕相乘(A combination of multiply and screen)类似于叠加,但上下图层互换了。
soft-light 用顶层减去底层或者相反来得到一个正值。
difference 一个柔和版本的强光(hard-light)。纯黑或纯白不会导致纯黑或纯白。
exclusion 和difference相似,但对比度较低。
hue 保留了底层的亮度(luma)和色度(chroma),同时采用了顶层的色调(hue)。
saturation 保留底层的亮度(luma)和色调(hue),同时采用顶层的色度(chroma)
color 保留了底层的亮度(luma),同时采用了顶层的色调(hue)和色度(chroma)
luminosity 保持底层的色调(hue)和色度(chroma),同时采用顶层的亮度(luma)

        // ctx.globalCompositeOperation = "saturation";//保留底层的亮度(luma)和色调(hue),同时采用顶层的色度(chroma)。
        // ctx.globalCompositeOperation = "color";//保留了底层的亮度(luma),同时采用了顶层的色调(hue)和色度(chroma)。
        ctx.globalCompositeOperation = "luminosity";//保持底层的色调(hue)和色度(chroma),同时采用顶层的亮度(luma)。



12.刮刮乐
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            border: 1px solid #000;
            width: 400px;
            height: 120px;
            font-size: 40px;
            line-height: 120px;
            text-align: center;
            position: relative;
            color: red;
            -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none;
        }
        #canvas1{
            position: absolute;
            left: 0;
            top: 0;
        }
    </style>
</head>
<body>
    <div>
        特等奖
        <canvas width="400" height="120" id="canvas1"></canvas>
    </div>

    <script>
        /* 刮刮乐 */
        let canvas1 = document.getElementById("canvas1");
        let ctx1 = canvas1.getContext('2d');

        ctx1.fillStyle = "grey";
        ctx1.fillRect(0,0,400,120);
        //
        ctx1.globalCompositeOperation = "destination-out";
        //
        canvas1.onmousedown = function(e){
            canvas1.onmousemove = function(event){
                //
                ctx1.beginPath();
                ctx1.arc(event.offsetX,event.offsetY,10,0,7,false);
                ctx1.fill();
            }
        }
    </script>
</body>
</html>

变形

属性/方法
translate和css的translate一样,空间平移
rotate参数为旋转角度
scale缩放(宽度缩放比,高度缩放比)>0 ,0~1为缩小,>1为放大
transform(a, b, c, d, e, f)a (m11)水平方向的缩放,b(m12)竖直方向的倾斜偏移,c(m21)水平方向的倾斜偏移,d(m22)竖直方向的缩放,e(dx)水平方向的移动,f(dy)竖直方向的移动

滚动的车轮案例

 <canvas id="mycanvas" width="1200" height="500"></canvas>

    <script>
        var canvs = document.getElementById("mycanvas");
        var ctx = canvs.getContext('2d');

        let img = new Image();
        img.src = "imgs/车轮.png";
        img.onload = function(){
            let deg = 0;
            let x = 200;
            setInterval(function(){
                ctx.clearRect(0, 0, canvs.width, canvs.height);
                x+=2;
                deg += 0.08;
                ctx.save();
                ctx.translate(x, 200);
                ctx.rotate(deg);
                ctx.drawImage(img, -200/2, -200/2);  
                ctx.restore();
            },50);
        }   
   </script>

在这里插入图片描述

合成

属性/方法描述
source-in取重合的部分
source-over之后的压盖前面的
source-out取不重合的部分
source-atop取之前的部分+重合的部分
destination-in之前的在上层,取重合的部分
destination-atop重合部分之前的在上层+之后的画布
destination-over之后的将被压盖
lighter重合的部分颜色会累加
copy只显示之后的部分
xor重合部分为透明
multiply重合部分像素乘以底层像素
screen重合部分像素被倒转,相乘,再倒转,结果是一幅更明亮的图片。
overlay重合部分multiply和screen的结合,原本暗的地方更暗,原本亮的地方更亮。
darken保留两个图层中最暗的像素。
lighten保留两个图层中最亮的像素。
color-dodge将底层除以顶层的反置。
color-burn将底层除以顶层的反置。
hard-light屏幕相乘(A combination of multiply and screen)类似于叠加,但上下图层互换了。
soft-light用顶层减去底层或者相反来得到一个正值
difference一个柔和版本的强光(hard-light)。纯黑或纯白不会导致纯黑或纯白。
exclusion和difference相似,但对比度较低。
hue保留了底层的亮度(luma)和色度(chroma),同时采用了顶层的色调(hue)。
saturation保留底层的亮度(luma)和色调(hue),同时采用顶层的色度(chroma)
color保留了底层的亮度(luma),同时采用了顶层的色调(hue)和色度(chroma)
luminosity保持底层的色调(hue)和色度(chroma),同时采用顶层的亮度(luma)
 // ctx.globalCompositeOperation = "saturation";//保留底层的亮度(luma)和色调(hue),同时采用顶层的色度(chroma)。
        // ctx.globalCompositeOperation = "color";//保留了底层的亮度(luma),同时采用了顶层的色调(hue)和色度(chroma)。
        ctx.globalCompositeOperation = "luminosity";//保持底层的色调(hue)和色度(chroma),同时采用顶层的亮度(luma)。

刮刮乐

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            border: 1px solid #000;
            width: 400px;
            height: 120px;
            font-size: 40px;
            line-height: 120px;
            text-align: center;
            position: relative;
            color: red;
            -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none;
        }
        #canvas1{
            position: absolute;
            left: 0;
            top: 0;
        }
    </style>
</head>
<body>
    <div>
        特等奖
        <canvas width="400" height="120" id="canvas1"></canvas>
    </div>

    <script>
        /* 刮刮乐 */
        let canvas1 = document.getElementById("canvas1");
        let ctx1 = canvas1.getContext('2d');

        ctx1.fillStyle = "grey";
        ctx1.fillRect(0,0,400,120);
        //
        ctx1.globalCompositeOperation = "destination-out";
        //
        canvas1.onmousedown = function(e){
            canvas1.onmousemove = function(event){
                //
                ctx1.beginPath();
                ctx1.arc(event.offsetX,event.offsetY,10,0,7,false);
                ctx1.fill();
            }
        }
    </script>
</body>
</html>

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值