Commit caa5a92f authored by Chen Jiping's avatar Chen Jiping

perf:完成开发

parent 8a51c964
...@@ -128,5 +128,8 @@ ...@@ -128,5 +128,8 @@
} }
} }
}, },
"defaultProject": "ng-template-generator" "defaultProject": "ng-template-generator",
"cli": {
"analytics": "f20c6511-f4ed-4db3-8182-6a41eadc5db4"
}
} }
\ No newline at end of file
export class Obj{
/**音频材料 */
audioUrl: String;
/**图片材料 */
picUrl:String;
val : String;
}
\ No newline at end of file
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
</div> </div>
<div nz-row nzType="flex" nzAlign="middle"> <div nz-row nzType="flex" nzAlign="middle">
<!--
<div nz-col nzSpan="5" nzOffset="1"> <div nz-col nzSpan="5" nzOffset="1">
<h5> add background: </h5> <h5> add background: </h5>
...@@ -18,7 +19,18 @@ ...@@ -18,7 +19,18 @@
</app-upload-image-with-preview> </app-upload-image-with-preview>
</div> </div>
</div> </div>
-->
<div nz-col nzSpan="3" nzOffset="1">
<h5> 音频材料: </h5>
<div style="width: 100%; margin-top: 5px;">
<app-audio-recorder
[audioUrl]="exercises?.audio_url"
(audioUploaded)="onItemAudioUploadSuccess($event, exercises)"
></app-audio-recorder>
</div>
</div>
<div nz-col nzSpan="5" nzOffset="1" class="img-box" <div nz-col nzSpan="5" nzOffset="1" class="img-box"
*ngFor="let it of hotZoneArr; let i = index"> *ngFor="let it of hotZoneArr; let i = index">
...@@ -68,7 +80,7 @@ ...@@ -68,7 +80,7 @@
<div class="bg-box"> <div class="bg-box">
<button nz-button nzType="dashed" (click)="addBtnClick()" <button nz-button nzType="dashed" (click)="addBtnClick()"
class="add-btn"> class="add-btn" [disabled]="hotZoneArr.length == 1 ? true : false">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i> <i nz-icon nzType="plus-circle" nzTheme="outline"></i>
<!--Add Image--> <!--Add Image-->
Add hot zone Add hot zone
......
...@@ -103,6 +103,17 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -103,6 +103,17 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
this.init(); this.init();
} }
_exercises = null;
get exercises(){
return this._exercises;
}
@Input()
set exercises(v){
this._exercises = v;
}
onResize(event) { onResize(event) {
this.winResizeEventStream.next(); this.winResizeEventStream.next();
} }
...@@ -129,7 +140,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -129,7 +140,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
onBackgroundUploadSuccess(e) { onBackgroundUploadSuccess(e) {
console.log('e: ', e); console.log('e: ', e);
this.bgItem.url = e.url; this.bgItem.picUrl = e.url;
this.refreshBackground(); this.refreshBackground();
} }
...@@ -151,9 +162,9 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -151,9 +162,9 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
} }
const bg = this.bg; const bg = this.bg;
if (this.bgItem.url) { if (this.bgItem.picUrl) {
bg.load(this.bgItem.url).then(() => { bg.load(this.bgItem.picUrl).then(() => {
const rate1 = this.canvasWidth / bg.width; const rate1 = this.canvasWidth / bg.width;
const rate2 = this.canvasHeight / bg.height; const rate2 = this.canvasHeight / bg.height;
...@@ -382,6 +393,12 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -382,6 +393,12 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
} }
initItem() { initItem() {
const refreshBg = () => {
setInterval(() => {
this.refreshBackground();
}, 1000);
}
if (!this.bgItem) { if (!this.bgItem) {
this.bgItem = {}; this.bgItem = {};
} else { } else {
...@@ -401,6 +418,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -401,6 +418,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
this.initHotZoneArr(); this.initHotZoneArr();
} }
refreshBg();
}); });
} }
...@@ -894,7 +912,13 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -894,7 +912,13 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
console.log('hotZoneItemArr: ', hotZoneItemArr); console.log('hotZoneItemArr: ', hotZoneItemArr);
this.save.emit({bgItem, hotZoneItemArr}); let exercises = this._exercises;
if(!exercises){
exercises = {};
}
this.save.emit({bgItem, hotZoneItemArr, exercises});
} }
private updatePos() { private updatePos() {
......
<div class="model-content"> <div class="model-content">
<div nz-row>
<div style="position: absolute; left: 200px; top: 100px; width: 800px;"> <div nz-col [nzSpan]="20" nzOffset="2">
<div nz-form>
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()"> <div id='title-anchor'>
<nz-divider nzText="基本信息" nzOrientation="left"></nz-divider>
<app-upload-image-with-preview </div>
[picUrl]="item.pic_url" <nz-form-item>
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')" <nz-form-label [nzSpan]="3">背景图片</nz-form-label>
></app-upload-image-with-preview> <nz-form-control [nzSpan]="6">
<app-upload-image-with-preview style="width: 100%" [picUrl]="item.bgItem.picUrl"
<app-audio-recorder (imageUploaded)="onImageUploadSuccess($event,item.bgItem, 'picUrl')">
[audioUrl]="item.audio_url" </app-upload-image-with-preview>
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url')" </nz-form-control>
></app-audio-recorder> </nz-form-item>
<app-custom-hot-zone></app-custom-hot-zone> </div>
<app-upload-video></app-upload-video> </div>
<app-lesson-title-config></app-lesson-title-config> </div>
<div nz-row>
<div id='listen-anchor' nz-col [nzSpan]="20" nzOffset="2">
<nz-divider nzText="练习题" nzOrientation="left"></nz-divider>
</div>
<div nz-col [nzSpan]="20" nzOffset="2" class='border'>
<div *ngFor="let data of item.exercisesArr;let i = index">
<div class='border-lite'>内容:{{i+1}}
<button style="margin: 10px;" nz-button nzType="danger" (click)="delExercisesItem(i)">
<span>删除</span>
</button>
</div>
<app-custom-hot-zone [bgItem]="item.bgItem" [hotZoneItemArr]="data.hotZoneItemArr" [isHasRect]="false"
[exercises]="data" [defaultItemType]="'text'" (save)="saveData($event, i)"></app-custom-hot-zone>
</div>
</div>
<hr>
<div id='listen-anchor' nz-col [nzSpan]="20" nzOffset="2">
<nz-form-item>
<nz-form-label [nzSpan]="6" nzFor="exercises">操作</nz-form-label>
<nz-form-control [nzSpan]="6">
<button nz-button nzType="dashed" class="add-btn" id="add-btn" (click)="addExercisesItem()">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
</button>
</nz-form-control>
</nz-form-item>
</div> </div>
</div>
</div> \ No newline at end of file
\ No newline at end of file
import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef, ChangeDetectorRef} from '@angular/core'; import { Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef, ChangeDetectorRef } from '@angular/core';
import { NzMessageService } from "ng-zorro-antd";
@Component({ @Component({
selector: 'app-form', selector: 'app-form',
...@@ -10,12 +10,14 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap ...@@ -10,12 +10,14 @@ 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 = "LST-04-01";
// 储存对象 // 储存对象
item; item;
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) {
constructor(private appRef: ApplicationRef, private changeDetectorRef: ChangeDetectorRef, private message: NzMessageService) {
} }
...@@ -24,8 +26,12 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -24,8 +26,12 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
this.item = {}; this.item = {};
this.item.bgItem = {};
this.item.exercisesArr = [];
// 获取存储的数据 // 获取存储的数据
(<any> window).courseware.getData((data) => { (<any>window).courseware.getData((data) => {
if (data) { if (data) {
this.item = data; this.item = data;
...@@ -50,6 +56,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -50,6 +56,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
init() { init() {
console.log('this.item: ', this.item);
} }
...@@ -58,9 +65,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -58,9 +65,9 @@ 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();
} }
...@@ -68,9 +75,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -68,9 +75,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
* 储存音频数据 * 储存音频数据
* @param e * @param e
*/ */
onAudioUploadSuccess(e, key) { onAudioUploadSuccess(e, item, key) {
this.item[key] = e.url; item[key] = e.url;
this.save(); this.save();
} }
...@@ -80,7 +87,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -80,7 +87,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
* 储存数据 * 储存数据
*/ */
save() { save() {
(<any> window).courseware.setData(this.item, null, this.saveKey); (<any>window).courseware.setData(this.item, null, this.saveKey);
this.refresh(); this.refresh();
} }
...@@ -93,5 +100,45 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -93,5 +100,45 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}, 1); }, 1);
} }
/**
* 添加练习
*/
addExercisesItem() {
let exercises = {};
this.item.exercisesArr.push(exercises);
this.save();
}
delExercisesItem(index) {
if (index !== -1) {
this.item.exercisesArr.splice(index, 1);
this.save();
}
}
saveData(e, i ) {
console.log(' in saveData e: ', e);
const { bgItem, hotZoneItemArr, exercises } = e;
this.item.exercisesArr[i].hotZoneItemArr = hotZoneItemArr;
this.item.exercisesArr[i].audio_url = exercises.audio_url;
this.item.bgItem = bgItem;
this.save();
this.message.create(
'success',
'保存成功'
);
}
} }
/**
*
* @param audio 音频
* @param now true-重新开始播放,flase-继续播放
* @param callback
*/
export function playAudio(audio, now = false, callback = null) {
if (audio) {
if (now) {
audio.pause();
audio.currentTime = 0;
}
if (callback) {
audio.onended = () => {
callback();
};
}
audio.play();
}
}
/**
* 暂停播放音频
* @param audio 音频
* @param reset 暂停是否重置:true-是,false-否
* @param callback
*/
export function pauseAudio(audio, reset = false, callback = null) {
if (audio) {
if (reset) {
audio.currentTime = 0;
}
audio.pause();
if (callback) {
callback();
}
}
}
\ No newline at end of file
import { playAudio } from './AudioUtil';
import { MySprite, ShapeRect, tweenChange } from './Unit';
export class Celebrate{
bg: ShapeRect;
images;
audioObj;
bigStar :MySprite;
smallStar : MySprite;
pic : MySprite;
init(images, audioObj){
this.images = images;
this.audioObj = audioObj;
const bg = new ShapeRect();
this.bg = bg;
bg.alpha = 0;
this.initPic();
}
initPic(){
const pic = new MySprite();
pic.init(this.images.get('bg_aswsome'), 0.5, 0.5);
pic.x = pic.width / 2;
pic.y = pic.height / 2;
this.bg.addChild(pic);
this.pic = pic;
this.bg.setSize(pic.width, pic.height);
;
const bigStar = new MySprite();
this.bigStar = bigStar
bigStar.init(this.images.get('icon_star2'), 0.5, 0.5);
bigStar.x = 49 + bigStar.width / 2;
bigStar.y = 94 + bigStar.height / 2;
this.bg.addChild(bigStar);
const smallStar = new MySprite();
this.smallStar = smallStar;
smallStar.init(this.images.get('icon_star1'));
smallStar.x = 474 + smallStar.width / 2;
smallStar.y = 143 + smallStar.height / 2;
this.bg.addChild(smallStar);
}
show(mapscale = 1, callback = null){
let tempScale = 1;
this.pic.setScaleXY(0);
this.smallStar.setScaleXY(0);
this.bigStar.setScaleXY(0);
playAudio(this.audioObj['celebrate'], true);
tweenChange(this.pic, {scaleX : tempScale, scaleY : tempScale}, 0.5, ()=>{
tweenChange(this.smallStar, {scaleX : tempScale * 1.3, scaleY : tempScale * 1.3}, 0.3, ()=>{
tweenChange(this.smallStar, {scaleX : tempScale, scaleY : tempScale}, 0.3)
});
tweenChange(this.bigStar, {scaleX : tempScale * 1.3, scaleY : tempScale * 1.3}, 0.3, ()=>{
tweenChange(this.bigStar, {scaleX : tempScale, scaleY : tempScale}, 0.3, callback)
});
})
}
}
\ No newline at end of file
import {
MySprite,
moveItem,
removeItemFromArr,
rotateItem
} from './Unit';
export class Petal {
renderArr = [];
images;
ctx;
playing = true;
tempRenderArr = [];
constructor(renderArr, images, ctx) {
this.renderArr = renderArr;
this.images = images;
this.ctx = ctx;
this.tempRenderArr = [];
}
stop(callback = null) {
this.playing = false;
const checkFinish = () => {
if (this.tempRenderArr.length == 0) {
if (callback) {
callback();
}
}
else {
setTimeout(() => {
checkFinish();
}, 100);
}
}
checkFinish();
}
/**
* 显示结束花瓣
* @param rect {x,y,width, height} 花瓣显示位置及大小
* @param mapScale
* @param timeout 花瓣显示间隔
* @param kinds 花瓣种类,即花瓣图片样式数组个数
*/
showPetal(rect, mapScale: number, timeout: number, kinds = 9) {
if (!this.playing) {
return;
}
const petal = this.getPetal(rect, mapScale, kinds);
this.renderArr.push(petal);
this.tempRenderArr.push(petal);
let toY = rect.y + rect.height;
moveItem(petal, petal.x, toY + petal.height * petal.scaleY, petal['time'], () => {
removeItemFromArr(this.renderArr, petal);
removeItemFromArr(this.tempRenderArr, petal);
});
rotateItem(petal, petal['tr'], petal['time']);
setTimeout(() => {
this.showPetal(rect, mapScale, timeout);
}, timeout);
}
/**
* 得到花瓣
* @param rect
* @param mapScale
* @param kinds
*/
private getPetal(rect, mapScale, kinds) {
const petal = new MySprite(this.ctx);
const id = Math.ceil(Math.random() * kinds);
petal.init(this.images.get('petal_' + id));
const randomS = (Math.random() * 0.4 + 0.6) * mapScale;
petal.setScaleXY(randomS);
const randomR = Math.random() * 360;
petal.rotation = randomR;
const randomX = rect.x + Math.random() * rect.width;
petal.x = randomX;
petal.y = rect.y - petal.height / 2 * petal.scaleY;
const randomT = 0.5 + Math.random() * 2;
petal['time'] = randomT;
let randomTR = 360 * Math.random(); // - 180;
if (Math.random() < 0.5) { randomTR *= -1; }
petal['tr'] = randomTR;
return petal;
}
}
\ No newline at end of file
...@@ -17,3 +17,8 @@ ...@@ -17,3 +17,8 @@
src: url("../../assets/font/BRLNSDB.TTF") ; src: url("../../assets/font/BRLNSDB.TTF") ;
} }
@font-face
{
font-family: 'MMTextBook-Bold';
src: url("../../assets/font/MMTextBook-Bold.otf") ;
}
\ No newline at end of file
import {Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener} from '@angular/core'; import { Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener } from '@angular/core';
import { import {
Label, Label,
MySprite, tweenChange, MyAnimation,
MySprite, shake, ShapeRect, tweenChange,
} from './Unit'; } from './Unit';
import {res, resAudio} from './resources'; import { res, resAudio } from './resources';
import {Subject} from 'rxjs'; import { Subject } from 'rxjs';
import {debounceTime} from 'rxjs/operators'; import { debounceTime } from 'rxjs/operators';
import TWEEN from '@tweenjs/tween.js'; import TWEEN from '@tweenjs/tween.js';
import { Petal } from './PetalUtil';
import { Celebrate } from './Celebrate';
...@@ -22,8 +25,8 @@ import TWEEN from '@tweenjs/tween.js'; ...@@ -22,8 +25,8 @@ import TWEEN from '@tweenjs/tween.js';
}) })
export class PlayComponent implements OnInit, OnDestroy { export class PlayComponent implements OnInit, OnDestroy {
@ViewChild('canvas', {static: true }) canvas: ElementRef; @ViewChild('canvas', { static: true }) canvas: ElementRef;
@ViewChild('wrap', {static: true }) wrap: ElementRef; @ViewChild('wrap', { static: true }) wrap: ElementRef;
// 数据 // 数据
data; data;
...@@ -57,17 +60,35 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -57,17 +60,35 @@ export class PlayComponent implements OnInit, OnDestroy {
canvasLeft; canvasLeft;
canvasTop; canvasTop;
saveKey = 'test_0011'; saveKey = 'LST-04-01';
btnLeft;
btnRight;
pic1;
pic2;
canTouch = true; canTouch = true;
curPic; private bg: any;
private hotZoneArr: any[];
private magnifier: MySprite;
private isMagnifierTouched: boolean;
private curHotZoneItem: any;
private photoAnima: MyAnimation;
private hotZoneRate: number;
private oldHotMapScale: number;
private textLabelArr: any;
private allBtns: any;
private curAudio: any;
private endRenderArr: any[];
private bgAudio: any;
private finished = false;
private curExercises: any;
private curIndex = 0;
timeId = null;
@HostListener('window:resize', ['$event']) @HostListener('window:resize', ['$event'])
onResize(event) { onResize(event) {
...@@ -79,8 +100,12 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -79,8 +100,12 @@ export class PlayComponent implements OnInit, OnDestroy {
this.data = {}; this.data = {};
this.data.bgItem = {};
this.data.exercisesArr = [];
// 获取数据 // 获取数据
const getData = (<any> window).courseware.getData; const getData = (<any>window).courseware.getData;
getData((data) => { getData((data) => {
if (data && typeof data == 'object') { if (data && typeof data == 'object') {
...@@ -285,6 +310,8 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -285,6 +310,8 @@ export class PlayComponent implements OnInit, OnDestroy {
}; };
} }
audio.play(); audio.play();
return audio;
} }
} }
...@@ -432,10 +459,50 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -432,10 +459,50 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initDefaultData() { initDefaultData() {
if (!this.data.pic_url) { if (!this.data.bgItem) {
this.data.pic_url = 'assets/play/default/pic.jpg'; this.data.bgItem = {
this.data.pic_url_2 = 'assets/play/default/pic.jpg'; rect: { height: 892, width: 1585, x: 392, y: 0 },
url: 'assets/play/default/pic.jpg'
};
}
if (!this.data.exercisesArr) {
this.data.exercisesArr = [{
hotZoneItemArr: [
{
audio_url: 'assets/play/default/audio.mp3',
fontColor: "#a63f0b",
fontName: "MMTextBook-Bold",
fontScale: 1.85,
fontSize: 52,
imgScale: 1,
index: 0,
itemType: "text",
mapScale: 1.85,
rect: { x: 391.84, y: 446.02, width: 244.05, height: 244.05 },
text: "test_1"
} }
]
}, {
hotZoneItemArr: [
{
audio_url: 'assets/play/default/audio.mp3',
fontColor: "#a63f0b",
fontName: "MMTextBook-Bold",
fontScale: 1.85,
fontSize: 52,
imgScale: 1,
index: 1,
itemType: "text",
mapScale: 1.85,
rect: { x: 961.36, y: 450.36, width: 244.05, height: 244.05 },
text: "test_2"
}
]
}
]
}
} }
...@@ -444,8 +511,19 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -444,8 +511,19 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initImg() { initImg() {
this.addUrlToImages(this.data.pic_url); this.addUrlToImages(this.data.bgItem.picUrl);
this.addUrlToImages(this.data.pic_url_2);
console.log('this.data:', this.data);
this.data.exercisesArr.forEach((item) => {
item.hotZoneItemArr.forEach(hotZoneItem => {
if (hotZoneItem.itemType === 'pic') {
this.addUrlToImages(hotZoneItem.pic_url);
}
});
});
} }
...@@ -454,12 +532,26 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -454,12 +532,26 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initAudio() { initAudio() {
// 音频资源 this.data.exercisesArr.forEach((item) => {
this.addUrlToAudioObj(this.data.audio_url);
this.addUrlToAudioObj(this.data.audio_url_2);
item.hotZoneItemArr.forEach(hotZoneItem => {
if (hotZoneItem.audio_url) {
this.addUrlToAudioObj(hotZoneItem.audio_url);
}
});
if (item.audio_url) {
this.addUrlToAudioObj(item.audio_url);
}
});
this.rawAudios.forEach((item, key) => {
// 音效 // 音效
this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3); this.addUrlToAudioObj(key, this.rawAudios.get(key));
})
} }
...@@ -481,10 +573,43 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -481,10 +573,43 @@ export class PlayComponent implements OnInit, OnDestroy {
this.renderArr = []; this.renderArr = [];
this.isMagnifierTouched = false;
this.photoAnima = null;
this.textLabelArr = [];
this.allBtns = [];
this.endRenderArr = [];
this.finished = false;
this.curIndex = 0;
this.curExercises = null;
} }
playBgAudio() {
if (this.timeId) {
clearTimeout(this.timeId);
}
if (this.bgAudio) {
this.bgAudio.pause();
}
if (this.finished && this.bgAudio) {
this.bgAudio.pause();
}
this.bgAudio = this.playAudio(this.curExercises.audio_url, true);
this.timeId = setTimeout(() => {
if (!this.finished) {
this.playBgAudio();
}
}, 3000);
}
/** /**
...@@ -492,130 +617,328 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -492,130 +617,328 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initView() { initView() {
this.initBg();
this.initPic(); this.showNext();
this.initBottomPart(); this.initMagnifier();
} }
initBottomPart() { private createSprite(key: string) {
const sprite = new MySprite();
sprite.init(this.images.get(key));
return sprite;
}
const btnLeft = new MySprite();
btnLeft.init(this.images.get('btn_left'));
btnLeft.x = this.canvasWidth - 150 * this.mapScale;
btnLeft.y = this.canvasHeight - 100 * this.mapScale;
btnLeft.setScaleXY(this.mapScale); private initBg() {
this.renderArr.push(btnLeft); console.log('data:', this.data);
const url = this.data.bgItem.picUrl;
const bg = this.createSprite(url);
this.btnLeft = btnLeft; bg.x = this.canvasWidth / 2;
bg.y = this.canvasHeight / 2;
const sx = this.canvasWidth / bg.width;
const sy = this.canvasHeight / bg.height;
const s = Math.min(sx, sy);
bg.setScaleXY(s);
this.bg = bg;
this.renderArr.push(bg);
}
showNext() {
const btnRight = new MySprite(); if (this.magnifier) {
btnRight.init(this.images.get('btn_right')); this.magnifier['light'].visible = false;
btnRight.x = this.canvasWidth - 50 * this.mapScale; this.magnifier['wrong'].visible = false;
btnRight.y = this.canvasHeight - 100 * this.mapScale; }
btnRight.setScaleXY(this.mapScale);
this.renderArr.push(btnRight);
this.btnRight = btnRight; if (this.curHotZoneItem) {
this.curHotZoneItem.alpha = 0;
this.curHotZoneItem = null;
} }
initPic() { if (this.bgAudio) {
this.bgAudio.pause();
}
const maxW = this.canvasWidth * 0.7; this.finished = false;
const pic1 = new MySprite(); if (this.data.exercisesArr.length == this.curIndex) {
pic1.init(this.images.get(this.data.pic_url)); this.showEnd();
pic1.x = this.canvasWidth / 2; return;
pic1.y = this.canvasHeight / 2; }
pic1.setScaleXY(maxW / pic1.width);
this.renderArr.push(pic1); this.allBtns = [];
this.pic1 = pic1;
this.curExercises = this.data.exercisesArr[this.curIndex];
const label1 = new Label(); if (!this.curExercises) {
label1.text = this.data.text; return;
label1.textAlign = 'center'; }
label1.fontSize = 50;
label1.fontName = 'BRLNSDB';
label1.fontColor = '#ffffff';
pic1.addChild(label1); this.initHotZone();
this.playBgAudio();
this.canTouch = true;
}
initHotZone() {
const pic2 = new MySprite(); let curBgRect;
pic2.init(this.images.get(this.data.pic_url_2)); if (this.bg) {
pic2.x = this.canvasWidth / 2 + this.canvasWidth; curBgRect = this.bg.getBoundingBox();
pic2.y = this.canvasHeight / 2; }
pic2.setScaleXY(maxW / pic2.width);
this.renderArr.push(pic2); let oldBgRect = this.data.bgItem.rect;
this.pic2 = pic2; if (!oldBgRect) {
oldBgRect = curBgRect;
}
const rate = curBgRect.width / oldBgRect.width;
this.hotZoneRate = rate;
this.curPic = pic1; this.hotZoneArr = [];
const arr = this.curExercises.hotZoneItemArr;
if (!arr && arr.length > 0) {
return;
} }
this.oldHotMapScale = arr[0].mapScale;
for (let i = 0; i < arr.length; i++) {
btnLeftClicked() { const data = JSON.parse(JSON.stringify(arr[i]));
data.rect.x *= rate;
data.rect.y *= rate;
data.rect.width *= rate;
data.rect.height *= rate;
data.rect.x += curBgRect.x;
data.rect.y += curBgRect.y;
const hotZone = this.getHotZoneItem(data, rate);
hotZone.alpha = 0;
this.hotZoneArr.push(hotZone);
this.lastPage();
} }
btnRightClicked() { }
this.nextPage(); getHotZoneItem(data, rate) {
const saveRect = data.rect;
let item;
if (data.itemType === 'rect') {
item = new ShapeRect(this.ctx);
item.setSize(saveRect.width, saveRect.height);
item.x = saveRect.x;
item.y = saveRect.y;
} else if (data.itemType == 'pic') {
item = this.createBtn(data.pic_url, null, 1);
item.setScaleXY(data.imgScale * rate);
item.x = saveRect.x + saveRect.width / 2;
item.y = saveRect.y + saveRect.height / 2;
item.onClick = () => {
console.log('item.data:', item.data);
if (this.curAudio && !this.curAudio.paused) {
this.curAudio.pause();
}
this.curAudio = this.playAudio(item.data.audio_url);
} }
lastPage() { } else if (data.itemType == 'text') {
item = new Label();
item.text = data.text;
item.textAlign = 'center';
item.fontSize = 52;
item.fontName = "MMTextBook-Bold";
item.fontColor = "#a63f0b";
item.x = saveRect.x + saveRect.width / 2;
item.y = saveRect.y + saveRect.height / 2;
item.childDepandAlpha = true;
item.setScaleXY(data.fontScale * rate);
item.refreshSize();
const textBg = this.createBtn('bg_zi', null, 1);
item.setMaxSize(textBg.width * 0.98);
textBg.onClick = () => {
console.log('item.data:', item.data);
if (this.curAudio && !this.curAudio.paused) {
this.curAudio.pause();
}
this.curAudio = this.playAudio(item.data.audio_url);
}
if (this.curPic == this.pic1) { textBg.y = 5;
return; textBg.setScaleXY(1 / item.scaleX * this.oldHotMapScale * this.hotZoneRate);
item.addChild(textBg, -1);
item.bg = textBg;
this.textLabelArr.push(item);
} }
this.canTouch = false; item['data'] = data;
const moveLen = this.canvasWidth; this.renderArr.push(item);
tweenChange(this.pic1, {x: this.pic1.x + moveLen}, 1);
tweenChange(this.pic2, {x: this.pic2.x + moveLen}, 1, () => { return item;
this.canTouch = true; }
this.curPic = this.pic1;
private initMagnifier() {
const magnifier = this.createSprite('bg_jing');
magnifier.setScaleXY(this.mapScale);
magnifier.x = this.canvasWidth / 2;
magnifier.y = this.canvasHeight / 2;
this.renderArr.push(magnifier);
console.log('rate: ', this.hotZoneRate);
const light = this.createSprite('icon_tiao');
light.x = -magnifier.width / 2;
light.y = -magnifier.height / 2;
magnifier.addChild(light);
magnifier['light'] = light;
light.visible = false;
const wrong = this.createSprite('bg_wrong');
wrong.x = 45;
wrong.y = -125;
magnifier.addChild(wrong);
magnifier['wrong'] = wrong;
wrong.visible = false;
this.magnifier = magnifier;
}
private touchDownMagnifier() {
this.isMagnifierTouched = true;
this.playAudio('click');
}
private magnifierMove() {
this.magnifier.x = this.mx;
this.magnifier.y = this.my;
}
private checkHotZone() {
this.magnifier['light'].visible = false;
this.magnifier['wrong'].visible = false;
let hotZoneItem;
this.hotZoneArr.forEach((item) => {
if (this.checkClickTarget(item)) {
hotZoneItem = item;
return;
}
}); });
if (hotZoneItem) {
if (this.curHotZoneItem && this.curHotZoneItem != hotZoneItem) {
this.curHotZoneItem.alpha = 0;
this.curHotZoneItem = null;
} }
nextPage() { this.curHotZoneItem = hotZoneItem;
if (this.curPic == this.pic2) { } else {
if (this.curHotZoneItem) {
this.curHotZoneItem.alpha = 0;
this.curHotZoneItem = null;
}
}
}
private showPhotoAnima() {
if (!this.photoAnima) {
this.photoAnima = this.createAnima('bg_', 15);
this.magnifier.addChild(this.photoAnima, -1);
} else {
this.photoAnima.frameIndex = 0;
}
this.photoAnima.playEndFunc = this.photoAnimaCloseEnd.bind(this);
this.photoAnima.visible = true;
this.photoAnima.play();
}
private createAnima(key, num, delayPerUnit = 0.07, loop = false) {
const anima = new MyAnimation();
for (let i = 1; i <= num; i++) {
anima.addFrameByImg(this.images.get(key + i));
}
anima.delayPerUnit = delayPerUnit;
anima.loop = loop;
return anima;
}
private photoAnimaCloseEnd() {
this.curHotZoneItem.answered = true;
console.log('close...');
tweenChange(this.curHotZoneItem, { alpha: 1 }, 0.2, () => {
this.photoAnima.visible = false;
this.photoAnima.reverse();
this.magnifier['light'].visible = false;
if (this.curAudio) {
this.curAudio.pause();
}
let answered = true;
this.hotZoneArr.forEach((item) => {
if (!item.answered) {
answered = false;
return; return;
} }
});
this.canTouch = false; console.log(answered);
const moveLen = this.canvasWidth; if (!answered) {
tweenChange(this.pic1, {x: this.pic1.x - moveLen}, 1); this.curAudio = this.playAudio(this.curHotZoneItem.data.audio_url, true, () => {
tweenChange(this.pic2, {x: this.pic2.x - moveLen}, 1, () => {
this.canTouch = true; this.canTouch = true;
this.curPic = this.pic2;
}); });
} }
else {
pic1Clicked() { this.finished = true;
this.playAudio(this.data.audio_url);
if (this.bgAudio) {
this.bgAudio.pause();
} }
pic2Clicked() {
this.playAudio(this.data.audio_url_2); this.curAudio = this.playAudio(this.curHotZoneItem.data.audio_url, true, () => {
this.curIndex++;
this.showNext();
});
} }
});
this.playAudio('find');
}
...@@ -625,33 +948,87 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -625,33 +948,87 @@ export class PlayComponent implements OnInit, OnDestroy {
return; return;
} }
if ( this.checkClickTarget(this.btnLeft) ) { if (this.curHotZoneItem) {
this.btnLeftClicked(); this.allBtns.forEach((btn) => {
if (this.curHotZoneItem == btn || this.curHotZoneItem.bg == btn && this.checkClickTarget(btn)) {
btn._onTouchStart();
return; return;
} }
});
}
if ( this.checkClickTarget(this.btnRight) ) { if (this.checkClickTarget(this.magnifier)) {
this.btnRightClicked(); this.touchDownMagnifier();
return; return;
} }
if ( this.checkClickTarget(this.pic1) ) {
this.pic1Clicked(); }
mapMove(event) {
if (!this.isMagnifierTouched) {
return; return;
} }
if ( this.checkClickTarget(this.pic2) ) { this.magnifierMove();
this.pic2Clicked(); this.checkHotZone();
this.allBtns.forEach((btn) => {
if (!this.checkClickTarget(btn)) {
btn._isDown = false;
return; return;
} }
});
} }
mapMove(event) { mapUp(event) {
this.allBtns.forEach((btn) => {
if (btn._isDown) {
btn._onTouchEnd();
}
});
if (this.isMagnifierTouched) {
if (this.curHotZoneItem) {
this.canTouch = false;
if (this.curHotZoneItem.alpha === 0) {
this.magnifier['light'].visible = true;
setTimeout(() => {
this.magnifier['light'].visible = false;
setTimeout(() => {
this.magnifier['light'].visible = true;
this.magnifier.x = this.curHotZoneItem.x;
this.magnifier.y = this.curHotZoneItem.y + 50 * this.mapScale;
this.showPhotoAnima();
}, 100);
}, 100);
}
} }
else {
this.magnifier['wrong'].visible = true;
mapUp(event) { this.canTouch = false;
this.playAudio('wrong', true);
shake(this.magnifier, 0.5, () => {
//加载下一个
this.curIndex++;
this.showNext();
})
}
}
this.isMagnifierTouched = false;
} }
...@@ -671,9 +1048,95 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -671,9 +1048,95 @@ export class PlayComponent implements OnInit, OnDestroy {
this.updateArr(this.renderArr); this.updateArr(this.renderArr);
this.updateArr(this.textLabelArr);
this.updateArr(this.endRenderArr);
}
private createBtn(url_up: string, url_down: string = null, downScale = 0.9) {
const btnUp: any = this.createSprite(url_up);
let btnDown;
if (url_down) {
btnDown = this.createSprite(url_down);
btnUp.addChild(btnDown);
} }
btnUp.btnDown = btnDown;
btnUp._onTouchStart = () => {
if (btnDown) {
btnDown.alpha = 1;
btnUp.alpha = 0;
}
if (!btnUp.baseScale) {
btnUp.baseScale = btnUp.scaleX;
}
btnUp.setScaleXY(btnUp.baseScale * downScale);
if (btnUp.onTouchStart) {
btnUp.onTouchStart();
}
btnUp._isDown = true;
};
btnUp._onTouchMove = () => {
};
btnUp._onTouchEnd = () => {
if (btnDown) {
btnDown.alpha = 0;
btnUp.alpha = 1;
}
btnUp.setScaleXY(btnUp.baseScale);
if (btnUp.onClick) {
btnUp.onClick();
}
btnUp._isDown = false;
};
this.allBtns.push(btnUp);
return btnUp;
}
showEnd() {
console.log('play end ....');
this.finished = true;
this.canTouch = false;
if (this.curAudio) {
this.curAudio.pause();
}
if (this.bgAudio) {
this.bgAudio.pause();
}
const mask = new ShapeRect();
mask.setSize(this.canvasWidth, this.canvasHeight);
mask.alpha = 0.5;
mask.fillColor = "#000000";
mask.x = 0;
mask.y = 0;
this.endRenderArr.push(mask);
let celebrate = new Celebrate();
celebrate.init(this.images, this.audioObj);
celebrate.bg.setScaleXY(this.mapScale);
celebrate.bg.x = (this.canvasWidth - celebrate.bg.getBoundingBox().width) / 2;
celebrate.bg.y = (this.canvasHeight - celebrate.bg.getBoundingBox().height) / 2;
this.endRenderArr.push(celebrate.bg);
celebrate.show(this.mapScale);
let petal = new Petal(this.endRenderArr, this.images, this.ctx);
//显示花瓣
petal.showPetal({ x: 0, y: 0, width: this.canvasWidth, height: this.canvasHeight }, this.mapScale, 100, 8);
}
} }
const res = [ const res = [
// ['bg', "assets/play/bg.jpg"],
['btn_left', "assets/play/btn_left.png"],
['btn_right', "assets/play/btn_right.png"],
// ['text_bg', "assets/play/text_bg.png"],
['bg_1', "assets/play/bg_1.png"],
['bg_2', "assets/play/bg_2.png"],
['bg_3', "assets/play/bg_3.png"],
['bg_4', "assets/play/bg_4.png"],
['bg_5', "assets/play/bg_5.png"],
['bg_6', "assets/play/bg_6.png"],
['bg_7', "assets/play/bg_7.png"],
['bg_8', "assets/play/bg_8.png"],
['bg_9', "assets/play/bg_9.png"],
['bg_10', "assets/play/bg_10.png"],
['bg_11', "assets/play/bg_11.png"],
['bg_12', "assets/play/bg_12.png"],
['bg_13', "assets/play/bg_13.png"],
['bg_14', "assets/play/bg_14.png"],
['bg_15', "assets/play/bg_15.png"],
['petal_1', "assets/play/petal_1.png"],
['petal_2', "assets/play/petal_2.png"],
['petal_3', "assets/play/petal_3.png"],
['petal_4', "assets/play/petal_4.png"],
['petal_5', "assets/play/petal_5.png"],
['petal_6', "assets/play/petal_6.png"],
['petal_7', "assets/play/petal_7.png"],
['petal_8', "assets/play/petal_8.png"],
['icon_star1', "assets/play/icon_star1.png"],
['icon_star2', "assets/play/icon_star2.png"],
['bg_aswsome', "assets/play/bg_aswsome.png"],
['bg_jing', "assets/play/bg_jing.png"],
['bg_wrong', "assets/play/bg_wrong.png"],
['bg_zi', "assets/play/bg_zi.png"],
['icon_tiao', "assets/play/icon_tiao.png"],
]; ];
...@@ -12,7 +41,10 @@ const res = [ ...@@ -12,7 +41,10 @@ const res = [
const resAudio = [ const resAudio = [
['click', "assets/play/music/click.mp3"], ['click', "assets/play/music/click.mp3"],
['celebrate', "assets/play/music/celebrate.mp3"],
['right', "assets/play/music/right.mp3"],
['find', "assets/play/music/find.mp3"],
['wrong', "assets/play/music/wrong.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