Commit 95625166 authored by Chen Jiping's avatar Chen Jiping

feat:模板测试

parent 9f3a2900
...@@ -128,5 +128,8 @@ ...@@ -128,5 +128,8 @@
} }
} }
}, },
"defaultProject": "ng-template-generator" "defaultProject": "ng-template-generator",
"cli": {
"analytics": "7c7a8542-14e3-4de4-86cb-ebfed4d5397e"
}
} }
\ No newline at end of file
import { Obj } from "./ObjBean";
export class ExercisesBean{
answer : AnswerBean;
}
export function getDefaultExercises(){
let exercises = new ExercisesBean();
exercises.answer = new AnswerBean();
return exercises;
}
export class LetterBean extends Obj{
backgroud:String;
isFill = '0';
}
export function getDefaultLetter(){
let letter = new LetterBean();
return letter;
}
export class AnswerBean extends Obj{
letterArr = [];
}
\ No newline at end of file
export class Obj{
/**音频材料 */
audioUrl: String;
/**图片材料 */
picUrl:String;
val : String;
}
\ No newline at end of file
import { Obj } from "./ObjBean";
export class TitleBean extends Obj{
part1 : String;
part2: String;
}
export function getDefaultTile(){
let title = new TitleBean();
title.part1 = "C";
title.part2 = "Read and point";
return title;
}
\ No newline at end of file
<div class="model-content"> <div class="model-content">
<div nz-row>
<div nz-col nzOffset='4'>
<div style="position: absolute; left: 200px; top: 100px; width: 800px;"> <h1 nz-title>课程练习内容编辑</h1>
<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>
<div nz-row>
<div nz-col [nzSpan]="15" nzOffset="3">
<nz-divider nzText="课程名称" nzOrientation="left"></nz-divider>
<nz-form-item>
<nz-form-label [nzSpan]="3" nzFor="part1">标题1</nz-form-label>
<nz-form-control [nzSpan]="6">
<nz-input-group nzAddOnBefore="Part">
<input type="text" id="part1" nz-input [(ngModel)]="item.title.part1" (blur)="save()">
</nz-input-group>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="3" nzFor="part2">标题2</nz-form-label>
<nz-form-control [nzSpan]="6">
<input nz-input type="text" id="part2" [(ngModel)]="item.title.part2" (blur)="save()">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="3" nzFor="audioUrl">发音</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-audio-recorder [audioUrl]="item.title.audioUrl" id="audioUrl"
(audioUploaded)="onAudioUploadSuccess($event, item.title, 'audioUrl')">
</app-audio-recorder>
</nz-form-control>
</nz-form-item>
<nz-divider nzText="听力材料" nzOrientation="left"></nz-divider>
<nz-form-item>
<nz-form-control [nzSpan]="6" nzOffset="3">
<app-audio-recorder id="item.audioUrl" [audioUrl]="item.audioUrl"
(audioUploaded)="onAudioUploadSuccess($event, item, 'audioUrl')">
</app-audio-recorder>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="3" nzFor="backgroudColor">主色调色号</nz-form-label>
<nz-form-control [nzSpan]="6">
<input nz-input type="text" nz-input placeholder="十六进制,如#000000" maxlength="7" id="backgroudColor"
[(ngModel)]="item.backgroudColor" (blur)="save()">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="3">字母背景颜色</nz-form-label>
<nz-form-control [nzSpan]="6">
<div [ngStyle]="{'background':item.backgroudColor,'width':'100px','height':'30px','border':'1px solid #CCC'}">
</div>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="3">序号背景颜色</nz-form-label>
<nz-form-control [nzSpan]="6">
<div
[ngStyle]="{'background':item.backgroudColor,'width':'100px','height':'30px','border':'1px solid #CCC','opacity':'0.7'}">
</div>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="3">区块背景颜色</nz-form-label>
<nz-form-control [nzSpan]="6">
<div
[ngStyle]="{'background':item.backgroudColor,'width':'100px','height':'30px','border':'1px solid #CCC','opacity':'0.1'}">
</div>
</nz-form-control>
</nz-form-item>
<nz-divider nzText="字母" nzOrientation="left"></nz-divider>
<nz-form-item>
<nz-form-label [nzSpan]="6" nzFor="exercises">操作</nz-form-label>
<nz-form-control [nzSpan]="6">
<button nz-button nzType="dashed" [disabled]="item.letterArr.length == 3 ? true : false" class="add-btn"
id="add-btn" (click)="addLetterItem(item)">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
</button>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzOffset]="2" [nzSpan]="24">
<nz-table #lettersTable nzBordered [nzData]="item.letterArr" [nzShowPagination]=false>
<thead>
<tr>
<th>序号</th>
<th>字母组合</th>
<th>音频</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of lettersTable.data;let j = index">
<td>{{ j+1 }}</td>
<td><input type="text" nz-input placeholder="max length is 5" [(ngModel)]="row.val" (blur)="save()"
maxlength="5"></td>
<td>
<app-audio-recorder [audioUrl]="row.audioUrl"
(audioUploaded)="onAudioUploadSuccess($event, row, 'audioUrl')">
</app-audio-recorder>
</td>
<td>
<a (click)="delLetter(item, j)">delete</a>
</td>
</tr>
</tbody>
</nz-table>
</nz-form-control>
</nz-form-item>
</div>
</div>
<div nz-row>
<div nz-col [nzSpan]="20" nzOffset="2">
<nz-card nzTitle="背景图片" [nzExtra]="bgTemplate">
<div *ngIf="item.skin == 'A'">
<nz-form-item>
<nz-form-label [nzSpan]="2">左上</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-upload-image-with-preview style="width: 100%" [picUrl]="item.skinA.lt_pic_url"
(imageUploaded)="onImageUploadSuccess($event, item.skinA, 'lt_pic_url')">
</app-upload-image-with-preview>
</nz-form-control>
<nz-form-label [nzSpan]="2">中上</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-upload-image-with-preview style="width: 100%" [picUrl]="item.skinA.mt_pic_url"
(imageUploaded)="onImageUploadSuccess($event, item.skinA, 'mt_pic_url')">
</app-upload-image-with-preview>
</nz-form-control>
<nz-form-label [nzSpan]="2">右上</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-upload-image-with-preview style="width: 100%" [picUrl]="item.skinA.rt_pic_url"
(imageUploaded)="onImageUploadSuccess($event, item.skinA, 'rt_pic_url')">
</app-upload-image-with-preview>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="2">左中</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-upload-image-with-preview style="width: 100%" [picUrl]="item.skinA.lm_pic_url"
(imageUploaded)="onImageUploadSuccess($event, item.skinA, 'lm_pic_url')">
</app-upload-image-with-preview>
</nz-form-control>
<div nz-col nzSpan="8"></div>
<nz-form-label [nzSpan]="2">右中</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-upload-image-with-preview style="width: 100%" [picUrl]="item.skinA.rm_pic_url"
(imageUploaded)="onImageUploadSuccess($event, item.skinA, 'rm_pic_url')">
</app-upload-image-with-preview>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="2">左下</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-upload-image-with-preview style="width: 100%" [picUrl]="item.skinA.lb_pic_url"
(imageUploaded)="onImageUploadSuccess($event, item.skinA, 'lb_pic_url')">
</app-upload-image-with-preview>
</nz-form-control>
<nz-form-label [nzSpan]="2">中下</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-upload-image-with-preview style="width: 100%" [picUrl]="item.skinA.mb_pic_url"
(imageUploaded)="onImageUploadSuccess($event, item.skinA, 'mb_pic_url')">
</app-upload-image-with-preview>
</nz-form-control>
<nz-form-label [nzSpan]="2">右下</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-upload-image-with-preview style="width: 100%" [picUrl]="item.skinA.rb_pic_url"
(imageUploaded)="onImageUploadSuccess($event, item.skinA, 'rb_pic_url')">
</app-upload-image-with-preview>
</nz-form-control>
</nz-form-item>
</div>
</nz-card>
<ng-template #bgTemplate>
<button style="margin: 10px;" nz-button nzType="danger" (click)="clearBg()">
<span>清空</span>
</button>
</ng-template>
</div>
</div>
<div nz-row>
<div *ngFor="let zone of item.zoneArr; let i = index" style="padding: 0.5vw;">
<div nz-col [nzSpan]="20" nzOffset="2">
<nz-card nzTitle="练习题区域-{{i + 1}}" [nzActions]="[actionAdd]">
<div>
<div *ngFor="let data of zone.exercisesArr;let j = index">
<div nz-col [nzSpan]="12">
<nz-card nzTitle="单词-{{j+1}}" [nzExtra]="extraTemplate" [nzHoverable]="true">
<nz-form-item>
<nz-form-label [nzSpan]="6">音频</nz-form-label>
<nz-form-control [nzSpan]="12">
<app-audio-recorder [audioUrl]="data.answer.audioUrl"
(audioUploaded)="onAudioUploadSuccess($event, data.answer, 'audioUrl')">
</app-audio-recorder>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="6">单词拆分</nz-form-label>
<nz-form-control [nzSpan]="12">
<button nz-button nzType="dashed" class="add-btn" id="add-btn"
(click)="addLetterItem(data.answer)">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
</button>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="6">单词预览</nz-form-label>
<nz-form-control [nzSpan]="12">
<span nz-text>
<label *ngFor="let letter of data.answer.letterArr;let j = index"
[ngStyle]="{'text-decoration':letter.isFill=='1'?'underline':'none','font-size':'40px'}">{{letter.val}}</label>
</span>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzOffset]="2" [nzSpan]="20">
<nz-table #lettersTable nzBordered nzTitle="按照单词填空需要进行拆分填写" [nzData]="data.answer.letterArr"
[nzShowPagination]=false>
<thead>
<tr>
<th>序号</th>
<th>字母组合</th>
<th>是否填空</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of lettersTable.data;let j = index">
<td>{{ j+1 }}</td>
<td><input type="text" nz-input placeholder="请录入字母(组合)" [(ngModel)]="row.val"
(blur)="save()">
</td>
<td>
<nz-radio-group [(ngModel)]="row.isFill" (ngModelChange)="radioChange($event, data.answer, row)">
<label nz-radio nzValue="1"></label>
<label nz-radio nzValue="0"></label>
</nz-radio-group>
</td>
<td>
<a (click)="delLetter(data.answer,j)">delete</a>
</td>
</tr>
</tbody>
</nz-table>
</nz-form-control>
</nz-form-item>
</nz-card>
<ng-template #extraTemplate>
<button style="margin: 10px;" nz-button nzType="danger" (click)="delExercisesItem(zone, j)">
<span>删除</span>
</button>
</ng-template>
</div>
</div>
</div>
<ng-template #actionAdd>
<button nz-button nzType="dashed" [disabled]="zone.exercisesArr.length == 3 ? true : false"
class="add-btn" id="add-btn" (click)="addExercisesItem(zone)">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
</button>
</ng-template>
</nz-card>
</div>
</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 { AnswerBean, getDefaultExercises, getDefaultLetter } from '../bean/Exercises';
import { getDefaultTile } from '../bean/TitleBean';
import { NzMessageService } from 'ng-zorro-antd/message'
@Component({ @Component({
...@@ -10,12 +12,12 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap ...@@ -10,12 +12,12 @@ 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 = "YM5-5";
// 储存对象 // 储存对象
item; item;
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) { constructor(private appRef: ApplicationRef, private changeDetectorRef: ChangeDetectorRef, private message: NzMessageService) {
} }
...@@ -24,8 +26,20 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -24,8 +26,20 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
this.item = {}; this.item = {};
this.item.skinA = {};
this.item.skin = 'A';
this.item.title = getDefaultTile();
this.item.letterArr = [];
/**练习题区域 */
this.item.zoneArr = [];
// 获取存储的数据 // 获取存储的数据
(<any> window).courseware.getData((data) => { (<any>window).courseware.getData((data) => {
if (data) { if (data) {
this.item = data; this.item = data;
...@@ -51,6 +65,60 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -51,6 +65,60 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
init() { init() {
if (!this.item.backgroudColor) {
this.item.backgroudColor = "#f2a14d";
}
if (!this.item.title) {
this.item.title = getDefaultTile();
}
if (!this.item.letterArr) {
this.item.letterArr = [];
}
if(!this.item.skin){
this.item.skin = 'A';
}
if (!this.item.skinA) {
this.item.skinA = {};
}
if (!this.item.zoneArr) {
this.item.zoneArr = [];
}
for (let i = this.item.zoneArr.length; i < 3; ++i) {
let zone = {
exercisesArr: []
};
this.item.zoneArr.push(zone);
}
for (let i = 0; i < this.item.zoneArr.length; ++i) {
let zone = this.item.zoneArr[i];
if (!zone) {
zone = {
exercisesArr: []
};
this.item.zoneArr[i] = zone;
}
for (let j = 0; j < zone.exercisesArr.length; ++j) {
if (!zone.exercisesArr[j]) {
zone.exercisesArr[j] = getDefaultExercises();
}
if (!zone.exercisesArr[j].answer) {
zone.exercisesArr[j].answer = new AnswerBean();
}
}
}
} }
...@@ -58,9 +126,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -58,9 +126,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 +136,71 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -68,9 +136,71 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
* 储存音频数据 * 储存音频数据
* @param e * @param e
*/ */
onAudioUploadSuccess(e, key) { onAudioUploadSuccess(e, item, key) {
item[key] = e.url;
this.save();
}
addLetterItem(item) {
let letter = getDefaultLetter();
item.letterArr.push(letter);
item.letterArr = [...item.letterArr];
this.save();
}
delLetter(item, index) {
if (index !== -1) {
item.letterArr.splice(index, 1);
item.letterArr = [...item.letterArr];
this.save();
}
}
addExercisesItem(item) {
let exercises = getDefaultExercises();
item.exercisesArr.push(exercises);
this.save();
}
delExercisesItem(item, index) {
if (index !== -1) {
item.exercisesArr.splice(index, 1);
item.exercisesArr = [...item.exercisesArr];
this.save();
}
}
radioChange(e, answer, letter){
//如果正确答案,则将其它答案置成否
if( e == '1'){
let letterArr = answer.letterArr;
for(let m = 0; m < letterArr.length; ++ m){
if(letterArr[m] == letter){
continue;
}
letterArr[m].isFill = '0';
}
answer['letterArr'] = [...answer['letterArr']];
}
this.save();
}
clearBg() {
if (this.item.skin === 'A') {
this.item.skinA = {};
}
this.item[key] = e.url;
this.save(); this.save();
} }
...@@ -80,7 +210,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -80,7 +210,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();
} }
......
/**
*
* @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 { Label, Label2, LabelText, Line, MySprite, ShapeCircle, ShapeRect } from "./Unit";
export class Exercises {
data;
images;
indexBgColor;
index: number;
bg: ShapeRect;
answer: ShapeRect;
answerFill : ShapeRect;
answerLabel: Label2;
showLetterArr: Array<Label> = [];
scaleX = 1;
scaleY = 1;
answered: Boolean = false;
indexLabel: Label;
indexLabelBg: ShapeCircle;
init(images, indexBgColor, data, scaleX = 1, scaleY = 1) {
this.images = images;
this.data = data;
this.scaleX = scaleX;
this.scaleY = scaleY;
this.indexBgColor = indexBgColor;
this.initBg();
this.initIndex();
this.initAnswer();
}
initBg() {
let height = 48 * this.scaleY;
let width = 284 * this.scaleX;
const bg = new ShapeRect();
bg.setSize(width, height);
bg.alpha = 0;
this.bg = bg;
}
initIndex() {
let indexBg = new ShapeCircle();
let r = 23 * this.scaleX;
indexBg.setRadius(r);
indexBg.fillColor = this.indexBgColor;
indexBg.x = r;
indexBg.y = this.bg.height / 2;
indexBg.alpha = 0.7;
this.bg.addChild(indexBg);
this.indexLabelBg = indexBg;
let index = new Label();
index.text = this.index + "";
index.textAlign = 'center';
index.fontSize = 36;
index.fontName = "FuturaB";
index.fontColor = "#ffffff";
index.x = 0;
index.y = 0;
index.setScaleXY(this.scaleX);
index.refreshSize();
indexBg.addChild(index);
index.alpha = 1;
this.indexLabel = index;
}
initAnswer() {
let startX = 46 * this.scaleX + 6 * this.scaleX;
let answer = this.getAnswerView(this.data.answer);
answer.x = startX;
this.answer = answer;
this.bg.addChild(answer);
let answerFill = this.getAnswerFillView(this.data.answer);
answerFill.x = startX;
this.answerFill= answerFill;
this.bg.addChild(answerFill);
}
getAnswerView(answerData) {
const getLabelText = (letter) => {
const text = new LabelText();
text.val = letter.val;
if (letter.isFill == '1') {
text.fontColor = "#c8161d";
}
else {
text.fontColor = "#000000";
}
text.underLine = false;
return text;
}
let labelTextArr = [];
for (let i = 0; i < answerData.letterArr.length; ++i) {
var letter = answerData.letterArr[i];
let label = getLabelText(letter);
labelTextArr.push(label);
}
const answer = new Label2();
answer.textArr = labelTextArr;
answer.fontSize = 48;
answer.fontName = "MMB";
answer.setScaleXY(this.scaleX);
answer.refreshSize();
this.answerLabel = answer;
const answerBg = new ShapeRect();
answerBg.alpha = 0;
answerBg.setSize(answer.getBoundingBox().width, answer.getBoundingBox().height);
answerBg.y = (this.bg.height - answerBg.height) / 2;
answer.y = answerBg.height / 2;
answer.x = 0;
answerBg.addChild(answer);
answerBg.visible = false;
this.bg.addChild(answerBg);
return answerBg;
}
private getAnswerFillView(answerData) {
const getLetterLabel = (letter) => {
const label = new Label();
label.fontName = "MMB";
label.fontSize = 48;
label.text = letter.val;
if (letter.isFill == '1') {
label.fontColor = "#c8161d";
}
else {
label.fontColor = "#000000";
}
label.scaleX = this.scaleX;
label.scaleY = this.scaleY;
label.refreshSize();
return label;
}
const answerFillBg = new ShapeRect();
answerFillBg.alpha = 0;
answerFillBg.height = this.bg.height;
let totalWidth = 0;
let startX = 0;
for (let i = 0; i < answerData.letterArr.length; ++i) {
var letter = answerData.letterArr[i];
let label = getLetterLabel(letter);
label.y = answerFillBg.height / 2;
let w = Math.ceil(label.getBoundingBox().width);
let dw = Math.ceil(4 * this.scaleX);
//如果是填空,则增加下划线
if (letter.isFill == '1') {
startX += dw;
let width = Math.ceil(80 * this.scaleX);
label.x = startX + (width - label.getBoundingBox().width) / 2;
let underLine = new Line();
underLine.lineColor = "#949494";
underLine.lineWidth = 3 * this.scaleX;
underLine.y = this.bg.height;
underLine.x = startX;
underLine.setLine(width);
answerFillBg.addChild(underLine);
w = width;
label.alpha = 0;
this.showLetterArr.push(label);
}
else {
if (answerData.letterArr[i - 1] && answerData.letterArr[i - 1].isFill == '1') {
startX += dw;
}
label.x = startX;
}
answerFillBg.addChild(label);
startX += w;
totalWidth += w;
}
answerFillBg.width = totalWidth;
answerFillBg.y = (this.bg.height - answerFillBg.height) / 2;
this.bg.addChild(answerFillBg);
return answerFillBg;
}
showLetter() {
if(!this.answered){
this.answered = true;
if(this.answerFill.visible){
for(let i = 0; i < this.showLetterArr.length; ++ i){
this.showLetterArr[i].alpha = 1;
}
}
}
return true;
}
}
\ No newline at end of file
import { Label, ShapeCircle, ShapeRect } from "./Unit";
export class Letter{
data;
images;
bgColor;
scaleX = 1;
scaleY = 1;
bg : ShapeCircle;
init(images, data, bgColor, scaleX = 1, scaleY = 1) {
this.images = images;
this.data = data;
this.bgColor = bgColor;
this.scaleX = scaleX;
this.scaleY = scaleY;
this.initBg();
this.initView();
}
initBg(){
let w = 180 * this.scaleX;
let h = 90 * this.scaleY;
let bg = new ShapeRect();
bg.setSize(w, h);
bg.fillColor = this.bgColor;
this.bg = bg;
}
initView(){
const letter = new Label();
letter.text = this.data.val;
letter.textAlign = 'center';
letter.fontSize = 64;
letter.fontName = "BRLNSDB";
letter.fontColor = "#ffffff";
letter.setScaleXY(this.scaleX);
letter.setMaxSize(170 * this.scaleX);
letter.refreshSize();
letter.x = this.bg.width / 2;
letter.y = this.bg.height / 2;
this.bg.addChild(letter);
}
}
\ No newline at end of file
import {
Label,
MySprite, ShapeRectNew,
ShapeCircle,
tweenChange,
ShapeRect
} from './Unit';
import {
playAudio,
pauseAudio
} from './AudioUtil';
export class Listening {
audio;
images;
bg;
btnPlay;
btnStop;
playing = false;
constructor(audio, images) {
this.audio = audio;
this.images = images;
}
init(scaleX = 1, scaleY = 1) {
const bg = new ShapeRect();
const btnPlay = new MySprite();
btnPlay.init(this.images.get('play'));
btnPlay.scaleX = scaleX;
btnPlay.scaleY = scaleY;
btnPlay.x = btnPlay.getBoundingBox().width / 2
btnPlay.y = btnPlay.getBoundingBox().height / 2
this.btnPlay = btnPlay;
bg.addChild(btnPlay);
const btnStop = new MySprite();
btnStop.init(this.images.get('stop'));
btnStop.x = btnPlay.x;
btnStop.y = btnPlay.y;
btnStop.alpha = 0;
btnStop.scaleX = scaleX;
btnStop.scaleY = scaleY;
this.btnStop = btnStop;
bg.addChild(btnStop);
bg.setSize(btnPlay.getBoundingBox().width, btnPlay.getBoundingBox().height);
bg.alpha = 0;
this.bg = bg;
}
play(callback = null){
console.log('playing:', this.playing);
if(!this.playing){
this.playAudio(callback);
return this.audio;
}
else{
this.pauseAudio(callback);
}
return null;
}
reset(){
this.btnPlay.alpha = 1;
this.btnStop.alpha = 0;
this.playing = false;
}
playAudio(callback = null){
this.btnPlay.alpha = 0;
this.btnStop.alpha = 1;
playAudio(this.audio, false, callback);
this.playing = true;
return this.audio;
}
pauseAudio(callback = null){
this.btnPlay.alpha = 1;
this.btnStop.alpha = 0;
this.playing = false;
pauseAudio(this.audio, false, callback)
}
}
\ No newline at end of file
import {
Label,
MySprite, ShapeRect,
} from './Unit';
import {
playAudio,
pauseAudio
} from './AudioUtil';
export class Title {
titleBg: ShapeRect;
audio;
images;
titleData;
constructor(titleData, images) {
this.titleData = titleData;
this.images = images;
}
init(mapScaleX = 1, mapScaleY = 1) {
let titleBg = new ShapeRect();
//初始化标题1背景
const titePart1Bg = new ShapeRect();
titePart1Bg.fillColor="#567790";
let pWidth = 117 * mapScaleX;
let pHeight = 65 * mapScaleY;
titePart1Bg.setSize(pWidth, pHeight);
titePart1Bg.setShadow(4,4,0, 'rgba(0, 0, 0, 0.2)');
titePart1Bg.x = 0;
titleBg.addChild(titePart1Bg);
//标题1内容
const part1 = new Label();
part1.text = this.titleData.part1;
part1.textAlign = 'left';
part1.fontSize = 48;
part1.fontName = "BRLNSDB";
part1.fontColor = "#ffffff";
part1.setScaleXY(mapScaleX);
part1.refreshSize();
part1.x = pWidth - part1.getBoundingBox().width - 13 * mapScaleX;
part1.y = 5 * mapScaleY + part1.getBoundingBox().height / 2;
titleBg.addChild(part1);
//标题2内容
const part2 = new Label();
part2.text = this.titleData.part2;
part2.fontSize = 36;
part2.fontName = "FuturaStd";
part2.fontColor = "#000000";
part2.setScaleXY(mapScaleX);
part2.refreshSize();
part2.x = titePart1Bg.getBoundingBox().width + 11 * mapScaleX;
part2.y = 16 * mapScaleY + part2.getBoundingBox().height / 2;
let height = Math.max(titePart1Bg.getBoundingBox().height, part2.getBoundingBox().height);
let width = titePart1Bg.getBoundingBox().width + part2.getBoundingBox().width + 11 * mapScaleX;
titePart1Bg.y = (height - pHeight)/2;
titleBg.setSize(width, height);
titleBg.alpha = 0;
titleBg.addChild(part2);
this.titleBg = titleBg;
}
getTitleBg(){
return this.titleBg;
}
setAudio(audio){
this.audio = audio;
}
playAudio(callback = null){
playAudio(this.audio, true, callback);
return this.audio;
}
pasueAudio(callback){
pauseAudio(this.audio, true, callback)
}
}
...@@ -709,6 +709,231 @@ export class Label extends MySprite { ...@@ -709,6 +709,231 @@ export class Label extends MySprite {
} }
export class LabelText {
private _val: string;
private _fontColor = "#000000";
private _underLine: boolean = false;
private _visiable = true;
set val(val) {
this._val = val;
}
get val() {
return this._val;
}
set fontColor(fontColor) {
this._fontColor = fontColor;
}
get fontColor() {
return this._fontColor;
}
set underLine(underLine) {
this._underLine = underLine;
}
get underLine() {
return this._underLine;
}
set visiable(visiable){
this._visiable = visiable;
}
get visiable(){
return this._visiable;
}
}
export class Label2 extends MySprite {
textArr: Array<LabelText> = [];
fontName = 'Verdana';
textAlign = 'left';
fontSize = 40;
fontColor = '#000000';
fontWeight = 900;
_maxWidth;
outline = 0;
outlineColor = '#ffffff';
_outlineFlag = false;
_outLineWidth;
_outLineColor;
underLineWidth: number;
underLineColor = "#000000";
constructor(ctx = null) {
super(ctx);
this.init();
}
refreshSize() {
this.ctx.save();
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.fontWeight = this.fontWeight;
let text = "";
let count = 0;
for (let i = 0; i < this.textArr.length; ++i) {
if(this.textArr[i].underLine){
count ++;
continue;
}
text += this.textArr[i].val;
}
if(count > 0){
this._width = this.ctx.measureText(text).width + 36 * count + 4 * (count - 1);
}
else{
this._width = this.ctx.measureText(text).width;
}
this._height = this.fontSize;
this.refreshAnchorOff();
this.ctx.restore();
}
setMaxSize(w) {
this._maxWidth = w;
this.refreshSize();
if (this.width >= w) {
this.scaleX *= w / this.width;
this.scaleY *= w / this.width;
}
}
show(callBack = null) {
this.visible = true;
if (this.alpha >= 1) {
return;
}
const tween = new TWEEN.Tween(this)
.to({ alpha: 1 }, 800)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
if (callBack) {
callBack();
}
})
.start(); // Start the tween immediately.
}
setOutline(width = 5, color = '#ffffff') {
this._outlineFlag = true;
this._outLineWidth = width;
this._outLineColor = color;
}
drawText() {
if (!this.textArr) { return; }
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.fontWeight = this.fontWeight;
var startX = 0;
for (let i = 0; i < this.textArr.length; ++i) {
var text = this.textArr[i];
let width = this.ctx.measureText(text.val).width;
let tempStartX = startX;
let dW = 0;
if (text.underLine && this.underLineWidth > 0) {
this.ctx.save();
this.ctx.lineWidth = this.underLineWidth;
this.ctx.strokeStyle = this.underLineColor;
let lineY = this.fontSize / 2;
this.ctx.moveTo(tempStartX, lineY);
this.ctx.lineTo(tempStartX + 36, lineY);
this.ctx.stroke();
this.ctx.restore();
tempStartX += (36 - width) / 2;
dW = 36 ;
if(this.textArr[i + 1] && this.textArr[i + 1].underLine){
dW += 4 ;
}
}
else{
dW = width;
}
if (this._outlineFlag) {
this.ctx.lineWidth = this._outLineWidth;
this.ctx.strokeStyle = this._outLineColor;
this.ctx.strokeText(text.val, tempStartX, 0);
}
if (this.outline > 0) {
this.ctx.lineWidth = this.outline;
this.ctx.strokeStyle = this.outlineColor;
this.ctx.strokeText(text.val, tempStartX, 0);
}
this.ctx.fillStyle = text.fontColor ? text.fontColor : this.fontColor;
if(text.visiable){
this.ctx.fillText(text.val, tempStartX, 0);
}
startX += dW;
}
}
drawSelf() {
super.drawSelf();
this.drawText();
}
}
export class RichTextOld extends Label { export class RichTextOld extends Label {
textArr = []; textArr = [];
...@@ -1235,7 +1460,35 @@ export class MyAnimation extends MySprite { ...@@ -1235,7 +1460,35 @@ export class MyAnimation extends MySprite {
} }
export class Line extends MySprite{
lineColor = '#ffffff';
lineWidth = 10;
setLine(length){
this.width = length;
}
drawLine() {
this.ctx.save();
this.ctx.beginPath();
this.ctx.lineWidth = this.lineWidth;
this.ctx.strokeStyle = this.lineColor;
this.ctx.moveTo(this._offX, this._offY);
this.ctx.lineTo(this._offX + this.width, this._offY);
this.ctx.stroke();
this.ctx.restore();
}
drawSelf() {
super.drawSelf();
this.drawLine();
}
}
// --------=========== util func =============------------- // --------=========== util func =============-------------
......
...@@ -17,3 +17,20 @@ ...@@ -17,3 +17,20 @@
src: url("../../assets/font/BRLNSDB.TTF") ; src: url("../../assets/font/BRLNSDB.TTF") ;
} }
@font-face
{
font-family: 'FuturaStd';
src: url("../../assets/font/FuturaStd-Medium.otf") ;
}
@font-face
{
font-family: 'FuturaB';
src: url("../../assets/font/FUTURAB.TTF") ;
}
@font-face
{
font-family: 'MMB';
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, MySprite, ShapeRectNew, 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 { Title } from './Title';
import { getDefaultTile } from '../bean/TitleBean';
import { Listening } from './Listening';
import { Letter } from './Letter';
import { Exercises } from './Exercises.spreat';
import { AnswerBean, getDefaultExercises } from '../bean/Exercises';
...@@ -22,8 +28,8 @@ import TWEEN from '@tweenjs/tween.js'; ...@@ -22,8 +28,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 +63,22 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -57,17 +63,22 @@ export class PlayComponent implements OnInit, OnDestroy {
canvasLeft; canvasLeft;
canvasTop; canvasTop;
saveKey = 'test_0011'; saveKey = 'YM5-5';
btnLeft;
btnRight;
pic1;
pic2;
canTouch = true; canTouch = true;
curPic; /**标题*/
title: Title;
listening: Listening;
curAudio;
letterArr: Array<Letter>;
exercisesArr: Array<Exercises> = [];
@HostListener('window:resize', ['$event']) @HostListener('window:resize', ['$event'])
onResize(event) { onResize(event) {
...@@ -80,7 +91,7 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -80,7 +91,7 @@ export class PlayComponent implements OnInit, OnDestroy {
this.data = {}; this.data = {};
// 获取数据 // 获取数据
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') {
...@@ -297,6 +308,8 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -297,6 +308,8 @@ export class PlayComponent implements OnInit, OnDestroy {
} }
audio.play(); audio.play();
} }
return audio;
} }
...@@ -341,7 +354,7 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -341,7 +354,7 @@ export class PlayComponent implements OnInit, OnDestroy {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const audio = new Audio(); const audio = new Audio();
audio.oncanplay = (a) => { audio.oncanplay = (a) => {
resolve(); resolve(a);
}; };
audio.onerror = () => { audio.onerror = () => {
reject(); reject();
...@@ -427,6 +440,13 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -427,6 +440,13 @@ export class PlayComponent implements OnInit, OnDestroy {
this.rawImages.set(url, url); this.rawImages.set(url, url);
} }
addUrlToImage(url, key) {
if (!key) {
key = url;
}
this.rawImages.set(key, url);
}
...@@ -443,9 +463,60 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -443,9 +463,60 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initDefaultData() { initDefaultData() {
if (!this.data.pic_url) { if (!this.data.title) {
this.data.pic_url = 'assets/play/default/pic.jpg'; this.data.title = getDefaultTile();
this.data.pic_url_2 = 'assets/play/default/pic.jpg'; }
if (!this.data.backgroudColor) {
this.data.backgroudColor = "#f2a14d";
}
if (!this.data.letterArr) {
this.data.letterArr = [];
}
if (!this.data.skin) {
this.data.skin = 'A';
}
if (!this.data.skinA) {
this.data.skinA = {};
}
if (!this.data.zoneArr) {
this.data.zoneArr = [];
}
for (let i = this.data.zoneArr.length; i < 3; ++i) {
let zone = {
exercisesArr: []
};
this.data.zoneArr.push(zone);
}
for (let i = 0; i < this.data.zoneArr.length; ++i) {
let zone = this.data.zoneArr[i];
if (!zone) {
zone = {
exercisesArr: []
};
this.data.zoneArr[i] = zone;
}
for (let j = 0; j < zone.exercisesArr.length; ++j) {
if (!zone.exercisesArr[j]) {
zone.exercisesArr[j] = getDefaultExercises();
}
if (!zone.exercisesArr[j].answer) {
zone.exercisesArr[j].answer = new AnswerBean();
}
}
} }
} }
...@@ -455,8 +526,44 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -455,8 +526,44 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initImg() { initImg() {
this.addUrlToImages(this.data.pic_url); const loadBg = (skin, skinType) => {
this.addUrlToImages(this.data.pic_url_2); if (skin.lt_pic_url) {
this.addUrlToImage(skin.lt_pic_url, skinType + "_" + skin.lt_pic_url);
}
if (skin.lm_pic_url) {
this.addUrlToImage(skin.lm_pic_url, skinType + "_" + skin.lm_pic_url);
}
if (skin.lb_pic_url) {
this.addUrlToImage(skin.lb_pic_url, skinType + "_" + skin.lb_pic_url);
}
if (skin.mt_pic_url) {
this.addUrlToImage(skin.mt_pic_url, skinType + "_" + skin.mt_pic_url);
}
if (skin.mb_pic_url) {
this.addUrlToImage(skin.mb_pic_url, skinType + "_" + skin.mb_pic_url);
}
if (skin.rt_pic_url) {
this.addUrlToImage(skin.rt_pic_url, skinType + "_" + skin.rt_pic_url);
}
if (skin.rm_pic_url) {
this.addUrlToImage(skin.rm_pic_url, skinType + "_" + skin.rm_pic_url);
}
if (skin.rb_pic_url) {
this.addUrlToImage(skin.rb_pic_url, skinType + "_" + skin.rb_pic_url);
}
}
if (this.data.skinA) {
loadBg(this.data.skinA, 'A');
}
} }
...@@ -465,13 +572,48 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -465,13 +572,48 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initAudio() { initAudio() {
// 音频资源
this.addUrlToAudioObj(this.data.audio_url);
this.addUrlToAudioObj(this.data.audio_url_2);
// 音效 // 音效
this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3); this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3);
this.addUrlToAudioObj('right', this.rawAudios.get('right'));
//标题发音
if (this.data.title.audioUrl) {
this.addUrlToAudioObj('titleAudio', this.data.title.audioUrl);
}
//听力材料
if (this.data.audioUrl) {
this.addUrlToAudioObj('listenAudio', this.data.audioUrl);
}
for (let i = 0; i < this.data.letterArr.length; ++i) {
let letter = this.data.letterArr[i];
if (letter.audioUrl) {
this.addUrlToAudioObj(letter.audioUrl);
}
}
for (let i = 0; i < this.data.zoneArr.length; ++i) {
let zone = this.data.zoneArr[i];
//练习题音效
for (let i = 0; i < zone.exercisesArr.length; ++i) {
let exercises = zone.exercisesArr[i];
if (exercises.answer && exercises.answer.audioUrl) {
this.addUrlToAudioObj('exercises_' + i, exercises.answer.audioUrl);
}
}
}
} }
...@@ -486,14 +628,18 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -486,14 +628,18 @@ 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.mapScale = sy;
this.renderArr = []; this.renderArr = [];
if (this.curAudio) {
this.curAudio.pause();
}
this.curAudio = null;
this.letterArr = [];
this.exercisesArr = [];
} }
...@@ -503,132 +649,228 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -503,132 +649,228 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initView() { initView() {
this.initBg();
this.initPic(); this.initTitle();
this.initBottomPart(); this.initBottomPart();
} this.initLetter();
initBottomPart() { this.initExercises();
}
const btnLeft = new MySprite(); initBg() {
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); const getPic = (key, anchorX: number = 0.5, anchorY: number = 0.5) => {
const pic = new MySprite();
pic.init(this.images.get(key), anchorX, anchorY);
pic.setScaleXY(this.mapScale);
this.renderArr.push(pic);
return pic;
}
this.renderArr.push(btnLeft); const initBg = (skin, skinType) => {
this.btnLeft = btnLeft; //左上
if (skin.lt_pic_url) {
const pic = getPic(skinType + '_' + skin.lt_pic_url, 0, 0);
pic.x = 0;
pic.y = 0;
}
//左中
if (skin.lm_pic_url) {
const pic = getPic(skinType + '_' + skin.lm_pic_url, 0);
pic.x = 0;
pic.y = (this.canvasHeight - pic.getBoundingBox().height) / 2;
}
const btnRight = new MySprite(); //左下
btnRight.init(this.images.get('btn_right')); if (skin.lb_pic_url) {
btnRight.x = this.canvasWidth - 50 * this.mapScale; const pic = getPic(skinType + '_' + skin.lb_pic_url, 0, 1);
btnRight.y = this.canvasHeight - 100 * this.mapScale; pic.x = 0;
btnRight.setScaleXY(this.mapScale); pic.y = this.canvasHeight;
}
this.renderArr.push(btnRight); //中上
if (skin.mt_pic_url) {
const pic = getPic(skinType + '_' + skin.mt_pic_url, 0.5, 0);
pic.x = this.canvasWidth / 2;
pic.y = 0;
}
this.btnRight = btnRight; //中下
if (skin.mb_pic_url) {
const pic = getPic(skinType + '_' + skin.mb_pic_url, 0.5, 1);
pic.x = this.canvasWidth / 2;
pic.y = this.canvasHeight;
} }
initPic() { //右上
if (skin.rt_pic_url) {
const pic = getPic(skinType + '_' + skin.rt_pic_url, 1, 0);
pic.x = this.canvasWidth;
pic.y = 0;
}
const maxW = this.canvasWidth * 0.7; //右中
if (skin.rm_pic_url) {
const pic = getPic(skinType + '_' + skin.rm_pic_url, 1, 0.5);
pic.x = this.canvasWidth;
pic.y = this.canvasHeight / 2;
}
const pic1 = new MySprite(); //右下
pic1.init(this.images.get(this.data.pic_url)); if (skin.rb_pic_url) {
pic1.x = this.canvasWidth / 2; const pic = getPic(skinType + '_' + skin.rb_pic_url, 1, 1);
pic1.y = this.canvasHeight / 2; pic.x = this.canvasWidth;
pic1.setScaleXY(maxW / pic1.width); pic.y = this.canvasHeight;
}
}
this.renderArr.push(pic1); if (this.data.skin === 'A') {
this.pic1 = pic1; if (this.data.skinA) {
initBg(this.data.skinA, 'A');
}
}
else {
if (this.data.skinB) {
initBg(this.data.skinB, 'B');
}
}
}
const label1 = new Label(); initBottomPart() {
label1.text = this.data.text;
label1.textAlign = 'center';
label1.fontSize = 50;
label1.fontName = 'BRLNSDB';
label1.fontColor = '#ffffff';
pic1.addChild(label1); const listening = new Listening(this.audioObj['listenAudio'], this.images);
listening.init(this.mapScale, this.mapScale);
listening.bg.x = this.canvasWidth - listening.bg.width - 10 * this.mapScale;
listening.bg.y = this.canvasHeight - listening.bg.height - 8 * this.mapScale;
this.listening = listening;
this.renderArr.push(listening.bg);
}
initTitle() {
const title = new Title(this.data.title, this.images);
const pic2 = new MySprite(); title.init(this.mapScale, this.mapScale);
pic2.init(this.images.get(this.data.pic_url_2)); title.audio = this.audioObj['titleAudio'];
pic2.x = this.canvasWidth / 2 + this.canvasWidth; this.title = title;
pic2.y = this.canvasHeight / 2;
pic2.setScaleXY(maxW / pic2.width);
this.renderArr.push(pic2); title.titleBg.y = 0;
this.pic2 = pic2; title.titleBg.x = 0;
this.curPic = pic1; this.renderArr.push(title.titleBg);
} }
btnLeftClicked() { initLetter() {
this.lastPage(); let letterArr = this.data.letterArr;
}
btnRightClicked() { let dW = (31 + 180) * this.mapScale;
this.nextPage(); let tW = (letterArr.length - 1) * dW;
}
lastPage() { let startX = (this.canvasWidth - tW) / 2;
if (this.curPic == this.pic1) { let y = this.canvasHeight / 2 - 192 * this.mapScale;
return;
}
this.canTouch = false; for (let i = 0; i < letterArr.length; ++i) {
const moveLen = this.canvasWidth; let letter = new Letter();
tweenChange(this.pic1, {x: this.pic1.x + moveLen}, 1); letter.init(this.images, letterArr[i], this.data.backgroudColor, this.mapScale, this.mapScale);
tweenChange(this.pic2, {x: this.pic2.x + moveLen}, 1, () => { letter.bg.x = startX + dW * i - letter.bg.width / 2;
this.canTouch = true; letter.bg.y = y - letter.bg.height / 2;
this.curPic = this.pic1; this.renderArr.push(letter.bg);
}); this.letterArr.push(letter);
}
} }
nextPage() {
if (this.curPic == this.pic2) { initExercises() {
return;
let w = 360 * this.mapScale;
let h = 360 * this.mapScale;
let r = 0;
let y = this.canvasHeight / 2 - 106 * this.mapScale;
let dW = 50;
let startX = (this.canvasWidth - (w * 3 + dW * (3 - 1))) / 2;
const getView = (item, index, x = 0, y = 0) => {
let exercises = new Exercises();
exercises.index = index;
exercises.init(this.images, this.data.backgroudColor, item, this.mapScale, this.mapScale);
exercises.bg.x = x;
exercises.bg.y = y;
return exercises;
} }
this.canTouch = false; let index = 1;
const moveLen = this.canvasWidth; for (let i = 0; i < this.data.zoneArr.length; ++i) {
tweenChange(this.pic1, {x: this.pic1.x - moveLen}, 1); const bg = new ShapeRectNew();
tweenChange(this.pic2, {x: this.pic2.x - moveLen}, 1, () => { bg.setSize(w, h, r);
this.canTouch = true; bg.fillColor = this.data.backgroudColor;
this.curPic = this.pic2; bg.x = startX;
}); bg.y = y;
bg.alpha = 0.1;
startX += w + dW;
this.renderArr.push(bg);
let exercisesArr = this.data.zoneArr[i].exercisesArr;
if (!exercisesArr || exercisesArr.length == 0) {
continue;
} }
pic1Clicked() { let x = 21 * this.mapScale;
this.playAudio(this.data.audio_url);
let disH = 57 * this.mapScale;
let startY = (h - exercisesArr.length * 48 * this.mapScale - (exercisesArr.length - 1) * disH) / 2;
for (let j = 0; j < exercisesArr.length; ++j) {
let exercises = getView(exercisesArr[j], index, x, startY);
bg.addChild(exercises.bg);
this.exercisesArr.push(exercises);
startY += exercises.bg.height + disH;
index += 1;
} }
pic2Clicked() {
this.playAudio(this.data.audio_url_2);
} }
}
mapDown(event) { mapDown(event) {
...@@ -636,26 +878,65 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -636,26 +878,65 @@ export class PlayComponent implements OnInit, OnDestroy {
return; return;
} }
if ( this.checkClickTarget(this.btnLeft) ) { if (this.curAudio) {
this.btnLeftClicked(); if (this.curAudio != this.listening.audio) {
return; this.curAudio.pause();
}
} }
if ( this.checkClickTarget(this.btnRight) ) { if (this.checkClickTarget(this.listening.bg)) {
this.btnRightClicked();
this.curAudio = this.listening.play(() => {
this.listening.reset();
});
return; return;
} }
if ( this.checkClickTarget(this.pic1) ) { if (this.curAudio) {
this.pic1Clicked(); if (this.curAudio == this.listening.audio) {
return; this.listening.pauseAudio();
}
else {
this.curAudio.pause();
}
} }
if ( this.checkClickTarget(this.pic2) ) { if (this.checkClickTarget(this.title.titleBg)) {
this.pic2Clicked(); this.curAudio = this.title.playAudio();
return; return;
} }
for (let i = 0; i < this.letterArr.length; ++i) {
let letter = this.letterArr[i];
if (this.checkClickTarget(letter.bg)) {
this.curAudio = this.playAudio(letter.data.audioUrl, true);
break;
}
}
let clicked = false;
for (let i = 0; i < this.exercisesArr.length; ++i) {
let exercises = this.exercisesArr[i];
if (this.checkClickTarget(exercises.answer) || this.checkClickTarget(exercises.indexLabelBg)) {
clicked = true;
this.clickExercises(exercises, i);
break;
}
}
if (clicked) {
return;
}
} }
mapMove(event) { mapMove(event) {
...@@ -685,6 +966,35 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -685,6 +966,35 @@ export class PlayComponent implements OnInit, OnDestroy {
} }
clickExercises(exercises: Exercises, index: number) {
const play = () => {
let key = 'exercises_' + index;
const audio = this.audioObj[key];
this.curAudio = audio;
this.playAudio(key, true);
exercises.answer.visible = true;
exercises.answerFill.visible = false;
}
if (exercises.answered) {
play();
}
else {
exercises.showLetter();
this.canTouch = false;
this.playAudio('right', true, () => {
this.canTouch = true;
});
}
}
} }
const res = [ const res = [
// ['bg', "assets/play/bg.jpg"], ['play', "assets/play/play.png"],
['btn_left', "assets/play/btn_left.png"], ['stop', "assets/play/stop.png"],
['btn_right', "assets/play/btn_right.png"],
// ['text_bg', "assets/play/text_bg.png"],
]; ];
...@@ -12,7 +9,7 @@ const res = [ ...@@ -12,7 +9,7 @@ const res = [
const resAudio = [ const resAudio = [
['click', "assets/play/music/click.mp3"], ['click', "assets/play/music/click.mp3"],
['right', "assets/play/music/right.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