canvas入门学习

看完这篇canvas学习笔记,立马入门(附带两个demo) DAY1: getContext('2d') moveTo(100,100); lineTo(200,100); stroke(); 线条不饱和解决: 设置颜色和线的宽度 ctx.beginPath()//开启新路径,可以设置新样式(和closePath不是对应关系,用处不同) ctx.fill()//填充 ctx.closePath()//开启自动闭合,如果手动闭合,会有一点点填充不满 非零环绕规则: 线的渐变实现: 画网格: ... 阅读详情

示例地址
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/

进度1,2,3,4,5,6,7,8,9,10,11,12,13,14

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>

在这里插入图片描述

threejs学习(五)--canvas入门学习 前言 最近项目中使用到了threejs中的sprite组件;为了更好实现sprite组件的界面效果;以及我们在h5中绘制图表,都需要用到canvas这个标签;所以需要对canvas有较为深入的学习; canvas是一个HTML5的标签,这个标签可以被浏览器渲染为画布;canvas只是一个容器;这个容器可以装在2d(let ctx = canvas.getContext(“2d”)),也可以装在3D(let ctx = canvas.getContext(“webgl”)); 这个容器没有绘图功能,canva 阅读详情

相关推荐

告别编译报错!手把手教你用VS2022命令行编译curl静态库(附完整测试代码)

本文详细介绍了如何在VS2022环境下通过命令行编译curl静态库,从环境准备、编译实战到项目集成,提供了完整的避坑指南和测试代码。特别针对常见的编译报错如LNK2019等给出了具体解决方案,帮助开发者高效完成网络库的静态编译与集成。

weixin_42557803的博客 447

面向 JavaScript 游戏动画仿真的物理学教程(六)

虽然一个粒子系统的精确定义可能并不存在,但是尝试定义它将有助于在我们做任何事情之前解释我们的想法。一组粒子它们移动和改变的规则他们互动的规则(如果有的话)这个定义非常笼统:所说的“规则”可以基于物理学、人工智能、生物学或任何类似的系统。不足为奇的是,我们将把自己限制在物理定律下的粒子运动和相互作用(也许这里和那里有一些奇怪的调整)。因此,我们将考虑的粒子系统将在我们在本书第二部分中讨论的力的子集的作用下,根据牛顿运动定律激活粒子。

龙哥盟 2716

【电击防护篇】电击防护技术详解:从人体效应到接地系统全解析

本文系统讲解了电击防护的关键知识,包括电流对人体的影响(如30mA是心室颤动阈值)、人体电阻特性(700Ω-6100Ω)以及电气接触防护措施。重点分析了TT、TN和IT三大接地系统的结构特点与应用场景,强调TN-S系统最安全,IT系统供电连续性最佳。详细介绍了漏电保护器(RCD)的工作原理与选型指南,建议人身防护选用30mA高灵敏度RCD。文章通过对比表总结三大系统的安全性、成本及适用场景,为电气安全设计提供实用参考。

2301_81299416的博客 1742

【R语言并行计算新突破】:future 1.33集群配置全攻略,提升计算效率90%以上

掌握R语言并行计算框架future 1.33的集群配置,轻松解决大规模数据计算瓶颈。适用于高性能计算与复杂模拟场景,通过plan()函数灵活调度多节点资源,显著提升执行效率90%以上。配置简单、兼容性强,值得收藏。

LiteProceed的博客 1012

存内计算路线再获加持,清华存内芯片登Science

通过这种方法,可以比较有效的控制二氧化铪忆阻层中的微观变化,以及内部的温度和电场,使得器件具有非常优异的电学特性,而且可以在工厂里大规模生产,推动了高性能忆阻器阵列的诞生。团队搭建了全硬件构成的完整存算一体系统,如下图7所示,在系统里集成了多个忆阻器阵列,并在该系统上高效运行了卷积神经网络算法,成功验证了图像识别功能,证明了存算一体架构全硬件实现的可行性,并且成功实现了以更小的功耗和更低的硬件成本完成复杂的计算[6]。根据测试,在一般神经网络中权重更新的最后阶段,调整步长非常接近0,如图9(C)所示,

PXX12345678的博客 1555

HFSS实战(二)——精准仿真高速PCB差分线的信号完整性

本文深入探讨了使用HFSS进行高速PCB差分线信号完整性仿真的关键技术与实战经验。从设计文件导入、模型裁剪到差分端口设置,详细解析了精准仿真的全流程,特别强调了材料特性和3D电磁场仿真在解决微带线损耗等问题中的重要性。文章还提供了常见问题排查指南和效率优化技巧,帮助工程师提升高速PCB设计的仿真精度与效率。

weixin_38170829的博客 572

R 4.5机器学习模型边缘部署:从12.8GB到196KB——4步量化剪枝+ONNX Runtime Tiny定制全流程

R 4.5机器学习模型边缘部署方法:将12.8GB模型压缩至196KB,支持树莓派等低资源设备。通过量化+剪枝+ONNX导出+Tiny Runtime定制四步流程,实现高精度、低延迟推理。适用于IoT与嵌入式场景,部署效率提升37倍,值得收藏。

ByteShoal的博客 329

2026马斯克《Moonshots》播客独家访谈全记录与深度解析

本次访谈是马斯克2026年首份重磅公开对话,录制于2025年12月22日美国得克萨斯州奥斯汀特斯拉超级工厂(Cybertruck与Optimus机器人核心生产基地),于2026年1月6日通过《Moonshots》播客正式上线,全时长近3小时。

lpfasd123的博客 2654

揭秘R语言构建系统发育树全流程:从数据准备到可视化一步到位

掌握R语言系统发育树构建全流程,从序列比对到进化树可视化一气呵成。适用于微生物进化、物种分类等研究,使用ape、phangorn等包实现最大似然法建树,操作清晰高效。科研人员必备技能,值得收藏。

CompiGlow的博客 816

Vision 机器视觉案例 之 零件边缘缺陷检测

缺陷检测工具

机器视觉李小白的博客 1386

初探802.11协议(6)——Wi-Fi 6新特性简介

Wi-Fi 6新机制(特性)介绍

FanFF的博客 1522

【R核心开发组内部文档节选】:R 4.5情感分析底层架构重构逻辑——为何现在必须重写你的get_sentiment()函数?

R 4.5情感分析底层重构,解决旧版get_sentiment()兼容性与精度瓶颈。新增基于词典增强+上下文感知的R 4.5文本挖掘情感分析方法,适用于社交媒体、客服评论等短文本场景,速度提升40%,支持多语言细粒度极性判定。值得收藏。

AlgoChat的博客 158

一根同轴线,真的扛得住 4K 吗? ——从摄像头带宽算起,聊透车载 SerDes 接口选型

如果你记住这三句话,这篇文章就值了:🎯摄像头带宽 = 分辨率 × 位深 × fps × 开销4K RAW 摄像头 ≈ 3.7Gbps,是现实不是理论SerDes 选型,宁可多留 20%,不要刚刚好。

weixin_43199439的博客 193

Canvas从入门到精通 - 系统化学习Canvas绘图技术

什么是 CanvasCanvas 的应用场景在浏览器中使用 Canvas 的方法1. 什么是 CanvasCanvas 呢,就像是一块可以在网页上画画的神奇 “画布”。它是 HTML5 中新增的一个元素,可以通过 JavaScript 来在上面绘制各种图形、图像和动画。它可以让网页变得更加生动有趣,不再只是单调的文字和图片。简单来说,Canvas 提供了一种在网页上进行图形绘制的强大工具,让开发者能够自由地创造各种视觉效果。2. Canvas 的应用场景。

YunWisdom 2000

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Canvas从入门到精通 - 系统学习Canvas 技术

Canvas从入门到进阶的系统学习

YunWisdom 4387

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Canvas学习:Canvas入门准备

由于工作的需要,最近开始在学习HTML5的canvas相关的知识。这里主要记录自己学习canvas相关的知识笔记。如果文章有不对之处,还请大婶们多多指正。 今天这篇文章是学习canvas的一些准备工作。 canvas元素 也是HTML中的一个元素,可以给这个元素添加一些HTML属性,比如使用width和height来控制其大小,也可以通过style给它设置一些基本样式。同样也可以它添加id名

wulixiaoxiao1的博客 2091

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

C# WPF入门学习主线篇(十二)—— Canvas布局容器

在《C# WPF入门学习主线篇(十二)—— Canvas布局容器》这篇文章中,我们详细介绍了WPF中的 `Canvas` 布局容器。本文涵盖了 `Canvas` 的基本概念、常见属性以及使用方法,通过具体的示例代码,展示了如何精确控制控件的位置。此外,还讨论了 `Canvas` 布局容器的优缺点,帮助读者在实际开发中做出更好的布局选择。

weixin_56595425的博客 1634

Canvas入门学习笔记

1. 什么是Canvas? 1.canvas标签是HTML5中的一个标签,是一个绘制面板(画布) 2.需要结合js代码进行操作,canvas定义为页面的一个可以绘制图像的区域 3.canvas默认像素是300*150 注意:如果浏览器不支持canvas标签,标签中的内容会显示出来 2. Canvas中的属性和方法 2.1 路径 方法 描述 moveTo() 把路径移动到画布中的指...

msyqmsyq的博客 424

Canvas学习笔记00:canvas基础知识,入门的开始

hello,我是贝格前端工场,最近在学习canvas,分享一些canvas的一些知识点笔记,本期分享canvas的基础知识,欢迎老铁们一同学习,欢迎关注。

贝格前端工场的博客 849

Canvas 30分钟跑通却被问为什么,机器学习入门+代码补全让我召回从60%拉到91%

用 SageMaker Canvas 无代码建模 30 分钟跑通客户流失预测,准确率 88% 却被业务质疑,发现只有 60% 的召回率。通过亚马逊云科技的机器学习入门课程看懂混淆矩阵、特征工程和数据预处理,结合代码补全重构特征,最终召回率提升到 91%,并产出可解释性报告让业务信服。本文适合从无代码工具转型的业务分析师,记录学习突破全过程。

weixin_47315004的博客 59

canvas 输入_canvas入门学习草稿纸5——canvas文字渲染

canvas文字渲染对于封装好的渲染功能,(这里想指的是那些不是由计算好定位然后绘制图案的操作,而是由canvas本身提供好的绘制功能。比如这里的文字,文字是自己输入的,而不是自己计算好位置,一横一竖的画出来的功能。),很多都可以和其他的地方进行类比,比如html渲染(包括css的样式控制) 可以类比想象到,如果canvas要实现文字渲染功能,肯定需要支持文字的字体、字号大小、文字颜色、粗细、行高...

weixin_42349214的博客 266

Canvas学习系列之入门

HTML 5 Canvas         ------------用于在网页绘制图形。   1、什么是Canvas?    题外话:从翻译角度来讲是帆布、油布    配合脚本在网页上绘制图像 画布是一个矩形区域,您可以控制其每一像素 有多种绘制路径、矩形、圆形、字符以及添加图像的方法 2、创建Canvas元素 &lt;canvas id="test...

Focus-Fe 140

canvas简单学习--入门级别

一直对canvas充满敬畏感,今天终于有空来看看,简单了解了下,算是入门吧 参照文档,做了几个示范,大概有了一定了认识,总的来说 canvas的制作会有几个步骤如下:(个人理解,不喜可喷) 1.通过canvas标签,创建 画布实例 // canvas标签 创建一块画布,可通过 宽高属性设置 大小,本身是没有绘图能力,需要通过 代码实现 <canvas class="canvas-r" id...

qq_45219069的博客 443

入门canvas - 通过刮奖效果来学习

一 、前言 一直在做PC端的前端开发,从互联网到行业软件。最近发现移动端已经成为前端必备技能了,真是不能停止学习。HTML5新增的一些东西,canvas是用的比较多也比较复杂的一个,简单的入门了一下,通过一个刮奖效果来学习。   二、canvas基础 本文的目标是做一个刮奖效果,但是如果都不知道canvas是怎么回事,那么肯定也无法进行下去,所以先讲讲canvas基础吧。 首先,该怎么理...

学习记录 551

html5 canvas学习入门之线性图

canvas简介: canvas 最早由Apple引入WebKit,用于Mac OS X 的 Dashboard,后来又在Safari和Google Chrome被实现。 基于 Gecko 1.8的浏览器,比如 Firefox 1.5, 同样支持这个元素。 canvas 元素是WhatWG Web applications 1.0规范的一部分,也包含于HTML 5中。 canvas 是 HTML...

邪小新的博客 612
上一篇: webuiPopover的使用
Checker_Code
博客等级 码龄7年 0粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值