소스 검색

音频功能开发

zhanghe 6 년 전
부모
커밋
4b66b82449

BIN
src/stage/index/assets/img/Audio/audio_last.png


BIN
src/stage/index/assets/img/Audio/audio_mute.png


BIN
src/stage/index/assets/img/Audio/audio_next.png


BIN
src/stage/index/assets/img/Audio/audio_play.png


BIN
src/stage/index/assets/img/Audio/audio_stop.png


BIN
src/stage/index/assets/img/Audio/audio_voice.png


+ 1 - 1
src/stage/index/index.html

@@ -65,7 +65,7 @@
 		document.head.appendChild(appCss);
 
 		var appScript = document.createElement('script');
-		appScript.src = './index.min.js?t=' + ts;
+		appScript.src = './index.js?t=' + ts;
 		document.body.appendChild(appScript);
 	</script>
 	<script>

+ 180 - 1
src/stage/index/scene/LessonScene.js

@@ -29,6 +29,8 @@ class LessonScene extends scene {
     this.curWareIndex = 0;    //当前课件在课件列表中的索引
     this.curImageList = null; //当前图片课件的图片列表
     this.curImageIndex = null;//当前图片在列表中的索引
+    this.curAudioList = null; //当前音频课件的音频列表
+    this.curAudioIndex = 0;   //当前音频在列表中的索引
     this.videoPosition = {
     	top: 270,
     	left: 790,
@@ -47,6 +49,7 @@ class LessonScene extends scene {
         		TVUtil.Toast.show('获取课件列表失败!', 1500);
                 return;
         	}
+            /*
         	if (response.data && response.data.list && response.data.list.length > 0) {
         		this.renderWareList(response.data.list);
         		this.wareList = response.data.list;
@@ -54,6 +57,33 @@ class LessonScene extends scene {
         		this.hideScene();
         		this.showScene(require('./DataBuildingScene'), {});
         	}
+            */
+            /* DEBUG */
+            let tmp = response.data.list || [];
+            tmp.push({
+                type: 1,
+                id: 'cxcxcxxccxxc',
+                category: '总结环节',
+                code: 'test-audio-code-1',
+                title: '小兔子过河',
+                list: [{
+                    type: 1,
+                    id: '324913247891',
+                    audioUrl: 'http://audio.ai160.com/audio/001/00103046/00103046021.mp3',
+                    url: 'resources/J/02/01/220101.jpg',
+                }, {
+                    type: 1,
+                    id: '324913247892',
+                    audioUrl: 'http://audio.ai160.com/audio/001/00103046/00103046021.mp3',
+                    url: 'resources/J/02/01/502001.jpg',
+                }, {
+                    type: 3,
+                    id: '32434243234',
+                    url: 'resources/J/02/01/502001.jpg',
+                }],
+            });
+    		this.renderWareList(tmp);
+    		this.wareList = tmp;
         });
     }
 
@@ -109,6 +139,8 @@ class LessonScene extends scene {
     		case Consts.TYPE_VIDEO:
     			item.icon = 'assets/img/LessonScene/video.png';
     			break;
+            case Consts.TYPE_AUDIO:
+                item.icon = 'assets/img/LessonScene/audio.png';
     	}
     	return `<div class="ware-item-frame">
               <div class="ware-type">${item.text}</div>
@@ -175,6 +207,26 @@ class LessonScene extends scene {
     				this.renderImageView();
     			}
     			break;
+            case Consts.TYPE_AUDIO:
+    			let audioViewDom =
+    			`
+    				<div id="view-full-screen" fe-role="Widget" class="view-full-screen-img"></div>
+    				<div id="view-previous" fe-role="Widget">
+                        <div class="transparent-btn">上一页</div>
+                    </div>
+    				<div id="view-page">1/1</div>
+                        <div id="view-next" fe-role="Widget">
+                        <div class="transparent-btn">下一页</div>
+                    </div>
+    			`;
+    			document.getElementById('view-bottom').innerHTML = audioViewDom;
+    			this.moye.root.reRender();
+    			this.curAudioList = list;
+    			if (this.curAudioList.length > 0) {
+    				this.curAudioIndex = 0;
+    				this.renderAudioView();
+    			}
+                break;
             default:
                 break;
     	}
@@ -185,11 +237,57 @@ class LessonScene extends scene {
     */
     renderImageView() {
     	const curImage = this.curImageList[this.curImageIndex];
-    	document.getElementById('view-page').innerHTML = (this.curImageIndex + 1) + '/' + this.curImageList.length; const imageDom = `<img src=${curImage.url} />`
+    	document.getElementById('view-page').innerHTML = (this.curImageIndex + 1) + '/' + this.curImageList.length;
+        const imageDom = `<img src=${curImage.url} />`
     	document.getElementById('view-content').innerHTML = imageDom;
     }
 
     /**
+     * 渲染音频视图
+     */
+    renderAudioView() {
+        const curAudio = this.curAudioList[this.curAudioIndex];
+        const { url, audioUrl } = curAudio;
+    	document.getElementById('view-page').innerHTML = (this.curAudioIndex + 1) + '/' + this.curAudioList.length;
+        const audio = document.querySelector('.audio-wrapper');
+        // 如果audio标签不存在, 重新渲染view-content的内容
+        if (!audio) {
+            const audioDom = `
+                <div class="img-wrapper">
+                    <img src="${Consts.IMG_PATH}/${url}" />
+                </div>
+                <div class="audio-wrapper">
+                    <audio id="courseware-audio" src="${audioUrl}">您的浏览器暂不支持音频播放</audio>
+                </div>
+                <div class="audio-controls" style="display: block" fe-role="Switch">
+                    <!-- 播放/暂停 -->
+                    <div id="audio-play" class="audio-controls-item btn-play paused" fe-role="Widget"></div>
+                    <!-- 有声/静音 -->
+                    <div id="audio-mute" class="audio-controls-item btn-mute" fe-role="Widget"></div>
+                    <!-- 下一个音频 -->
+                    <div id="audio-next" class="audio-controls-item btn-next" fe-role="Widget"></div>
+                    <!-- 上一个音频 -->
+                    <div id="audio-last" class="audio-controls-item btn-last" fe-role="Widget"></div>
+                </div>
+            `;
+            document.getElementById('view-content').innerHTML = audioDom;
+            this.moye.root.reRender();
+            return;
+        }
+        // 如果audio标签已存在更新图片和音频内容
+        if (url) {
+            const newImgDom = `<img src="${Consts.IMG_PATH}/${url}"/>`;
+            document.querySelector('.img-wrapper').innerHTML = newImgDom;
+        }
+        if (audioUrl) {
+            document.querySelector('#courseware-audio').src = audioUrl;
+            document.querySelector('.audio-controls').style.display = 'block';
+        } else {
+            document.querySelector('.audio-controls').style.display = 'none';
+        }
+    }
+
+    /**
     * 渲染视频视图
     */
     renderVideoView(name, url, type) {
@@ -270,12 +368,80 @@ class LessonScene extends scene {
     			this.moye.root.reRender();
     			this.renderImageView();
     			break;
+    		case Consts.TYPE_AUDIO:
+    			let audioViewDom =
+    			`
+    				<div id="view-full-screen" fe-role="Widget" class="view-full-screen-img"></div>
+    				<div id="view-previous" fe-role="Widget">
+                        <div class="transparent-btn">上一页</div>
+                    </div>
+    				<div id="view-page">1/1</div>
+    				<div id="view-next" fe-role="Widget">
+                        <div class="transparent-btn">下一页</div>
+                    </div>
+    			`;
+    			document.getElementById('view-bottom').innerHTML = audioViewDom;
+    			this.moye.root.reRender();
+    			this.renderAudioView();
+    			break;
             default:
                 break;
     	}
     }
 
     /**
+     * 音频播放控制
+     */
+    audioPlayControl(eventId) {
+        let targetAudio = document.getElementById('courseware-audio');
+        if (!targetAudio) { return; }
+        const changeContent = () => {
+            // 更换图片
+            let imgDom = document.getElementById('img-wrapper');
+            let curAudio = this.curAudioList[this.curAudioIndex];
+            const { bgUrl, playUrl } = curAudio;
+            let newImg = `<img src="${Consts.IMG_PATH}/${bgUrl}" />`
+            imgDom.innerHTML = newImg;
+        }
+        switch (eventId) {
+            case 'audio-play':
+                let playBtn = document.querySelector('#audio-play');
+                if (targetAudio.paused) {
+                    targetAudio.play();
+                    playBtn.classList.remove('paused');
+                } else {
+                    targetAudio.pause();
+                    playBtn.classList.add('paused');
+                }
+                break;
+            case 'audio-mute':
+                let muteBtn = document.querySelector('#audio-mute');
+                if (targetAudio.muted) {
+                    targetAudio.muted = false;
+                    muteBtn.classList.remove('muted');
+                } else {
+                    targetAudio.muted = true;
+                    muteBtn.classList.add('muted');
+                }
+                break;
+            case 'audio-next':
+                if (this.curAudioIndex < this.curAudioList.length -1) {
+                    this.curAudioIndex += 1;
+                    this.renderAudioView();
+                }
+                break;
+            case 'audio-last':
+                if (this.curAudioIndex > 0) {
+                    this.curAudioIndex -= 1;
+                    this.renderAudioView();
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    /**
     * 记录播放行为事件
     */
     postPlayRecord(lessonId, courseId, playStopTime=1){
@@ -331,6 +497,11 @@ class LessonScene extends scene {
 
     onOK() {
     	const leaf = FocusEngine.getFocusedLeaf();
+        // 拦截音频控制相关事件单独处理
+        if (leaf.id && leaf.id.startsWith('audio')) {
+            this.audioPlayControl(leaf.id);
+            return;
+        }
     	switch (leaf.id) {
     		case 'view-video-start':
     			if (this.curWareType == Consts.TYPE_VIDEO) {
@@ -371,6 +542,10 @@ class LessonScene extends scene {
     				this.curImageIndex -= 1;
     				this.renderImageView();
     			}
+                if (this.curWareType === Consts.TYPE_AUDIO && this.curAudioIndex - 1 >= 0) {
+                    this.curAudioIndex -= 1;
+                    this.renderAudioView();
+                }
     			this.postPlayRecord(this.curWareId, this.courseId);
     			break;
     		case 'view-next':
@@ -378,6 +553,10 @@ class LessonScene extends scene {
     				this.curImageIndex += 1;
     				this.renderImageView();
     			}
+                if (this.curWareType === Consts.TYPE_AUDIO && this.curAudioIndex + 1 < this.curAudioList.length) {
+                    this.curAudioIndex += 1;
+                    this.renderAudioView();
+                }
     			this.postPlayRecord(this.curWareId, this.courseId);
     			break;
             default:

+ 59 - 0
src/stage/index/style/LessonScene.less

@@ -124,6 +124,65 @@
 				width: 100%;
 				height: 100%;
 			}
+			.img-wrapper {
+				width: 10.72rem;
+				height: 6.03rem;
+				img {
+					width: 100%;
+					height: 100%;
+				}
+			}
+			.audio-wrapper {
+				width: 10.72rem;
+				height: 6.03rem;
+				audio {
+					width: 100%;
+					height: 100%;
+				}
+			}
+			.audio-controls {
+				z-index: 10;
+				position: absolute;
+				left: 0;
+				bottom: 1.22rem;
+				width: 10.72rem;
+				height: .6rem;
+				.audio-controls-item {
+					width: .6rem;
+					height: .6rem;
+					border: solid unit(@borderSize, rem) transparent;
+					border-radius: 50%;
+					background-size: 100% 100%;
+					background-repeat: no-repeat;
+					&.btn-play {
+						float: left;
+						margin-left: .2rem;
+						background-image: url(assets/img/Audio/audio_stop.png);
+						&.paused {
+							background-image: url(assets/img/Audio/audio_play.png);
+						}
+					}
+					&.btn-mute {
+						float: left;
+						background-image: url(assets/img/Audio/audio_mute.png);
+						&.muted {
+							background-image: url(assets/img/Audio/audio_voice.png);
+						}
+					}
+					&.btn-last {
+						float: right;
+						background-image: url(assets/img/Audio/audio_last.png);
+					}
+					&.btn-next {
+						float: right;
+						margin-right: .2rem;
+						background-image: url(assets/img/Audio/audio_next.png);
+					}
+					&.fe-focus {
+						.after-focus(@borderSize; #ffe100; .1rem; rgba(0,0,0,0.5));
+					}
+				}
+			}
 		}
 
 		#view-bottom {

+ 1 - 0
src/util/Consts.js

@@ -16,6 +16,7 @@ Consts.VIDEO_PATH = 'http://ljvideo.ai160.com/vs2m';
 
 //图片/视频资源类型代号
 Consts.TYPE_VIDEO = 0;
+Consts.TYPE_AUDIO = 1;
 Consts.TYPE_IMAGE = 3;
 
 //产品类型