惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

zodream梦想开源/个人编程日记

angular 21 升级使用 signals 方案笔记-zodream梦想开源/个人编程日记 文件解析笔记-zodream梦想开源/个人编程日记 密码本开发笔记之读写与保存-zodream梦想开源/个人编程日记 基于 SkiaSharp 的轮廓获取-zodream梦想开源/个人编程日记 SkiaSharp 把 pixel byte[] 转成 SKBitmap-zodream梦想开源/个人编程日记 nas 使用 Docker 安装 gogs-zodream梦想开源/个人编程日记 复制 android 手机中的文件到电脑-zodream梦想开源/个人编程日记 最新|个人日记-zodream梦想开源/个人编程日记 升级 SiteServer CMS 并迁移到 Linux 服务器-zodream梦想开源/个人编程日记 最新|个人日记-zodream梦想开源/个人编程日记 最新|个人日记-zodream梦想开源/个人编程日记 最新|个人日记-zodream梦想开源/个人编程日记 周报:寻找优质的周刊-zodream梦想开源/个人编程日记 开发日志:对Markdown的代码块新增引用来源支持-zodream梦想开源/个人编程日记 周报:怎么写技术类的教程文章-zodream梦想开源/个人编程日记 css display:flex 布局尺寸超出问题-zodream梦想开源/个人编程日记 周报:SEO优化的思考-zodream梦想开源/个人编程日记 Edge 浏览器不适用 Edge Image Viewer 打开图片 -zodream梦想开源/个人编程日记 SEO 学习笔记(一) 内容来源-zodream梦想开源/个人编程日记 PHP 实现双因素身份认证(2FA)-zodream梦想开源/个人编程日记 winui3 自定义标题栏-zodream梦想开源/个人编程日记 WPF MVVM 获取List 多选数据-zodream梦想开源/个人编程日记 php 接入 WebAuthn 登录-zodream梦想开源/个人编程日记 Burp Suite 抓包-zodream梦想开源/个人编程日记 lnmp php集成环境安装包使用-zodream梦想开源/个人编程日记 js 进行在线编辑器开发-zodream梦想开源/个人编程日记 使用 indexnow 注意事项-zodream梦想开源/个人编程日记 Godot 使用字体图标 例如: Iconfont、FontAwesome-zodream梦想开源/个人编程日记 angular 15 对指定页面进行访问限制-zodream梦想开源/个人编程日记 CSS 使用 column-count 实现瀑布流出现内容分割的解决办法-zodream梦想开源/个人编程日记 angular 15 实现按下确认键,焦点移动到下一个表单或提交表单-zodream梦想开源/个人编程日记 input 确认按键事件在手机端不生效-zodream梦想开源/个人编程日记 C# 使用socket 进行通讯-zodream梦想开源/个人编程日记 Maui开发中Windows应用开启管理员权限-zodream梦想开源/个人编程日记 Maui 中自定义控件-zodream梦想开源/个人编程日记 TencentOS Server 3.1 安装 Nginx 1.23、PHP 8.2、MariaDB 10.11-zodream梦想开源/个人编程日记 angular 14 使用 ng-template 实现tree 结构显示-zodream梦想开源/个人编程日记 angular 14 替换 ComponentFactoryResolver 实现动态创建组件-zodream梦想开源/个人编程日记 c# 动态安装和卸载dll-zodream梦想开源/个人编程日记 慎用 CompositionTarget.Rendering-zodream梦想开源/个人编程日记 c# 重写 c++ 程序笔记:数据初始化-zodream梦想开源/个人编程日记 源码编译 aseprite-zodream梦想开源/个人编程日记 记录一下字符串分隔split各语言之间的不同-zodream梦想开源/个人编程日记 c# Gzip解码无头内容-zodream梦想开源/个人编程日记 Windows 10 查看内存占用-zodream梦想开源/个人编程日记 UWP 使用 win2d:加阴影-zodream梦想开源/个人编程日记 清除 PowerShell 历史记录-zodream梦想开源/个人编程日记 c# 调用 c++ 的dll-zodream梦想开源/个人编程日记 c# 重写 c++ 程序笔记:遍历-zodream梦想开源/个人编程日记 Net Core 与 UWP 共用类开发-zodream梦想开源/个人编程日记 hashcat(二)找回rar解压密码-zodream梦想开源/个人编程日记 Godot 学习笔记(一)-zodream梦想开源/个人编程日记 升级vue3记录-zodream梦想开源/个人编程日记 angular 12 显示数学公式-zodream梦想开源/个人编程日记 js 监听按键事件-zodream梦想开源/个人编程日记 angular 12 ng-deep 使用注意事项-zodream梦想开源/个人编程日记 angular 16 动态生成组件-zodream梦想开源/个人编程日记 angular 12 动画执行完成事件-zodream梦想开源/个人编程日记 angular 12 全局搜索组件-zodream梦想开源/个人编程日记 angular 12 中单例 Service 的使用-zodream梦想开源/个人编程日记 js 实现一个正则替换-zodream梦想开源/个人编程日记 uwp win2d 使用-zodream梦想开源/个人编程日记 UWP Custom Control自定义控件开发-zodream梦想开源/个人编程日记 UWP 读取应用内资源-zodream梦想开源/个人编程日记 gin 使用笔记(二)出错点-zodream梦想开源/个人编程日记 gin 使用笔记(一)基础-zodream梦想开源/个人编程日记 angular 关于自定义组件事件传递-zodream梦想开源/个人编程日记 angular 11 怎么获取 Content-Disposition-zodream梦想开源/个人编程日记 apache 使用gzip 压缩 js、css-zodream梦想开源/个人编程日记 angular 11 返回上一页保留页面数据的思考-zodream梦想开源/个人编程日记 Net Core 实现一个简单的分页功能-zodream梦想开源/个人编程日记 关于内容中的 @用户 加 话题 的一些想法-zodream梦想开源/个人编程日记 Github Host 更改-zodream梦想开源/个人编程日记 OBS-Studio 等录屏软件录制显示器内容的黑屏的解决方法-zodream梦想开源/个人编程日记 angular 11 FormBuilder 中 FormGroup 和 FormArray 使用-zodream梦想开源/个人编程日记 angular 11 ngrx/effects 使用理解-zodream梦想开源/个人编程日记 angular 11 ngrx/store 使用理解-zodream梦想开源/个人编程日记 angular 10 直接获取表单值-zodream梦想开源/个人编程日记 angular 10 使用 tinymce 编辑器-zodream梦想开源/个人编程日记 htaccess 搭配 angular 10 放在二级目录-zodream梦想开源/个人编程日记 微信小程序跨页面传值-zodream梦想开源/个人编程日记 js 对 FileList 进行文件过滤上传-zodream梦想开源/个人编程日记 angular自定义表单组件支持 formControlName-zodream梦想开源/个人编程日记 基于不同形式的json响应处理-zodream梦想开源/个人编程日记 flutter CupertinoPicker 使用不显示-zodream梦想开源/个人编程日记 CC协议-zodream梦想开源/个人编程日记 flutter margin 负值实现-zodream梦想开源/个人编程日记 win10添加删除开机自启项-zodream梦想开源/个人编程日记 Wallpager Engine 删除记录-zodream梦想开源/个人编程日记 angular10教程之http 拦截器-zodream梦想开源/个人编程日记 dpl 文件-zodream梦想开源/个人编程日记 微信小程序开发记录(一)真机无法进入页面-zodream梦想开源/个人编程日记 flutter 跳转页面操作上一页-zodream梦想开源/个人编程日记 Regex Generator 使用指南-zodream梦想开源/个人编程日记 go init函数-zodream梦想开源/个人编程日记 angular 9 升级 angular 10-zodream梦想开源/个人编程日记 kotlin AndroidManifest 注意事项-zodream梦想开源/个人编程日记 对于zodream 框架的优化的思考-zodream梦想开源/个人编程日记 flutter 页面滚动条-zodream梦想开源/个人编程日记 flutter swiper 使用-zodream梦想开源/个人编程日记
一个简单的HTML音视频播放器-zodream梦想开源/个人编程日记
2021-04-05 · via zodream梦想开源/个人编程日记

一个简单的HTML音视频播放器

适用场景

本播放器适用场景: 播客类型的文章,需要一个播放器,但是不需要预加载资源文件的。可以尽可能的减少不必要的加载及访客流量浪费。

版本

本播放器有两个版本:

  1. 基于 Jquery 的版本。本文的源码属于这个版本。
  2. 基于Angular 11 的版本。源码见【Github】需要的自取。这个版本音频视频播放器是分开的,而且视频内置了自动区分 iframe 使用。

注意:播放器中的图标都是字体图标,所以只能参考修改。

音频播放器

视频播放器初始界面

视频播放器播放界面

代码


interface IPlayerOption {
    [key: string]: any;
    src: string;
    type?: 'audio' | 'video' | 'iframe'
}

;(function($: any) {
    const EVENT_TIME_UPDATE = 'timeupdate';
    const EVENT_PLAY = 'play';
    const EVENT_PAUSE = 'pause';
    const EVENT_ENDED = 'ended';
    const EVENT_VOLUME_UPDATE = 'volumeupdate';
    const EVENT_TAP_PLAY = 'tap_play';
    const EVENT_TAP_PAUSE = 'tap_pause';
    const EVENT_BOOT = 'boot';
    const EVENT_TAP_VOLUME = 'tap_volume';
    const EVENT_TAP_TIME = 'tap_time';
    const EVENT_ENTER_FULL_SCREEN = 'full_screen';
    const EVENT_EXIT_FULL_SCREEN = 'exit_full_screen';

    const screenFull = function() {
        const fnMap = [
            [
                'requestFullscreen',
                'exitFullscreen',
                'fullscreenElement',
                'fullscreenEnabled',
                'fullscreenchange',
                'fullscreenerror'
            ],
            // New WebKit
            [
                'webkitRequestFullscreen',
                'webkitExitFullscreen',
                'webkitFullscreenElement',
                'webkitFullscreenEnabled',
                'webkitfullscreenchange',
                'webkitfullscreenerror'

            ],
            // Old WebKit
            [
                'webkitRequestFullScreen',
                'webkitCancelFullScreen',
                'webkitCurrentFullScreenElement',
                'webkitCancelFullScreen',
                'webkitfullscreenchange',
                'webkitfullscreenerror'

            ],
            [
                'mozRequestFullScreen',
                'mozCancelFullScreen',
                'mozFullScreenElement',
                'mozFullScreenEnabled',
                'mozfullscreenchange',
                'mozfullscreenerror'
            ],
            [
                'msRequestFullscreen',
                'msExitFullscreen',
                'msFullscreenElement',
                'msFullscreenEnabled',
                'MSFullscreenChange',
                'MSFullscreenError'
            ]
        ];

        for (const item of fnMap) {
            if (item && item[1] in document) {
                return item;
            }
        }
        return false;
    }();

    class MediaPlayer {
        constructor(
            public element: JQuery,
            public options: IPlayerOption
        ) {
            if (!this.options.src) {
                return;
            }
            this.init();
            this.bindCustomEvent();
        }

        private playerElement: HTMLVideoElement|HTMLAudioElement;
        private playerBar: JQuery;
        private booted = false;
        private volumeLast = 100;
        private duration = 0;

        public on(event: string, callback: Function): this {
            this.options['on' + event] = callback;
            return this;
        }

        public hasEvent(event: string): boolean {
            return this.options.hasOwnProperty('on' + event);
        }

        public trigger(event: string, ... args: any[]) {
            let realEvent = 'on' + event;
            if (!this.hasEvent(event)) {
                return;
            }
            return this.options[realEvent].call(this, ...args);
        }

        private bindCustomEvent() {
            this.on(EVENT_BOOT, () => {
                if (this.booted) {
                    return;
                }
                if (this.options.type === 'audio') {
                    this.bindAudioEvent();
                    return;
                }
                if (this.options.type === 'iframe') {
                    this.videoFrame();
                    this.booted = true;
                    return;
                }
                this.videoPlayer();
                this.initBar(this.element.find('.player-bar'));
                this.bindVideoEvent();
            }).on(EVENT_TAP_PLAY, () => {
                this.playerElement.play();
            }).on(EVENT_TAP_PAUSE, () => {
                this.playerElement.pause();
            }).on(EVENT_TIME_UPDATE, (p: number, t: number) => {
                this.duration = t;
                this.playerBar.find('.time').text(this.formatMinute(p) + '/' + this.formatMinute(t));
                const progess = this.playerBar.find('.slider .progress');
                progess.attr('title', parseInt(p.toString()));
                progess.find('.progress-bar').css('width', p * 100 / t + '%');
            }).on(EVENT_PLAY, () => {
                this.playerBar.find('.icon .fa').addClass('fa-pause').removeClass('fa-play');
            }).on(EVENT_PAUSE, () => {
                this.playerBar.find('.icon .fa').removeClass('fa-pause').addClass('fa-play');
            }).on(EVENT_ENDED, () => {
                this.trigger(EVENT_PAUSE);
            }).on(EVENT_TAP_VOLUME, (v: number) => {
                if (!this.playerElement) {
                    return;
                }
                this.playerElement.volume = v / 100;
                this.trigger(EVENT_VOLUME_UPDATE, v);
            }).on(EVENT_VOLUME_UPDATE, (v: number) => {
                const progess = this.playerBar.find('.volume-slider .progress');
                progess.attr('title', parseInt(v.toString()));
                progess.find('.progress-bar').css('width', v + '%');
                let volumeCls = 'fa-volume-up';
                if (v <= 0) {
                    volumeCls = 'fa-volume-off';
                } else if (v < 60) {
                    volumeCls = 'fa-volume-down';
                }
                this.playerBar.find('.volume-icon .fa').attr('class', 'fa ' + volumeCls);
            }).on(EVENT_TAP_TIME, (p: number) => {
                if (!this.playerElement) {
                    return;
                }
                this.playerElement.currentTime = p;
            }).on(EVENT_EXIT_FULL_SCREEN, () => {
                this.playerBar.find('.full-icon .fa').attr('class', 'fa fa-expand');
                this.element.removeClass('player-full');
            }).on(EVENT_ENTER_FULL_SCREEN, () => {
                this.element.addClass('player-full');
                this.playerBar.find('.full-icon .fa').attr('class', 'fa fa-compress');
            });
        }

        private init() {
            if (this.options.type === 'audio') {
                this.initAudio();
                return;
            }
            this.initVideo();
        }

        private initAudio() {
            this.audioPlayer();
            this.initBar(this.element);
        }

        private initBar(bar: JQuery) {
            this.playerBar = bar;
            const that = this;
            bar.on('click', '.icon .fa', function() {
                if (!that.booted) {
                    that.trigger(EVENT_BOOT);
                }
                that.trigger($(this).hasClass('fa-play') ? EVENT_TAP_PLAY : EVENT_TAP_PAUSE);
            }).on('click', '.volume-icon .fa', function() {
                const $this = $(this);
                if ($this.hasClass('fa-volume-mute') || $this.hasClass('fa-volume-off')) {
                    that.trigger(EVENT_TAP_VOLUME, that.volumeLast);
                    return;
                }
                if (that.playerElement) {
                    that.volumeLast = that.playerElement.volume * 100;
                }
                that.trigger(EVENT_TAP_VOLUME, 0);
            }).on('click', '.slider .progress', function(event) {
                const $this = $(this);
                that.trigger(EVENT_TAP_TIME, (event.clientX - $this.offset().left) * that.duration / $this.width());
            }).on('click', '.volume-slider .progress', function(event) {
                const $this = $(this);
                that.trigger(EVENT_TAP_VOLUME, (event.clientX - $this.offset().left) * 100 / $this.width());
            }).on('click', '.full-icon .fa', function() {
                if (that.element.hasClass('player-full')) {
                    that.exitFullscreen();
                    return;
                }
                that.fullScreen();
            });
        }

        private initVideo() {
            this.videoMask();
            this.element.on('click', '.player-mask', () => {
                this.trigger(EVENT_BOOT);
                if (this.playerElement) {
                    this.trigger(EVENT_TAP_PLAY);
                }
            });
        }

        private bindAudioEvent() {
            if (this.booted) {
                return;
            }
            this.booted = true;
            this.playerElement = document.createElement('audio');
            this.playerElement.src = this.options.src;
            this.playerElement.addEventListener('timeupdate', () => {
                if (isNaN(this.playerElement.duration) || !isFinite(this.playerElement.duration) || this.playerElement.duration <= 0) {
                    this.trigger(EVENT_TIME_UPDATE, 0, 0);
                    return;
                }
                this.trigger(EVENT_TIME_UPDATE, this.playerElement.currentTime, this.playerElement.duration);
            });
            this.playerElement.addEventListener('ended', () => {
                this.trigger(EVENT_ENDED);
            });
            this.playerElement.addEventListener('pause', () => {
                this.trigger(EVENT_PAUSE);
            });
            this.playerElement.addEventListener('play', () => {
                this.trigger(EVENT_PLAY);
            });
            this.trigger(EVENT_VOLUME_UPDATE, this.playerElement.volume * 100);
        }

        private bindVideoEvent() {
            if (this.booted) {
                return;
            }
            this.booted = true;
            this.playerElement = this.element.find('.player-video')[0] as HTMLVideoElement;
            this.playerElement.addEventListener('timeupdate', () => {
                if (isNaN(this.playerElement.duration) || !isFinite(this.playerElement.duration) || this.playerElement.duration <= 0) {
                    this.trigger(EVENT_TIME_UPDATE, 0, 0);
                    return;
                }
                this.trigger(EVENT_TIME_UPDATE, this.playerElement.currentTime, this.playerElement.duration);
            });
            this.playerElement.addEventListener('ended', () => {
                this.trigger(EVENT_ENDED);
            });
            this.playerElement.addEventListener('pause', () => {
                this.trigger(EVENT_PAUSE);
            });
            this.playerElement.addEventListener('play', () => {
                this.trigger(EVENT_PLAY);
            });
            this.trigger(EVENT_VOLUME_UPDATE, this.playerElement.volume * 100);
            if (screenFull) {
                document.addEventListener(screenFull[4], () => {
                    if (this.checkFull()) {
                        this.trigger(EVENT_ENTER_FULL_SCREEN);
                        return;
                    }
                    this.trigger(EVENT_EXIT_FULL_SCREEN);
                });
            }
        }

        private audioPlayer() {
            this.element.addClass('audio-player');
            this.element.html(`<div class="icon" title="播放">
            <i class="fa fa-play"></i>
        </div>
        <div class="slider">
            <div class="progress" title="0">
                <div class="progress-bar"></div>
            </div>
        </div>
        <div class="time">
            00:00/00:00
        </div>
        <div class="volume-icon">
            <i class="fa fa-volume-up"></i>
        </div>
        <div class="volume-slider">
            <div class="progress" title="100">
                <div class="progress-bar" style="width: 100%;"></div>
            </div>
        </div>`);
        }

        private videoMask() {
            this.element.addClass('video-player');
            this.element.html(`<div class="player-mask" title="此处有视频,点击即可播放">
            <i class="fa fa-play"></i>
        </div>`);
        }

        private videoFrame() {
            this.element.html(`
            <iframe class="player-frame" src="${this.options.src}" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>`);
        }

        private videoPlayer() {
            this.element.html(`<video class="player-video" src="${this.options.src}"></video>
            <div class="player-bar">
                <div class="icon" title="播放">
                    <i class="fa fa-play"></i>
                </div>
                <div class="slider">
                    <div class="progress" title="0">
                        <div class="progress-bar"></div>
                    </div>
                </div>
                <div class="time">
                    00:00/00:00
                </div>
                <div class="volume-icon">
                    <i class="fa fa-volume-up"></i>
                </div>
                <div class="volume-slider">
                    <div class="progress" title="100">
                        <div class="progress-bar" style="width: 100%;"></div>
                    </div>
                </div>
                <div class="full-icon">
                    <i class="fa fa-expand"></i>
                </div>
            </div>`);
        }

        private formatMinute(time: number): string {
            return this.twoPad(Math.floor(time / 60)) + ':' + this.twoPad(Math.floor(time % 60));
        }

        private twoPad(n: number) {
            const str = n.toString();
            return str[1] ? str : '0' + str;
        }

        private fullScreen(element: any = document.documentElement) {
            if (!screenFull) {
                return;
            }
            element[screenFull[0]]();
        }

        private exitFullscreen(element: any = document) {
            if (!screenFull) {
                return;
            }
            element[screenFull[1]]();
        }

        private checkFull(): boolean {
            return screenFull && Boolean(document[screenFull[2]]);
        }
    }
    $.fn.player = function(option?: IPlayerOption) {
        return new MediaPlayer(this, option);
    };
})(jQuery);

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386

样式

.audio-player,
.video-player {
    .progress {
        height: .4em;
        border-radius: 0;
        margin-top: .2em;
        display: flex;
        overflow: hidden;
        line-height: 0;
        font-size: .75rem;
        background-color: #e9ecef;
        .progress-bar {
            cursor: default;
            display: flex;
            flex-direction: column;
            justify-content: center;
            overflow: hidden;
            color: #fff;
            text-align: center;
            white-space: nowrap;
            background-color: #007bff;
            transition: width .6s ease;
        }
        &:hover {
            height: .8em;
            margin-top: 0;
        }
    }
}
.audio-player {
    box-shadow: 0 2px 2px 0 rgb(0 0 0 / 7%), 0 1px 5px 0 rgb(0 0 0 / 10%);
    display: flex;
    box-sizing: border-box;
    line-height: 2.5em;
    i {
        font-style: normal;
    }
    .icon {
        width: 2.5em;
        text-align: center;
    }
    .slider {
        flex: 1;
        padding-top: 1em;
    }
    .time {
        line-height: 80rpx;
        font-size: .8em;
    }
    .volume-icon {
        padding-left: .5em;
    }
    .volume-slider {
        width: 3em;
        padding-top: 1em;
        padding-right: .5em;
    }
    &.player-mini {
        .volume-icon,
        .volume-slider {
            display: none;
        }
    }
}
.video-player {
    position: relative;
    box-shadow: 0 2px 2px 0 rgb(0 0 0 / 7%), 0 1px 5px 0 rgb(0 0 0 / 10%);
    i {
        font-style: normal;
    }
    .player-mask {
        background-color: #000;
        text-align: center;
        padding: 1em;
        .fa {
            color: #fff;
            font-size: 4em;
        }
        &:hover {
            .fa {
                color: #a10000;
            }
        }
    }
    .player-frame {
        border: 0;
        width: 100%;
        height: 100vw;
        max-height: 400px;
    }
    .player-video {
        border: 0;
        width: 100%;
        height: 100vw;
        max-height: 400px;
        background-color: #000;
        margin: 0;
    }
    .player-bar {
        display: flex;
        box-sizing: border-box;
        line-height: 2.5em;
        .icon {
            width: 2.5em;
            text-align: center;
        }
        .slider {
            flex: 1;
            padding-top: 1em;
        }
        .time {
            line-height: 80rpx;
            font-size: .8em;
        }
        .volume-icon {
            padding-left: .5em;
        }
        .volume-slider {
            width: 3em;
            padding-top: 1em;
            padding-right: .5em;
        }
        .full-icon {
            width: 2em;
            text-align: center;
        }
    }
    &.player-full {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        top: 0;
        z-index: 9999;
        background-color: #000;
        box-shadow: none;
        .player-video {
            width: 100%;
            height: 100%;
            max-height: 100%;
        }
        .player-bar {
            background-color: rgba(43,51,63,.7);
            color: #fff;
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            opacity: 0;
            transition: 1s opacity;
            &:hover {
                opacity: 1;
            }
        }
    }
}

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156

使用


<link type="text/css" href="player.css" rel="stylesheet" media="all">


<div id="player"></div>


<script src="jquery.player.min.js"></script>

<script type="text/javascript">
jQuery(document).ready(function () {
    $('#player').player({
        src: "1616073275141535.mp3",
        type: "audio"
    });
});
</script>

123456789101112131415161718

请先引入jquery.js

参数说明

src  为资源文件的网络路径
type 可选值 video|audio|iframe ;默认为 video ; audio 即音频;iframe 为其他网址的视频,例如 bilibili 分享的链接

参考资料

  1. screenfull.js

转载请保留原文链接: https://zodream.cn/blog/id/198.html