Commit 0fe5f9bf authored by Li Mingzhe's avatar Li Mingzhe

feat: 首次提交

parent 8a51c964
<div class="model-content">
<div style="padding: 30px">
<div style="position: absolute; left: 200px; top: 100px; width: 800px;">
<div style="display: flex; align-items: center; ">
<h2> 题干类型: </h2>
<nz-radio-group [(ngModel)]="item.questionType" style="margin-left: 20px; margin-top: -11px" (ngModelChange)="save()">
<label nz-radio nzValue="text">文本</label>
<label nz-radio nzValue="pic">图片</label>
<label nz-radio nzValue="audio">音频</label>
<label nz-radio nzValue="video">视频</label>
</nz-radio-group>
</div>
<div style="width: 700px">
<div *ngIf="item.questionType == 'text'">
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()">
</div>
<div *ngIf="item.questionType == 'pic'" style="width: 80%">
<app-upload-image-with-preview
[picUrl]="item.pic_url"
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')"
></app-upload-image-with-preview>
</div>
<div *ngIf="item.questionType == 'audio'">
<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 *ngIf="item.questionType == 'video'">
<app-upload-video
(videoUploaded)="onVideoUploadSuccess($event)"
[item]="item"
[videoUrl]="item.video_url"></app-upload-video>
</div>
</div>
</div>
<nz-divider style=" margin-top: 80px; margin-bottom: 80px;"></nz-divider>
<div style="display: flex; align-items: center;">
<h2> 答案类型: </h2>
<nz-radio-group [(ngModel)]="item.answerType" style="margin-left: 20px; margin-top: -11px" (ngModelChange)="save()">
<label nz-radio nzValue="text">文本</label>
<label nz-radio nzValue="pic">图片</label>
</nz-radio-group>
</div>
<div *ngFor="let it of item.answerArr; let i = index">
<div style="margin-bottom: 30px; width : 500px; border: 1px solid #ccc; border-radius: 10px; padding: 5px;">
<span> 答案{{i+1}}: </span>
<nz-radio-group style="margin-left: 20px; margin-bottom: 5px;" [(ngModel)]="it.answerRight" (ngModelChange)="save()">
<label nz-radio nzValue="0">错误</label>
<label nz-radio nzValue="1">正确</label>
<button style="margin-left: 200px" nz-button nzType="danger" nzsize="small" (click)="deleteAnswer(i)">删除</button>
</nz-radio-group>
<input *ngIf="item.answerType == 'text'" type="text" nz-input [(ngModel)]="it.text" (blur)="save()">
<app-upload-image-with-preview
*ngIf="item.answerType == 'pic'"
[picUrl]="it.pic_url"
(imageUploaded)="onImageUploadSuccess($event, 'pic_url', it)"
></app-upload-image-with-preview>
</div>
</div>
</div>
<div *ngIf="item.answerArr.length < 4" style="padding: 30px;" (click)="addAnswer()">
<button nz-button nzType="dashed" style="width: 200px; height: 100px; margin-top: -30px">添加答案</button>
</div>
</div>
......@@ -10,7 +10,7 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap
export class FormComponent implements OnInit, OnChanges, OnDestroy {
// 储存数据用
saveKey = "test_0011";
saveKey = "pu06";
// 储存对象
item;
......@@ -23,7 +23,6 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
ngOnInit() {
this.item = {};
// 获取存储的数据
(<any> window).courseware.getData((data) => {
......@@ -51,6 +50,33 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
init() {
if (!this.item.questionType) {
this.item.questionType = 'text';
this.item.answerType = 'text';
this.item.answerArr = [];
// for (let i = 0; i < 4; i++) {
// this.item.answerArr.push({
// text: '',
// pic_url: '',
// answerRight: '0',
// });
// }
}
}
deleteAnswer(i) {
this.item.answerArr.splice(i, 1);
this.save();
}
addAnswer() {
this.item.answerArr.push({
text: '',
pic_url: '',
answerRight: '0',
});
this.save();
}
......@@ -58,9 +84,12 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
* 储存图片数据
* @param e
*/
onImageUploadSuccess(e, key) {
onImageUploadSuccess(e, key, item = null) {
this.item[key] = e.url;
if (!item) {
item = this.item;
}
item[key] = e.url;
this.save();
}
......@@ -75,6 +104,10 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}
onVideoUploadSuccess(e) {
this.item.video_url = e.url;
this.save();
}
/**
* 储存数据
......
......@@ -4,6 +4,7 @@ import TWEEN from '@tweenjs/tween.js';
interface AirWindow extends Window {
air: any;
curCtx: any;
curImages: any;
}
declare let window: AirWindow;
......@@ -36,7 +37,6 @@ class Sprite {
export class MySprite extends Sprite {
_width = 0;
......@@ -69,6 +69,13 @@ export class MySprite extends Sprite {
img;
_z = 0;
_showRect;
_bitmapFlag = false;
_offCanvas;
_offCtx;
init(imgObj = null, anchorX: number = 0.5, anchorY: number = 0.5) {
......@@ -87,6 +94,10 @@ export class MySprite extends Sprite {
}
setShowRect(rect) {
this._showRect = rect;
}
setShadow(offX, offY, blur, color = 'rgba(0, 0, 0, 0.3)') {
......@@ -103,6 +114,8 @@ export class MySprite extends Sprite {
}
update($event = null) {
if (!this.visible && this.childDepandVisible) {
return;
......@@ -139,21 +152,21 @@ export class MySprite extends Sprite {
if (this._radius) {
const r = this._radius;
const w = this.width;
const h = this.height;
this.ctx.lineTo(-w / 2, h / 2); // 创建水平线
this.ctx.arcTo(-w / 2, -h / 2, -w / 2 + r, -h / 2, r);
this.ctx.arcTo(w / 2, -h / 2, w / 2, -h / 2 + r, r);
this.ctx.arcTo(w / 2, h / 2, w / 2 - r, h / 2, r);
this.ctx.arcTo(-w / 2, h / 2, -w / 2, h / 2 - r, r);
this.ctx.clip();
}
//
// if (this._radius) {
//
// const r = this._radius;
// const w = this.width;
// const h = this.height;
//
// this.ctx.lineTo(-w / 2, h / 2); // 创建水平线
// this.ctx.arcTo(-w / 2, -h / 2, -w / 2 + r, -h / 2, r);
// this.ctx.arcTo(w / 2, -h / 2, w / 2, -h / 2 + r, r);
// this.ctx.arcTo(w / 2, h / 2, w / 2 - r, h / 2, r);
// this.ctx.arcTo(-w / 2, h / 2, -w / 2, h / 2 - r, r);
//
// this.ctx.clip();
// }
}
......@@ -176,10 +189,14 @@ export class MySprite extends Sprite {
if (this.img) {
if (this._showRect) {
const rect = this._showRect;
this.ctx.drawImage(this.img, rect.x, rect.y, rect.width, rect.height, this._offX + rect.x, this._offY + rect.y, rect.width, rect.height);
} else {
this.ctx.drawImage(this.img, this._offX, this._offY);
}
}
}
......@@ -257,6 +274,13 @@ export class MySprite extends Sprite {
}
}
set bitmapFlag(v) {
this._bitmapFlag = v;
}
get bitmapFlag() {
return this._bitmapFlag;
}
set alpha(v) {
this._alpha = v;
if (this.childDepandAlpha) {
......@@ -305,7 +329,6 @@ export class MySprite extends Sprite {
getBoundingBox() {
const getParentData = (item) => {
let px = item.x;
......@@ -343,11 +366,6 @@ export class MySprite extends Sprite {
const width = this.width * Math.abs(data.sx);
const height = this.height * Math.abs(data.sy);
// const x = this.x + this._offX * Math.abs(this.scaleX);
// const y = this.y + this._offY * Math.abs(this.scaleY);
// const width = this.width * Math.abs(this.scaleX);
// const height = this.height * Math.abs(this.scaleY);
return {x, y, width, height};
}
......@@ -759,6 +777,7 @@ export class RichText extends Label {
disH = 30;
offW = 10;
constructor(ctx?: any) {
super(ctx);
......@@ -788,7 +807,7 @@ export class RichText extends Label {
const chr = this.text.split(' ');
let temp = '';
const row = [];
const w = selfW - 80;
const w = selfW - this.offW * 2;
const disH = (this.fontSize + this.disH) * this.scaleY;
......@@ -1020,7 +1039,7 @@ export class MyAnimation extends MySprite {
loop = false;
playEndFunc;
delayPerUnit = 1;
delayPerUnit = 0.07;
restartFlag = false;
reverseFlag = false;
......@@ -1109,8 +1128,9 @@ export class MyAnimation extends MySprite {
this.frameArr[this.frameIndex].visible = true;
if (this.playEndFunc) {
this.playEndFunc();
const func = this.playEndFunc;
this.playEndFunc = null;
func();
}
}
......@@ -1200,7 +1220,7 @@ export function tweenChange(item, obj, time = 0.8, callBack = null, easing = nul
export function rotateItem(item, rotation, time = 0.8, callBack = null, easing = null) {
export function rotateItem(item, rotation, time = 0.8, callBack = null, easing = null, loop = false) {
const tween = new TWEEN.Tween(item).to({ rotation }, time * 1000);
......@@ -1208,7 +1228,14 @@ export function rotateItem(item, rotation, time = 0.8, callBack = null, easing =
tween.onComplete(() => {
callBack();
});
} else if (loop) {
const speed = (rotation - item.rotation) / time;
tween.onComplete(() => {
item.rotation %= 360;
rotateItem(item, item.rotation + speed * time, time, null, easing, true);
});
}
if (easing) {
tween.easing(easing);
}
......@@ -1525,10 +1552,15 @@ export function formatTime(fmt, date) {
return fmt;
}
export function getMinScale(item, maxLen) {
const sx = maxLen / item.width;
const sy = maxLen / item.height;
export function getMinScale(item, maxW, maxH = null) {
if (!maxH) {
maxH = maxW;
}
const sx = maxW / item.width;
const sy = maxH / item.height;
const minS = Math.min(sx, sy);
return minS;
}
......@@ -1571,6 +1603,46 @@ export function jelly(item, time = 0.7) {
run();
}
export function jellyPop(item, time) {
if (item.jellyTween) {
TWEEN.remove(item.jellyTween);
}
const t = time / 6;
const baseSX = item.scaleX;
const baseSY = item.scaleY;
let index = 0;
const run = () => {
if (index >= arr.length) {
item.jellyTween = null;
return;
}
const data = arr[index];
const t = tweenChange(item, {scaleX: data[0], scaleY: data[1]}, data[2], () => {
index ++;
run();
}, TWEEN.Easing.Sinusoidal.InOut);
item.jellyTween = t;
};
const arr = [
[baseSX * 1.3, baseSY * 1.3, t],
[baseSX * 0.85, baseSY * 0.85, t * 1],
[baseSX * 1.1, baseSY * 1.1, t * 1],
[baseSX * 0.95, baseSY * 0.95, t * 1],
[baseSX * 1.02, baseSY * 1.02, t * 1],
[baseSX * 1, baseSY * 1, t * 1],
];
item.setScaleXY(0);
run();
}
export function showPopParticle(img, pos, parent, num = 20, minLen = 40, maxLen = 80, showTime = 0.4) {
......@@ -1672,5 +1744,41 @@ export function shake(item, time = 0.5, callback = null, rate = 1) {
}
export function getMaxScale(item, maxW, maxH) {
const sx = maxW / item.width;
const sy = maxH / item.height;
const maxS = Math.max(sx, sy);
return maxS;
}
export function createSprite(key) {
const image = window.curImages;
const spr = new MySprite();
spr.init(image.get(key));
return spr;
}
export class MyVideo extends MySprite {
element;
initVideoElement(videoElement) {
this.element = videoElement;
this.width = this.element.videoWidth;
this.height = this.element.videoHeight;
this.element.currentTime = 0.01;
}
drawSelf() {
super.drawSelf();
this.ctx.drawImage(this.element, 0, 0, this.width, this.height);
}
}
// --------------- custom class --------------------
......@@ -13,7 +13,7 @@
@font-face
{
font-family: 'BRLNSDB';
src: url("../../assets/font/BRLNSDB.TTF") ;
font-family: 'MMTextBook-Bold';
src: url("../../assets/font/MMTextBook-Bold.otf") ;
}
<div style="display: none">
<video [src]="data.video_url" #videoNode></video>
</div>
<div class="game-container" #wrap>
<canvas id="canvas" #canvas></canvas>
</div>
<label style="position: absolute; top: 0px; opacity: 0; font-family: 'MMTextBook-Bold'">1</label>
import {Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener} from '@angular/core';
import {
Label,
MySprite, tweenChange,
ApplicationRef,
ChangeDetectorRef,
Component,
ElementRef,
HostListener,
OnDestroy,
OnInit,
ViewChild
} from '@angular/core';
import {
createSprite,
formatTime,
getMaxScale,
getMinScale, jelly, jellyPop,
Label, moveItem,
MySprite,
MyVideo, removeItemFromArr,
RichText, rotateItem,
shake, ShapeRect,
tweenChange,
} from './Unit';
import {res, resAudio} from './resources';
......@@ -13,8 +29,6 @@ import {debounceTime} from 'rxjs/operators';
import TWEEN from '@tweenjs/tween.js';
@Component({
selector: 'app-play',
templateUrl: './play.component.html',
......@@ -25,6 +39,8 @@ export class PlayComponent implements OnInit, OnDestroy {
@ViewChild('canvas', {static: true }) canvas: ElementRef;
@ViewChild('wrap', {static: true }) wrap: ElementRef;
@ViewChild('videoNode', {static: true }) videoNode: ElementRef;
// 数据
data;
......@@ -57,17 +73,26 @@ export class PlayComponent implements OnInit, OnDestroy {
canvasLeft;
canvasTop;
saveKey = 'test_0011';
saveKey = 'pu06';
btnLeft;
btnRight;
pic1;
pic2;
canTouch = true;
curPic;
private oven: MySprite;
private ovenBg: MySprite;
private curAudio: any;
private progressBarBg ;
private currentTime: number;
private isClickedProgress: boolean;
private allBtns: any;
private curVideo: MyVideo;
private videoBtn: MySprite;
private answerArr: any;
private ovenLight: MySprite;
private petalTime: number;
private showPetalFlag: boolean;
private endPageArr: any;
@HostListener('window:resize', ['$event'])
onResize(event) {
......@@ -86,7 +111,7 @@ export class PlayComponent implements OnInit, OnDestroy {
if (data && typeof data == 'object') {
this.data = data;
}
// console.log('data:' , data);
console.log('data:' , data);
// 初始化 各事件监听
this.initListener();
......@@ -141,6 +166,7 @@ export class PlayComponent implements OnInit, OnDestroy {
this.canvas.nativeElement.height = this.canvasHeight;
window['curCtx'] = this.ctx;
window['curImages'] = this.images;
}
......@@ -270,7 +296,7 @@ export class PlayComponent implements OnInit, OnDestroy {
}
playAudio(key, now = false, callback = null) {
playAudio(key, now = true, callback = null) {
const audio = this.audioObj[key];
if (audio) {
......@@ -313,6 +339,15 @@ export class PlayComponent implements OnInit, OnDestroy {
pr.push(a);
});
// if (this.videoNode && this.videoNode.nativeElement) {
// const a = this.preloadVideo(this.videoNode.nativeElement)
// .then(() => {
// console.log('video load end');
// })
// .catch(err => console.log(err));
// pr.push(a);
// }
return Promise.all(pr);
}
......@@ -340,6 +375,19 @@ export class PlayComponent implements OnInit, OnDestroy {
});
}
preloadVideo(video) {
return new Promise((resolve, reject) => {
video.addEventListener('canplay', () => {
console.log('video canplay');
resolve();
})
video.addEventListener('error', (e) => {
console.log('video error: ', e);
reject();
})
video.load();
});
}
renderAfterResize() {
this.canvasWidth = this.wrap.nativeElement.clientWidth;
......@@ -350,7 +398,6 @@ export class PlayComponent implements OnInit, OnDestroy {
checkClickTarget(target) {
const rect = target.getBoundingBox();
......@@ -421,6 +468,7 @@ export class PlayComponent implements OnInit, OnDestroy {
// ======================================================编写区域==========================================================================
......@@ -436,6 +484,32 @@ export class PlayComponent implements OnInit, OnDestroy {
this.data.pic_url = 'assets/play/default/pic.jpg';
this.data.pic_url_2 = 'assets/play/default/pic.jpg';
}
if (!this.data.questionType) {
this.data = {
answerArr: [
{
answerRight: "1",
text: "This option is correct."
},
{
answerRight: "0",
text: "This option is wrong."
},
{
answerRight: "0",
text: "This option is wrong."
},
{
answerRight: "1",
text: "This option is correct."
}
],
answerType: "text",
questionType: "text",
text: "This is a test question."
}
}
}
......@@ -445,7 +519,10 @@ export class PlayComponent implements OnInit, OnDestroy {
initImg() {
this.addUrlToImages(this.data.pic_url);
this.addUrlToImages(this.data.pic_url_2);
this.data.answerArr.forEach(( item ) => {
this.addUrlToImages(item.pic_url);
});
}
......@@ -456,15 +533,15 @@ export class PlayComponent implements OnInit, OnDestroy {
// 音频资源
this.addUrlToAudioObj(this.data.audio_url);
this.addUrlToAudioObj(this.data.audio_url_2);
// 音效
this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3);
this.addUrlToAudioObj('wrong', this.rawAudios.get('wrong'), 1);
this.addUrlToAudioObj('right', this.rawAudios.get('right'), 0.5);
this.addUrlToAudioObj('finish', this.rawAudios.get('finish'), 0.5);
}
/**
* 初始化数据
*/
......@@ -481,8 +558,11 @@ export class PlayComponent implements OnInit, OnDestroy {
this.renderArr = [];
this.currentTime = 0;
this.allBtns = [];
this.answerArr = [];
this.endPageArr = [];
}
......@@ -492,188 +572,675 @@ export class PlayComponent implements OnInit, OnDestroy {
*/
initView() {
this.initBg();
this.initQuestion();
this.initAnswer();
}
this.initPic();
this.initBottomPart();
mapDown(event) {
if (!this.canTouch) {
return;
}
initBottomPart() {
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;
if (this.data.questionType == 'video' && this.checkClickTarget(this.ovenBg)) {
this.clickedVideo();
return;
}
btnLeft.setScaleXY(this.mapScale);
for (let i = 0; i < this.answerArr.length; i++) {
if (this.checkClickTarget(this.answerArr[i])) {
this.clickedAnswer(this.answerArr[i]);
return;
}
}
this.renderArr.push(btnLeft);
// ------- 播放器 --------
if (this.curAudio) {
if (this.checkClickTarget(this.progressBarBg)) {
this.isClickedProgress = true;
this.touchDownProgressBar(this.progressBarBg);
return;
}
if (this.checkClickTarget(this.curAudio.playBtn)) {
this.touchDownAudioBtn(this.curAudio);
return;
}
}
// ------------------------
}
mapMove(event) {
if (!this.isClickedProgress) {
return;
}
this.btnLeft = btnLeft;
this.touchDownProgressBar(this.progressBarBg);
}
const btnRight = new MySprite();
btnRight.init(this.images.get('btn_right'));
btnRight.x = this.canvasWidth - 50 * this.mapScale;
btnRight.y = this.canvasHeight - 100 * this.mapScale;
btnRight.setScaleXY(this.mapScale);
mapUp(event) {
this.renderArr.push(btnRight);
this.btnRight = btnRight;
this.isClickedProgress = false;
}
initPic() {
const maxW = this.canvasWidth * 0.7;
const pic1 = new MySprite();
pic1.init(this.images.get(this.data.pic_url));
pic1.x = this.canvasWidth / 2;
pic1.y = this.canvasHeight / 2;
pic1.setScaleXY(maxW / pic1.width);
update() {
this.renderArr.push(pic1);
this.pic1 = pic1;
// ----------------------------------------------------------
this.animationId = window.requestAnimationFrame(this.update.bind(this));
// 清除画布内容
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
// tween 更新动画
TWEEN.update();
// ----------------------------------------------------------
const label1 = new Label();
label1.text = this.data.text;
label1.textAlign = 'center';
label1.fontSize = 50;
label1.fontName = 'BRLNSDB';
label1.fontColor = '#ffffff';
pic1.addChild(label1);
this.updateArr(this.renderArr);
this.updateArr(this.endPageArr);
this.updateTime();
}
private updateTime() {
if (!this.isClickedProgress && this.curAudio) {
const progress = this.curAudio.currentTime / this.curAudio.duration;
this.setAudioProgress(this.progressBarBg, progress);
}
}
const pic2 = new MySprite();
pic2.init(this.images.get(this.data.pic_url_2));
pic2.x = this.canvasWidth / 2 + this.canvasWidth;
pic2.y = this.canvasHeight / 2;
pic2.setScaleXY(maxW / pic2.width);
this.renderArr.push(pic2);
this.pic2 = pic2;
this.curPic = pic1;
private createPlayPauseButton(playKey, pauseKey) {
const button = createSprite(playKey);
const btnPause = createSprite(pauseKey);
this.hide(btnPause);
button.addChild(btnPause);
this.curAudio.playBtn = button;
this.curAudio.stopBtn = btnPause;
return button;
}
private createProgressBar(barTopKey, barBottomKey, barBtnKey) {
const container = new MySprite();
const progressBarBg = createSprite(barBottomKey);
progressBarBg.anchorX = 0;
this.progressBarBg = progressBarBg;
const progressBarPlayed = createSprite(barTopKey);
progressBarPlayed.anchorX = 0;
progressBarBg['bar'] = progressBarPlayed;
container['bar'] = progressBarPlayed;
const btn = createSprite(barBtnKey)
btn.y = -3;
progressBarBg['btn'] = btn;
const currentTime = this.createTime();
currentTime.text = formatTime('mm:ss', new Date(this.currentTime * 1000));
currentTime.refreshSize();
currentTime.x = 0;
currentTime.y = 30;
progressBarBg['timeLabel'] = currentTime;
const totalTime = this.createTime();
totalTime.text = formatTime('mm:ss', new Date(this.curAudio.duration * 1000));
totalTime.refreshSize();
totalTime.x = progressBarBg.width - totalTime.width;
totalTime.y = currentTime.y;
container.addChild(progressBarBg);
container.addChild(progressBarPlayed);
container.addChild(btn);
container.addChild(currentTime)
container.addChild(totalTime)
return container;
}
private createTime() {
const label = new Label();
label.fontSize = 22;
label.fontColor = '#c7edc8';
label.fontName = 'MMTextBook-Bold';
// label.setShadow(1, 1, 2, '#000000')
return label;
}
btnLeftClicked() {
private setAudioProgress(target: any, progress: number) {
target.btn.x = target.width * progress;
this.lastPage();
const showRect = {x: 0, y: 0, width: target.bar.width * progress, height: target.bar.height};
target.bar.setShowRect(showRect);
this.currentTime = Math.floor(progress * this.curAudio.duration);
target.timeLabel.text = formatTime('mm:ss', new Date(this.currentTime * 1000));
}
btnRightClicked() {
private touchDownProgressBar(target) {
this.setAudioState(this.curAudio, false);
this.nextPage();
const rect = target.getBoundingBox();
const sx = rect.width / target.width;
const tmpW = (this.mx - rect.x) / sx;
if (tmpW >= 0 && tmpW <= target.width) {
const progress = tmpW / target.width;
this.curAudio.currentTime = progress * this.curAudio.duration;
this.setAudioProgress(target, progress);
}
}
lastPage() {
private setAudioState(audio: any, isPlay: boolean) {
if (isPlay) {
this.hide(audio.playBtn);
this.show(audio.stopBtn);
audio.play();
} else {
this.hide(audio.stopBtn);
this.show(audio.playBtn);
audio.pause();
}
}
if (this.curPic == this.pic1) {
return;
private hide(element: MySprite) {
element.alpha = 0;
}
private show(element: MySprite) {
element.alpha = 1;
}
this.canTouch = false;
private touchDownAudioBtn(audio) {
if (audio.paused) {
audio.play();
this.setAudioState(audio, true);
} else {
audio.pause();
this.setAudioState(audio, false);
}
}
const moveLen = this.canvasWidth;
tweenChange(this.pic1, {x: this.pic1.x + moveLen}, 1);
tweenChange(this.pic2, {x: this.pic2.x + moveLen}, 1, () => {
this.canTouch = true;
this.curPic = this.pic1;
});
private initBg() {
const bg = createSprite('bg');
bg.setScaleXY(getMaxScale(bg, this.canvasWidth, this.canvasHeight));
bg.x = this.canvasWidth / 2;
bg.y = this.canvasHeight - bg.height / 2 * bg.scaleY;
this.renderArr.push(bg);
const oven = createSprite('oven');
oven.setScaleXY(this.mapScale);
oven.x = this.canvasWidth / 2;
oven.y = this.canvasHeight - oven.height / 2 * oven.scaleY - 10 * this.mapScale;
this.oven = oven;
this.renderArr.push(oven);
const ovenBg = createSprite('question_text_bg');
ovenBg.x = 0.6;
ovenBg.y = -110;
ovenBg.setScaleXY(1.01);
this.oven.addChild(ovenBg, -1);
this.ovenBg = ovenBg;
const light = createSprite('light');
oven.addChild(light);
light.anchorY = 0;
light.alpha = 0;
light.y = -oven.height / 2 + 62;
this.ovenLight = light;
}
nextPage() {
private initQuestion() {
switch (this.data.questionType) {
case 'text':
this.initQuestionText();
break;
if (this.curPic == this.pic2) {
return;
case 'pic':
this.initQuestionPic();
break;
case 'audio':
this.initQuestionAudio();
break;
case 'video':
this.initQuestionVideo();
break;
}
}
this.canTouch = false;
private initQuestionText() {
const questionLabel = new RichText();
questionLabel.text = this.data.text;
questionLabel.width = this.ovenBg.width * 0.98;
questionLabel.x = -questionLabel.width / 2;
questionLabel.y = -28;
questionLabel.fontColor = '#f6dc92';
questionLabel.fontName = 'MMTextBook-Bold';
questionLabel.disH = 5;
questionLabel.fontSize = 50;
this.ovenBg.addChild(questionLabel);
}
const moveLen = this.canvasWidth;
tweenChange(this.pic1, {x: this.pic1.x - moveLen}, 1);
tweenChange(this.pic2, {x: this.pic2.x - moveLen}, 1, () => {
this.canTouch = true;
this.curPic = this.pic2;
});
private initQuestionPic() {
const questionPic = createSprite(this.data.pic_url);
questionPic.setScaleXY(getMinScale(questionPic, this.ovenBg.width, this.ovenBg.height));
this.ovenBg.addChild(questionPic);
}
private initQuestionAudio() {
const res = {
btnPlay: 'btn_play',
btnPause: 'btn_pause',
barTop: 'bar_top',
barBottom: 'bar_bottom',
barBtn: 'bar_btn',
};
this.initAudioPlayer(res);
}
private initQuestionVideo() {
const video = new MyVideo();
const initVideoAndBtn = () => {
console.log('in initSize');
video.initVideoElement(this.videoNode.nativeElement);
video.setScaleXY(getMinScale(video, this.ovenBg.width, this.ovenBg.height));
video.x = -video.width / 2 * video.scaleX;
video.y = -video.height / 2 * video.scaleY;
video.element.removeEventListener('canplaythrough', initVideoAndBtn);
if (this.videoBtn) {
this.videoBtn.x = video.width / 2;
this.videoBtn.y = video.height / 2;
}
};
initVideoAndBtn();
video.element.onended = () => {
this.videoBtn.visible = true;
video.element.currentTime = 0;
this.refreshVideoState(video.element, true);
}
this.curVideo = video;
this.ovenBg.addChild(video);
const videoBtn = this.createVideoBtn();
videoBtn.x = video.width / 2;
videoBtn.y = video.height / 2;
video.addChild(videoBtn);
this.videoBtn = videoBtn;
video.element.src = this.data.video_url;
video.element.load();
video.element.addEventListener('canplaythrough', initVideoAndBtn);
pic1Clicked() {
this.playAudio(this.data.audio_url);
}
pic2Clicked() {
this.playAudio(this.data.audio_url_2);
initAudioPlayer(res) {
this.curAudio = this.audioObj[this.data.audio_url];
this.curAudio.onended = () => {
this.setAudioState(this.curAudio, false);
this.curAudio.currentTime = 0;
}
const playerCake = createSprite('player_cake');
this.oven.addChild(playerCake);
playerCake.y = -85;
const audioPlayer = this.createAudioPlayer(res);
audioPlayer.y = 10;
playerCake.addChild(audioPlayer);
this.setAudioProgress(this.progressBarBg, 0);
mapDown(event) {
return audioPlayer;
}
if (!this.canTouch) {
return;
private createAudioPlayer(res) {
const audioPlayer = new MySprite();
const playBtn = this.createPlayPauseButton(res.btnPlay, res.btnPause);
playBtn.x = 0;
playBtn.y = -120;
audioPlayer.addChild(playBtn);
audioPlayer['playBtn'] = playBtn;
const progressBarContainer = this.createProgressBar(res.barTop, res.barBottom, res.barBtn);
progressBarContainer.x = -this.progressBarBg.width / 2;
progressBarContainer.y = 80;
audioPlayer.addChild(progressBarContainer);
return audioPlayer;
}
if ( this.checkClickTarget(this.btnLeft) ) {
this.btnLeftClicked();
return;
private createVideoBtn() {
const btn = createSprite('video_play');
const pauseBtn = createSprite('video_pause');
pauseBtn.alpha = 0;
btn['pauseBtn'] = pauseBtn;
btn.addChild(pauseBtn);
return btn;
}
if ( this.checkClickTarget(this.btnRight) ) {
this.btnRightClicked();
return;
private clickedVideo() {
if (this.videoBtn.visible) {
this.videoBtn.visible = false;
} else {
this.videoBtn.visible = true;
}
if ( this.checkClickTarget(this.pic1) ) {
this.pic1Clicked();
return;
const videoElement = this.curVideo.element;
if (videoElement.paused) {
videoElement.play();
this.refreshVideoState(videoElement);
} else {
videoElement.pause();
this.refreshVideoState(videoElement);
}
}
if ( this.checkClickTarget(this.pic2) ) {
this.pic2Clicked();
private refreshVideoState(video, isPlay = null) {
if (isPlay == null) {
isPlay = !video.paused;
}
if (isPlay) {
this.hide(this.videoBtn['pauseBtn']);
this.show(this.videoBtn);
} else {
this.hide(this.videoBtn);
this.show(this.videoBtn['pauseBtn']);
}
}
private initAnswer() {
if (this.data.answerType == 'text') {
this.initTextAnswer();
} else {
this.initPicAnswer();
}
}
private initTextAnswer() {
const offX = 620 * this.mapScale;
const offY = 150 * this.mapScale;
const baseX = this.canvasWidth / 2 - offX / 2;
let baseY = this.canvasHeight - 230 * this.mapScale;
if (this.data.answerArr.length < 3) {
baseY += offY / 2;
}
for (let i = 0; i < this.data.answerArr.length; i++) {
const textAnswer = this.createAnswerText(this.data.answerArr[i], i + 1);
this.answerArr.push(textAnswer);
textAnswer.x = baseX + (i % 2) * offX;
textAnswer.y = baseY;
if (i % 2 === 1) {
baseY += offY;
}
}
}
private initPicAnswer() {
const answerNum = this.data.answerArr.length;
const disW = 10 * this.mapScale;
const picW = 300 * this.mapScale;
const baseX = this.canvasWidth / 2 - (picW * answerNum + disW * (answerNum - 1)) / 2 + picW / 2 ;
const baseY = this.canvasHeight - 150 * this.mapScale;
for (let i = 0; i < this.data.answerArr.length; i++) {
const textAnswer = this.createAnswerPic(this.data.answerArr[i], i + 1);
this.answerArr.push(textAnswer);
textAnswer.x = baseX + i * (picW + disW);
textAnswer.y = baseY;
}
}
private createAnswerText(answerData: any, id) {
const textBg = createSprite('text_bg');
textBg.setScaleXY(this.mapScale);
this.renderArr.push(textBg);
const textId = createSprite('text_' + id);
textBg.addChild(textId);
textId.x = -textBg.width / 2 + 29;
textId.y = -42;
const label = new Label();
label.text = answerData.text;
label.fontColor = '#393158';
label.fontSize = 50;
label.fontName = 'MMTextBook-Bold';
label.textAlign = 'center';
label.setMaxSize(textBg.width * 0.86);
label.refreshSize();
label.y = 9;
label.x = 12;
textBg.addChild(label);
textBg['answerRight'] = answerData.answerRight === '1' ? true : false;
if (textBg['answerRight']) {
const rightIcon = createSprite('text_bg_right');
textBg.addChild(rightIcon, -1);
rightIcon.x = 8.3;
rightIcon.y = 12;
rightIcon.alpha = 0;
textBg['rightIcon'] = rightIcon;
}
return textBg;
}
private clickedAnswer(answerArrElement: any) {
if (answerArrElement.answerRight) {
this.showAnswerRight(answerArrElement);
} else {
this.showAnswerWrong(answerArrElement);
}
}
private showAnswerRight(answerArrElement: any) {
tweenChange(answerArrElement['rightIcon'], {alpha: 1}, 0.5, () => {
this.checkGameEnd();
});
this.playAudio('right');
this.showOvenLight();
}
private showAnswerWrong(answerArrElement: any) {
shake(answerArrElement);
this.playAudio('wrong');
}
private checkGameEnd() {
for (let i = 0; i < this.answerArr.length; i++) {
if (this.answerArr[i].rightIcon && this.answerArr[i].rightIcon.alpha == 0) {
return;
}
}
this.gameEnd();
}
mapMove(event) {
private showOvenLight() {
if (this.ovenLight['tween']) {
this.ovenLight['tween'].stop();
}
this.ovenLight['tween'] = tweenChange(this.ovenLight, {alpha: 1}, 0.7, () => {
this.ovenLight['tween'] = tweenChange(this.ovenLight, {alpha: 0}, 0.7, () => {
}, TWEEN.Easing.Cubic.Out);
}, TWEEN.Easing.Cubic.Out);
}
mapUp(event) {
private createAnswerPic(data: any, id: number) {
const picBg = createSprite('pic_bg');
picBg.setScaleXY(this.mapScale);
this.renderArr.push(picBg);
const picIcon = createSprite('pic_icon');
picBg.addChild(picIcon);
picIcon.x = -picBg.width / 2 + 30;
picIcon.y = -picBg.height / 2 + 20;
const textId = createSprite('text_' + id);
picIcon.addChild(textId);
// textId.x = -picBg.width / 2 + 27;
textId.y = -12;
const maxW = 225;
const maxH = 140;
const pic = createSprite(data.pic_url);
pic.setScaleXY(getMinScale(pic, maxW, maxH));
pic.y = -6.5;
pic.x = 1;
picBg.addChild(pic);
picBg['answerRight'] = data.answerRight === '1' ? true : false;
if (picBg['answerRight']) {
const rightIcon = createSprite('pic_bg_right');
picBg.addChild(rightIcon, -1);
rightIcon.x = 0;
rightIcon.y = -6.5;
rightIcon.alpha = 0;
picBg['rightIcon'] = rightIcon;
}
return picBg;
}
private gameEnd() {
update() {
this.showEndPetal();
this.showCakeAnima();
// ----------------------------------------------------------
this.animationId = window.requestAnimationFrame(this.update.bind(this));
// 清除画布内容
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
// tween 更新动画
TWEEN.update();
// ----------------------------------------------------------
this.canTouch = false;
}
showEndPetal() {
this.setMaskLayer();
console.log('showEndPetal');
this.petalTime = 0;
this.showPetalFlag = true;
this.addPetal();
this.playAudio('finish');
this.updateArr(this.renderArr);
(<any> window).courseware.sendEvent('gameEnd');
setTimeout(() => {
this.showPetalFlag = false;
}, 6000);
}
setMaskLayer() {
const shapeRect = new ShapeRect();
shapeRect.fillColor = '#000000';
shapeRect.width = this.canvasWidth;
shapeRect.height = this.canvasHeight;
shapeRect.alpha = 0.5;
this.endPageArr = [shapeRect];
}
addPetal() {
if (!this.showPetalFlag) {
return;
}
const petal = this.getPetal();
this.endPageArr.push(petal);
moveItem(petal, petal.x, this.canvasHeight + petal.height * petal.scaleY, petal['time'], () => {
removeItemFromArr(this.endPageArr, petal);
});
rotateItem(petal, petal['tr'], petal['time']);
setTimeout(() => {
this.addPetal();
}, 0 + this.petalTime);
this.petalTime += 5;
}
getPetal() {
const petal = new MySprite();
const id = Math.ceil( Math.random() * 6 );
petal.init(this.images.get('petal_' + id));
const randomS = (Math.random() * 0.4 + 0.6) * this.mapScale;
petal.setScaleXY(randomS);
const randomR = Math.random() * 360;
petal.rotation = randomR;
const randomX = Math.random() * this.canvasWidth;
petal.x = randomX;
petal.y = -petal.height / 2 * petal.scaleY;
const randomT = 1 + Math.random() * 3;
petal['time'] = randomT;
let randomTR = 360 * Math.random(); // - 180;
if (Math.random() < 0.5) { randomTR *= -1; }
petal['tr'] = randomTR;
return petal;
}
private showCakeAnima() {
const cake = createSprite('finish_cake');
cake.x = this.canvasWidth / 2;
cake.y = this.canvasHeight / 2;
cake.setScaleXY(this.mapScale);
this.endPageArr.push(cake);
const light = createSprite('finish_light');
cake.addChild(light, -1);
rotateItem(light, 180, 4, null, null, true);
jellyPop(cake, 1);
}
}
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', "assets/play/bg.png"],
['oven', "assets/play/oven.png"],
['question_text_bg', "assets/play/question_text_bg.png"],
['light', "assets/play/light.png"],
['btn_play', "assets/play/player/btn_play.png"],
['btn_pause', "assets/play/player/btn_pause.png"],
['bar_top', "assets/play/player/bar_top.png"],
['bar_bottom', "assets/play/player/bar_bottom.png"],
['bar_btn', "assets/play/player/bar_btn.png"],
['player_cake', "assets/play/player/cake.png"],
['video_pause', "assets/play/video_pause.png"],
['video_play', "assets/play/video_play.png"],
['text_bg', "assets/play/text_bg.png"],
['text_bg_right', "assets/play/text_bg_right.png"],
['text_1', "assets/play/text_1.png"],
['text_2', "assets/play/text_2.png"],
['text_3', "assets/play/text_3.png"],
['text_4', "assets/play/text_4.png"],
['pic_bg', "assets/play/pic_bg.png"],
['pic_icon', "assets/play/pic_icon.png"],
['pic_bg_right', "assets/play/pic_bg_right.png"],
['finish_light', "assets/play/finish_light.png"],
['finish_cake', "assets/play/finish_cake.png"],
['petal_1', "assets/play/particle/1.png"],
['petal_2', "assets/play/particle/2.png"],
['petal_3', "assets/play/particle/3.png"],
['petal_4', "assets/play/particle/4.png"],
['petal_5', "assets/play/particle/5.png"],
['petal_6', "assets/play/particle/6.png"],
];
......@@ -11,7 +46,9 @@ const res = [
const resAudio = [
['click', "assets/play/music/click.mp3"],
['wrong', "assets/play/music/wrong.mp3"],
['right', "assets/play/music/right.mp3"],
['finish', "assets/play/music/finish.mp3"],
];
......
File mode changed from 100644 to 100755
src/assets/play/text_bg.png

293 Bytes | W: | H:

src/assets/play/text_bg.png

5.6 KB | W: | H:

src/assets/play/text_bg.png
src/assets/play/text_bg.png
src/assets/play/text_bg.png
src/assets/play/text_bg.png
  • 2-up
  • Swipe
  • Onion skin
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