canvas 实现声呐发声效果

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title>声纳</title>
        <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>

        <style>
            body {
                margin: 0;
            }

            #mainCanvas {
                display: block;
            }

            .legend {
                pointer-events: none;
                position: absolute;
                color: white;
                font-family: sans-serif;
            }

            .legend p {
                -webkit-user-select: none;
                /* Chrome/Safari */
                -moz-user-select: none;
                /* Firefox */
                -ms-user-select: none;
                /* IE10+ */
                /* Rules below not implemented in browsers yet */
                -o-user-select: none;
                user-select: none;
                top: 10px;
                left: 25px;
                position: relative;
                margin: 0;
                text-transform: uppercase;
                letter-spacing: 5px;
            }

            .legend p.vert {
                left: 5px;
                margin-top: 10px;
                writing-mode: vertical-lr;
                text-orientation: upright;
            }
        </style>
    </head>

    <body>
        <script src="https://cdn.bootcss.com/pizzicato/0.6.1/Pizzicato.min.js"></script>
        <div class="legend">
            <p class="">Pitch</p>
            <p class="vert">Volume</p>
        </div>
        <canvas id="mainCanvas" background="#FFFFFF">Canvas fail!</canvas>
        <script>
            var SceneManager = function(ctx) {
                this.waves = [];
                this.hue = 208;
                this.sat = 64;
                this.lum = 15;
                this.opacity = 1;
                this.msgOpacity = 1;
                this.started = false;

                //button handlers
                this.mouseOff = function() {}
                this.mouseHover = function(mouse) {}
                this.mouseClick = function(mouse) {
                    this.started = true;
                    this.createWave(mouse.x, mouse.y)
                }

                this.createWave = function(centerX, centerY) {
                    var wave = new Wave(ctx, centerX, centerY);
                    wave.init();
                    this.waves.push(wave);
                }

                this.destroyWave = function(index) {
                    this.waves.splice(index, 1);
                }

                this.update = function() {
                    if(this.started) {
                        this.msgOpacity -= 0.05;
                    }
                    for(var i = 0; i < this.waves.length; i++) {
                        this.waves[i].update();
                        if(this.waves[i].ripples.length === 0) {
                            this.destroyWave(this.waves[i]);
                        }
                    }
                }

                this.render = function() {
                    ctx.beginPath();
                    ctx.lineWidth = 1;
                    ctx.textAlign = "start";
                    ctx.fillStyle = "hsla(" + this.hue + ", " + this.sat + "%, " + this.lum + "%, " + this.opacity + ")";
                    ctx.fillRect(0, 0, canvasWidth, canvasHeight);
                    ctx.strokeStyle = "hsla(255, 255%, 255%, 1)";
                    ctx.moveTo(5, 25);
                    ctx.lineTo(250, 25);
                    ctx.moveTo(20, 5);
                    ctx.lineTo(20, 250);
                    ctx.font = "15px Arial";
                    ctx.strokeText('+', 240, 20);
                    ctx.strokeText('+', 5, 240);
                    ctx.font = "32px Arial";
                    ctx.textAlign = "center";
                    ctx.fillStyle = "hsla(255, 255%, 255%," + this.msgOpacity + " )";
                    ctx.fillText('点击任何地方发出一些噪音', canvasWidth / 2, canvasHeight / 2);
                    ctx.stroke();
                    ctx.closePath();
                    for(var i = 0; i < this.waves.length; i++) {
                        this.waves[i].render();
                    }
                }
            }

            var Wave = function(ctx, cx, cy) {
                this.ripples = [];
                this.rippleSpeed = 10;
                this.rippleCount = 4;

                this.init = function() {
                    for(var i = 1; i < this.rippleCount + 1; i++) {
                        var decay = Math.pow(0.65, i);
                        var ripple = new Ripple(ctx, cx, cy, this.rippleSpeed, decay);
                        ripple.init();
                        this.ripples.push(ripple);
                    }
                    this.ripples[0].sound.play();
                }

                this.destroyRipple = function(index) {
                    this.ripples.splice(index, 1);
                }

                this.update = function() {
                    for(var i = 0; i < this.ripples.length; i++) {
                        this.ripples[i].update();
                        if(this.ripples[i].killMe) {
                            this.destroyRipple(i);
                        }
                    }
                }

                this.render = function() {
                    for(var i = 0; i < this.ripples.length; i++) {
                        this.ripples[i].render();
                    }
                }
            }

            var Ripple = function(ctx, cx, cy, r, decay) {
                this.radius = 1;
                this.shadowRadius = 0;
                this.rSpeed = r;
                this.decay = decay;
                this.lineWidth = 10;
                this.epicenterX = cx;
                this.epicenterY = cy;
                this.sound;
                this.killMe = false;
                this.opacity = 1;

                this.init = function() {
                    this.createSound();
                }

                this.createSound = function() {
                    this.sound = new Pizzicato.Sound({
                        source: 'wave',
                        options: {
                            volume: this.epicenterY / canvasHeight,
                            frequency: this.epicenterX
                        }
                    });
                    var delay = new Pizzicato.Effects.DubDelay({
                        feedback: 0.5,
                        time: 0.7,
                        mix: 0.5,
                        cutoff: 500
                    });
                    this.sound.addEffect(delay);
                }

                this.update = function() {
                    this.rDelta = this.rSpeed * this.decay;
                    this.radius += this.rDelta;
                    this.shadowRadius += this.rDelta;
                    if(this.radius > 100) {
                        this.sound.stop();
                    }
                    if(this.lineWidth > 1) {
                        this.lineWidth -= 0.35 * this.decay;
                    }
                    if(this.radius > 250 && this.opacity > 0) {
                        this.opacity -= 0.1;
                    }
                    //this.build();
                    if(this.radius > 400) {
                        this.killMe = true;
                    }
                }

                this.render = function() {
                    ctx.beginPath();
                    ctx.lineWidth = this.lineWidth + 2;
                    ctx.strokeStyle = "hsla(33, 97%, 49%, " + this.opacity + ")";
                    ctx.arc(this.epicenterX, this.epicenterY, this.shadowRadius, 0, 2 * Math.PI);
                    ctx.stroke();
                    ctx.closePath();
                    ctx.beginPath();
                    ctx.lineWidth = this.lineWidth;

                    ctx.strokeStyle = "hsla(255, 255%, 255%, " + this.opacity + ")";
                    ctx.arc(this.epicenterX, this.epicenterY, this.radius, 0, 2 * Math.PI);
                    ctx.stroke();
                    ctx.closePath();
                }
            }

            // LIFECYCLE
            var frames = 0;

            function update() {
                frames++;
                sm.update();

                // render
                render();
            }

            function render() {

                // clear
                context.clearRect(0, 0, canvasWidth, canvasHeight);

                sm.render();

                requestAnimationFrame(update);

            }

            // DEFINITIONS
            var canvas = document.getElementById('mainCanvas');
            var context = canvas.getContext('2d');
            var canvasWidth = canvas.width = window.innerWidth;
            var canvasHeight = canvas.height = window.innerHeight;
            var currentFrame = 0;
            var mouseX = -1;
            var mouseY = -1;
            var isMousePressed = false;

            var sm = new SceneManager(context);

            window.onresize = function() {
                canvasWidth = canvas.width = window.innerWidth;
                canvasHeight = canvas.height = window.innerHeight;
            }

            function onMouseMove(evt) {
                mouseX = evt.clientX;
                mouseY = evt.clientY;
            }

            function onMouseDown(evt) {
                isMousePressed = true;
            }

            function onMouseUp(evt) {
                isMousePressed = false;
                sm.mouseClick(evt);
            }

            canvas.addEventListener("mousemove", onMouseMove);
            canvas.addEventListener("mousedown", onMouseDown);
            canvas.addEventListener("mouseup", onMouseUp);

            requestAnimationFrame(update);
        </script>

    </body>

</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值