Commit a4b75e80 authored by 范雪寒's avatar 范雪寒

feat: 功能基本完成。发布,等待测试

parent 1eab45d9
......@@ -6,3 +6,35 @@
height: 100%;
}
.border {
border-radius: 20px;
border-style: dashed;
padding: 20px;
margin: 20px;
/*width: 500px; */
/*//border-radius: 20px;*/
/*//border-width: 2px;*/
/*//border-color: #000000;*/
}
.border-lite {
border: 2px dashed #ddd;
border-radius: 0.5rem;
padding: 10px;
margin: 10px;
}
@font-face
{
font-family: 'MMTextBook-Bold';
src: url("../../assets/font/MMTextBook-Bold.otf") ;
}
@font-face
{
font-family: 'MMTextBook';
src: url("../../assets/font/MMTextBook.otf") ;
}
\ No newline at end of file
<div class="model-content">
<div class="border" style="width: 650px; height: 190px;">
<span style="float: left; height: 30px; font-size: 18px;">标题字母:</span>
<input type="text" style="width: 50px;" nz-input [(ngModel)]="item.tittle.word" (blur)="save()">
<br>
<br>
<span style="float: left; height: 30px; font-size: 18px;">标题:</span>
<input type="text" style="width: 550px;" nz-input [(ngModel)]="item.tittle.text" (blur)="save()">
<br>
<br>
<span style="float: left; height: 30px; font-size: 18px;">标题音频:</span>
<app-audio-recorder
[audioUrl]="item.tittle.audio"
(audioUploaded)="onTittleAudioUploadSuccess($event, 'audio_url')"
></app-audio-recorder>
</div>
<div class="border" style="width: 650px; height: 180px;">
<span style="float: left; height: 30px; font-size: 18px;">题目:</span>
<input type="text" style="width: 350px;" nz-input [(ngModel)]="item.questionsTittle" (blur)="save()">
<br>
<br>
<span style="float: left; height: 30px; font-size: 18px;">题目音频:</span>
<app-audio-recorder
[audioUrl]="item.audio"
(audioUploaded)="onWholeQuestionAudioUploadSuccess($event, 'audio_url')"
></app-audio-recorder>
<br>
<span style="float: left; height: 30px; font-size: 18px;">整体音频:</span>
<app-audio-recorder
[audioUrl]="item.audio"
(audioUploaded)="onWholeAudioUploadSuccess($event, 'audio_url')"
></app-audio-recorder>
</div>
<div *ngFor="let question of item.questions; let i = index" style="float: left;">
<div class="border">
<span style="height: 30px; font-size: 18px;">序号:</span>
<input type="text" style="width: 70px;" nz-input [(ngModel)]="question.questionTittle" (blur)="save()">
<br>
<br>
<span style="float: left; height: 30px; font-size: 18px;">行音频:</span>
<app-audio-recorder
[audioUrl]="question.audio"
(audioUploaded)="onQuestionAudioUploadSuccess($event, i)"
></app-audio-recorder>
<br>
<span style="height: 30px; font-size: 18px;">行全文:</span>
<input type="text" style="width: 500px;" nz-input [(ngModel)]="question.words" (blur)="clearWords(i)">
<br>
<br>
<span style="height: 30px; font-size: 16px;">点击下方单词选择加粗/变红:</span>
<br>
<div *ngFor="let word of words[i]; let j = index" style="float: left;">
<div>
<div *ngIf="(!word.block)">
<div *ngIf="(word.style == 'disable')">
<a style="font-size: 48px; font-family: MMTextBook; border:1px,#ff0000,solid; color:#070408; margin-right: 15px;">{{word.word}}</a>
</div>
<div *ngIf="(word.style == 'normal')">
<a style="font-size: 48px; font-family: MMTextBook; color:#070408; margin-right: 2px;" (click)="onWordClicked(i, j)">{{word.word}}</a>
</div>
</div>
<div *ngIf="(word.block)">
<div *ngIf="(word.style == 'normal')">
<a style="font-size: 48px; font-family: MMTextBook; color:#070408; margin-right: 2px;" (click)="onWordClicked(i, j)">{{word.word}}</a>
</div>
<div *ngIf="(word.style == 'red')">
<a style="font-size: 48px; font-family: MMTextBook; color:#c8161e; margin-right: 2px;" (click)="onWordClicked(i, j)">{{word.word}}</a>
</div>
<div *ngIf="(word.style == 'bold')">
<a style="font-size: 48px; font-family: MMTextBook; color:#070408; margin-right: 2px;" (click)="onWordClicked(i, j)"><b>{{word.word}}</b></a>
</div>
<div>
<nz-radio-group [(ngModel)]="word.style">
<label [nzValue]="'bold'" nz-radio (click)="radioClick(i, j, 'bold')" style="font-size: 22px;"><b>加粗</b></label>
<br>
<label [nzValue]="'red'" nz-radio (click)="radioClick(i, j, 'red')" style="font-size: 22px; color:#c8161e;">红色</label>
</nz-radio-group>
<div *ngIf="(word.style == 'red')">
<app-audio-recorder
[audioUrl]="word.audio"
(audioUploaded)="onWordAudioUploadSuccess($event, i, j)"
></app-audio-recorder>
<app-upload-image-with-preview
[picUrl]="word.img"
(imageUploaded)="onImageUploadSuccess($event, i, j)"
></app-upload-image-with-preview>
</div>
</div>
<br>
<br>
</div>
</div>
</div>
<br>
<br>
<div *ngIf="(item.questions.length > 6)">
<div style="padding-top: 30px;">
<button style="width: 100%; height: 35px; float: none;" nz-button nzType="dashed" class="add-btn" (click)="deleteQuestion(i)">
删除
</button>
</div>
</div>
<div *ngIf="(item.questions.length == 6)">
<div style="padding-top: 5px;">
<img src="assets/play/Img_white.jpg" style="width: 100%; height: 5px; float: none;"/>
</div>
</div>
</div>
</div>
<div *ngIf="(item.questions.length < 16)">
<div style="float: left; width: 650px; height: 200px; padding: 20px;" nz-col nzSpan="8" class="add-btn-box" >
<button style=" margin: auto; width: 100%; height: 100%;" nz-button nzType="dashed" class="add-btn" (click)="addQuestion()">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>
Add
</button>
</div>
</div>
<!--
<div style="position: absolute; left: 200px; top: 100px; width: 800px;">
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()">
......@@ -18,7 +137,7 @@
<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>
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';
@Component({
selector: 'app-form',
......@@ -10,28 +8,62 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap
export class FormComponent implements OnInit, OnChanges, OnDestroy {
// 储存数据用
saveKey = "test_0011";
saveKey = "ym-2-32";
// 储存对象
item;
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) {
}
constructor(private appRef: ApplicationRef, private changeDetectorRef: ChangeDetectorRef) { }
ngOnInit() {
this.item = {};
this.item = {
tittle: {
word: "",
text: "",
audio: ""
},
audio: '',
questions: [{
questionTittle: '',
words: "",
audio: '',
blocks: [],
},{
questionTittle: '',
words: "",
audio: '',
blocks: [],
},{
questionTittle: '',
words: "",
audio: '',
blocks: [],
},{
questionTittle: '',
words: "",
audio: '',
blocks: [],
},{
questionTittle: '',
words: "",
audio: '',
blocks: [],
},{
questionTittle: '',
words: "",
audio: '',
blocks: [],
}],
};
// 获取存储的数据
(<any> window).courseware.getData((data) => {
(<any>window).courseware.getData((data) => {
if (data) {
this.item = data;
}
this.init();
this.updateWords();
this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges();
this.refresh();
......@@ -40,6 +72,76 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}
onWordClicked(questionIdx, wordIdx) {
let findIdx = this.item.questions[questionIdx].blocks.findIndex((block) => block.idx == wordIdx);
if (findIdx == -1) {
this.addBlock(questionIdx, wordIdx);
} else {
this.item.questions[questionIdx].blocks.splice(findIdx, 1);
}
this.save();
}
addQuestion() {
this.item.questions.push({
questionTittle: '',
words: "",
audio: '',
blocks: [],
});
this.save();
}
deleteQuestion(idx) {
this.item.questions.splice(idx, 1);
this.save();
}
// 标题音频
onTittleAudioUploadSuccess(e, key) {
this.item.tittle.audio = e.url;
this.save();
}
onWholeAudioUploadSuccess(e, idx) {
this.item.audio = e.url;
this.save();
}
onWholeQuestionAudioUploadSuccess(e, idx) {
this.item.tittleAudio = e.url;
this.save();
}
onQuestionAudioUploadSuccess(e, idx) {
this.item.questions[idx].audio = e.url;
this.save();
}
onWordAudioUploadSuccess(e, questionIdx, wordIdx) {
let block = this.item.questions[questionIdx].blocks.find(block => block.idx == wordIdx);
if (block) {
block.audio = e.url;
}
this.save();
}
addBlock(questionIdx, wordIdx) {
this.item.questions[questionIdx].blocks.push({
idx: wordIdx,
type: 'none',
audio: '',
img: '',
});
}
radioClick(questionIdx, wordIdx, style) {
let block = this.item.questions[questionIdx].blocks.find(block => block.idx == wordIdx);
if (block) {
if (block.type == style) {
block.type = 'none';
} else {
block.type = style;
}
}
this.save();
}
ngOnChanges() {
}
......@@ -58,9 +160,11 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
* 储存图片数据
* @param e
*/
onImageUploadSuccess(e, key) {
this.item[key] = e.url;
onImageUploadSuccess(e, questionIdx, wordIdx) {
let block = this.item.questions[questionIdx].blocks.find(block => block.idx == wordIdx);
if (block) {
block.img = e.url;
}
this.save();
}
......@@ -74,13 +178,68 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
this.save();
}
words = [[]];
updateWords() {
this.words = [];
this.item.questions.forEach((quesiton, idx) => {
this.words.push([]);
if (quesiton.words == '') {
return;
}
this.words[idx].push(...quesiton.words.match(/(([a-z]|[A-Z]|[0-9]|'|-|&|_)+|.)/g).map((word, wordIdx) => {
let disable = true;
let block = false;
let color = false;
let bold = false;
let audio = '';
let img = '';
let findIdx = quesiton.blocks.findIndex((block) => block.idx == wordIdx);
if (findIdx != -1) {
block = true;
color = quesiton.blocks[findIdx].type == 'red';
bold = quesiton.blocks[findIdx].type == 'bold';
audio = quesiton.blocks[findIdx].audio;
img = quesiton.blocks[findIdx].img;
}
if (word.match(/(([a-z]|[A-Z]|[0-9])+)/)) {
disable = false;
}
let style = 'normal';
if (color) {
style = 'red';
}
if (bold) {
style = 'bold';
}
if (disable) {
style = 'disable';
block = false;
}
return {
word: word,
block: block,
style: style,
audio: audio,
img: img,
}
}));
});
}
clearWords(questionIdx) {
this.save();
}
/**
* 储存数据
*/
save() {
(<any> window).courseware.setData(this.item, null, this.saveKey);
(<any>window).courseware.setData(this.item, null, this.saveKey);
this.updateWords();
this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges();
this.refresh();
}
......
......@@ -6,218 +6,98 @@ export let defaultData = {
audio: "tittle"
},
audio: 'total_audio',
audio: 'whole',
questionsTittle: 'A pig and a bin',
tittleAudio: 'total_audio',
questionsTittle: 'Horse, king and artist.',
tittleAudio: 'Horse, king and artist',
questions: [{
questionTittle: '1',
words: "Let 's put the toys into the box. box. box.",
audio: 'question_1',
words: "Long, long ago there lived a king.",
audio: 'line1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
idx: 7,
type: 'bold'
}],
}, {
questionTittle: '2',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'He loved horses.',
audio: 'line2',
blocks: [],
}, {
questionTittle: '3',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'One day he asked an artist to draw him a beautiful horse.',
audio: 'line3',
blocks: [],
}, {
questionTittle: '3',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'The artist said, "All right, but you must wait."',
audio: 'line4',
blocks: [],
}, {
questionTittle: '3',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'So the king waited.',
audio: 'line5',
blocks: [],
}, {
questionTittle: '3',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'He waited and waited.',
audio: 'line6',
blocks: [],
}, {
questionTittle: '3',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'At last, after a year he could not wait any longer.',
audio: 'line7',
blocks: [],
}, {
questionTittle: '3',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'He went to see the artist himself.',
audio: 'line8',
blocks: [],
}, {
questionTittle: '3',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'Quickly the artist brought out paper and a brush.',
audio: 'line9',
blocks: [],
}, {
questionTittle: '4',
words: "Let 's go.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'In five minutes he finished drawing a very beautiful horse.',
audio: 'line10',
blocks: [],
}, {
questionTittle: '',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'The king was angry.',
audio: 'line11',
blocks: [],
}, {
questionTittle: '5',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: '"You can draw a good horse in five minutes,yet you kept me waiting for a year.Why?"',
audio: 'line12',
blocks: [],
}, {
questionTittle: '6',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: '"baiCome with me, please," said the artist.',
audio: 'line13',
blocks: [],
}, {
questionTittle: '7',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'They went to the artist’s workroom.',
audio: 'line14',
blocks: [],
}, {
questionTittle: '8',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'There the king saw piles and piles of paper.',
audio: 'line15',
blocks: [],
}, {
questionTittle: '9',
words: "Let 's put the toys into the box.",
audio: 'question_1',
blocks: [{
idx: 5,
type: 'red',
audio: 'the',
img: 'cave'
}, {
idx: 6,
type: 'bold'
}],
words: 'On every piece of paper was a picture of a horse.',
audio: 'line16',
blocks: [],
}]
};
\ No newline at end of file
......@@ -49,9 +49,11 @@ export class MyGame extends Game {
let imgUrlList = [];
let audioUrlList = [];
imgUrlList.push(...this.data.questions.map(question => question.blocks.map(block => block.img)).flat(Infinity));
imgUrlList = imgUrlList.filter((data) => data != null && data != '');
audioUrlList.push(this.data.audio);
audioUrlList.push(this.data.tittleAudio);
audioUrlList.push(this.data.tittle.audio);
audioUrlList.push(...this.data.questions.map(question => question.audio));
audioUrlList.push(...this.data.questions.map(question => question.blocks.map(block => block.audio)).flat(Infinity));
......@@ -231,12 +233,15 @@ export class MyGame extends Game {
scrollViewBg.scaleX = 1200 / scrollViewBg.width;
scrollViewBg.scaleY = 580 / scrollViewBg.height;
scrollViewBg.setPosition(0, this.bg.height / 2 + 100);
scrollViewBg.addTouchBeganListener(this.onScrollViewBgTouchBegan.bind(this));
scrollViewBg.addTouchMoveListener(this.onScrollViewBgTouchMoved.bind(this));
scrollViewBg.alpha = 0.1;
scrollViewBg.setName('scrollViewBg');
this.bg.addChild(scrollViewBg);
if (this.data.questions.length > 6) {
scrollViewBg.addTouchBeganListener(this.onScrollViewBgTouchBegan.bind(this));
scrollViewBg.addTouchMoveListener(this.onScrollViewBgTouchMoved.bind(this));
}
let scrollBaseNode = new TouchSprite();
scrollBaseNode.init(this.images.get('Img_white'));
scrollBaseNode.anchorX = 0.5;
......@@ -259,14 +264,9 @@ export class MyGame extends Game {
question.words.match(/(([a-z]|[A-Z]|[0-9]|'|-|&|_)+|.)/g).forEach((word, wordIdx) => {
let block = question.blocks.find(block => block.idx == wordIdx);
let posX = labelList.reduce((offsetX, label) => offsetX + label.width * label.scaleX, 0);
let posX = labelList.reduce((offsetX, label, labelIdx) => {
if (labelIdx < wordIdx) {
return offsetX + label.width;
} else {
return offsetX;
}
}, 0);
console.log('posX = ' + posX);
let questionLabel = new MyLabel();
questionLabel.fontSize = 42;
......@@ -279,6 +279,7 @@ export class MyGame extends Game {
if (match && block && block.type == 'bold') {
questionLabel.fontName = 'MMTextBook-Bold';
}
questionLabel.refreshSize();
if (match && block && block.type == 'red') {
questionLabel.fontColor = '#c8161e';
questionLabel.set('audio', block.audio);
......@@ -286,9 +287,17 @@ export class MyGame extends Game {
let labelImg = new TouchSprite();
labelImg.init(this.images.get(block.img));
labelImg.anchorX = 0;
labelImg.setScaleXY(48 / labelImg.height);
labelImg.setPositionX(posX + questionLabel.width);
labelImg.alpha = 0;
baseNode.addChild(labelImg);
questionLabel.set('img', labelImg);
labelList.push(labelImg);
}
questionLabel.refreshSize();
questionLabel.setPositionX(posX + questionLabel.width / 2);
baseNode.addChild(questionLabel, 2);
labelList.push(questionLabel);
......@@ -309,7 +318,7 @@ export class MyGame extends Game {
}
if (question.audio != '') {
let offsetX = labelList.reduce((offsetX, label) => { return offsetX + label.width }, 0);
let offsetX = labelList.reduce((offsetX, label) => { return offsetX + label.width * label.scaleX }, 0);
this._createSpeacker(
this.images.get('Btn_s_play'),
this.images.get('Btn_s_pause'),
......@@ -325,16 +334,14 @@ export class MyGame extends Game {
}
onClickWord(block) {
this.playAudio(block.get('audio'));
if (block.get('moved')) {
return;
}
block.set('moved', true);
block.setScaleXY(3);
tweenChange(block, { scaleX: 1, scaleY: 1 }, 0.5, () => {
this.playAudio(block.get('audio'));
}, TWEEN.Easing.Cubic.In);
tweenChange(block, { alpha: 1 }, 0.5, null, TWEEN.Easing.Quintic.In);
let labelImg = block.get('img');
tweenChange(labelImg, { alpha: 1 }, 0.5, null, TWEEN.Easing.Quintic.In);
}
createScrollBar() {
......
......@@ -13,18 +13,43 @@ const res = [
['Img_scroll_bg', "assets/play/Img_scroll_bg.png"],
['Img_scroll_bar', "assets/play/Img_scroll_bar.png"],
['cave', "assets/play/default/cave.png"],
];
const resAudio = [
['audio_new_page', "assets/play/audio_new_page.mp3"],
['Horse, king and artist', "assets/play/default/Horse, king and artist.mp3"],
['into', "assets/play/default/into.mp3"],
['let', "assets/play/default/let.mp3"],
['line1', "assets/play/default/line1.mp3"],
['line2', "assets/play/default/line2.mp3"],
['line3', "assets/play/default/line3.mp3"],
['line4', "assets/play/default/line4.mp3"],
['line5', "assets/play/default/line5.mp3"],
['line6', "assets/play/default/line6.mp3"],
['line7', "assets/play/default/line7.mp3"],
['line8', "assets/play/default/line8.mp3"],
['line9', "assets/play/default/line9.mp3"],
['line10', "assets/play/default/line10.mp3"],
['line11', "assets/play/default/line11.mp3"],
['line12', "assets/play/default/line12.mp3"],
['line13', "assets/play/default/line13.mp3"],
['line14', "assets/play/default/line14.mp3"],
['line15', "assets/play/default/line15.mp3"],
['line16', "assets/play/default/line16.mp3"],
['line17', "assets/play/default/line17.mp3"],
['put', "assets/play/default/put.mp3"],
['question_1', "assets/play/default/question_1.mp3"],
['the', "assets/play/default/the.mp3"],
['tittle', "assets/play/default/tittle.mp3"],
['question_1', "assets/play/default/question_1.mp3"],
['total_audio', "assets/play/default/total_audio.mp3"],
['whole', "assets/play/default/whole.mp3"],
];
export { res, resAudio };
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