Browse Source

播放1.0

skyblued 2 years ago
parent
commit
b74fbddc52

+ 32 - 0
src/views/coursewarePlay/component/video-play.tsx

@@ -0,0 +1,32 @@
+import { defineComponent, nextTick, onMounted } from "vue";
+import 'plyr/dist/plyr.css'
+import Plyr from "plyr";
+import { ref } from "vue";
+
+export default defineComponent({
+    name: 'video-play',
+    props:{
+        item: {
+            type: Object,
+            default: () => {return {}}
+        }
+    },
+    setup(props){
+        const videoRef = ref()
+        const item = props.item
+        onMounted(() => {
+            const v = new Plyr(videoRef.value, {
+                muted: true
+            })
+            v.play()
+            nextTick(() => {
+                v.muted = false
+            })
+        })
+        return () => (
+            <div style={{width: '100%', height: '100%'}}>
+                <video style={{width: '100%', height: '100%'}} src={item.content} ref={videoRef}></video>
+            </div>
+        )
+    }
+})

File diff suppressed because it is too large
+ 0 - 0
src/views/coursewarePlay/datas/data.json


+ 29 - 9
src/views/coursewarePlay/index.module.less

@@ -1,7 +1,13 @@
+.playContent {
+  width: 100vw;
+  height: 100vh;
+  background-color: #000;
+}
 .coursewarePlay {
   position: relative;
   height: 100vh;
-  background-color: rgba(89, 98, 126, 0.2);
+  margin: 0 auto;
+  overflow: hidden;
 }
 .playModel {
   position: absolute;
@@ -13,14 +19,14 @@
   pointer-events: none;
 }
 .headerContainer {
-  position: fixed;
+  position: absolute;
   top: 0;
   left: 0;
   right: 0;
   z-index: 1;
   display: flex;
   align-items: center;
-  background: linear-gradient(180deg, rgba(0, 0, 0, .6), transparent);
+  background: linear-gradient(180deg, rgba(0, 0, 0, 0.6), transparent);
 }
 .backBtn {
   color: #fff;
@@ -55,7 +61,7 @@
     }
   }
 }
-.swipeItem{
+.swipeItem {
   overflow: hidden;
 }
 .itemDiv {
@@ -74,7 +80,7 @@
   }
 }
 .rightFixedBtns {
-  position: fixed;
+  position: absolute;
   top: 50%;
   transform: translateY(-50%);
   right: 20px;
@@ -89,7 +95,7 @@
   }
 }
 .leftFixedBtns {
-  position: fixed;
+  position: absolute;
   top: 50%;
   transform: translateY(-50%);
   left: 26px;
@@ -127,8 +133,8 @@
   }
   .slider {
     padding: 8px 20px;
-    :global{
-      .van-slider__button{
+    :global {
+      .van-slider__button {
         background: var(--van-primary);
       }
     }
@@ -140,7 +146,7 @@
     font-size: 12px;
     padding: 0 10px 0 20px;
     align-items: center;
-    .actionBtn{
+    .actionBtn {
       display: flex;
     }
     .actionBtn > img {
@@ -174,6 +180,7 @@
   .left-enter-from,
   .left-leave-to {
     left: -60px;
+    opacity: 0;
   }
 
   .right-enter-active,
@@ -184,6 +191,7 @@
   .right-enter-from,
   .right-leave-to {
     right: -60px;
+    opacity: 0;
   }
 
   .bottom-enter-active,
@@ -196,3 +204,15 @@
     transform: translateY(100%);
   }
 }
+
+.loadWrap{
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  background: linear-gradient(45deg, #21232A, #111218);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}

+ 279 - 257
src/views/coursewarePlay/index.tsx

@@ -42,7 +42,9 @@ import iconDown from './image/icon-down.svg'
 import iconVideobg from './image/icon-videobg.png'
 import Points from './component/points'
 import { browser, getSecondRPM } from '@/helpers/utils'
-import { useRect } from '@vant/use'
+import VideoPlay from './component/video-play'
+import { Vue3Lottie } from 'vue3-lottie'
+import playLoadData from './datas/data.json'
 
 export default defineComponent({
   name: 'CoursewarePlay',
@@ -75,6 +77,18 @@ export default defineComponent({
       handleInit(1)
       window.removeEventListener('message', iframeHandle)
     })
+    /** 设置播放容器 16:9 */
+    const parentContainer = reactive({
+      width: '100vw'
+    })
+    const setContainer = () => {
+      let width = screen.height * (16 / 9)
+      if (width > screen.width) {
+        return
+      }
+      parentContainer.width = width + 'px'
+    }
+    setContainer()
 
     const route = useRoute()
     const headeRef = ref()
@@ -226,6 +240,7 @@ export default defineComponent({
       getDetail()
       getCourseSchedule()
       window.addEventListener('message', iframeHandle)
+      window.addEventListener('resize', setContainer)
     })
     // 返回
     const goback = () => {
@@ -378,276 +393,283 @@ export default defineComponent({
     }
 
     return () => (
-      <div class={styles.coursewarePlay}>
-        <Swipe
-          style={{ height: '100vh' }}
-          ref={swipeRef}
-          showIndicators={false}
-          loop={false}
-          vertical
-          lazyRender={true}
-          touchable={false}
-          initialSwipe={popupData.firstIndex}
-          onChange={handleSwipeChange}
-        >
-          {data.itemList.map((m: any, mIndex: number) => {
-            return (
-              <SwipeItem class={styles.swipeItem}>
-                <>
-                  <div
-                    class={styles.itemDiv}
-                    onClick={() => {
-                      clearTimeout(activeData.timer)
-                      if (Date.now() - activeData.nowTime < 300) {
-                        handleDbClick(m)
-                        return
-                      }
-                      activeData.nowTime = Date.now()
-                      activeData.timer = setTimeout(() => {
-                        activeData.model = !activeData.model
-                        setModelOpen()
-                      }, 300)
-                    }}
-                  >
-                    {m.type === 'VIDEO' ? (
-                      <>
-                        <video
-                          playsinline="false"
-                          muted={m.muted}
-                          preload="auto"
-                          class="player"
-                          poster={iconVideobg}
-                          data-vid={m.id}
-                          src={m.content}
-                          loop={m.loop}
-                          autoplay={m.autoPlay}
-                          onLoadedmetadata={(e: Event) => {
-                            const videoEle = e.target as unknown as HTMLVideoElement
-                            m.currentTime = videoEle.currentTime
-                            m.duration = videoEle.duration
-                            m.videoEle = videoEle
-                            m.isprepare = true
-                          }}
-                          onTimeupdate={(e: Event) => {
-                            if (!m.isprepare) return
-                            const videoEle = e.target as unknown as HTMLVideoElement
-                            m.currentTime = videoEle.currentTime
-                            m.progress = Number(
-                              ((videoEle.currentTime / m.duration) * 100).toFixed(1)
-                            )
-                          }}
-                          onPlay={() => {
-                            // 播放
-                            m.paused = false
-                            console.log('播放')
-                            setModelOpen()
-                            m.muted = false
-                          }}
-                          onPause={() => {
-                            //暂停
-                            clearTimeout(activeData.timer)
-                            m.paused = true
-                          }}
-                          onEnded={() => handleEnded(m)}
-                        >
-                          <source src={m.content} type="video/mp4" />
-                        </video>
-                        <Transition name="bottom">
-                          {activeData.model && (
-                            <div class={[styles.bottomFixedContainer]}>
-                              <div class={styles.time}>
-                                <span>{getSecondRPM(m.currentTime)}</span>
-                                <span>{getSecondRPM(m.duration)}</span>
-                              </div>
-                              <div class={styles.slider}>
-                                <Slider
-                                  onClick={() => {
-                                    setModelOpen()
-                                  }}
-                                  style={{ display: m.isprepare ? 'block' : 'none' }}
-                                  buttonSize={16}
-                                  step={0.1}
-                                  modelValue={m.progress}
-                                  onUpdate:modelValue={(val: any) => {
-                                    m.progress = val
-                                    handleChangeSlider(m)
-                                  }}
-                                  onDragStart={(e: Event) => {
-                                    // 开始拖动,暂停播放
-                                    console.log('开始拖动')
-                                    // 如果拖动之前,视频是播放状态,拖动完毕后继续播放
-                                    if (!m.paused) {
-                                      m.isDrage = true
-                                    }
-                                    handlePaused(e, m)
-                                  }}
-                                  onDragEnd={(e: Event) => {
-                                    console.log('结束拖动')
-                                    if (m.isDrage) {
-                                      m.isDrage = false
-                                      handlePlay(e, m)
-                                    }
-                                  }}
-                                  min={0}
-                                  max={100}
-                                />
-                              </div>
+      <div class={styles.playContent}>
+        <div class={styles.coursewarePlay} style={{ ...parentContainer }}>
+          <Swipe
+            style={{ height: '100%' }}
+            ref={swipeRef}
+            showIndicators={false}
+            loop={false}
+            vertical
+            lazyRender={true}
+            touchable={false}
+            initialSwipe={popupData.firstIndex}
+            onChange={handleSwipeChange}
+          >
+            {data.itemList.map((m: any, mIndex: number) => {
+              return (
+                <SwipeItem class={styles.swipeItem}>
+                  <>
+                    <div
+                      class={styles.itemDiv}
+                      onClick={() => {
+                        clearTimeout(activeData.timer)
+                        if (Date.now() - activeData.nowTime < 300) {
+                          handleDbClick(m)
+                          return
+                        }
+                        activeData.nowTime = Date.now()
+                        activeData.timer = setTimeout(() => {
+                          activeData.model = !activeData.model
+                          setModelOpen()
+                        }, 300)
+                      }}
+                    >
+                      {m.type === 'VIDEO' ? (
+                        <>
+                          <video
+                            playsinline="false"
+                            muted={m.muted}
+                            preload="auto"
+                            class="player"
+                            poster={iconVideobg}
+                            data-vid={m.id}
+                            src={m.content}
+                            loop={m.loop}
+                            autoplay={m.autoPlay}
+                            onLoadedmetadata={(e: Event) => {
+                              const videoEle = e.target as unknown as HTMLVideoElement
+                              m.currentTime = videoEle.currentTime
+                              m.duration = videoEle.duration
+                              m.videoEle = videoEle
+                              m.isprepare = true
+                            }}
+                            onTimeupdate={(e: Event) => {
+                              if (!m.isprepare) return
+                              const videoEle = e.target as unknown as HTMLVideoElement
+                              m.currentTime = videoEle.currentTime
+                              m.progress = Number(
+                                ((videoEle.currentTime / m.duration) * 100).toFixed(1)
+                              )
+                            }}
+                            onPlay={() => {
+                              // 播放
+                              m.paused = false
+                              console.log('播放')
+                              setModelOpen()
+                              m.muted = false
+                            }}
+                            onPause={() => {
+                              //暂停
+                              clearTimeout(activeData.timer)
+                              m.paused = true
+                            }}
+                            onEnded={() => handleEnded(m)}
+                          >
+                            <source src={m.content} type="video/mp4" />
+                          </video>
+                          {m.muted && (
+                            <div class={styles.loadWrap}>
+                              <Vue3Lottie animationData={playLoadData}></Vue3Lottie>
+                            </div>
+                          )}
+                          <Transition name="bottom">
+                            {activeData.model && (
+                              <div class={[styles.bottomFixedContainer]}>
+                                <div class={styles.time}>
+                                  <span>{getSecondRPM(m.currentTime)}</span>
+                                  <span>{getSecondRPM(m.duration)}</span>
+                                </div>
+                                <div class={styles.slider}>
+                                  <Slider
+                                    onClick={() => {
+                                      setModelOpen()
+                                    }}
+                                    style={{ display: m.isprepare ? 'block' : 'none' }}
+                                    buttonSize={16}
+                                    step={0.1}
+                                    modelValue={m.progress}
+                                    onUpdate:modelValue={(val: any) => {
+                                      m.progress = val
+                                      handleChangeSlider(m)
+                                    }}
+                                    onDragStart={(e: Event) => {
+                                      // 开始拖动,暂停播放
+                                      console.log('开始拖动')
+                                      // 如果拖动之前,视频是播放状态,拖动完毕后继续播放
+                                      if (!m.paused) {
+                                        m.isDrage = true
+                                      }
+                                      handlePaused(e, m)
+                                    }}
+                                    onDragEnd={(e: Event) => {
+                                      console.log('结束拖动')
+                                      if (m.isDrage) {
+                                        m.isDrage = false
+                                        handlePlay(e, m)
+                                      }
+                                    }}
+                                    min={0}
+                                    max={100}
+                                  />
+                                </div>
 
-                              <div class={styles.actions}>
-                                <div class={styles.actionBtn}>
-                                  {m.isprepare ? (
-                                    <>
-                                      {m.paused ? (
-                                        <img
-                                          src={iconplay}
-                                          onClick={(e: Event) => handlePlay(e, m)}
-                                        />
-                                      ) : (
-                                        <img
-                                          src={iconpause}
-                                          onClick={(e: Event) => handlePaused(e, m)}
-                                        />
-                                      )}
-                                    </>
-                                  ) : (
-                                    <Loading color="#fff" />
-                                  )}
+                                <div class={styles.actions}>
+                                  <div class={styles.actionBtn}>
+                                    {m.isprepare ? (
+                                      <>
+                                        {m.paused ? (
+                                          <img
+                                            src={iconplay}
+                                            onClick={(e: Event) => handlePlay(e, m)}
+                                          />
+                                        ) : (
+                                          <img
+                                            src={iconpause}
+                                            onClick={(e: Event) => handlePaused(e, m)}
+                                          />
+                                        )}
+                                      </>
+                                    ) : (
+                                      <Loading color="#fff" />
+                                    )}
 
-                                  {m.loop ? (
-                                    <img
-                                      src={iconLoopActive}
-                                      onClick={(e: Event) => {
-                                        e.stopPropagation()
-                                        m.loop = false
-                                      }}
-                                    />
-                                  ) : (
-                                    <img
-                                      src={iconLoop}
-                                      onClick={(e: Event) => {
-                                        e.stopPropagation()
-                                        m.loop = true
-                                      }}
-                                    />
-                                  )}
+                                    {m.loop ? (
+                                      <img
+                                        src={iconLoopActive}
+                                        onClick={(e: Event) => {
+                                          e.stopPropagation()
+                                          m.loop = false
+                                        }}
+                                      />
+                                    ) : (
+                                      <img
+                                        src={iconLoop}
+                                        onClick={(e: Event) => {
+                                          e.stopPropagation()
+                                          m.loop = true
+                                        }}
+                                      />
+                                    )}
+                                  </div>
+                                  <div>{m.name}</div>
                                 </div>
-                                <div>{m.name}</div>
                               </div>
-                            </div>
-                          )}
-                        </Transition>
-                      </>
-                    ) : m.type === 'IMG' ? (
-                      <img src={m.content} />
-                    ) : (
-                      <MusicScore
-                        data-vid={m.id}
-                        music={m}
-                        onSetIframe={(el: any) => {
-                          m.iframeRef = el
-                        }}
-                      />
-                    )}
-                  </div>
-                </>
-              </SwipeItem>
-            )
-          })}
-        </Swipe>
+                            )}
+                          </Transition>
+                        </>
+                      ) : m.type === 'IMG' ? (
+                        <img src={m.content} />
+                      ) : (
+                        <MusicScore
+                          data-vid={m.id}
+                          music={m}
+                          onSetIframe={(el: any) => {
+                            m.iframeRef = el
+                          }}
+                        />
+                      )}
+                    </div>
+                  </>
+                </SwipeItem>
+              )
+            })}
+          </Swipe>
 
-        <Transition name="top">
-          {activeData.model && (
-            <div class={styles.headerContainer} ref={headeRef}>
-              <div class={styles.backBtn} onClick={() => goback()}>
-                <Icon name={iconBack} />
-                返回
+          <Transition name="top">
+            {activeData.model && (
+              <div class={styles.headerContainer} ref={headeRef}>
+                <div class={styles.backBtn} onClick={() => goback()}>
+                  <Icon name={iconBack} />
+                  返回
+                </div>
+                <div class={styles.menu}>{popupData.tabName}</div>
               </div>
-              <div class={styles.menu}>{popupData.tabName}</div>
-            </div>
-          )}
-        </Transition>
+            )}
+          </Transition>
 
-        <Transition name="right">
-          {activeData.model && (
-            <div class={styles.rightFixedBtns}>
-              <div
-                class={styles.fullBtn}
-                onClick={() => {
-                  clearTimeout(activeData.timer)
-                  popupData.open = true
-                }}
-              >
-                <img src={iconMenu} />
-                <span>知识点</span>
+          <Transition name="right">
+            {activeData.model && (
+              <div class={styles.rightFixedBtns}>
+                <div
+                  class={styles.fullBtn}
+                  onClick={() => {
+                    clearTimeout(activeData.timer)
+                    popupData.open = true
+                  }}
+                >
+                  <img src={iconMenu} />
+                  <span>知识点</span>
+                </div>
+                {data.isCourse && (
+                  <>
+                    <div
+                      class={[styles.fullBtn, styles.point]}
+                      onClick={() => gotoRollCall('student_roll_call')}
+                    >
+                      <img src={iconDian} />
+                      <span>点名</span>
+                    </div>
+                    <div class={styles.fullBtn} onClick={() => gotoRollCall('sign_out')}>
+                      <img src={iconPoint} />
+                      <span>签退</span>
+                    </div>
+                  </>
+                )}
               </div>
-              {data.isCourse && (
-                <>
+            )}
+          </Transition>
+
+          <Transition name="left">
+            {activeData.model && (
+              <div class={styles.leftFixedBtns}>
+                {popupData.activeIndex != 0 && (
                   <div
-                    class={[styles.fullBtn, styles.point]}
-                    onClick={() => gotoRollCall('student_roll_call')}
+                    class={[styles.fullBtn, styles.prePoint]}
+                    onClick={() => handlePreAndNext('up')}
                   >
-                    <img src={iconDian} />
-                    <span>点名</span>
+                    <img src={iconUp} />
+                    <span style={{ textAlign: 'center' }}>上一个</span>
                   </div>
-                  <div class={styles.fullBtn} onClick={() => gotoRollCall('sign_out')}>
-                    <img src={iconPoint} />
-                    <span>签退</span>
+                )}
+                {popupData.activeIndex != data.itemList.length - 1 && (
+                  <div class={styles.fullBtn} onClick={() => handlePreAndNext('down')}>
+                    <span style={{ textAlign: 'center' }}>下一个</span>
+                    <img src={iconDown} />
                   </div>
-                </>
-              )}
-            </div>
-          )}
-        </Transition>
-
-        <Transition name="left">
-          {activeData.model && (
-            <div class={styles.leftFixedBtns}>
-              {popupData.activeIndex != 0 && (
-                <div
-                  class={[styles.fullBtn, styles.prePoint]}
-                  onClick={() => handlePreAndNext('up')}
-                >
-                  <img src={iconUp} />
-                  <span style={{ textAlign: 'center' }}>上一个</span>
-                </div>
-              )}
-              {popupData.activeIndex != data.itemList.length - 1 && (
-                <div class={styles.fullBtn} onClick={() => handlePreAndNext('down')}>
-                  <span style={{ textAlign: 'center' }}>下一个</span>
-                  <img src={iconDown} />
-                </div>
-              )}
-            </div>
-          )}
-        </Transition>
+                )}
+              </div>
+            )}
+          </Transition>
 
-        <Popup
-          class={styles.popup}
-          overlayClass={styles.overlayClass}
-          position="right"
-          round
-          v-model:show={popupData.open}
-          onClose={() => {
-            const item = data.itemList[popupData.activeIndex]
-            if (item?.type == 'VIDEO') {
-              setModelOpen()
-            }
-          }}
-        >
-          <Points
-            data={data.knowledgePointList}
-            tabActive={popupData.tabActive}
-            itemActive={popupData.itemActive}
-            onHandleSelect={(res: any) => {
-              // console.log(res)
-              popupData.tabActive = res.tabActive
-              popupData.itemActive = res.itemActive
-              popupData.tabName = res.tabName
-              popupData.open = false
-              toggleMaterial()
+          <Popup
+            class={styles.popup}
+            overlayClass={styles.overlayClass}
+            position="right"
+            round
+            v-model:show={popupData.open}
+            onClose={() => {
+              const item = data.itemList[popupData.activeIndex]
+              if (item?.type == 'VIDEO') {
+                setModelOpen()
+              }
             }}
-          />
-        </Popup>
+          >
+            <Points
+              data={data.knowledgePointList}
+              tabActive={popupData.tabActive}
+              itemActive={popupData.itemActive}
+              onHandleSelect={(res: any) => {
+                // console.log(res)
+                popupData.tabActive = res.tabActive
+                popupData.itemActive = res.itemActive
+                popupData.tabName = res.tabName
+                popupData.open = false
+                toggleMaterial()
+              }}
+            />
+          </Popup>
+        </div>
       </div>
     )
   }

Some files were not shown because too many files changed in this diff