richard1015 5 years ago
parent
commit
f2784412a4

+ 28 - 13
src/packages/leftslip/leftslip.vue

@@ -33,6 +33,10 @@ export default {
         btnSlipDel: {
             type: Boolean,
             default: false
+        },
+        customBtnWidth: {
+            type: Number,
+            default: 40
         }
     },
     data() {
@@ -45,7 +49,8 @@ export default {
             buttonWidth: 0,
             offset: 0, //移动距离
             deleteSlider: '', //滑动时的效果
-            delBtnStyle: '' //单个删除键拖拽删除效果
+            delBtnStyle: '', //单个删除键拖拽删除效果
+            openState: false
         };
     },
     mounted() {
@@ -58,11 +63,11 @@ export default {
             }
         });
 
-        window.addEventListener('scroll', this.handleScroll, true);
+        // window.addEventListener('scroll', this.handleScroll, true);
     },
     beforeDestroy() {
         // 移除监听
-        window.removeEventListener('scroll', this.handleScroll, true);
+        // window.removeEventListener('scroll', this.handleScroll, true);
     },
     methods: {
         handleScroll() {
@@ -79,9 +84,12 @@ export default {
             this.restSlide();
         },
         touchStart(e) {
+            // if(this.openState){
+            //     return
+            // }
             this.restSlide();
             e = e || event;
-            e.preventDefault();
+            // e.preventDefault();
             //等于1时表示此时有只有一只手指在触摸屏幕
             if (e.touches.length == 1) {
                 this.startX = e.touches[0].clientX;
@@ -95,40 +103,42 @@ export default {
             let parentElement = e.currentTarget.parentElement;
 
             let itemWd = this.$refs.slipItem.offsetWidth;
-            let wd = this.onlyDelBtn ? 40 : this.buttonWidth;
+            let wd = this.onlyDelBtn ? this.customBtnWidth : this.buttonWidth;
 
             if (e.touches.length == 1) {
                 this.moveY = e.touches[0].clientY;
                 this.moveX = e.touches[0].clientX;
-              
+
                 if (Math.abs(this.moveY - this.startY) < 40) {
-                   
                     this.offset = this.startX - this.moveX;
-                   
+
                     if (this.onlyDelBtn) {
                         //单一删除,左滑一键删除
                         if (this.offset < 0 || this.offset == 0) {
                             this.deleteSlider = 'transform:translateX(0px)';
+                            this.openState = false;
                         }
                         this.deleteSlider = 'transform:translateX(-' + this.offset + 'px)';
                         this.delBtnStyle = 'width:' + this.offset + 'px';
                         parentElement.dataset.type = 1; //设置滑动展开隐藏标志位,左滑展开为1,右滑或复位为0
+                        this.openState = true;
                     } else {
-                        
                         if (this.offset < wd / 4 || this.offset == 0) {
                             this.deleteSlider = 'transform:translateX(0px)';
                             parentElement.dataset.type = 0;
+                            this.openState = false;
                         } else if (this.offset > wd / 4) {
                             parentElement.dataset.type = 1;
                             this.deleteSlider = 'transform:translateX(-' + this.offset + 'px)';
                             // 最大也只能等于删除按钮宽度
-                            if (this.offset * 1.5 >= wd) {
+                            if (this.offset >= wd) {
                                 if (wd >= itemWd) {
-                                    this.deleteSlider = 'transform:translateX(-' + (itemWd - 40) + 'px)';
+                                    this.deleteSlider = 'transform:translateX(-' + (itemWd - this.customBtnWidth) + 'px)';
                                 } else {
                                     this.deleteSlider = 'transform:translateX(-' + wd + 'px)';
                                 }
                             }
+                            this.openState = true;
                         }
                     }
                 }
@@ -138,7 +148,7 @@ export default {
             e = e || event;
             let parentElement = e.currentTarget.parentElement;
             let itemWd = this.$refs.slipItem.offsetWidth;
-            let wd = this.onlyDelBtn ? 40 : this.buttonWidth;
+            let wd = this.onlyDelBtn ? this.customBtnWidth : this.buttonWidth;
 
             if (e.changedTouches.length == 1) {
                 let endY = e.changedTouches[0].clientY;
@@ -151,29 +161,34 @@ export default {
                         if (this.offset < 0 || this.offset == 0) {
                             this.deleteSlider = 'transform:translateX(0px)';
                             parentElement.dataset.type = 0;
+                            this.openState = false;
                         } else if (this.offset < itemWd - 20) {
                             parentElement.dataset.type = 1;
                             this.deleteSlider = 'transform:translateX(-50px);';
                             this.delBtnStyle = ' width:0px;';
+                            this.openState = true;
                         } else {
                             this.deleteSlider = 'transform:translateX(-' + itemWd + 'px);';
                             this.delBtnStyle = ' width:' + itemWd + 'px;';
                             parentElement.dataset.type = 1;
+                            this.openState = true;
                             this.onlyDelClick();
                         }
                     } else {
                         if (this.offset < wd / 4) {
                             parentElement.dataset.type = 0;
                             this.deleteSlider = 'transform:translateX(0px)';
+                            this.openState = false;
                         } else {
                             //大于一半 滑动到最大值
                             parentElement.dataset.type = 1;
                             if (wd >= itemWd) {
                                 //按钮数不可超出整行宽度
-                                this.deleteSlider = 'transform:translateX(-' + (itemWd - 40) + 'px)';
+                                this.deleteSlider = 'transform:translateX(-' + (itemWd - this.customBtnWidth) + 'px)';
                             } else {
                                 this.deleteSlider = 'transform:translateX(-' + wd + 'px)';
                             }
+                            this.openState = true;
                         }
                     }
                 }

+ 10 - 7
src/packages/video/demo.vue

@@ -68,18 +68,21 @@ export default {
         };
     },
     methods: {
-        play(){
-            console.log('play')
+        play(elm){
+            console.log('play',elm)
         },
-        pause(){
+        pause(e){
             console.log('pause')
-
         },
-        playend(){
-            console.log('playend')
+        playend(e){
+            alert('播放结束')
         }
     }
 };
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.nut-video{
+    height:240px;
+}
+</style>

+ 11 - 1
src/packages/video/doc.md

@@ -11,6 +11,15 @@
 	@playend="playend">
 </nut-video>
 ```
+> source属性:设置视频地址和格式类型,可设置多种视频文件格式以便支持不同浏览器的解析支持,一般采用:MP4、webm、ogv等格式
+
+> options属性:设置视频的播放参数,如:autoplay、controls、poster、loop、volume等
+
+> play事件:监听视频播放
+
+> pause事件:监听视频暂停播放
+
+> playend事件:监听视频播放完成
 
 ```javascript
 export default {
@@ -37,6 +46,7 @@ export default {
 
 autoplay属性设置视频自动播放
 
+
 ```html
 <nut-video :sources="sources" :options="options2"></nut-video>
 ```
@@ -144,7 +154,7 @@ export default {
 | options.controls    | 是否展示操作栏                             | Boolean | true     |
 | options.muted       | 是否静音                                   | Boolean | false    |
 | options.volume      | 音量控制                                   | Number | 0.5    |
-| options.disabled    | 是否自动播放                               | Boolean | false    |
+| options.disabled    | 禁用操作(如循环播放的背景图,禁止操作)                               | Boolean | false    |
 | options.playsinline | 是否设置为行内播放元素(解决安卓兼容问题) | Boolean | false    |
 
 

+ 103 - 13
src/packages/video/video.scss

@@ -5,6 +5,7 @@
     display: flex;
     .nut-videoplayer {
         width: 100%;
+        background:#000;
     }
     .playing-mask {
         width: 100%;
@@ -14,27 +15,34 @@
         right: 0;
         bottom: 60px;
     }
+    video{
+        width:100%;
+        height:100%;
+        object-fit:fill;
+    }
     .nut-video-play-btn {
         // display: none;
-        top: 50%;
-        left: 50%;
-        margin-left: -1em;
-        width: 2em;
+        width: 80px;
+        height: 50px;
+        margin-top: -25px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
         border: 0;
-        background-color: rgba(0, 0, 0, .45);
+        background-color: rgba(0, 0, 0, 0.45);
         color: #fff;
-        transition: border-color .4s, outline .4s, background-color .4s;
+        transition: border-color 0.4s, outline 0.4s, background-color 0.4s;
         position: absolute;
+        top: 50%;
+        left: 50%;
+        margin-left: -40px;
         padding: 0;
         cursor: pointer;
         opacity: 1;
-        background-color: rgba(0, 0, 0, .5);
-        font-size: 2.5em;
+        background-color: rgba(0, 0, 0, 0.5);
+        font-size: 30px;
         border-radius: 20%;
-        height: 1.4em;
-        line-height: 1.4em;
-        margin-top: -.7em;
-        text-align: center;
+
         &:hover {
             background-color: #cc181e;
         }
@@ -47,4 +55,86 @@
             background-size: contain;
         }
     }
-}
+    .nut-video-controller {
+        position: absolute;
+        display: flex;
+        left: 0;
+        bottom: 0;
+        background-color: rgba(0, 0, 0, 1);
+        height: 35px;
+        width: 100%;
+        z-index: 11111111;
+        align-items: center;
+        .duration-time,
+        .current-time {
+            color: #fff;
+            padding: 0 5px;
+            font-size: 14px;
+        }
+        .progress-container {
+            position: relative;
+            display: inline-block;
+            height: 100%;
+            width: 100%;
+            overflow: hidden;
+            margin: 0 10px;
+            transition: all 0.2s ease-in;
+            flex: 1;
+            .progress {
+                position: absolute;
+                top: 50%;
+                width: 100%;
+                height: 2px;
+                margin-top: -0.05rem;
+                background: rgba(255, 255, 255, 0.5);
+                // overflow: hidden;
+            }
+            .buffered {
+                background: rgba(255, 255, 255, 0.8);
+                height: 2px;
+            }
+            .video-ball {
+                width: 15px;
+                height: 15px;
+                background: #fff;
+                box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.2);
+                position: absolute;
+                top: -6px;
+                left: 50%;
+                margin-left: -7px;
+                border-radius: 50%;
+            }
+        }
+        .fullscreen-icon {
+            width: 40px;
+            height: 35px;
+            background: url('../../assets/img/video-icon.png') no-repeat;
+            background-size: 218px 38px;
+            background-position: -71px 0px;
+        }
+    }
+    .nut-video-error{
+        position: absolute;
+        width: 100%;
+        height: 100%;
+        z-index: 111111;
+        background: #000;
+        color: #fff;
+        text-align: center;
+        p{
+            color: #fff;
+        }
+    }
+}
+// video::-webkit-media-controls-play-button{
+//     display: none!important;
+// }
+// ::-webkit-media-controls {
+//     display: none !important;
+// }
+// video::-webkit-media-controls {
+//     display: none !important;
+// }
+// video::-webkit-media-controls-enclosure {
+//     display: none !important;
+// }

+ 142 - 37
src/packages/video/video.vue

@@ -7,15 +7,29 @@
             :muted="options.muted"
             :autoplay="options.autoplay"
             :loop="options.loop"
-            :controls="options.controls"
             :poster="options.poster"
+            :controls="options.controls"
             @error="handleError"
         >
             <source v-for="source in sources" :src="source.src" :type="source.type" :key="source.src" />
         </video>
         <div class="playing-mask" @click="play"></div>
-        <div class="nut-video-play-btn" v-show="!state.playing" @click="play"></div>
-        <div class="nut-video-controller"></div>
+        <div class="nut-video-play-btn" ref="palyBtn" v-show="!state.playing" @click="play"></div>
+        <!-- <div class="nut-video-controller" v-show="showToolbox">
+            <div class="current-time">{{ videoSet.displayTime }}</div>
+            <div class="progress-container">
+                <div class="progress" ref="progressBar">
+                    <div class="buffered" style="width:50%"></div>
+                    <div class="video-ball">
+                        <div></div>
+                    </div>
+                    <div class="played" ref="playedBar"></div>
+                </div>
+            </div>
+            <div class="duration-time">{{ videoSet.totalTime }}</div>
+            <div class="volume"></div>
+            <div class="fullscreen-icon" @click="fullScreen"></div>
+        </div> -->
         <!-- 错误弹窗 -->
         <div class="nut-video-error" v-show="state.isError">
             <p class="lose">视频加载失败</p>
@@ -24,6 +38,7 @@
     </div>
 </template>
 <script>
+import {throttle} from '../../utils/throttle';
 export default {
     name: 'nut-video',
     props: {
@@ -32,7 +47,6 @@ export default {
             type: Boolean,
             default: false
         },
-
         sources: Array,
         options: {
             type: Object,
@@ -45,8 +59,7 @@ export default {
                     controls: true,
                     muted: false, //是否静音
                     disabled: false, //禁止操作
-                    playsinline: false, //行内展示
-                    
+                    playsinline: false //行内展示
                 };
             },
             required: true
@@ -54,13 +67,31 @@ export default {
     },
     data() {
         return {
-            video: null,
+            videoElm: null,
             initial: true, //控制封面的显示
             showToolbox: false, //控制控制器和标题的显示
-            progress: 0, //进度
-            duration: 0, //总时长
+            // 视频容器元素
+            player: {
+                $player: null,
+                pos: null
+            },
+            // progress进度条元素
+            progressBar: {
+                progressElm: null, // 进度条DOM对象
+                pos: null
+            },
+            // video控制显示设置
+            videoSet: {
+                loaded: 0, // 缓存长度
+                displayTime: '00:00', // 进度时间
+                totalTime: '00:00', // 总时间
+                progress: {
+                    width: 0, // 进度条长度
+                    current: 0 // 进度条当前位置
+                }
+            },
             state: {
-                contrlShow: true,
+                contrlShow: false,
                 vol: 0.5, //音量
                 currentTime: 0, //当前时间
                 fullScreen: false,
@@ -76,67 +107,141 @@ export default {
     },
     methods: {
         init() {
-            this.video = this.$el.getElementsByTagName('video')[0]
+            this.videoElm = this.$el.getElementsByTagName('video')[0];
             if (this.options.autoplay) {
                 this.play();
             }
 
             if (this.options.playsinline) {
-                this.video.setAttribute('playsinline', this.options.playsinline);
-                this.video.setAttribute('webkit-playsinline', this.options.playsinline);
-                this.video.setAttribute('x5-playsinline', this.options.playsinline);
-                this.video.setAttribute('x5-video-player-type', 'h5');
-                this.video.setAttribute('x5-video-player-fullscreen', false);
+                this.videoElm.setAttribute('playsinline', this.options.playsinline);
+                this.videoElm.setAttribute('webkit-playsinline', this.options.playsinline);
+                this.videoElm.setAttribute('x5-playsinline', this.options.playsinline);
+                this.videoElm.setAttribute('x5-video-player-type', 'h5');
+                this.videoElm.setAttribute('x5-video-player-fullscreen', false);
             }
             this.volumeHandle();
-            
-            this.video.addEventListener('play', ()=>{
+
+            // const $player = this.$el;
+            // const $progress = this.$el.getElementsByClassName('progress')[0];
+            // // 播放器位置
+            // this.player.$player = $player;
+            // this.progressBar.$progress = $progress;
+            // this.player.pos = $player.getBoundingClientRect();
+            // this.progressBar.pos = $progress.getBoundingClientRect();
+            // this.videoSet.progress.width = Math.round($progress.getBoundingClientRect().width);
+
+            this.videoElm.addEventListener('play', () => {
                 this.state.playing = true;
             });
-            this.video.addEventListener('pause', ()=>{
+            this.videoElm.addEventListener('pause', () => {
                 this.state.playing = false;
             });
         },
         play() {
             this.state.playing = !this.state.playing;
-            
+
             if (this.options.autoplay && this.options.disabled) {
                 this.state.playing = true;
                 return false;
             }
-            if (this.video) {
+            if (this.videoElm) {
+                // if (this.state.playing) {
+                //     this.videoElm.play();
+                //     this.videoElm.addEventListener('ended', this.playEnded);
+                //     this.$emit('play', this.video);
+                // } else {
+                //     this.videoElm.pause();
+                //     this.$emit('pause', this.video);
+                // }
+                // 播放状态
                 if (this.state.playing) {
-                    this.video.play();
-                    this.video.addEventListener('ended', this.playEnded);
-                    this.$emit('play', this.video)
-                    
-                } else {
-                    this.video.pause();
-                    this.$emit('pause', this.video)
+                    try {
+                        this.videoElm.play();
+                        // this.isPauseTouch = false;
+                        // 监听缓存进度
+                        // this.videoElm.addEventListener('progress', e => {
+                        //     this.getLoadTime();
+                        // });
+                        // // 监听播放进度
+                        // this.videoElm.addEventListener('timeupdate', throttle(this.getPlayTime, 100, 1));
+                        // 监听结束
+                        this.videoElm.addEventListener('ended', this.playEnded);
+                        this.$emit('play', this.videoElm);
+                    } catch (e) {
+                        // 捕获url异常出现的错误
+                        this.handleError()
+                    }
+                }
+                // 停止状态
+                else {
+                    this.isPauseTouch = true;
+                    this.videoElm.pause();
+                    this.$emit('pause', this.videoElm);
                 }
             }
         },
-        volumeHandle(){
-            this.state.vol = this.video.volume
+        volumeHandle() {
+            this.state.vol = this.videoElm.volume;
         },
-        playEnded(){
-            this.state.playing = false;
-            this.video.currentTime = 0;
+        playEnded() {
             // console.log('ended')
-            this.$emit('playend', this.video)
+            this.state.playing = false;
+            this.state.isEnd = true;
+            this.state.controlBtnShow = true;
+            this.videoSet.displayTime = '00:00';
+            this.videoSet.progress.current = 0;
+            this.videoElm.currentTime = 0;
+            this.$emit('playend', this.videoElm);
         },
         // 数据加载出错
         handleError() {
             // console.log('error')
             this.state.isError = true;
         },
+
+        fullScreen() {
+            if (!this.state.fullScreen) {
+                this.state.fullScreen = true;
+                this.video.webkitRequestFullScreen();
+            } else {
+                this.state.fullScreen = false;
+                document.webkitCancelFullScreen();
+            }
+            setTimeout(this.initVideo, 200);
+        },
+        // 获取播放时间
+        getPlayTime() {
+            console.log(222);
+            const percent = this.videoElm.currentTime / this.videoElm.duration;
+            this.videoSet.progress.current = Math.round(this.videoSet.progress.width * percent);
+            // 赋值时长
+            this.videoSet.totalTime = timeParse(this.videoElm.duration);
+            this.videoSet.displayTime = timeParse(this.videoElm.currentTime);
+        },
+        // 获取缓存时间
+        getLoadTime() {
+            // console.log('缓存了...',this.videoElm.buffered.end(0));
+            this.videoSet.loaded = (this.videoElm.buffered.end(0) / this.videoElm.duration) * 100;
+        },
+        getTime() {
+            this.videoElm.addEventListener('durationchange', e => {
+                console.log(e);
+            });
+            this.videoElm.addEventListener('progress', e => {
+                this.videoSet.loaded = (-1 + this.videoElm.buffered.end(0) / this.videoElm.duration) * 100;
+            });
+            this.videoSet.len = this.videoElm.duration;
+        },
+        sliderStart() {},
+        touchmove() {},
+        touchend() {},
         // 点击重新加载
         retry() {
+            console.log('error')
             this.state.isError = false;
             this.init();
-        },
+        }
     },
-    beforeDestroy() {
-    }
+    beforeDestroy() {}
 };
 </script>

+ 32 - 0
src/utils/throttle.js

@@ -0,0 +1,32 @@
+/**
+ * @desc 函数节流
+ * @param func 函数
+ * @param wait 延迟执行毫秒数
+ * @param type 1 表时间戳版,2 表定时器版
+ */
+export const throttle = (func, wait, type) => {
+    if (type === 1) {
+        var previous = 0;
+    } else if (type === 2) {
+        var timeout;
+    }
+    return function() {
+        let context = this;
+        let args = arguments;
+        if (type === 1) {
+            let now = Date.now();
+
+            if (now - previous > wait) {
+                func.apply(context, args);
+                previous = now;
+            }
+        } else if (type === 2) {
+            if (!timeout) {
+                timeout = setTimeout(() => {
+                    timeout = null;
+                    func.apply(context, args);
+                }, wait);
+            }
+        }
+    };
+};

+ 2 - 0
types/nutui.d.ts

@@ -70,3 +70,5 @@ export declare class TabSelect extends UIComponent {}
 export declare class Popup extends UIComponent {}
 
 export declare class LuckDraw extends UIComponent {}
+export declare class Video extends UIComponent {}
+export declare class Signature extends UIComponent {}