Commit 86c4d69b 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": "29e14fb6-b14a-4775-987f-2ceb56e73fa0"
}
}
\ No newline at end of file
import { Obj } from './ObjBean';
export class ExercisesBean extends Obj {
answerArr : Array<AnswerBean> = [];
rightAnswer : AnswerBean;
}
export class AnswerBean extends Obj {
/**类型:T-文本, P - 图片 */
contentType = 'T';
/**正确答案:0-否,1-是 */
isRight = '0';
}
export function getDefaultExercises(){
const exercises = new ExercisesBean();
exercises.rightAnswer = getDefaultAnswer();
exercises.rightAnswer.isRight = "1";
exercises.answerArr = [];
return exercises;
}
export function getDefaultAnswer(){
const answer = new AnswerBean();
return answer;
}
\ No newline at end of file
export class Obj{
/**音频材料 */
audioUrl: String;
/**图片材料 */
picUrl:String;
val : String;
}
\ 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>
</div>
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()"> </div>
<div nz-row>
<app-upload-image-with-preview <div nz-col [nzSpan]="20" nzOffset="2">
[picUrl]="item.pic_url" <nz-form-item>
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')" <nz-form-label [nzSpan]="6"> 问题音频:</nz-form-label>
></app-upload-image-with-preview> <nz-form-control [nzSpan]="12">
<app-audio-recorder [audioUrl]="item.audioUrl"
<app-audio-recorder (audioUploaded)="onAudioUploadSuccess($event, item, 'audioUrl')">
[audioUrl]="item.audio_url" </app-audio-recorder>
(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 nz-col [nzSpan]="20" nzOffset="2">
<h5>正确答案</h5>
<nz-form-item>
<nz-form-label [nzSpan]="6"> 音频:</nz-form-label>
<nz-form-control [nzSpan]="12">
<app-audio-recorder [audioUrl]="item.rightAnswer.audioUrl"
(audioUploaded)="onAudioUploadSuccess($event, item.rightAnswer, '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]="6">
<nz-radio-group [(ngModel)]="item.rightAnswer.contentType" (ngModelChange)="setContentType($event, item.rightAnswer)">
<label nz-radio nzValue="T">文字</label>
<label nz-radio nzValue="P">图片</label>
</nz-radio-group>
</nz-form-control>
</nz-form-item>
<div *ngIf="item.rightAnswer.contentType == 'T'">
<nz-form-item>
<nz-form-label [nzSpan]="6" >文本</nz-form-label>
<nz-form-control [nzSpan]="6">
<input nz-input type="text" placeholder="请录入内容" [(ngModel)]="item.rightAnswer.val" (blur)="save()">
</nz-form-control>
</nz-form-item>
</div>
<div *ngIf="item.rightAnswer.contentType == 'P'">
<nz-form-item>
<nz-form-label [nzSpan]="6">图片</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-upload-image-with-preview
style="width: 100%"
[picUrl]="item.rightAnswer.picUrl"
(imageUploaded)="onImageUploadSuccess($event, item.rightAnswer, 'picUrl')"
></app-upload-image-with-preview>
</nz-form-control>
</nz-form-item>
</div>
</div> </div>
</div> <div nz-col [nzSpan]="20" nzOffset="2">
<h5>备选答案</h5>
\ No newline at end of file <div *ngFor="let data of item.answerArr;let j = index" class="card-item" style="padding: 0.5vw;">
<div class="border">
<nz-divider nzText="备选答案-{{j+1}}" nzOrientation="left"></nz-divider>
<nz-form-item>
<button style="margin: 10px;" nz-button nzType="danger"
(click)="deleteAnswer(item, 'answerArr', j)">
<span>删除</span>
</button>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="6" nzFor="data.audioUrl"> 音频:</nz-form-label>
<nz-form-control [nzSpan]="12">
<app-audio-recorder [audioUrl]="data.audioUrl"
(audioUploaded)="onAudioUploadSuccess($event, data, '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]="6">
<nz-radio-group [(ngModel)]="data.contentType" (ngModelChange)="setContentType($event, data)">
<label nz-radio nzValue="T">文字</label>
<label nz-radio nzValue="P">图片</label>
</nz-radio-group>
</nz-form-control>
</nz-form-item>
<div *ngIf="data.contentType == 'T'">
<nz-form-item>
<nz-form-label [nzSpan]="6" >文本</nz-form-label>
<nz-form-control [nzSpan]="6">
<input nz-input type="text" placeholder="请录入内容" [(ngModel)]="data.val" (blur)="save()">
</nz-form-control>
</nz-form-item>
</div>
<div *ngIf="data.contentType == 'P'">
<nz-form-item>
<nz-form-label [nzSpan]="6">图片</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-upload-image-with-preview
style="width: 100%"
[picUrl]="data.picUrl"
(imageUploaded)="onImageUploadSuccess($event, data, 'picUrl')"
></app-upload-image-with-preview>
</nz-form-control>
</nz-form-item>
</div>
</div>
</div>
<hr>
<div id='listen-anchor'>
<nz-form-item>
<nz-form-label [nzSpan]="6" >操作</nz-form-label>
<nz-form-control [nzSpan]="6">
<button nz-button nzType="dashed" class="add-btn" id="add-btn" (click)="addAnswer(item, 'answerArr')">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
</button>
</nz-form-control>
</nz-form-item>
</div>
</div>
</div>
\ 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 { getDefaultAnswer, getDefaultExercises } from '../bean/ExercisesBean';
...@@ -10,7 +11,7 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap ...@@ -10,7 +11,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 = "LST-05";
// 储存对象 // 储存对象
item; item;
...@@ -22,7 +23,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -22,7 +23,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
ngOnInit() { ngOnInit() {
this.item = {}; this.item = getDefaultExercises();
// 获取存储的数据 // 获取存储的数据
(<any> window).courseware.getData((data) => { (<any> window).courseware.getData((data) => {
...@@ -58,19 +59,19 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -58,19 +59,19 @@ 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();
} }
...@@ -93,5 +94,35 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -93,5 +94,35 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}, 1); }, 1);
} }
deleteAnswer(item, key, index){
if (index !== -1) {
item[key].splice(index, 1);
item[key] = [...item[key]];
this.save();
}
}
addAnswer(item, key){
let answer = getDefaultAnswer();
item[key] = [...item[key], answer];
this.save();
}
setContentType(e, item){
item['contentType'] = e;
if("T" == e){
item['picUrl'] = "";
}
else if("P" == e){
item['val'] = "";
}
this.save();
}
} }
import {
MySprite, tweenChange,
ShapeRect
} from './Unit';
export class AudioAnimation {
private x = 0;
private y = 0;
images = new Map();
bg: ShapeRect;
playPic1;
playPic2;
playPic3;
playPic4;
curAudio;
playing = false;
hideFlag = true;
/**
* 设置播放帧图片
* @param images
*/
constructor(images) {
this.images = images;
}
setXY(x, y) {
this.x = x;
this.y = y;
}
/**
* 初始化图
* @param parent 图片显示父对象
* @param show 是否直接显示
*/
initPic(parent, show: boolean) {
if (!parent) {
return;
}
const bg = new ShapeRect();
const getAudioPic = (index) => {
const playPic = new MySprite();
playPic.init(this.images.get("btn_laba" + index));
playPic.alpha = 0;
playPic.x = playPic.getBoundingBox().width / 2;
playPic.y = playPic.getBoundingBox().height / 2;
bg.addChild(playPic);
return playPic;
};
const playPic1 = getAudioPic(1);
if (show) {
playPic1.alpha = 1;
this.hideFlag = false;
}
else {
playPic1.alpha = 0;
this.hideFlag = true;
}
this.playPic1 = playPic1;
const playPic2 = getAudioPic(2);
this.playPic2 = playPic2;
const playPic3 = getAudioPic(3);
this.playPic3 = playPic3;
const playPic4 = getAudioPic(4);
this.playPic4 = playPic4;
bg.setSize(playPic1.getBoundingBox().width, playPic1.getBoundingBox().height);
bg.alpha = 0;
this.bg = bg;
bg.x = this.x;
bg.y = this.y;
if (parent instanceof Array) {
parent.push(bg);
}
else {
parent.addChild(bg);
}
}
/**
* 显示播放状态
*/
showPlayStauts() {
this.hideFlag = false;
const setPause = () => {
if (this.hideFlag) {
this.playPic1.alpha = 0;
}
else {
this.playPic1.alpha = 1;
}
this.playPic2.alpha = 0;
this.playPic3.alpha = 0;
this.playPic4.alpha = 0;
}
const show1 = () => {
if (this.playing) {
this.playPic1.alpha = 0;
this.playPic2.alpha = 1;
this.playPic3.alpha = 0;
this.playPic4.alpha = 0;
setTimeout(() => {
show2();
}, 500);
}
else {
setPause();
}
};
const show2 = () => {
if (this.playing) {
this.playPic1.alpha = 0;
this.playPic2.alpha = 0;
this.playPic3.alpha = 1;
this.playPic4.alpha = 0;
setTimeout(() => {
show3();
}, 500);
}
else {
setPause();
}
};
const show3 = () => {
if (this.playing) {
this.playPic1.alpha = 0;
this.playPic2.alpha = 0;
this.playPic3.alpha = 0;
this.playPic4.alpha = 1;
setTimeout(() => {
show4();
}, 500);
}
else {
setPause();
}
};
const show4 = () => {
if (this.playing) {
this.playPic1.alpha = 1;
this.playPic2.alpha = 0;
this.playPic3.alpha = 0;
this.playPic4.alpha = 0;
setTimeout(() => {
show1();
}, 500);
}
else {
setPause();
}
};
show1();
}
/**
*
* @param audio 播放音频
* @param callback
*/
playAudio(audio, callback = null) {
//console.log(audio);
if (!audio) {
return;
}
this.curAudio = audio;
audio.onended = () => {
this.playing = false;
if (callback) {
callback();
}
};
audio.play();
this.playing = true;
this.showPlayStauts();
}
/**
*
* @param reset 是否重置
* @param callback 暂停后执行方法
*/
pauseAudio(reset = false, callback = null) {
const audio = this.curAudio;
if (audio) {
this.playing = false;
if (reset) {
audio.currentTime = 0;
}
audio.pause();
if (callback) {
callback();
}
}
}
/**
* 隐藏音频播放动画
* @param reset 是否重置
*/
hide(reset = false) {
this.hideFlag = true;
this.pauseAudio(reset);
this.playPic1.alpha = 0;
this.playPic2.alpha = 0;
this.playPic3.alpha = 0;
this.playPic4.alpha = 0;
}
/**
* 显示播放动画
*/
show() {
this.hideFlag = false;
this.playPic1.alpha = 1;
this.playPic2.alpha = 0;
this.playPic3.alpha = 0;
this.playPic4.alpha = 0;
}
}
\ No newline at end of file
/**
*
* @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 { Item } from './Item';
import { MySprite, tweenChange } from './Unit';
import { playAudio } from './AudioUtil';
export class Button extends Item{
btnPic : MySprite;
private _outX = 0;
set outX(v){
this._outX =v ;
}
get outX(){
return this._outX;
}
private _outY = 0;
set outY(v){
this._outY =v ;
}
get outY(){
return this._outY;
}
init(picName){
const btnPic = this.getPic(picName);
this.width = btnPic.width;
this.height = btnPic.height;
btnPic.x = this.x;
btnPic.y = this.y;
this.btnPic = btnPic;
}
click(callback = null){
playAudio(this.audioObj['click'], true);
//放大
tweenChange(this.btnPic, {scaleX: this.scaleX * 1.3, scaleY : this.scaleY * 1.3}, 0.1, ()=>{
//恢复
tweenChange(this.btnPic, {scaleX: this.scaleX, scaleY : this.scaleY}, 0.1, ()=>{
//移出
tweenChange(this.btnPic, {x : this.outX, y:this.outY}, 0.3, ()=>{
if(callback){
callback();
}
})
});
})
}
show(callback = null){
this.btnPic.x = this.x;
this.btnPic.y = this.y;
this.btnPic.visible = true;
if(callback){
callback();
}
}
}
\ No newline at end of file
import { Label, MySprite, ShapeRect } from './Unit';
export class Card {
images;
mapScale = 1;
bg: ShapeRect;
initX = 0;
initY = 0;
toX = 0;
toY = 0;
canClick = false;
curAnswer = null;
bgPic: MySprite;
bgWord: MySprite;
h = 0;
canHit = false;
endFlag = false;
init(images, mapScale = 1) {
this.mapScale = mapScale;
this.images = images;
const bg = new ShapeRect();
bg.alpha = 0;
this.bg = bg;
const pic = new MySprite();
pic.init(this.images.get('bg_ip'));
pic.setScaleXY(mapScale);
bg.setSize(pic.getBoundingBox().width, pic.getBoundingBox().height);
pic.x = bg.width / 2;
pic.y = bg.height / 2;
bg.addChild(pic);
this.initPic();
this.canClick = false;
this.h = bg.height;
}
private initPic() {
const bgPic = new MySprite();
bgPic.init(this.images.get('bg_pic'));
bgPic.setScaleXY(this.mapScale);
bgPic.x = this.bg.width / 2;
bgPic.y = - bgPic.getBoundingBox().height / 2 + 15 * this.mapScale;
this.bgPic = bgPic;
this.bg.addChild(bgPic);
this.bgPic.visible = false;
const bgWord = new MySprite();
bgWord.init(this.images.get('bg_word'));
bgWord.setScaleXY(this.mapScale);
bgWord.x = this.bg.width / 2;
bgWord.y = - bgWord.getBoundingBox().height / 2 + 15 * this.mapScale;
this.bgWord = bgWord;
this.bg.addChild(bgWord);
this.bgWord.visible = false;
}
showNext(answer, callback = null) {
this.curAnswer = answer;
if (!answer) {
if (callback) {
callback();
}
}
this.bgPic.removeChildren();
this.bgWord.removeChildren();
this.bgPic.visible = false;
this.bgWord.visible = false;
const setMaxScale = (target: MySprite, maxW, maxH) => {
const sx = maxW / target.width;
const sy = maxH / target.height;
const s = Math.min(sx, sy);
target.setScaleXY(Math.round(s * 1000) / 1000);
}
if (answer.contentType == 'P') {
this.bgPic.visible = true;
const pic = new MySprite();
pic.init(this.images.get(answer.picUrl));
pic.x = 0;
pic.y = 0;
setMaxScale(pic, 230, 172);
this.bgPic.addChild(pic);
this.h = this.bgPic.getBoundingBox().height;
}
else if (answer.contentType == 'T') {
this.bgWord.visible = true;
const label = new Label();
label.text = answer.val;
label.fontSize = 70;
label.fontName = 'MMTextBook-Bold';
label.textAlign = 'center';
label.fontColor = '#18408d';
label.setMaxSize(320);
label.y = 0;
label.x = 0;
this.bgWord.addChild(label);
this.h = this.bgWord.getBoundingBox().height;
}
}
}
\ No newline at end of file
import { MySprite, ShapeRect } from './Unit';
interface AirWindow extends Window {
air: any;
curCtx: any;
}
declare let window: AirWindow;
export class Item {
/**图片集合 */
images;
audioObj;
_scaleX = 1;
_scaleY = 1;
ctx;
_width = 0;
_height = 0;
_x = 0;
_y = 0;
bg: ShapeRect;
constructor(images, audioObj, scaleX = 1, scaleY = 1, ctx = null) {
this.images = images;
this.audioObj = audioObj;
this._scaleX = scaleX;
this._scaleY = scaleY;
if (!ctx) {
this.ctx = window.curCtx;
} else {
this.ctx = ctx;
}
}
set width(width) {
this._width = width * this.scaleX;
if(this.bg){
this.bg.width = this._width;
}
}
get width() {
return this._width;
}
set height(height) {
this._height = height * this.scaleY;
if(this.bg){
this.bg.height = this._height;
}
}
get height() {
return this._height;
}
set scaleX(v) {
this._scaleX = v;
}
get scaleX() {
return this._scaleX;
}
set scaleY(v) {
this._scaleY = v;
}
get scaleY() {
return this._scaleY;
}
set x(x) {
this._x = x;
if (this.bg) {
this.bg.x = this._x;
}
}
get x() {
return this._x;
}
set y(y) {
this._y = y;
if (this.bg) {
this.bg.y = this._y;
}
}
get y() {
return this._y;
}
getPic(picName, anchorX: number = 0.5, anchorY: number = 0.5) {
const pic = new MySprite();
pic.init(this.images.get(picName), anchorX, anchorY);
pic.scaleX = this.scaleX;
pic.scaleY = this.scaleY;
pic.x = 0;
pic.y = 0;
return pic;
}
checkClickTarget(target, mx: number, my: number) {
const rect = target.getBoundingBox();
if (this.checkPointInRect(mx, my, rect)) {
return true;
}
return false;
}
checkPointInRect(x, y, rect) {
if (x >= rect.x && x <= rect.x + rect.width) {
if (y >= rect.y && y <= rect.y + rect.height) {
return true;
}
}
return false;
}
}
export function setScale(pW: number, pH: number, child) {
let width = child.width;
let height = child.height;
let sx = pW / width;
let sy = pH / height;
let scale = Math.min(sx, sy);
if (scale < 1) {
child.setScaleXY(scale);
}
}
\ 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
This diff is collapsed.
const res = [ const res = [
// ['bg', "assets/play/bg.jpg"], ['btn_laba1', "assets/play/btn_laba1.png"],
['btn_left', "assets/play/btn_left.png"], ['btn_laba2', "assets/play/btn_laba2.png"],
['btn_right', "assets/play/btn_right.png"], ['btn_laba3', "assets/play/btn_laba3.png"],
// ['text_bg', "assets/play/text_bg.png"], ['btn_laba4', "assets/play/btn_laba4.png"],
['bg', "assets/play/bg.png"],
['bg_behind', "assets/play/bg_behind.png"],
['bg_front', "assets/play/bg_front.png"],
['bg_ip', "assets/play/bg_ip.png"],
['bg_pic', "assets/play/bg_pic.png"],
['bg_word', "assets/play/bg_word.png"],
['btn_restart', "assets/play/btn_restart.png"],
['btn_start', "assets/play/btn_start.png"],
]; ];
...@@ -12,7 +22,8 @@ const res = [ ...@@ -12,7 +22,8 @@ const res = [
const resAudio = [ const resAudio = [
['click', "assets/play/music/click.mp3"], ['click', "assets/play/music/click.mp3"],
['right', "assets/play/music/right.mp3"],
['wrong', "assets/play/music/wrong.mp3"]
]; ];
export {res, resAudio}; export {res, resAudio};
This diff is collapsed.
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