Commit 825a5dc2 authored by Chen Jiping's avatar Chen Jiping

完成模块

parent 4b326c83
...@@ -128,5 +128,8 @@ ...@@ -128,5 +128,8 @@
} }
} }
}, },
"defaultProject": "ng-template-generator" "defaultProject": "ng-template-generator",
} "cli": {
"analytics": false
}
}
\ No newline at end of file
<div class="model-content"> <div class="model-content">
<div nz-row>
<div nz-col nzOffset='4'><h1 nz-title>课程内容编辑</h1></div>
<div style="position: absolute; left: 200px; top: 100px; width: 800px;">
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()">
<app-upload-image-with-preview
[picUrl]="item.pic_url"
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')"
></app-upload-image-with-preview>
<app-audio-recorder
[audioUrl]="item.audio_url"
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url')"
></app-audio-recorder>
<app-custom-hot-zone></app-custom-hot-zone>
<app-upload-video></app-upload-video>
<app-lesson-title-config></app-lesson-title-config>
</div> </div>
<div nz-form>
<!--
<nz-form-item>
<!-- div style="position: absolute; left: 1000px; top: 100px; width: 300px;"> <nz-form-control [nzSpan]="6" nzOffset="3" class="add-btn-box">
<button nz-button nzType="dashed" class="add-btn" id="add-btn"
<input type="text" nz-input [(ngModel)]="item.text_2" (blur)="save()"> (click)="addExercisesItem()">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
<app-upload-image-with-preview </button>
[picUrl]="item.pic_url_2" </nz-form-control>
(imageUploaded)="onImageUploadSuccess($event, 'pic_url_2')" </nz-form-item>
></app-upload-image-with-preview> -->
<nz-form-item>
<app-audio-recorder <nz-form-control [nzSpan]="15" nzOffset="3">
[audioUrl]="item.audio_url_2" <div *ngFor="let it of item.exercises; let i = index" class="card-item" style="padding: 0.5vw;">
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url_2')" <div class="border">
></app-audio-recorder> <nz-divider nzText="练习-{{i+1}}" nzOrientation="left"></nz-divider>
<!--
</div --> <button style="margin: 10px;" nz-button nzType="danger" (click)="delExercisesItem(i)">
<span>删除</span>
</button>
-->
<div nz-form>
<nz-form-item>
</div> <nz-form-label [nzSpan]="6" nzFor="it.contents">内容</nz-form-label>
<nz-form-control [nzSpan]="6">
<button nz-button nzType="dashed" class="add-btn" id="add-btn"
(click)="addContentItem(it.contents)">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
</button>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<div nz-col [nzSpan]="22" nzOffset="1">
<nz-table #answersTable [nzHideOnSinglePage]="true" [nzBordered]="true" [nzNoResult]=''>
<thead>
<tr>
<th>序号</th>
<th>内容(文字)</th>
<th>内容(图片)</th>
<th>发音</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of it.contents;let j = index">
<td>{{j+1}}</td>
<td><input type="text" nz-input placeholder="请录入内容" [(ngModel)]="data.val" (blur)="save()"></td>
<td>
<app-upload-image-with-preview
style="width: 100%"
[picUrl]="data.pic_url"
(imageUploaded)="onImageUploadSuccess($event, data, 'pic_url')"
></app-upload-image-with-preview>
</td>
<td>
<app-audio-recorder id="data.audio_url"
[audioUrl]="data.audio_url"
(audioUploaded)="onAudioUploadSuccess($event, data, 'audio_url')">
</app-audio-recorder>
</td>
<td>
<a (click)="delContentItem(it.contents, j)">delete</a>
</td>
</tr>
</tbody>
</nz-table>
</div>
</nz-form-item>
</div>
</div>
</div>
<!--<app-audio-recorder--> </nz-form-control>
<!--[audioUrl]="item.audio_url"--> </nz-form-item>
<!--(audioUploaded)="onAudioUploadSuccess($event)"--> </div>
<!--&gt;</app-audio-recorder>--> </div>
\ No newline at end of file
<!--<div *ngFor="let it of picArr; let i = index"-->
<!--nz-col nzSpan="8" >-->
<!--<div class="item-box">-->
<!--<app-upload-image-with-preview-->
<!--style="width: 100%"-->
<!--[picUrl]="it.pic_url"-->
<!--(imageUploaded)="onImageUploadSuccessByItem($event, it)"-->
<!--&gt;</app-upload-image-with-preview>-->
<!--<div style="display: flex; justify-items: center; padding-top: 10px">-->
<!--<app-audio-recorder-->
<!--[audioUrl]="it.audio_url"-->
<!--(audioUploaded)="onAudioUploadSuccessByItem($event, it)">-->
<!--</app-audio-recorder>-->
<!--<button style="margin-left: 10px;" nz-button nzType="danger" (click)="deleteItem(it)">-->
<!--<i nz-icon type="close"></i>-->
<!--</button>-->
<!--</div>-->
<!--</div>-->
<!--&lt;!&ndash;<h5> id-{{i+1}} </h5>&ndash;&gt;-->
<!--&lt;!&ndash;<div style="display: flex; align-items: center; justify-content: center; padding-bottom: 5px">&ndash;&gt;-->
<!--&lt;!&ndash;<input type="text" nz-input placeholder="" [(ngModel)]="it.text" (blur)="saveItem()">&ndash;&gt;-->
<!--&lt;!&ndash;<button style="margin-left: 10px;" nz-button nzType="danger" (click)="deleteItem(it)">&ndash;&gt;-->
<!--&lt;!&ndash;<i nz-icon type="close"></i>&ndash;&gt;-->
<!--&lt;!&ndash;</button>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<app-upload-image-with-preview&ndash;&gt;-->
<!--&lt;!&ndash;style="width: 100%"&ndash;&gt;-->
<!--&lt;!&ndash;[picUrl]="it.pic_url"&ndash;&gt;-->
<!--&lt;!&ndash;(imageUploaded)="onImageUploadSuccessByItem($event, it)"&ndash;&gt;-->
<!--&lt;!&ndash;&gt;</app-upload-image-with-preview>&ndash;&gt;-->
<!--&lt;!&ndash;<div style="display: flex; align-items: center; justify-content: center">&ndash;&gt;-->
<!--&lt;!&ndash;<span style="width: 80px;">&ndash;&gt;-->
<!--&lt;!&ndash;question:&ndash;&gt;-->
<!--&lt;!&ndash;</span>&ndash;&gt;-->
<!--&lt;!&ndash;<app-audio-recorder&ndash;&gt;-->
<!--&lt;!&ndash;[audioUrl]="it['q_audio_url']"&ndash;&gt;-->
<!--&lt;!&ndash;(audioUploaded)="onAudioUploadSuccessByItem($event, it, 'q')">&ndash;&gt;-->
<!--&lt;!&ndash;</app-audio-recorder>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div style="display: flex; align-items: center; justify-content: center">&ndash;&gt;-->
<!--&lt;!&ndash;<span style="width: 80px;">&ndash;&gt;-->
<!--&lt;!&ndash;answer:&ndash;&gt;-->
<!--&lt;!&ndash;</span>&ndash;&gt;-->
<!--&lt;!&ndash;<app-audio-recorder&ndash;&gt;-->
<!--&lt;!&ndash;[audioUrl]="it['a_audio_url']"&ndash;&gt;-->
<!--&lt;!&ndash;(audioUploaded)="onAudioUploadSuccessByItem($event, it, 'a')">&ndash;&gt;-->
<!--&lt;!&ndash;</app-audio-recorder>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<nz-radio-group [(ngModel)]="it.radioValue" >&ndash;&gt;-->
<!--&lt;!&ndash;<label nz-radio nzValue="A" (click)="radioClick(it, 'A')"> <i nz-icon nzType="check" nzTheme="outline"></i> </label>&ndash;&gt;-->
<!--&lt;!&ndash;<label nz-radio nzValue="B" (click)="radioClick(it, 'B')"> <i nz-icon nzType="close" nzTheme="outline"></i> </label>&ndash;&gt;-->
<!--&lt;!&ndash;</nz-radio-group>&ndash;&gt;-->
<!--</div>-->
<!--<div nz-col nzSpan="8" class="add-btn-box" >-->
<!--&lt;!&ndash;<div style="width: 100%; height: 100%;">&ndash;&gt;-->
<!--<button style=" margin: auto; width: 60%; height: 60%;" nz-button nzType="dashed" class="add-btn"-->
<!--(click)="addPic()">-->
<!--<i nz-icon nzType="plus-circle" nzTheme="outline"></i>-->
<!--Add-->
<!--</button>-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--</div>-->
<!--&lt;!&ndash;<div style="padding-bottom: 30px;">&ndash;&gt;-->
<!--&lt;!&ndash;<h5> title-sound: </h5>&ndash;&gt;-->
<!--&lt;!&ndash;<app-audio-recorder&ndash;&gt;-->
<!--&lt;!&ndash;[audioUrl]="item.contentObj.title_audio_url"&ndash;&gt;-->
<!--&lt;!&ndash;(audioUploaded)="onAudioUploadSuccessByItem($event, item.contentObj, 'title')">&ndash;&gt;-->
<!--&lt;!&ndash;</app-audio-recorder>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div style="padding-bottom: 30px;">&ndash;&gt;-->
<!--&lt;!&ndash;<h5> bg-sound: </h5>&ndash;&gt;-->
<!--&lt;!&ndash;<app-audio-recorder&ndash;&gt;-->
<!--&lt;!&ndash;[audioUrl]="item.contentObj.bg_audio_url"&ndash;&gt;-->
<!--&lt;!&ndash;(audioUploaded)="onAudioUploadSuccessByItem($event, item.contentObj, 'bg')">&ndash;&gt;-->
<!--&lt;!&ndash;</app-audio-recorder>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<span style="margin-bottom: 20px"> 10 : 23 </span>&ndash;&gt;-->
<!--&lt;!&ndash;<div *ngFor="let it of picArr; let i = index">&ndash;&gt;-->
<!--&lt;!&ndash;<span> pic-{{i + 1}}: </span>&ndash;&gt;-->
<!--&lt;!&ndash;<div style="display: flex; align-items: center; padding-bottom: 20px">&ndash;&gt;-->
<!--&lt;!&ndash;<div style="width: 40%; padding-right: 20px">&ndash;&gt;-->
<!--&lt;!&ndash;<app-upload-image-with-preview&ndash;&gt;-->
<!--&lt;!&ndash;[picUrl]="it.pic_url"&ndash;&gt;-->
<!--&lt;!&ndash;(imageUploaded)="onImageUploadSuccessByItem($event, it)"&ndash;&gt;-->
<!--&lt;!&ndash;&gt;</app-upload-image-with-preview>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div class="pic-sound-box">&ndash;&gt;-->
<!--&lt;!&ndash;<div nz-row style="width: 50%; padding-bottom: 20px;">&ndash;&gt;-->
<!--&lt;!&ndash;<div *ngFor="let it2 of it.soundArr; let i2 = index" nz-col nzSpan="8">&ndash;&gt;-->
<!--&lt;!&ndash;<label nz-checkbox nzValue="{{'answer_' + (i2 + 1)}}" [(ngModel)]="it2.answer" (ngModelChange)="clickCheckBox()" >{{i2 + 1}}</label>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div *ngFor="let it2 of it.soundArr; let i2 = index" style="display: flex; align-items: center; padding-bottom: 5px">&ndash;&gt;-->
<!--&lt;!&ndash;<span style="padding-right: 10px">sound-{{i2 + 1}}:</span>&ndash;&gt;-->
<!--&lt;!&ndash;<app-audio-recorder&ndash;&gt;-->
<!--&lt;!&ndash;[audioUrl]="it2.audio_url"&ndash;&gt;-->
<!--&lt;!&ndash;(audioUploaded)="onAudioUploadSuccessByItem($event, it2)">&ndash;&gt;-->
<!--&lt;!&ndash;</app-audio-recorder>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div style="margin: auto; width: 95%;" nz-row nzType="flex" nzJustify="start" nzAlign="middle">&ndash;&gt;-->
<!--&lt;!&ndash;<div *ngFor="let it of picArr; let i = index"&ndash;&gt;-->
<!--&lt;!&ndash;nz-col nzSpan="8" >&ndash;&gt;-->
<!--&lt;!&ndash;<div class="item-box">&ndash;&gt;-->
<!--&lt;!&ndash;<h5> id-{{i+1}} </h5>&ndash;&gt;-->
<!--&lt;!&ndash;<div style="display: flex; align-items: center; justify-content: center; padding-bottom: 5px">&ndash;&gt;-->
<!--&lt;!&ndash;<input type="text" nz-input placeholder="" [(ngModel)]="it.text" (blur)="saveItem()">&ndash;&gt;-->
<!--&lt;!&ndash;<button style="margin-left: 10px;" nz-button nzType="danger" (click)="deleteItem(it)">&ndash;&gt;-->
<!--&lt;!&ndash;<i nz-icon type="close"></i>&ndash;&gt;-->
<!--&lt;!&ndash;</button>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<app-upload-image-with-preview&ndash;&gt;-->
<!--&lt;!&ndash;style="width: 100%"&ndash;&gt;-->
<!--&lt;!&ndash;[picUrl]="it.pic_url"&ndash;&gt;-->
<!--&lt;!&ndash;(imageUploaded)="onImageUploadSuccessByItem($event, it)"&ndash;&gt;-->
<!--&lt;!&ndash;&gt;</app-upload-image-with-preview>&ndash;&gt;-->
<!--&lt;!&ndash;<div style="display: flex; align-items: center; justify-content: center">&ndash;&gt;-->
<!--&lt;!&ndash;<span style="width: 80px;">&ndash;&gt;-->
<!--&lt;!&ndash;question:&ndash;&gt;-->
<!--&lt;!&ndash;</span>&ndash;&gt;-->
<!--&lt;!&ndash;<app-audio-recorder&ndash;&gt;-->
<!--&lt;!&ndash;[audioUrl]="it['q_audio_url']"&ndash;&gt;-->
<!--&lt;!&ndash;(audioUploaded)="onAudioUploadSuccessByItem($event, it, 'q')">&ndash;&gt;-->
<!--&lt;!&ndash;</app-audio-recorder>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div style="display: flex; align-items: center; justify-content: center">&ndash;&gt;-->
<!--&lt;!&ndash;<span style="width: 80px;">&ndash;&gt;-->
<!--&lt;!&ndash;answer:&ndash;&gt;-->
<!--&lt;!&ndash;</span>&ndash;&gt;-->
<!--&lt;!&ndash;<app-audio-recorder&ndash;&gt;-->
<!--&lt;!&ndash;[audioUrl]="it['a_audio_url']"&ndash;&gt;-->
<!--&lt;!&ndash;(audioUploaded)="onAudioUploadSuccessByItem($event, it, 'a')">&ndash;&gt;-->
<!--&lt;!&ndash;</app-audio-recorder>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<nz-radio-group [(ngModel)]="it.radioValue" >&ndash;&gt;-->
<!--&lt;!&ndash;<label nz-radio nzValue="A" (click)="radioClick(it, 'A')"> <i nz-icon nzType="check" nzTheme="outline"></i> </label>&ndash;&gt;-->
<!--&lt;!&ndash;<label nz-radio nzValue="B" (click)="radioClick(it, 'B')"> <i nz-icon nzType="close" nzTheme="outline"></i> </label>&ndash;&gt;-->
<!--&lt;!&ndash;</nz-radio-group>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--</div>-->
...@@ -10,7 +10,7 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap ...@@ -10,7 +10,7 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap
export class FormComponent implements OnInit, OnChanges, OnDestroy { export class FormComponent implements OnInit, OnChanges, OnDestroy {
// 储存数据用 // 储存数据用
saveKey = "test_0011"; saveKey = "DF_L204";
// 储存对象 // 储存对象
item; item;
...@@ -31,6 +31,12 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -31,6 +31,12 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
this.item = data; this.item = data;
} }
if(!this.item.exercises){
this.item.exercises = [];
this.addExercisesItem();
}
this.init(); this.init();
this.refresh(); this.refresh();
...@@ -52,28 +58,27 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -52,28 +58,27 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
} }
/** /**
* 储存图片数据 * 储存图片数据
* @param e * @param e
*/ */
onImageUploadSuccess(e, key) { onImageUploadSuccess(e, item, key) {
this.item[key] = e.url; item[key] = e.url;
this.save(); this.save();
} }
/** /**
* 储存音频数据 * 储存音频数据
* @param e * @param e
*/ */
onAudioUploadSuccess(e, key) { onAudioUploadSuccess(e, item, key) {
this.item[key] = e.url; item[key] = e.url;
this.save(); this.save();
} }
/** /**
* 储存数据 * 储存数据
*/ */
...@@ -91,5 +96,72 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -91,5 +96,72 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}, 1); }, 1);
} }
/**
* 添加练习
*/
addExercisesItem(){
let exercises = this.getDefaultExercisesItem();
this.item.exercises.push(exercises);
this.save();
}
delExercisesItem(index){
if (index !== -1) {
this.item.exercises.splice(index, 1);
this.save();
}
}
/**
* 获取缺省的练习题内容
*/
getDefaultExercisesItem(){
let exercises = {
contents:[]
}
return exercises;
}
/**
* 添加练习题内容
*/
addContentItem(contents){
let content = this.getDefaultContentItem();
contents.push(content);
this.save();
}
/**
* 删除练习题内容
* @param contents
* @param index
*/
delContentItem(contents, index){
if (index !== -1) {
contents.splice(index, 1);
this.save();
}
}
/**
* 获取缺省的练习题内容
*/
getDefaultContentItem(){
let content = {
val:"",
pic_url:"",
audio_url:""
}
return content;
}
} }
...@@ -2,8 +2,12 @@ import {Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener ...@@ -2,8 +2,12 @@ import {Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener
import { import {
Label, Label,
MySprite, tweenChange, MySprite,
ShapeCircle,
rotateItem,
tweenChange,
removeItemFromArr,
getPosByAngle
} from './Unit'; } from './Unit';
import {res, resAudio} from './resources'; import {res, resAudio} from './resources';
...@@ -57,17 +61,41 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -57,17 +61,41 @@ export class PlayComponent implements OnInit, OnDestroy {
canvasLeft; canvasLeft;
canvasTop; canvasTop;
saveKey = 'test_0011'; saveKey = 'DF_L204';
btn_go;
btn_go_val;
bg_pic;
//转盘
rotaryTable;
times = 0;
//卡片半径
cardOuterR = 90;
//卡片内半径
cardInerR = 65;
btnLeft; initRotaryTableScale = 0.7;
btnRight;
pic1;
pic2;
canTouch = true; first = true;
curPic; canTouch = false;
nextExercisesIndex = 0;
curExercises;
playingStatus = false;
//练习题内容
curContents = [];
curContent;
@HostListener('window:resize', ['$event']) @HostListener('window:resize', ['$event'])
onResize(event) { onResize(event) {
...@@ -127,6 +155,10 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -127,6 +155,10 @@ export class PlayComponent implements OnInit, OnDestroy {
this.initCtx(); this.initCtx();
this.initData(); this.initData();
this.initView(); this.initView();
this.playAudio('begin', false, ()=>{
this.canTouch = true;
});
} }
initCtx() { initCtx() {
...@@ -288,7 +320,19 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -288,7 +320,19 @@ export class PlayComponent implements OnInit, OnDestroy {
} }
} }
pauseAudio(key, callback = null){
const audio = this.audioObj[key];
if (audio) {
if (callback) {
audio.onended = () => {
callback();
};
}
audio.pause();
}
}
loadResources() { loadResources() {
const pr = []; const pr = [];
...@@ -432,9 +476,8 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -432,9 +476,8 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initDefaultData() { initDefaultData() {
if (!this.data.pic_url) { if(!this.data.exercises){
this.data.pic_url = 'assets/play/default/pic.jpg'; this.data.exercises = [];
this.data.pic_url_2 = 'assets/play/default/pic.jpg';
} }
} }
...@@ -444,8 +487,16 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -444,8 +487,16 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initImg() { initImg() {
this.addUrlToImages(this.data.pic_url); for(let i = 0; i < this.data.exercises.length; ++ i){
this.addUrlToImages(this.data.pic_url_2);
let exercises = this.data.exercises[i];
for(let j = 0; j < exercises.contents.length; ++ j){
let content = exercises.contents[j];
this.addUrlToImages(content.pic_url);
}
}
} }
...@@ -454,12 +505,26 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -454,12 +505,26 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initAudio() { initAudio() {
// 音频资源 this.addUrlToAudioObj('playing', this.rawAudios.get('playing'));
this.addUrlToAudioObj(this.data.audio_url);
this.addUrlToAudioObj(this.data.audio_url_2); this.addUrlToAudioObj('begin', this.rawAudios.get('begin'));
this.addUrlToAudioObj('stop', this.rawAudios.get('stop'));
// 音效 this.addUrlToAudioObj('pop-up', this.rawAudios.get('pop-up'));
this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3);
for(let i = 0; i < this.data.exercises.length; ++ i){
let exercises = this.data.exercises[i];
for(let j = 0; j < exercises.contents.length; ++ j){
let content = exercises.contents[j];
this.addUrlToAudioObj(content.audio_url);
}
}
} }
...@@ -475,14 +540,23 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -475,14 +540,23 @@ export class PlayComponent implements OnInit, OnDestroy {
const s = Math.min(sx, sy); const s = Math.min(sx, sy);
this.mapScale = s; this.mapScale = s;
// this.mapScale = sx; this.cardOuterR = 90;
// this.mapScale = sy;
this.cardInerR = 80;
this.renderArr = []; this.renderArr = [];
this.curExercises = {};
this.nextExercisesIndex = 0;
this.curContents = [];
this.times = 0;
this.initRotaryTableScale = this.initRotaryTableScale * this.mapScale;
this.curContent = {};
} }
...@@ -496,128 +570,303 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -496,128 +570,303 @@ export class PlayComponent implements OnInit, OnDestroy {
this.initPic(); this.initPic();
this.initBottomPart(); this.initBottomPart();
} }
initBottomPart() { initBottomPart() {
const btnLeft = new MySprite(); const btnGo = new MySprite();
btnLeft.init(this.images.get('btn_left')); btnGo.init(this.images.get('btn_go'));
btnLeft.x = this.canvasWidth - 150 * this.mapScale; btnGo.x = this.canvasWidth - 100 * this.mapScale;
btnLeft.y = this.canvasHeight - 100 * this.mapScale; btnGo.y = this.canvasHeight - 100 * this.mapScale;
btnGo.setScaleXY(this.mapScale);
btnLeft.setScaleXY(this.mapScale); this.renderArr.push(btnGo);
this.renderArr.push(btnLeft); this.btn_go = btnGo;
this.btnLeft = btnLeft;
let btn_go_val = new Label();
btn_go_val.text = "Go";
btn_go_val.textAlign='middle';
btn_go_val.fontSize = 50;
btn_go_val.fontName = "BRLNSDB";
btn_go_val.fontColor = "#FFFFFF";
btn_go_val.refreshSize();
const btnRight = new MySprite(); btn_go_val.x = - btn_go_val.getBoundingBox().width/2;
btnRight.init(this.images.get('btn_right'));
btnRight.x = this.canvasWidth - 50 * this.mapScale;
btnRight.y = this.canvasHeight - 100 * this.mapScale;
btnRight.setScaleXY(this.mapScale);
this.renderArr.push(btnRight); this.btn_go.addChild(btn_go_val);
this.btnRight = btnRight; this.btn_go_val = btn_go_val;
} }
initPic() { initPic() {
const maxW = this.canvasWidth * 0.7; const bg_pic = new MySprite();
bg_pic.init(this.images.get('bg'));
bg_pic.x = this.canvasWidth / 2;
bg_pic.y = this.canvasHeight / 2;
bg_pic.setScaleXY(this.canvasWidth / bg_pic.width);
const pic1 = new MySprite(); this.renderArr.push(bg_pic);
pic1.init(this.images.get(this.data.pic_url)); this.bg_pic = bg_pic;
pic1.x = this.canvasWidth / 2;
pic1.y = this.canvasHeight / 2;
pic1.setScaleXY(maxW / pic1.width);
this.renderArr.push(pic1); this.initRotaryTable();
this.pic1 = pic1; }
/**
* 初始化转盘
*/
initRotaryTable(){
let rotaryTable = new ShapeCircle();
const label1 = new Label(); rotaryTable.setRadius(this.canvasHeight * 0.35);
label1.text = this.data.text;
label1.textAlign = 'center';
label1.fontSize = 50;
label1.fontName = 'BRLNSDB';
label1.fontColor = '#ffffff';
pic1.addChild(label1); rotaryTable.x = this.canvasWidth/2;
rotaryTable.y = this.canvasHeight/2;
rotaryTable.alpha = 0;
this.renderArr.push(rotaryTable);
this.rotaryTable = rotaryTable;
this.initExercises();
rotaryTable.setScaleXY(this.initRotaryTableScale);
const pic2 = new MySprite(); setTimeout(() => {
pic2.init(this.images.get(this.data.pic_url_2)); //由小变大
pic2.x = this.canvasWidth / 2 + this.canvasWidth; tweenChange(rotaryTable, {scaleX:this.mapScale, scaleY:this.mapScale}, 0.5, ()=>{
pic2.y = this.canvasHeight / 2; });
pic2.setScaleXY(maxW / pic2.width); }, 500);
}
this.renderArr.push(pic2); initExercises(){
this.pic2 = pic2; if(!this.data.exercises){
return;
}
this.curPic = pic1; //结束整个练习则不再初始化
} if(this.nextExercisesIndex == this.data.exercises.length){
return;
}
this.curExercises = this.data.exercises[this.nextExercisesIndex];
//循环处初始化卡片内容
for(let i = 0; i < this.curExercises.contents.length; ++ i){
let content = this.curExercises.contents[i];
let tContent = {card:null,audio_url:null};
let contentCard = this.getContentCard(content);
this.rotaryTable.addChild(contentCard);
tContent.card = contentCard;
tContent.audio_url = content.audio_url;
this.curContents.push(tContent);
}
//计算角度
if(!this.curContents){
return;
}
//卡片半径
let card_r = this.cardOuterR * this.mapScale;
//圆盘半径
let rotaryTable_r = this.rotaryTable.getBoundingBox().width/2;
//间隔角度
let interval_angle = Math.floor(360/this.curContents.length);
//获取角度对应的弧长
let arc_length = this.rotaryTable.getBoundingBox().width * Math.PI/this.curContents.length;
console.log('arc length', arc_length);
let scale = this.mapScale;
let interval = 0;
if(this.curContents.length > 6){
interval = 100;
}
else{
interval = 110;
}
btnLeftClicked() { //如果弧长小于卡片直径,则缩小卡片半径
if((arc_length - interval) < card_r * 2){
scale = (arc_length - interval) / (2 * card_r);
this.lastPage(); console.log('new scale:',scale );
}
console.log('new scale:',scale );
let start_angle = 0;
//计算坐标
for(let i = 0; i < this.curContents.length; ++ i){
let content = this.curContents[i];
let pos = getPosByAngle(start_angle, (rotaryTable_r - card_r) * this.mapScale);
content.card.x = pos.x;
content.card.y = pos.y;
content.card.setScaleXY(scale);
//记录初始x坐标
content.initX = pos.x;
//记录初始y坐标
content.initY = pos.y;
content.initScale = scale;
start_angle = start_angle + interval_angle;
}
} }
btnRightClicked() { /**
* 获取卡片
* @param content 练习题内容
*/
getContentCard(content){
const contentCard = new MySprite();
//卡片
contentCard.init(this.images.get('card'));
contentCard.setScaleXY(this.mapScale);
//图片存在,则渲染图片
if(content.pic_url){
const content_pic = new MySprite();
content_pic.init(this.images.get(content.pic_url));
let w = content_pic.width;
let h = content_pic.height;
let r = Math.sqrt( w * w + h * h)/2;
content_pic.setScaleXY(this.cardInerR / r);
content_pic.x = 0;
content_pic.y = 0;
contentCard.addChild(content_pic);
}
else{
let content_val = new Label();
content_val.text = content.val;
content_val.textAlign='middle';
content_val.fontSize = 50;
content_val.fontName = "BRLNSDB";
content_val.fontColor = "#e05e14";
content_val.refreshSize();
this.setFontSize(contentCard.width, content_val);
content_val.refreshSize();
content_val.x = - content_val.getBoundingBox().width/2;
contentCard.addChild(content_val);
}
contentCard.childDepandAlpha = true;
this.nextPage(); return contentCard;
} }
lastPage() { setFontSize(parWidth, contentVal: Label){
if (this.curPic == this.pic1) { if(!contentVal){
return; return;
} }
this.canTouch = false; let changed = false;
const moveLen = this.canvasWidth; let w = contentVal.width;
tweenChange(this.pic1, {x: this.pic1.x + moveLen}, 1);
tweenChange(this.pic2, {x: this.pic2.x + moveLen}, 1, () => { let h = contentVal.height;
this.canTouch = true;
this.curPic = this.pic1; let r = Math.sqrt( w * w + h * h)/2;
});
//如果宽度超过,则缩小字体
if(r > (parWidth - 40)/2){
let fontSize = contentVal.fontSize;
fontSize = fontSize - 2;
contentVal.fontSize = fontSize;
contentVal.refreshSize();
this.setFontSize(parWidth, contentVal);
changed = true;
}
return changed;
} }
nextPage() { magnifyingFontSize(parWidth, contentVal: Label){
if (this.curPic == this.pic2) { if(!contentVal){
return; return;
} }
this.canTouch = false; let changed = false;
const moveLen = this.canvasWidth; let w = contentVal.width;
tweenChange(this.pic1, {x: this.pic1.x - moveLen}, 1);
tweenChange(this.pic2, {x: this.pic2.x - moveLen}, 1, () => {
this.canTouch = true;
this.curPic = this.pic2;
});
}
pic1Clicked() { let h = contentVal.height;
this.playAudio(this.data.audio_url);
}
pic2Clicked() { let r = Math.sqrt( w * w + h * h)/2;
this.playAudio(this.data.audio_url_2);
} //如果宽度超过,则缩小字体
if(r < (parWidth - 40)/2){
let fontSize = contentVal.fontSize;
fontSize = fontSize + 2;
contentVal.fontSize = fontSize;
contentVal.refreshSize();
this.setFontSize(parWidth, contentVal);
changed = true;
}
return changed;
}
mapDown(event) { mapDown(event) {
...@@ -625,24 +874,17 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -625,24 +874,17 @@ export class PlayComponent implements OnInit, OnDestroy {
return; return;
} }
if ( this.checkClickTarget(this.btnLeft) ) { if ( !this.playingStatus && this.checkClickTarget(this.btn_go) ) {
this.btnLeftClicked(); this.initGame();
return; return;
} }
if ( this.checkClickTarget(this.btnRight) ) { if(this.curContent){
this.btnRightClicked();
return;
}
if ( this.checkClickTarget(this.pic1) ) { if(this.checkClickTarget(this.curContent.card)){
this.pic1Clicked(); this.playAudio(this.curContent.audio_url);
return; }
}
if ( this.checkClickTarget(this.pic2) ) {
this.pic2Clicked();
return;
} }
} }
...@@ -675,5 +917,145 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -675,5 +917,145 @@ export class PlayComponent implements OnInit, OnDestroy {
} }
initGame(){
this.playingStatus = true;
if(this.first){
this.first = false;
this.playGame();
}
else{
this.rotaryTable.setScaleXY(this.initRotaryTableScale);
this.pauseAudio(this.curContent.audio_url);
//重置音频
const audio = this.audioObj[this.curContent.audio_url];
if(audio){
audio.currentTime = 0;
}
//卡片恢复原状
for(let i = 0; i < this.curContents.length; ++ i){
let t_content = this.curContents[i];
t_content.card.alpha = 1;
t_content.card.x = t_content.initX;
t_content.card.y = t_content.initY;
//设置初始大小
t_content.card.setScaleXY(t_content.initScale);
}
//由小变大
tweenChange(this.rotaryTable, {scaleX:this.mapScale, scaleY:this.mapScale}, 0.5, ()=>{
this.playGame();
});
}
}
playGame(){
this.playAudio('playing', false, ()=>{
this.setBtnGoText("GO");
});
this.setBtnGoText("···");
//音频长度
const audio = this.audioObj['playing'];
let duration = Math.ceil(audio.duration);
this.times = this.times + 1;
let angle = duration * 360;
rotateItem(this.rotaryTable, angle, duration,()=>{
this.playAudio('stop');
//抽取卡片
this.drawCard();
this.playingStatus = false;
//重置旋转角度
this.rotaryTable.rotation = 0;
//console.log('this.rotaryTable:', this.rotaryTable);
});
}
/**
* 抽取卡片
*/
drawCard(){
this.curContent = this.getRandomItemFromArr(this.curContents);
this.playAudio('pop-up');
//新坐标
let x = this.canvasWidth/2;
//新坐标
let y = this.canvasHeight/2;
//调整位置
this.rotaryTable.removeChild(this.curContent.card);
this.rotaryTable.addChild(this.curContent.card);
let scaleX = this.curContent.card.scaleX;
let scale = this.rotaryTable.getBoundingBox().width/this.curContent.card.width;
//由小变大
tweenChange(this.curContent.card, {scaleX:scale, scaleY:scale}, 0.5, ()=>{
//隐藏其它的卡片
for(let i = 0; i < this.curContents.length; ++ i){
if(this.curContents[i] != this.curContent){
this.curContents[i].card.alpha = 0;
this.curContents[i].card.setScaleXY(0);
}
}
});
//移动新位置
tweenChange(this.curContent.card,{x:0,y:0},0.5);
}
getRandomItemFromArr(arr){
if(!arr){
return;
}
let length = arr.length;
let index = Math.ceil(Math.random()*100000000)%length;
return arr[index];
}
setBtnGoText(text){
this.btn_go_val.text = text;
this.btn_go_val.refreshSize();
this.btn_go_val.x = -this.btn_go_val.getBoundingBox().width/2;
}
} }
const res = [ const res = [
// ['bg', "assets/play/bg.jpg"], ['bg', "assets/play/bg.png"],
['btn_left', "assets/play/btn_left.png"], ['btn_go', "assets/play/btn_go.png"],
['btn_right', "assets/play/btn_right.png"], ['card', "assets/play/card.png"],
// ['text_bg', "assets/play/text_bg.png"], ['card-3x', "assets/play/card@3x.png"]
]; ];
...@@ -12,7 +12,10 @@ const res = [ ...@@ -12,7 +12,10 @@ const res = [
const resAudio = [ const resAudio = [
['click', "assets/play/music/click.mp3"], ['click', "assets/play/music/click.mp3"],
['playing', "assets/play/music/playing.mp3"],
['begin', "assets/play/music/begin.mp3"],
['stop', "assets/play/music/stop.mp3"],
['pop-up', "assets/play/music/pop-up.mp3"]
]; ];
export {res, resAudio}; export {res, resAudio};
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment