五、  Canvas 入门案例

1.  canvas 圆形绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas圆形绘制</title>

    <style>
        * {
            margin: 0;
        }

        #canvas {
            display: block;
            margin: 50px auto;
            background-color: #ffffff;
        }
    </style>
</head>
<body bgcolor="black">
<canvas id="canvas" width="500" height="500"></canvas>
</body>
<script>
    var cxt = canvas.getContext('2d');//画笔

    var color = cxt.createLinearGradient(0, 200, 0, 300);
    color.addColorStop(0, 'pink');
    color.addColorStop(1, 'red');
    cxt.shadowColor = 'red';
    cxt.shadowOffsetX = 1;
    cxt.shadowOffsetY = 1;
    cxt.shadowBlur = 50;//模糊度

    cxt.save();//保存路径
    cxt.fillStyle = color;//填充颜色
    cxt.beginPath();//开始路径
    cxt.arc(250, 250, 50, 0, Math.PI * 2, false);//绘制圆(x,y,r,0deg,360deg,false/true);
    cxt.closePath();//闭合路径
    cxt.fill();//填充方法
    cxt.restore();//释放路径
</script>
</html>

2.  canvas 线条绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas线条绘制</title>

    <style>
        *{
            margin: 0;
        }
        #canvas{
            display: block;
            margin: 50px auto;
            background-color: #ffffff;
        }
    </style>
</head>
<body bgcolor="black">
<canvas id="canvas" width="500" height="500"></canvas>
</body>
<script>
    var cxt = canvas.getContext('2d');//画笔

    //线条颜色渐变
    var  color = cxt.createLinearGradient(100,200,300,200);
    color.addColorStop(0,'yellow');
    color.addColorStop(1,'red');

    cxt.save();//保存路径
    cxt.strokeStyle = color;//线条颜色
    cxt.lineWidth = 1;//线条宽度
    cxt.beginPath();//开始路径
    cxt.moveTo(100,200);//起点坐标 绘制线;
    cxt.lineTo(300,200);//终点坐标 绘制线;
    cxt.closePath();//闭合路径
    cxt.stroke();//线条颜色方法
    cxt.restore();//释放路径
</script>
</html>

3.  canvas 矩形绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>canvas矩形绘制</title>
    <style>
        * {
            margin: 0;
        }

        #canvas {
            display: block;
            margin: 50px auto;
            background-color: #ffffff;
        }
    </style>
</head>
<body bgcolor="black">
<canvas id="canvas" width="500" height="500"></canvas>
</body>
<script>
    var cxt = canvas.getContext('2d');//画笔

    var color = cxt.createLinearGradient(0, 200, 0, 300);
    color.addColorStop(0, 'pink');
    color.addColorStop(1, 'red');
    cxt.shadowColor = 'red';
    cxt.shadowOffsetX = 1;
    cxt.shadowOffsetY = 1;
    cxt.shadowBlur = 50;//模糊度

    cxt.save();//保存路径
    cxt.fillStyle = color;//填充颜色
    cxt.beginPath();//开始路径
    cxt.rect(200,200,6,160);//绘制矩形(x,y,w,h);
    cxt.closePath();//闭合路径
    cxt.fill();//填充方法
    cxt.restore();//释放路径
</script>
</html>

4.  粒子连线

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>粒子连线</title>

</head>
<body>
<canvas id="canvas" style="background-color: black"></canvas>
</body>
<script>
    function Star() {
        this.cxt = canvas.getContext('2d');
        console.log(this.cxt);
        this.CircleNum = 200;//粒子个数
        this.data = [];//存储粒子的数据
    }

    Star.prototype = {
        //初始化
        init: function () {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            this.cW = canvas.width;
            this.cH = canvas.height;

            for (var i = 0; i < this.CircleNum; i++) {
                this.data[i] = {
                    //粒子位置
                    x: Math.random() * this.cW,
                    y: Math.random() * this.cH,
                    //粒子速度增量
                    sX: -0.3 + Math.random() * 0.6,
                    sY: -0.3 + Math.random() * 0.6,
                };
                // this.drawCircle(this.data[i].x, this.data[i].y);
            }
        },
        //绘制粒子
        drawCircle: function (x, y) {
            var cxt = this.cxt;
            cxt.save();//保存路径
            cxt.fillStyle = 'pink';//填充颜色
            cxt.beginPath();//开始路径
            cxt.arc(x, y, 1, 0, Math.PI * 2, false);//绘制圆(x,y,r,0deg,360deg,false/true);
            cxt.closePath();//闭合路径
            cxt.fill();//填充方法
            cxt.restore();//释放路径
        },
        //移动粒子以及粒子连线
        moveCircle: function () {
            var self = this;
            var cxt = self.cxt;
            var cW = self.cW;
            var cH = self.cH;

            cxt.clearRect(0, 0, cW, cH);//先清空画布
            for (var i = 0; i < self.CircleNum; i++) {
                self.data[i].x += self.data[i].sX;
                self.data[i].y += self.data[i].sY;

                //边界的碰撞检测
                if (self.data[i].x > cW || self.data[i].x < 0)
                    self.data[i].sX = -self.data[i].sX;
                if (self.data[i].y > cH || self.data[i].y < 0)
                    self.data[i].sY = -self.data[i].sY;

                self.drawCircle(self.data[i].x, self.data[i].y);

                //判断粒子连线:连成三角形,勾股定理
                for (var j = 0; j < self.CircleNum; j++) {//下一个点
                    if (Math.pow(self.data[i].x - self.data[j].x, 2) +
                        Math.pow(self.data[i].y - self.data[j].y, 2) <= 60 * 60) {
                        self.drawLine(self.data[i].x, self.data[i].y, self.data[j].x, self.data[j].y);
                    }
                }

                //鼠标移入进行连线
                var mouse = document.getElementById("canvas");
                mouse.onmousemove = function (event) {//获取鼠标坐标
                    var e = event || window.event;
                    self.mouseX = Math.floor(e.clientX);//e.pageX/pageY
                    self.mouseY = Math.floor(e.clientY);
                };
                //console.log(self.mouseX+":"+self.mouseY );
                if (Math.pow(self.data[i].x - self.mouseX, 2) +
                    Math.pow(self.data[i].y - self.mouseY, 2) <= 100 * 100) {
                    self.drawLine(self.data[i].x, self.data[i].y, self.mouseX, self.mouseY);
                }
            }
        },
        //绘制线条
        drawLine: function (x1, y1, x2, y2) {
            var cxt = this.cxt;
            //线条颜色渐变
            var color = cxt.createLinearGradient(x1, y1, x2, y2);
            color.addColorStop(0, '#0ff');
            color.addColorStop(1, '#06f');

            cxt.save();//保存路径
            cxt.strokeStyle = color;//线条颜色
            cxt.globalCompositeOperation = "lighter";
            cxt.lineWidth = .1;//线条宽度
            cxt.beginPath();//开始路径
            cxt.moveTo(x1, y1);//起点坐标 绘制线;
            cxt.lineTo(x2, y2);//终点坐标 绘制线;
            cxt.closePath();//闭合路径
            cxt.stroke();//线条颜色方法
            cxt.restore();//释放路径
        }
    };

    var star = new Star();//实例化对象
    star.init();

    /*    setInterval(function () {
            star.moveCircle();
        }, 6);*/

    function render() {
        star.moveCircle();
        requestAnimationFrame(render);//请求帧动画, 回调稳步执行
    }
    render();

</script>
</html>

5.  鼠标滑动冒泡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="KeyWords" content="">
    <meta name="Description" content="">
    <title>canvas鼠标滑动气泡</title>

</head>
<body>
<canvas id="canvas" style="background-color: black"></canvas>
</body>
<script>
    (function () {
        function Bubble(x,y) {
            this.cxt = canvas.getContext('2d');
            this.x = x;
            this.y = y;
            this.r = Math.random() * 90;
            this.color = "#"+Math.floor(Math.random()*1000);
            this.sX = -2 + Math.random() * 4;
            this.sY = -2 + Math.random() * 4;
        }

        Bubble.prototype = {
            //初始化canvas
            init: function () {
                canvas.width = window.innerWidth;
                canvas.height = window.innerHeight;
                this.cW = canvas.width;
                this.cH = canvas.height;
            },
            //画气泡
            drawBubble: function () {
                var cxt = this.cxt;
                cxt.save();
                cxt.fillStyle = this.color;
                cxt.globalCompositeOperation = "lighter";//颜色叠加方案xor
                cxt.beginPath();
                cxt.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);//false逆时针
                cxt.closePath();
                cxt.fill();
                cxt.restore();
            },
            //鼠标滑动气泡
            moveBubble: function () {
                var self = this;
                self.x +=self.sX;
                self.y +=self.sY;
                self.r *=0.96;
            },
            //按键恢复气泡的大小
            change:function () {
                this.r = 90;
            }
        };

        var bubbleList = [];//储存气泡的容器
        var bubble = new Bubble();
        bubble.init();

        canvas.addEventListener("mousemove", function (e) {
            bubbleList.push(new Bubble(e.clientX, e.clientY));
        });

        function render() {
            bubble.cxt.clearRect(0,0,bubble.cW,bubble.cH);
            bubbleList.forEach(function (ball) {//绘制操作
                ball.drawBubble();
                ball.moveBubble();
            });
            for (var i in bubbleList){//释放空间,维护操作
                if (bubbleList[i].r == 0.001)
                    bubbleList.splice(i,1);
            }
            requestAnimationFrame(render);
        }

        render();

        window.addEventListener("keydown",function (e) {//按键还原气泡
            if (e.keyCode =='32'){
           bubbleList.forEach(function (ball) {
               ball.change();
           });
        }
        });

    })();
</script>
</html>

6.  彩虹雨

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Canvas雨滴</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
    </style>
</head>
<style>
</style>
<body>
<canvas id="canvas" style="background-color: black">
    <audio src="下雨声.mp3" controls autoplay="autoplay" loop="loop"></audio>
</canvas>

</body>
<script>
    (function () {
            function Rain() {
                this.cxt = canvas.getContext('2d');
                this.rainData = {
                    x: random(0, window.innerWidth),
                    y: random(-1, 0),
                    vX: random(8, 16),
                    vY: random(16, 32),
                    r: random(2, 6),
                    h: -60,
                };
                this.color = {
                    red: Math.floor(random(0, 255)),
                    green: Math.floor(random(0, 255)),
                    black: Math.floor(random(0, 255)),
                };
            }

            function random(min, max) {
                return min + Math.random() * (max - min);
            }

            Rain.prototype = {
                //初始化
                init: function () {
                    canvas.width = window.innerWidth;
                    canvas.height = window.innerHeight;
                    this.cW = canvas.width;
                    this.cH = canvas.height;

                    this.cloudNum = 66;
                    this.cloudData = [];
                    for (var i = 0; i < this.cloudNum; i++)
                        this.cloudData[i] = {
                            x: random(-100, 1300),
                            y: random(360, 600),
                            r: random(20, 60),
                        };
                },
                //空中雨滴
                drawRain: function () {
                    var cxt = this.cxt;
                    var c = this.color;
                    var data = this.rainData;
                    var color = cxt.createLinearGradient(data.x, data.y, data.x, data.y + data.h);
                    color.addColorStop(0, "rgba(" + c.red + "," + c.green + "," + c.black + "," + "1)");
                    color.addColorStop(1, "rgba(" + c.red + "," + c.green + "," + c.black + "," + "0.1)");
                    cxt.save();
                    cxt.fillStyle = color;
                    cxt.beginPath();
                    cxt.rect(data.x, data.y, 1, data.h);
                    cxt.closePath();
                    cxt.fill();
                    cxt.restore();
                },

                moveRain: function () {
                    var flag,
                        inX,
                        inY,
                        lastX;
                    for (var i = 0; i < rain.cloudNum; i++) { //碰撞检测
                        if (Math.pow(rain.cloudData[i].x - this.rainData.x, 2) + Math.pow(rain.cloudData[i].y - this.rainData.y, 2) <= rain.cloudData[i].r * rain.cloudData[i].r) {
                            flag = true;
                            inX = this.rainData.x;
                            inY = this.rainData.y;
                            break;
                        } else {
                            flag = false;
                        }
                    }
                    //console.log(flag);
                    if (flag) {
                        this.rainData.h = 0;
                        lastX = rain.cloudData[i].x;
                        this.rainData.y -= this.rainData.vY * random(0, 6);
                        this.rainData.x += (this.rainData.x > lastX ? this.rainData.vX : -this.rainData.vX);
                        this.drawCircle(inX, inY - this.rainData.r, this.rainData.r, this.color.red, this.color.green, this.color.black);
                    } else {
                        if (this.rainData.h > -60)
                            this.rainData.h -= 6;
                        this.rainData.y += this.rainData.vY;
                    }
                },
                //云层雨滴
                drawCircle: function (x, y, r, red, green, black) {
                    var cxt = this.cxt;
                    cxt.save();
                    cxt.fillStyle = "rgb(" + red + "," + green + "," + black + ")";
                    cxt.shadowColor = "rgb(" + red + "," + green + "," + black + ")";
                    cxt.shadowBlur = 30;
                    cxt.globalCompositeOperation = 'lighter';
                    cxt.beginPath();
                    cxt.arc(x, y, r, 0, Math.PI * 2, false);
                    cxt.closePath();
                    cxt.fill();
                    cxt.restore();
                },
                //云层
                drawCloud: function (x, y, r) {
                    this.drawCircle(x, y, r, 15, 15, 15);
                },
                //云层移动与碰撞检测
                moveCloud: function () {
                    var data = this.cloudData;
                    for (var i = 0; i < this.cloudNum; i++) {
                        data[i].x += 0.8;
                        if (data[i].x - data[i].r > this.cW)
                            data[i].x = -data[i].r;
                        data[i].r *= random(0.9999, 1);
                        if (data[i].r < 20 || data[i].r > 60)
                            data[i].r = random(20, 60);

                        this.drawCloud(data[i].x, data[i].y, data[i].r);
                    }
                },
            };

            var rain = new Rain();
            rain.init();
            var rainArr = [];

            function produce() {
                for (var i = 0; i < 2; i++)
                    rainArr.push(new Rain());
            }

            function render() {
                rain.cxt.clearRect(0, 0, rain.cW, rain.cH);
                produce();
                rainArr.forEach(function (rainer) {
                    rainer.drawRain();
                    rainer.moveRain();
                });
                rain.drawRain();
                rain.moveCloud();
                //回收机制
                for (var i in rainArr) {
                    if (rainArr[i].rainData.y > rain.cH || rainArr[i].rainData.x > rain.cW)
                        rainArr.splice(i, 1);
                }
                //console.log(rainArr.length);
                requestAnimationFrame(render);
            }

            render();
        }
    )();
</script>
</html>
05-11 16:21