Commit 25544071 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": "c98da0cb-87a0-4cb4-8a5d-5f3f3012ad61"
}
}
\ 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 SentenceBean extends Obj{
renderTo = "";
letterArr = [];
}
export function getDefaultSentence(){
let sentence = new SentenceBean();
return sentence;
}
export class LetterBean extends Obj{
fontColor = "#000000";
}
export function getDefaultLetter(){
let letter = new LetterBean();
return letter;
}
\ 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
...@@ -1959,6 +1959,8 @@ export class HotZoneItem extends MySprite { ...@@ -1959,6 +1959,8 @@ export class HotZoneItem extends MySprite {
private _itemType; private _itemType;
private shapeRect: ShapeRect; private shapeRect: ShapeRect;
key;
get itemType() { get itemType() {
return this._itemType; return this._itemType;
} }
......
<div class="p-image-children-editor"> <div class="p-image-children-editor">
<h5 style="margin-left: 2.5%;"> preview: </h5> <h5 style="margin-left: 2.5%;">右侧图片</h5>
<div class="preview-box" #wrap> <div class="preview-box" #wrap>
<canvas id="canvas" #canvas></canvas> <canvas id="canvas" #canvas></canvas>
</div> </div>
<div nz-row nzType="flex" nzAlign="middle"> <div nz-row nzType="flex" nzAlign="middle">
<div nz-col nzSpan="5" nzOffset="1"> <div nz-col nzSpan="3" nzOffset="1">
<h5> add background: </h5> <h5>请上传一张图片</h5>
<div class="bg-box"> <div class="bg-box">
<app-upload-image-with-preview <app-upload-image-with-preview
...@@ -24,8 +24,7 @@ ...@@ -24,8 +24,7 @@
<div <div
style="margin: auto; padding: 5px; margin-top: 30px; width:90%; border: 2px dashed #ddd; border-radius: 10px"> style="margin: auto; padding: 5px; margin-top: 30px; width:90%; border: 2px dashed #ddd; border-radius: 10px">
<span style="margin-left: 40%;"> item-{{i + 1}} <span>序号区域-{{i + 1}}</span>
</span>
<button style="float: right;" nz-button nzType="danger" nzSize="small" (click)="deleteBtnClick(i)"> <button style="float: right;" nz-button nzType="danger" nzSize="small" (click)="deleteBtnClick(i)">
X X
</button> </button>
...@@ -34,29 +33,7 @@ ...@@ -34,29 +33,7 @@
<div style="margin-top: -20px; margin-bottom: 5px"> <div style="margin-top: -20px; margin-bottom: 5px">
<nz-radio-group [ngModel]="it.itemType" (ngModelChange)="radioChange($event, it)"> <input type="text" nz-input [(ngModel)]="it.text" (ngModelChange)="changeText(it)">
<label *ngIf="isHasRect" nz-radio nzValue="rect">矩形</label>
<label *ngIf="isHasPic" nz-radio nzValue="pic">图片</label>
<label *ngIf="isHasText" nz-radio nzValue="text">文本</label>
</nz-radio-group>
</div>
<div *ngIf="it.itemType == 'pic'">
<app-upload-image-with-preview
[picUrl]="it?.pic_url"
(imageUploaded)="onItemImgUploadSuccess($event, it)">
</app-upload-image-with-preview>
</div>
<div *ngIf="it.itemType == 'text'">
<input type="text" nz-input [(ngModel)]="it.text" (blur)="saveText(it)">
</div>
<div style="width: 100%; margin-top: 5px;">
<app-audio-recorder
[audioUrl]="it.audio_url"
(audioUploaded)="onItemAudioUploadSuccess($event, it)"
></app-audio-recorder>
</div> </div>
</div> </div>
...@@ -64,27 +41,24 @@ ...@@ -64,27 +41,24 @@
</div> </div>
<div nz-col nzSpan="5" nzOffset="1"> <div nz-col nzSpan="3" nzOffset="1">
<div class="bg-box"> <div class="bg-box">
<button nz-button nzType="dashed" (click)="addBtnClick()" <button nz-button nzType="dashed" (click)="addBtnClick()"
class="add-btn"> class="add-btn">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i> <i nz-icon nzType="plus-circle" nzTheme="outline"></i>
<!--Add Image--> 添加序号
Add hot zone
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<nz-divider></nz-divider> <nz-divider></nz-divider>
<div class="save-box"> <div class="save-box">
<button class="save-btn" nz-button nzType="primary" [nzSize]="'large'" nzShape="round" <button class="save-btn" nz-button nzType="primary" [nzSize]="'large'" nzShape="round"
(click)="saveClick()" > (click)="saveClick()" [disabled]="saveDisabled ? true : false">
<i nz-icon nzType="save"></i> <i nz-icon nzType="save"></i>
Save Save
</button> </button>
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
.preview-box { .preview-box {
margin: auto; margin: auto;
width: 95%; width: 371px;
height: 35vw; height: 539px;
border: 2px dashed #ddd; border: 2px dashed #ddd;
border-radius: 0.5rem; border-radius: 0.5rem;
......
...@@ -57,11 +57,11 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -57,11 +57,11 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
saveDisabled = true; saveDisabled = true;
canvasWidth = 1280; canvasWidth = 371;
canvasHeight = 720; canvasHeight = 539;
canvasBaseW = 1280; canvasBaseW = 371;
// @HostListener('window:resize', ['$event']) // @HostListener('window:resize', ['$event'])
canvasBaseH = 720; canvasBaseH = 539;
mapScale = 1; mapScale = 1;
ctx; ctx;
mx; mx;
...@@ -128,18 +128,24 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -128,18 +128,24 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
onBackgroundUploadSuccess(e) { onBackgroundUploadSuccess(e) {
console.log('e: ', e); //console.log('e: ', e);
this.bgItem.url = e.url; this.bgItem.url = e.url;
this.refreshBackground(); this.refreshBackground();
this.saveDisabled = false;
} }
onItemImgUploadSuccess(e, item) { onItemImgUploadSuccess(e, item) {
item.pic_url = e.url; item.pic_url = e.url;
this.loadHotZonePic(item.pic, e.url); this.loadHotZonePic(item.pic, e.url);
this.saveDisabled = false;
} }
onItemAudioUploadSuccess(e, item) { onItemAudioUploadSuccess(e, item) {
item.audio_url = e.url; item.audio_url = e.url;
this.saveDisabled = false;
} }
...@@ -152,7 +158,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -152,7 +158,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
const bg = this.bg; const bg = this.bg;
if (this.bgItem.url) { if (this.bgItem.url) {
bg.load(this.bgItem.url).then(() => { bg.load(this.bgItem.url).then(() => {
const rate1 = this.canvasWidth / bg.width; const rate1 = this.canvasWidth / bg.width;
const rate2 = this.canvasHeight / bg.height; const rate2 = this.canvasHeight / bg.height;
...@@ -178,27 +184,35 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -178,27 +184,35 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
// this.hotZoneArr.push({}); // this.hotZoneArr.push({});
const item = this.getHotZoneItem(); const item = this.getHotZoneItem();
item.key = 'key_' + new Date().getTime();
this.hotZoneArr.push(item); this.hotZoneArr.push(item);
this.hotZoneArr = [...this.hotZoneArr];
this.refreshItem(item); this.refreshItem(item);
this.refreshHotZoneId(); this.refreshHotZoneId();
this.saveDisabled = false;
} }
deleteBtnClick(index) { deleteBtnClick(index) {
const item = this.hotZoneArr.splice(index, 1)[0]; const item = this.hotZoneArr.splice(index, 1)[0];
removeItemFromArr(this.renderArr, item.pic); removeItemFromArr(this.renderArr, item.pic);
removeItemFromArr(this.renderArr, item.textLabel); removeItemFromArr(this.renderArr, item.textLabel);
this.hotZoneArr = [...this.hotZoneArr];
this.refreshHotZoneId(); this.refreshHotZoneId();
this.saveDisabled = false;
} }
onImgUploadSuccessByImg(e, img) { onImgUploadSuccessByImg(e, img) {
img.pic_url = e.url; img.pic_url = e.url;
this.refreshImage(img); this.refreshImage(img);
this.saveDisabled = false;
} }
refreshImage(img) { refreshImage(img) {
...@@ -217,8 +231,8 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -217,8 +231,8 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
this.hotZoneArr[i].index = i; this.hotZoneArr[i].index = i;
if (this.hotZoneArr[i]) { if (this.hotZoneArr[i]) {
this.hotZoneArr[i].title = 'item-' + (i + 1); this.hotZoneArr[i].title = this.hotZoneArr[i].text;
this.hotZoneArr[i].showLineDash();
} }
} }
} }
...@@ -238,8 +252,8 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -238,8 +252,8 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
getHotZoneItem(saveData = null) { getHotZoneItem(saveData = null) {
const itemW = 200; const itemW = 50;
const itemH = 200; const itemH = 50;
const item = new HotZoneItem(this.ctx); const item = new HotZoneItem(this.ctx);
item.setSize(itemW, itemH); item.setSize(itemW, itemH);
item.anchorX = 0.5; item.anchorX = 0.5;
...@@ -257,7 +271,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -257,7 +271,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
item.scaleY = saveRect.height / item.height; item.scaleY = saveRect.height / item.height;
item.x = saveRect.x + saveRect.width / 2; item.x = saveRect.x + saveRect.width / 2;
item.y = saveRect.y + saveRect.height / 2; item.y = saveRect.y + saveRect.height / 2;
item.text = saveData.text;
} }
item.showLineDash(); item.showLineDash();
...@@ -337,14 +351,22 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -337,14 +351,22 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
onAudioUploadSuccessByImg(e, img) { onAudioUploadSuccessByImg(e, img) {
img.audio_url = e.url; img.audio_url = e.url;
this.saveDisabled = false;
}
onAudioUploadSuccess(e, item, key) {
item[key] = e.url;
this.saveDisabled = false;
} }
deleteItem(e, i) { deleteItem(e, i) {
// this.imgArr.splice(i , 1);
// this.refreshImageId();
this.hotZoneArr.splice(i, 1); this.hotZoneArr.splice(i, 1);
this.refreshHotZoneId(); this.refreshHotZoneId();
this.saveDisabled = false;
} }
...@@ -353,7 +375,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -353,7 +375,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
this.refreshItem(item); this.refreshItem(item);
// console.log(' in radioChange e: ', e); this.saveDisabled = false;
} }
refreshItem(item) { refreshItem(item) {
...@@ -449,9 +471,10 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -449,9 +471,10 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
item.pic_url = data.pic_url; item.pic_url = data.pic_url;
item.text = data.text; item.text = data.text;
item.itemType = data.itemType; item.itemType = data.itemType;
item.key = data.key;
this.refreshItem(item); this.refreshItem(item);
console.log('item: ', item);
this.hotZoneArr.push(item); this.hotZoneArr.push(item);
} }
...@@ -582,7 +605,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -582,7 +605,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
this.oldPos = {x: this.mx, y: this.my}; this.oldPos = {x: this.mx, y: this.my};
this.saveDisabled = true; this.saveDisabled = false;
} }
...@@ -880,7 +903,8 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -880,7 +903,8 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
fontColor: this.hotZoneFontObj.color, fontColor: this.hotZoneFontObj.color,
fontScale: hotZoneArr[i].textLabel ? hotZoneArr[i].textLabel.scaleX : 1, fontScale: hotZoneArr[i].textLabel ? hotZoneArr[i].textLabel.scaleX : 1,
imgScale: hotZoneArr[i].pic ? hotZoneArr[i].pic.scaleX : 1, imgScale: hotZoneArr[i].pic ? hotZoneArr[i].pic.scaleX : 1,
mapScale: this.mapScale mapScale: this.mapScale,
key:hotZoneArr[i].key
}; };
hotZoneItem['rect'] = hotZoneArr[i].getBoundingBox(); hotZoneItem['rect'] = hotZoneArr[i].getBoundingBox();
hotZoneItem['rect'].x = Math.round((hotZoneItem['rect'].x - bgItem['rect'].x) * 100) / 100; hotZoneItem['rect'].x = Math.round((hotZoneItem['rect'].x - bgItem['rect'].x) * 100) / 100;
...@@ -892,9 +916,11 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -892,9 +916,11 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
hotZoneItemArr.push(hotZoneItem); hotZoneItemArr.push(hotZoneItem);
} }
console.log('hotZoneItemArr: ', hotZoneItemArr); //console.log('hotZoneItemArr: ', hotZoneItemArr);
this.save.emit({bgItem, hotZoneItemArr}); this.save.emit({bgItem, hotZoneItemArr});
this.saveDisabled = true;
} }
private updatePos() { private updatePos() {
...@@ -983,4 +1009,14 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ...@@ -983,4 +1009,14 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
pic.setScaleXY(s); pic.setScaleXY(s);
}); });
} }
changeText(hotZoneItem = null){
if(hotZoneItem){
hotZoneItem.title = hotZoneItem.text;
hotZoneItem.showLineDash();
}
this.saveDisabled = false;
}
} }
<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]="15" nzOffset="3">
[picUrl]="item.pic_url" <div nz-form>
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')" <div id='title-anchor'>
></app-upload-image-with-preview> <nz-divider nzText="课程名称" nzOrientation="left"></nz-divider>
<nz-form-item>
<app-audio-recorder <nz-form-label [nzSpan]="3" nzFor="part1">标题1</nz-form-label>
[audioUrl]="item.audio_url" <nz-form-control [nzSpan]="6">
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url')" <nz-input-group nzAddOnBefore="Part">
></app-audio-recorder> <input type="text" id="part1" nz-input [(ngModel)]="item.title.part1" (blur)="save()">
<app-custom-hot-zone></app-custom-hot-zone> </nz-input-group>
<app-upload-video></app-upload-video> </nz-form-control>
<app-lesson-title-config></app-lesson-title-config> </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>
</div>
<div id='listen-anchor'>
<nz-divider nzText="听力材料" nzOrientation="left"></nz-divider>
<nz-form-item>
<nz-form-control [nzSpan]="6" nzOffset="3">
<app-audio-recorder id="item.listenAudioUrl" [audioUrl]="item.listenAudioUrl"
(audioUploaded)="onAudioUploadSuccess($event, item, 'listenAudioUrl')">
</app-audio-recorder>
</nz-form-control>
</nz-form-item>
</div>
</div>
</div>
</div>
<br>
<br>
<div nz-row>
<div nz-col [nzSpan]="15" nzOffset="2">
<app-custom-hot-zone [bgItem]="item.bgItem" [hotZoneItemArr]="item.hotZoneItemArr" [defaultItemType]="'rect'"
(save)="saveData($event, item)"></app-custom-hot-zone>
</div>
</div> </div>
<br>
<div nz-row>
<div nz-col [nzSpan]="24">
<nz-card [nzExtra]="actionAdd" [nzActions]="[actionSetting]" nzTitle="句子">
<nz-form-item>
<nz-form-label [nzSpan]="3" nzFor="titleVal">标题</nz-form-label>
<nz-form-control [nzSpan]="6">
<input nz-input type="text" id="titleVal" [(ngModel)]="item.titleVal" (blur)="save()">
</nz-form-control>
</nz-form-item>
<div *ngFor="let data of item.sentenceArr; let i=index" style="padding: 0.5vw;" nz-col [nzXs]='24' [nzSm]='20'
[nzMd]='20' [nzLg]='20'>
<nz-card nzTitle="句子-{{i+1}}" [nzHoverable]="true" [nzExtra]="actionDelSentence">
<nz-form-item>
<nz-form-label [nzSpan]="3">所属序号</nz-form-label>
<nz-form-control [nzSpan]="3">
<div *ngFor="let hotZoneItem of this.item.hotZoneItemArr">
<div *ngIf="(hotZoneItem.key == data.renderTo)">{{hotZoneItem.text}}</div>
</div>
</nz-form-control>
<nz-form-control [nzSpan]="12">
<button nz-button nzType="dashed" (click)="setIndexBtnClick(data)" style="margin-right: 10px">
<i nz-icon nzType="tool" nzTheme="outline"></i>
配置序号
</button>
<button nz-button nzType="danger" (click)="resetSentence(data)">
<i nz-icon nzType="delete" nzTheme="outline"></i>重置
</button>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="3">音频</nz-form-label>
<nz-form-control [nzSpan]="5">
<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]="3">语句</nz-form-label>
<nz-form-control [nzSpan]="10">
<textarea rows="4" nz-input [(ngModel)]="data.val" (blur)="saveContent(data)"></textarea>
</nz-form-control>
</nz-form-item>
<nz-divider nzText="点击字母设置变红" nzOrientation="left"></nz-divider>
<nz-form-item>
<nz-form-control [nzSpan]="20">
<div *ngFor="let letter of data.letterArr; let j = index" style="float: left;">
<a [ngStyle]="{'float': 'left','font-size': '42px','font-family': 'GOTHICB','color':letter.fontColor, 'margin-right': '2px'}"
(click)="clickLetter(letter, j)">{{letter.val == ' ' ? '&nbsp;' : letter.val}}</a>
</div>
</nz-form-control>
</nz-form-item>
</nz-card>
<ng-template #actionDelSentence>
<button nz-button nzType="danger" (click)="delSentence(item,i)">
<i nz-icon nzType="delete" nzTheme="outline"></i>删除
</button>
</ng-template>
</div>
</nz-card>
<ng-template #actionAdd>
<button nz-button nzType="dashed" class="add-btn" id="add-btn" (click)="addSentence(item)">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
</button>
</ng-template>
<ng-template #actionSetting>
<button nz-button nzType="dashed" class="add-btn" id="add-btn" (click)="addSentence(item)">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
</button>
</ng-template>
</div>
</div>
<nz-modal [(nzVisible)]="indexPanelVisible" nzTitle="序号选择" (nzOnCancel)="indexPanelCancel()" (nzOnOk)="indexPanelOk()"
nzOkText="保存">
<nz-radio-group [(ngModel)]="renderTo">
<label nz-radio [nzValue]="option.key"
*ngFor="let option of hotZoneItemArr; let j = index">序号-({{option.text}})</label>
</nz-radio-group>
</div> </nz-modal>
</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 { getDefaultLetter, getDefaultSentence } from '../bean/SentenceBean';
import { getDefaultTile } from '../bean/TitleBean';
...@@ -10,12 +12,19 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap ...@@ -10,12 +12,19 @@ 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-17";
// 储存对象 // 储存对象
item; item;
indexPanelVisible = false;
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) { curSentence;
renderTo = "";
hotZoneItemArr = [];
constructor(private appRef: ApplicationRef, private changeDetectorRef: ChangeDetectorRef) {
} }
...@@ -24,13 +33,21 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -24,13 +33,21 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
this.item = {}; this.item = {};
this.item.title = getDefaultTile();
this.item.hotZoneItemArr = [];
this.item.sentenceArr = [];
this.curSentence = {};
// 获取存储的数据 // 获取存储的数据
(<any> window).courseware.getData((data) => { (<any>window).courseware.getData((data) => {
if (data) { if (data) {
this.item = data; this.item = data;
} }
console.log('data:' , data);
this.init(); this.init();
this.changeDetectorRef.markForCheck(); this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges(); this.changeDetectorRef.detectChanges();
...@@ -50,6 +67,17 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -50,6 +67,17 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
init() { init() {
if (!this.item.title) {
this.item.title = getDefaultTile();
}
if (!this.item.hotZoneItemArr) {
this.item.hotZoneItemArr = [];
}
if (!this.item.sentenceArr) {
this.item.sentenceArr = [];
}
} }
...@@ -58,29 +86,56 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -58,29 +86,56 @@ 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();
} }
saveData(e, item) {
const { bgItem, hotZoneItemArr } = e;
item.bgItem = bgItem;
item.hotZoneItemArr = hotZoneItemArr;
this.save();
}
addSentence(item) {
let sentence = getDefaultSentence();
item.sentenceArr.push(sentence);
this.save();
}
delSentence(item, index) {
if (index !== -1) {
item.sentenceArr.splice(index, 1);
item.sentenceArr = [...item.sentenceArr];
this.save();
}
}
/** /**
* 储存数据 * 储存数据
*/ */
save() { save() {
(<any> window).courseware.setData(this.item, null, this.saveKey); (<any>window).courseware.setData(this.item, null, this.saveKey);
this.refresh(); this.refresh();
} }
...@@ -93,5 +148,101 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -93,5 +148,101 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}, 1); }, 1);
} }
saveContent(item) {
let val = "";
if(!item.letterArr){
item.letterArr = [];
}
for (let i = 0; i < item.letterArr.length; ++i) {
val += item.letterArr[i].val;
}
//值发生改变,则重新处理数据
if (item.val != val) {
item.letterArr = [];
for (let i = 0; i < item.val.length; ++i) {
let letter = getDefaultLetter();
letter.val = item.val.charAt(i);
item.letterArr.push(letter);
}
}
this.save();
}
resetSentence(item){
item.renderTo = "";
this.save();
}
clickLetter(letter, i) {
if(letter.fontColor == "#000000"){
letter.fontColor = "#c8171e";
}
else{
letter.fontColor = "#000000";
}
this.save();
}
setIndexBtnClick(item) {
this.curSentence = item;
this.renderTo = item.renderTo;
this.indexPanelVisible = true;
this.hotZoneItemArr = [];
for(let i = 0; i < this.item.hotZoneItemArr.length; ++ i){
let hotZoneItem = this.item.hotZoneItemArr[i];
if(item.renderTo == hotZoneItem.key){
this.hotZoneItemArr.push(hotZoneItem);
continue;
}
let exist = false;
for(let j = 0; j < this.item.sentenceArr.length; ++ j){
let sentence = this.item.sentenceArr[j];
if(sentence.renderTo == hotZoneItem.key){
exist = true;
break;
}
}
if(!exist){
this.hotZoneItemArr.push(hotZoneItem);
}
}
this.refresh();
}
indexPanelCancel() {
this.indexPanelVisible = false;
}
indexPanelOk() {
this.indexPanelVisible = false;
this.curSentence.renderTo = this.renderTo;
this.save();
}
} }
/**
*
* @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, ShapeCircle } from "./Unit";
export class Index {
data;
images;
scaleX = 1;
scaleY = 1;
bg;
constructor(data, images) {
this.data = data;
this.images = images;
}
init(mapScaleX = 1, mapScaleY = 1) {
this.scaleX = mapScaleX;
this.scaleY = mapScaleY;
this.initBg();
this.initPic();
}
private initBg() {
let r = 10 * this.scaleX;
const bg = new ShapeCircle();
bg.setRadius(r);
bg.fillColor = "#000000";
this.bg = bg;
}
private initPic() {
//序号
const index = new Label();
index.text = this.data.text;
index.textAlign = 'center';
index.fontSize = 15;
index.fontName = "FUTURA";
index.fontColor = "#ffffff";
index.setScaleXY(this.scaleX);
index.refreshSize();
index.x = 0;
index.y = 0;
this.bg.addChild(index);
}
}
\ 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){
this.btnPlay.alpha = 1;
this.btnStop.alpha = 0;
this.playing = false;
pauseAudio(this.audio, false, callback)
}
}
\ No newline at end of file
import { constants } from "node:buffer";
import { ShapeRect, ShapeRectNew } from "./Unit";
export class Scrollbar {
scaleX = 1;
scaleY = 1;
/**视窗高度 */
viewHight = 0;
/**总高度 */
hight = 0;
bg: ShapeRect;
shown = true;
scrollbar: ShapeRectNew;
scrollbarBg: ShapeRectNew;
scrollbarInitY = 0;
width = 0;
canMoveDis = 0;
perRowDis = 0;
/**触摸y坐标 */
touchY = 0;
touched = false;
curY = 0;
/**滚动比例 */
scale = 1;
init(scaleX = 1, scaleY = 1, viewHight = 0, hight = 0, width = 0) {
this.scaleX = scaleX;
this.scaleY = scaleY;
this.viewHight = viewHight;
this.hight = hight;
this.width = width;
this.initBg();
this.initView();
}
private initBg() {
const bg = new ShapeRect();
bg.setSize(this.width * this.scaleX, this.viewHight);
bg.alpha = 0;
this.bg = bg;
}
private initView() {
const scrollbarBg = new ShapeRectNew();
scrollbarBg.setSize(this.width * this.scaleX, this.viewHight, 7.5 * this.scaleX);
scrollbarBg.fillColor = "#000000";
scrollbarBg.x = 0;
scrollbarBg.y = 0;
scrollbarBg.alpha = 0;
this.scrollbarBg = scrollbarBg;
this.bg.addChild(scrollbarBg);
const scrollbar = new ShapeRectNew();
scrollbar.setSize(8 * this.scaleX, 0 * this.scaleY, 4 * this.scaleX);
scrollbar.fillColor = "#fef89a";
scrollbar.x = (this.bg.width - scrollbar.width) / 2;
scrollbar.y = 3 * this.scaleY;
scrollbar.visible = false;
this.bg.addChild(scrollbar);
this.scrollbar = scrollbar;
this.scrollbarInitY = scrollbar.y;
}
hide(){
this.bg.visible = false;
this.shown = false;
}
show(){
this.bg.visible = true;
this.shown = true;
}
showScrollbar() {
if (this.hight <= this.viewHight) {
this.scrollbarBg.alpha = 0;
this.scrollbar.visible = false;
}
else {
this.scrollbarBg.alpha = 1;
this.scrollbar.visible = true;
let draghight = this.viewHight - 6 * this.scaleY;
let height = draghight / (this.hight / draghight);
this.scrollbar.height = height;
this.canMoveDis = draghight - height;
if(this.canMoveDis != 0){
this.scale = (this.hight - draghight) / this.canMoveDis
}
}
}
touchScrollbar(my: number) {
this.touchY = my;
this.curY = this.scrollbar.y;
this.touched = true;
}
drag(dis: number, callback) {
if (!this.touched) {
return;
}
let newY = this.curY + dis;
if (newY < this.scrollbarInitY) {
newY = this.scrollbarInitY;
}
else if (newY > this.scrollbarInitY + this.canMoveDis) {
newY = this.scrollbarInitY + this.canMoveDis;
}
this.scrollbar.y = newY;
let tDis = newY - this.curY;
if(callback){
let dis = tDis * this.scale;
callback(dis);
}
}
}
\ 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="#763c92";
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 = "#facf46";
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 = "FUTURA";
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)
}
}
\ No newline at end of file
This diff is collapsed.
...@@ -17,3 +17,44 @@ ...@@ -17,3 +17,44 @@
src: url("../../assets/font/BRLNSDB.TTF") ; src: url("../../assets/font/BRLNSDB.TTF") ;
} }
@font-face
{
font-family: 'FUTURAB';
src: url("../../assets/font/FUTURAB.TTF") ;
}
@font-face
{
font-family: 'GOTHIC';
src: url("../../assets/font/GOTHIC.TTF") ;
}
@font-face
{
font-family: 'GOTHICB';
src: url("../../assets/font/GOTHICB.TTF") ;
}
@font-face
{
font-family: 'TCB';
src: url("../../assets/font/TCB.TTF") ;
}
@font-face
{
font-family: 'FUTURA';
src: url("../../assets/font/Futura.ttc") ;
}
@font-face
{
font-family: 'FuturaStd';
src: url("../../assets/font/FuturaStd-Medium.otf") ;
}
@font-face
{
font-family: 'ahronbd-1';
src: url("../../assets/font/ahronbd-1.ttf") ;
}
\ No newline at end of file
This diff is collapsed.
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"], ['titlePart1Bg', "assets/play/title-part1-bg.png"],
// ['text_bg', "assets/play/text_bg.png"], ['close', "assets/play/close.png"],
['overturn', "assets/play/overturn.png"],
['box', "assets/play/box.png"],
]; ];
...@@ -12,7 +13,10 @@ const res = [ ...@@ -12,7 +13,10 @@ const res = [
const resAudio = [ const resAudio = [
['click', "assets/play/music/click.mp3"], ['click', "assets/play/music/click.mp3"],
['back', "assets/play/music/back.mp3"],
['waves', "assets/play/music/waves.mp3"],
['turn', "assets/play/music/turn.mp3"],
['page', "assets/play/music/page.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