Home > Net >  Stop the audio player
Stop the audio player

Time:10-31

I have an audio script with play/pause, I want to make the audio stop when I click on the square button at the left, and to add the timing to the right

here is the code: https://codepen.io/Amirafik/pen/YzxQZQw

HTML

<div class="title">
  Dina Mohamed
</div>
<div class="stop"></div>
<div id="audioButton">
  <div id="playerContainer">
    <div class="listen">LISTEN</div>
  </div>
</div>
<div class="duration">
  00:12
</div>
<br>_____________________________________________________</br>
<div class="note">
  <p>All items were more than perfect, we loved the experience and will order ONE OAK services again in the future for sure. <!--<span style="color:#F04E36"><br> Dina sent us an amazing feedback about her experience, tap the play button to listen to her cheerful words.</span></p>-->
</div

CSS

@import url('https://fonts.googleapis.com/css?family=montserrat:100,200,300,400,500,600,700,800,900');

body {
  background: #ffffff;
  color: #000000;
  font-size: 16px ;
  font-family: "montserrat" ;
  font-weight: 500;
  -webkit-tap-highlight-color: transparent;
}
a {
  color: #F04E36;
}
.title {
  max-width: 700px;
  margin: 0 auto;
  color: #000000;
  font-weight:700;
  display:inline-block;
}
.note {
  max-width: 380px;
  margin: 0 auto;
  color: #000000;
  display:inline-block;
}
.circle-audio-player {
  cursor: pointer;
  width:25px;
  padding:0px;
  margin-top:-67%;
  margin-bottom:-50%;
  margin-left:-7px;
  background-color:#EDEBE7;
  border-radius:50%;
  vertical-align:middle;
}
#playerContainer {
  padding: 0px;
  vertical-align:middle;
}

#audioButton {
  border-radius: 50px;
  border: 2px solid #000000;
  padding: 10px; 
  max-width: 85px;
  height: 10px;  
  display: inline-block;
  vertical-align:middle;
  margin-left:2px;
}
.listen {
  margin-left: 5px;
  color: #000000;
  font-weight:700;
  display:inline-block;
  float:right;
  vertical-align:middle;
  margin-top:-5%;
  font-size: 14px ;
}
.stop {
  max-width: 500px;
  margin-left:10px;
  height: 10px;
  width: 10px;
  background-color: #000000;
  font-weight:500;
  font-size: 14px ;
  display:inline-block;
  vertical-align:middle;
}
.duration {
  max-width: 500px;
  margin-left: 2px;
  color: #000000;
  font-weight:500;
  font-size: 14px ;
  display:inline-block;
}

JS



// settings
var DEFAULTS = {
    borderColor: "#EDEBE7",
    playedColor: "#F04E36",
    backgroundColor: "#d3cdc2",
    iconColor: "#000000",
    borderWidth: 2,
    size: 48,
    className: 'circle-audio-player'
  
};

// reused values
var pi = Math.PI;
var doublePi = pi * 2;
var arcOffset = -pi / 2;
var animTime = 200;
var loaderTime = 1800;

var CircleAudioPlayer = function (options) {
    options = options || {};
    for (var property in DEFAULTS) {
        this[property] = options[property] || DEFAULTS[property];
    }

    // create some things we need
    this._canvas = document.createElement('canvas');
    this._canvas.setAttribute('class', this.className   ' is-loading');
    this._canvas.addEventListener('mousedown', (function () {
        if (this.playing) {
            this.pause();
        }
        else {
            this.play();
        }
    }).bind(this));
    this._ctx = this._canvas.getContext('2d');

    // set up initial stuff
    this.setAudio(options.audio);
    this.setSize(this.size);

    // redraw loop
    (function cAPAnimationLoop (now) {
        // check if we need to update anything
        if (this.animating) {
            this._updateAnimations(now);
        }
        if (this._forceDraw || this.playing || this.animating || this.loading) {
            this._draw();
            this._forceDraw = false;
        }

        requestAnimationFrame(cAPAnimationLoop.bind(this));
    }).call(this, new Date().getTime());
};
CircleAudioPlayer.prototype = {
    // private methods
    _animateIcon: function (to, from) {
        // define a few things the first time
        this._animationProps = {
            animStart: null,
            from: from,
            to: to
        };
        if (from) {
            this.animating = true;
        }
        else {
            this._animationProps.current = this._icons[to].slice();
            this.draw();
        }
    },
    _updateAnimations: function (now) {
        this._animationProps.animStart = this._animationProps.animStart || now;
        var deltaTime = now - this._animationProps.animStart;
        var perc = (1 - Math.cos(deltaTime / animTime * pi / 2));
        if (deltaTime >= animTime) {
            this.animating = false;
            perc = 1;
            this._animationProps.current = this._icons[this._animationProps.to].slice();
            this.draw();
        }
        else {
            var from = this._icons[this._animationProps.from];
            var current = [];
            for (var i = 0; i < from.length; i  ) {
                current.push([]);
                for (var j = 0; j < from[i].length; j  ) {
                    current[i].push([]);
                    var to = this._icons[this._animationProps.to][i][j];
                    current[i][j][0] = from[i][j][0]   (to[0] - from[i][j][0]) * perc;
                    current[i][j][1] = from[i][j][1]   (to[1] - from[i][j][1]) * perc;
                }
            }
            this._animationProps.current = current;
        }
    },
    _draw: function (progress) {
        // common settings
        if (isNaN(progress)) {
            progress = this.audio.currentTime / this.audio.duration || 0;
        }

        // clear existing
        this._ctx.clearRect(0, 0, this.size, this.size);

        // draw bg
        this._ctx.beginPath();
        this._ctx.arc(this._halfSize, this._halfSize, this._halfSize - (this.borderWidth / 2), 0, doublePi);
        this._ctx.closePath();
        this._ctx.fillStyle = this.backgroundColor;
        this._ctx.fill();

        // draw border
        // our active path is already the full circle, so just stroke it
        this._ctx.lineWidth = this.borderWidth;
        this._ctx.strokeStyle = this.borderColor;
        this._ctx.stroke();

        // play progress
        if (progress > 0) {
            this._ctx.beginPath();
            this._ctx.arc(this._halfSize, this._halfSize, this._halfSize - (this.borderWidth / 2), arcOffset, arcOffset   doublePi * progress);
            this._ctx.strokeStyle = this.playedColor;
            this._ctx.stroke();
        }

        // icons
        this._ctx.fillStyle = this.iconColor;
        if (this.loading) {
            var loaderOffset = -Math.cos((new Date().getTime() % (loaderTime)) / (loaderTime) * pi) * doublePi - (pi / 3) - (pi / 2);
            this._ctx.beginPath();
            this._ctx.arc(this._halfSize, this._halfSize, this._halfSize / 3, loaderOffset, loaderOffset   pi / 3 * 2);
            this._ctx.strokeStyle = this.iconColor;
            this._ctx.stroke();
        }
        else {
            this._ctx.beginPath();
            var icon = (this._animationProps && this._animationProps.current) || this._icons.play;
            for (var i = 0; i < icon.length; i  ) {
                this._ctx.moveTo(icon[i][0][0], icon[i][0][1]);

                for (var j = 1; j < icon[i].length; j  ) {
                    this._ctx.lineTo(icon[i][j][0], icon[i][j][1]);
                }
            }

            // this._ctx.closePath();
            this._ctx.fill();
            // stroke to fill in for retina
            this._ctx.strokeStyle = this.iconColor;
            this._ctx.lineWidth = 2;
            this._ctx.lineJoin = 'miter';
            this._ctx.stroke();
        }
    },
    _setState: function (state) {
        this.playing = false;
        this.loading = false;
        if (state === 'playing') {
            this.playing = true;
            this._animateIcon('pause', 'play');
        }
        else if (state === 'loading') {
            this.loading = true;
        }
        else if (this.state !== 'loading') {
            this._animateIcon('play', 'pause');
        }
        else {
            this._animateIcon('play', null);
        }
        this.state = state;
        this._canvas.setAttribute('class', this.className   ' is-'   state);
        this.draw();
    },
    // public methods
    draw: function () {
        this._forceDraw = true;
    },
    setSize: function (size) {
        this.size = size;
        this._halfSize = size / 2; // we do this a lot. it's not heavy, but why repeat?
        this._canvas.width = size;
        this._canvas.height = size;
        // set icon paths
        var iconSize = this.size / 2;
        var pauseGap = iconSize / 10;
        var playLeft = Math.cos(pi / 3 * 2) * (iconSize / 2)   this._halfSize;
        var playRight = iconSize / 2   this._halfSize;
        var playHalf = (playRight - playLeft) / 2   playLeft;
        var top = this._halfSize - Math.sin(pi / 3 * 2) * (iconSize / 2);
        var bottom = this.size - top;
        var pauseLeft = this._halfSize - iconSize / 3;
        var pauseRight = this.size - pauseLeft;
        this._icons = {
            play: [
                [
                    [playLeft, top],
                    [playHalf, (this._halfSize - top) / 2   top],
                    [playHalf, (this._halfSize - top) / 2   this._halfSize],
                    [playLeft, bottom]
                ],
                [
                    [playHalf, (this._halfSize - top) / 2   top],
                    [playRight, this._halfSize],
                    [playRight, this._halfSize],
                    [playHalf, (this._halfSize - top) / 2   this._halfSize]
                ]
            ],
            pause: [
                [
                    [pauseLeft, top   pauseGap],
                    [this._halfSize - pauseGap, top   pauseGap],
                    [this._halfSize - pauseGap, bottom - pauseGap],
                    [pauseLeft, bottom - pauseGap]
                ],
                [
                    [this._halfSize   pauseGap, top   pauseGap],
                    [pauseRight, top   pauseGap],
                    [pauseRight, bottom - pauseGap],
                    [this._halfSize   pauseGap, bottom - pauseGap]
                ]
            ]
        };

        if (this._animationProps && this._animationProps.current) {
            this._animateIcon(this._animationProps.to);
        }
        if (!this.playing) {
            this.draw();
        }
    },
    setAudio: function (audioUrl) {
        this.audio = new Audio(audioUrl);
        this._setState('loading');

        this.audio.addEventListener('canplaythrough', (function () {
            this._setState('paused');
        }).bind(this));
        this.audio.addEventListener('play', (function () {
            this._setState('playing');
        }).bind(this));
        this.audio.addEventListener('pause', (function () {
            // reset when finished
            if (this.audio.currentTime === this.audio.duration) {
                this.audio.currentTime = 0;
            }
            this._setState('paused');
        }).bind(this));
    },
    appendTo: function (element) {
        element.appendChild(this._canvas);
    },
    play: function () {
        this.audio.play();
    },
    pause: function () {
        this.audio.pause();
    }
};


// now init one as an example
var cap = new CircleAudioPlayer({
    audio: 'https://www.siriusxm.com/content/dam/sxm-com/audio/test/audio-previews/audio_test03.mp3.png',
  size: 120,
  borderWidth: 8
});
cap.appendTo(playerContainer);

CodePudding user response:

You can simply use AudioElement.pause() to pause an running element, and the next AudioElement.play() will start from where you left off. You can essentially set the currentTime property of the audio element to start from the beginning

A simple demonstration of how it works

const pause = document.getElementById('pause');
const stop = document.getElementById('stop');
const play = document.getElementById('play');
const container = document.getElementById('player');
const duration = document.getElementById('duration');
const audio = new Audio('https://www.siriusxm.com/content/dam/sxm-com/audio/test/audio-previews/audio_test03.mp3.png');
let played = 0;
let playing = true;

const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
run = async function () {
    while(playing) {
        if (played == Math.floor(audio.duration)) break;
        duration.innerText = `${played} / ${Math.floor(audio.duration)}`;
        played  ;
        await wait(1000);
    }
}
container.appendChild(audio);
stop.addEventListener('click', () => {
    duration.innerText = `0 / ${Math.floor(audio.duration)}`
    audio.pause();
    audio.currentTime = 0;
    played = 0;
    playing = false;
});

pause.addEventListener('click', () => {
    audio.pause();
    playing = false;
});

play.addEventListener('click', () => {
    playing = true
    audio.play();
    run();
});
<div id="player"></div>
<div id="duration">0.0</div>
<button id="play">play</button>
<button id="stop">stop</button>
<button id="pause">pause</button>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related