Commit 1ba521e9 authored by limingzhe's avatar limingzhe

feat: 首次提交

parent 9f3a2900
...@@ -128,5 +128,8 @@ ...@@ -128,5 +128,8 @@
} }
} }
}, },
"defaultProject": "ng-template-generator" "defaultProject": "ng-template-generator",
} "cli": {
"analytics": false
}
}
\ No newline at end of file
...@@ -24,6 +24,9 @@ import {AudioRecorderComponent} from './common/audio-recorder/audio-recorder.com ...@@ -24,6 +24,9 @@ import {AudioRecorderComponent} from './common/audio-recorder/audio-recorder.com
import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome'; import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome';
import { fas } from '@fortawesome/free-solid-svg-icons'; import { fas } from '@fortawesome/free-solid-svg-icons';
import { far } from '@fortawesome/free-regular-svg-icons'; import { far } from '@fortawesome/free-regular-svg-icons';
import { CustomActionComponent } from './common/custom-action/custom-action.component';
import { UploadDragonBoneComponent } from './common/upload-dragon-bone/upload-dragon-bone.component';
import { SubTemplateComponent } from './common/sub-template/sub-template.component';
registerLocaleData(zh); registerLocaleData(zh);
...@@ -40,8 +43,11 @@ registerLocaleData(zh); ...@@ -40,8 +43,11 @@ registerLocaleData(zh);
TimePipe, TimePipe,
UploadVideoComponent, UploadVideoComponent,
CustomHotZoneComponent, CustomHotZoneComponent,
SubTemplateComponent,
PlayerContentWrapperComponent PlayerContentWrapperComponent,
CustomActionComponent,
UploadDragonBoneComponent
], ],
imports: [ imports: [
......
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
<ng-template #truthyTemplate > <ng-template #truthyTemplate >
<div class="btn-delete" (click)="onBtnDeleteAudio()"> <div class="btn-delete" (click)="onBtnDeleteAudio()">
<fa-icon icon="close"></fa-icon> <!-- <fa-icon icon="close"></fa-icon> -->
<i nz-icon nzType="close" nzTheme="outline"></i>
</div> </div>
</ng-template> </ng-template>
......
...@@ -26,7 +26,7 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { ...@@ -26,7 +26,7 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
uploadData; uploadData;
@Input() @Input()
needRemove = false; needRemove = true;
@Input() @Input()
audioItem: any = null; audioItem: any = null;
...@@ -62,8 +62,25 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { ...@@ -62,8 +62,25 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
this.uploadUrl = url; this.uploadUrl = url;
this.uploadData = data; this.uploadData = data;
}; };
this.setUploadUrl();
} }
setUploadUrl() {
if (!this.uploadUrl) {
this.uploadUrl = (<any> window).courseware.uploadUrl();
this.uploadData = (<any> window).courseware.uploadData();
setTimeout(() => {
this.setUploadUrl();
}, 500);
}
}
init() { init() {
this.playIcon = 'play'; this.playIcon = 'play';
this.isPlaying = false; this.isPlaying = false;
...@@ -157,6 +174,7 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { ...@@ -157,6 +174,7 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
onBtnDeleteAudio() { onBtnDeleteAudio() {
this.audioUrl = null; this.audioUrl = null;
this.audioUploaded.emit({});
this.audioRemoved.emit(); this.audioRemoved.emit();
} }
......
<div class="position-relative">
<button nz-button (click)="setAnimaBtnClick()" style=" border-radius: 0.5rem; border: 1px solid #ddd;" >
<i nz-icon nzType="tool" nzTheme="outline"></i>
{{btnName}}
</button>
<!--配置龙骨面板-->
<nz-modal [(nzVisible)]="panelVisible" (nzAfterClose)="closePanel()" [nzTitle]="btnName" (nzOnCancel)="panelCancel()" (nzOnOk)="panelOk()" nzOkText="保存">
<div>
<h4>基础内容:</h4>
<div style="margin-bottom: 10px; width: 80%; margin: auto;">
<!-- <nz-radio-group [ngModel]="item.type" (ngModelChange)="radioChange($event)">
<label nz-radio nzValue="pic">图片</label>
<label nz-radio nzValue="text">文本</label>
</nz-radio-group> -->
<div *ngIf="item.type == 'pic'">
<app-upload-image-with-preview
[picUrl]="item?.pic_url"
(imageUploaded)="onItemImgUploadSuccess($event, item)">
</app-upload-image-with-preview>
</div>
<div *ngIf="item.type == 'text'">
<input type="text" nz-input [(ngModel)]="item.text" (blur)="saveText(item)">
</div>
<div *ngIf="item.type == 'anima'" style="margin-left: 100px;">
<app-upload-dragon-bone
[skeJsonData]=item.skeJsonData
[texJsonData]=item.texJsonData
[texPngData]=item.texPngData
(save)="saveAnima($event)"
>
</app-upload-dragon-bone>
</div>
</div>
<nz-divider style="margin-top: 10px;"></nz-divider>
<h4>状态设置:</h4>
<div style="display: flex; justify-content: space-around;">
<div style="width: 30%; display: flex; align-items: center; flex-direction: column;">
<h5> 开始状态 </h5>
<div *ngFor="let op of item.changeOption; let i = index" style="margin-bottom: 5px; ">
<div style="display: flex; align-items: center; justify-content: center;">
<span>{{op[0]}}: </span> <input type="text" nz-input [(ngModel)]="op[1]" (blur)="saveText(op)" style="margin-left: 5px;">
</div>
</div>
</div>
<div style="width: 30%; display: flex; align-items: center; flex-direction: column; ">
<h5> 切换时间 </h5>
<div style="display: flex; width: 100%; align-items: center; justify-content: center;">
<span>time: </span> <input type="text" nz-input [(ngModel)]="item.changeTime" (blur)="saveText(item.changeTime)" style="width: 80px; margin-left: 5px;">
</div>
</div>
<div style="width: 30%; display: flex; align-items: center; flex-direction: column;">
<h5> 结束状态 </h5>
<div *ngFor="let op of item.changeOption; let i = index" style="margin-bottom: 5px; ">
<div style="display: flex; align-items: center; justify-content: center;">
<span>{{op[0]}}: </span> <input [disabled]="op[2] == null" type="text" nz-input [(ngModel)]="op[2]" (blur)="saveText(op)" style="margin-left: 5px;">
</div>
</div>
</div>
</div>
<div style="display: flex; align-items: center; justify-content: center; margin-top: 10px;">
<button style="margin-left: 20px; margin-top: -5px" nz-button (click)="copyChangeData()"> 复制数据 </button>
<div style="margin-left: 20px; margin-top: -5px" >
<span>粘贴数据: </span>
<input style="width: 100px;" type="text" nz-input [(ngModel)]="pasteData" >
<button style="margin-left: 5px;" nz-button [disabled]="pasteData==''" nzType="primary" (click)="importData()">导入</button>
</div>
</div>
<nz-divider style="margin-top: 10px;"></nz-divider>
<h4> 音频设置 </h4>
<app-audio-recorder
style="margin: auto"
[audioUrl]="item?.audio_url"
(audioUploaded)="onItemAudioUploadSuccess($event, item)"
></app-audio-recorder>
</div>
<!--
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 ske_json 文件: </span>
<nz-upload [nzShowUploadList]="false"
nzAccept="application/json"
[nzAction]="uploadUrl"
[nzData]="uploadData"
(nzChange)="skeJsonHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isSkeJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="skeJsonData && skeJsonData['name']" style="margin-left: 10px"><u> {{skeJsonData['name']}} </u></span>
</div>
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 tex_json 文件: </span>
<nz-upload [nzShowUploadList]="false"
nzAccept="application/json"
[nzAction]="uploadUrl"
[nzData]="uploadData"
(nzChange)="texJsonHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isTexJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="texJsonData && texJsonData['name']" style="margin-left: 10px"><u> {{texJsonData['name']}} </u></span>
</div>
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 tex_png 文件: </span>
<nz-upload [nzShowUploadList]="false"
nzAccept = "image/*"
[nzAction]="uploadUrl"
[nzData]="uploadData"
(nzChange)="texPngHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isTexPngLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="texPngData && texPngData['name']" style="margin-left: 10px"><u> {{texPngData['name']}} </u></span>
</div>
<div class="anima-upload-btn" *ngIf="animaNames && animaNames.length > 0">
提示:需包含动画: {{animaNames.toString()}}.
</div> -->
</nz-modal>
</div>
@import '../../style/common_mixin.css';
.p-image-uploader {
position: relative;
display: block;
width: 100%;
height: 0;
padding-bottom: 56.25%;
.p-box {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 2px dashed #ddd;
border-radius: 0.5rem;
background-color: #fafafa;
text-align: center;
color: #aaa;
.p-upload-icon {
text-align: center;
margin: auto;
.anticon-upload {
color: #888;
font-size: 5rem;
}
.p-progress-bar {
position: relative;
width: 20rem;
height: 1.5rem;
border: 1px solid #ccc;
border-radius: 1rem;
.p-progress-bg {
background-color: #1890ff;
border-radius: 1rem;
height: 100%;
}
.p-progress-value {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-shadow: 0 0 4px #000;
color: white;
text-align: center;
font-size: 0.9rem;
line-height: 1.5rem;
}
}
}
.p-preview {
width: 100%;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
background-position: 50% 50%;
//background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png");
}
}
.d-flex{
display: flex;
}
}
.p-btn-delete {
position: absolute;
right: -0.5rem;
top: -0.5rem;
width: 2rem;
height: 2rem;
border: 0.2rem solid white;
border-radius: 50%;
font-size: 1.2rem;
background-color: #fb781a;
color: white;
text-align: center;
}
.p-upload-progress-bg {
position: absolute;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
& .i-text {
position: absolute;
text-align: center;
color: white;
text-shadow: 0 0 2px rgba(0, 0, 0, .85);
}
& .i-bg {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: #27b43f;
border-radius: 0.5rem;
}
}
.anima-upload-btn {
padding: 10px;
}
:host ::ng-deep .ant-upload {
display: block;
}
import {ApplicationRef, Component, EventEmitter, Input, OnChanges, OnDestroy, Output} from '@angular/core';
import { NzMessageService, UploadXHRArgs, UploadFile } from 'ng-zorro-antd';
@Component({
selector: 'app-custom-action',
templateUrl: './custom-action.component.html',
styleUrls: ['./custom-action.component.scss']
})
export class CustomActionComponent implements OnDestroy, OnChanges {
uploading = false;
progress = 0;
@Input()
btnName = '配置变化状态';
@Input()
option = []
@Input()
item;
@Input()
type = 'text'
@Output()
save = new EventEmitter();
@Output()
refreshEmitter = new EventEmitter();
uploadUrl;
uploadData;
panelVisible = false;
pasteData = '';
constructor(private appRef: ApplicationRef, private nzMessageService: NzMessageService) {
window['air'].getUploadCallback = (url, data) => {
this.uploadUrl = url;
this.uploadData = data;
};
const tmpId = setInterval(() => {
console.log(' in setInterval')
this.uploadUrl = (<any> window).courseware.uploadUrl();
this.uploadData = (<any> window).courseware.uploadData();
if (this.uploadUrl) {
clearInterval(tmpId);
}
}, 500)
}
ngOnInit() {
this.initItem();
}
ngOnChanges() {
}
initItem() {
console.log('```this.item: ', this.item);
if (!this.item) {
this.item = {
type: this.type,
skeJsonData: {},
texJsonData: {},
texPngData: {},
changeStart: [
],
changeEnd: [
],
changeTime: 0.3
};
if (this.option) {
this.item.changeOption = JSON.parse(JSON.stringify(this.option));
}
}
console.log('initItem', this.item);
}
setAnimaBtnClick() {
this.panelVisible = true;
this.refresh();
}
panelCancel() {
this.panelVisible = false;
this.refresh();
}
panelOk() {
// this.sendItemDragonBoneData();
this.panelVisible = false;
this.refresh();
this.save.emit(this.item);
}
saveText(t) {
}
radioChange(e) {
this.item.type = e;
console.log('e: ', e);
}
onItemImgUploadSuccess(e, item) {
item.pic_url = e.url;
this.refresh();
}
onItemAudioUploadSuccess(e, item) {
item.audio_url = e.url;
this.refresh();
}
saveAnima(e) {
console.log("~ e: ", e);
}
copyChangeData() {
console.log('this.item: ', this.item);
const jsonData = {
changeOption: this.item.changeOption,
changeTime : this.item.changeTime
// bgItem,
// hotZoneItemArr,
// isHasRect: this.isHasRect,
// isHasPic: this.isHasPic,
// isHasText: this.isHasText,
// isHasAudio: this.isHasAudio,
// isHasAnima: this.isHasAnima,
// hotZoneFontObj: this.hotZoneFontObj,
// defaultItemType: this.defaultItemType,
// hotZoneImgSize: this.hotZoneImgSize,
};
const oInput = document.createElement('input');
oInput.value = JSON.stringify(jsonData);
document.body.appendChild(oInput);
oInput.select(); // 选择对象
document.execCommand('Copy'); // 执行浏览器复制命令
document.body.removeChild(oInput);
this.nzMessageService.success('复制成功');
}
importData() {
if (!this.pasteData) {
return;
}
try {
const data = JSON.parse(this.pasteData);
console.log('data:', data);
const {
changeOption,
changeTime
} = data;
this.item.changeOption = changeOption;
this.item.changeTime = changeTime;
this.pasteData = '';
} catch (e) {
console.log('err: ', e);
this.nzMessageService.error('导入失败');
}
}
/**
* 刷新 渲染页面
*/
refresh() {
// this.refreshEmitter.emit();
setTimeout(() => {
this.appRef.tick();
}, 1);
}
closePanel() {
console.log(' in closePanel ');
this.refresh();
}
ngOnDestroy() {
}
}
This diff is collapsed.
...@@ -81,6 +81,10 @@ ...@@ -81,6 +81,10 @@
} }
} }
.anima-upload-btn {
padding: 10px;
}
h5 { h5 {
margin-top: 1rem; margin-top: 1rem;
} }
...@@ -89,8 +93,8 @@ h5 { ...@@ -89,8 +93,8 @@ h5 {
@font-face @font-face
{ {
font-family: 'BRLNSR_1'; font-family: 'ahronbd-1';
src: url("/assets/font/BRLNSR_1.TTF") ; src: url("/assets/font/ahronbd-1.ttf") ;
} }
...@@ -105,106 +109,3 @@ h5 { ...@@ -105,106 +109,3 @@ h5 {
//@import '../../../style/common_mixin';
//
//.p-image-uploader {
// position: relative;
// display: block;
// width: 100%;
// height: 0;
// padding-bottom: 56.25%;
// .p-box {
// position: absolute;
// left: 0;
// top: 0;
// right: 0;
// bottom: 0;
// border: 2px dashed #ddd;
// border-radius: 0.5rem;
// background-color: #fafafa;
// text-align: center;
// color: #aaa;
// .p-upload-icon {
// text-align: center;
// margin: auto;
// .anticon-upload {
// color: #888;
// font-size: 5rem;
// }
// .p-progress-bar {
// position: relative;
// width: 20rem;
// height: 1.5rem;
// border: 1px solid #ccc;
// border-radius: 1rem;
// .p-progress-bg {
// background-color: #1890ff;
// border-radius: 1rem;
// height: 100%;
// }
// .p-progress-value {
// position: absolute;
// top: 0;
// left: 0;
// width: 100%;
// height: 100%;
// text-shadow: 0 0 4px #000;
// color: white;
// text-align: center;
// font-size: 0.9rem;
// line-height: 1.5rem;
// }
// }
// }
// .p-preview {
// width: 100%;
// height: 100%;
// //background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png");
// @include k-img-bg();
// }
// }
//}
//
//.p-btn-delete {
// position: absolute;
// right: -0.5rem;
// top: -0.5rem;
// width: 2rem;
// height: 2rem;
// border: 0.2rem solid white;
// border-radius: 50%;
// font-size: 1.2rem;
// background-color: #fb781a;
// color: white;
// text-align: center;
//}
//
//.p-upload-progress-bg {
// position: absolute;
// width: 100%;
// height: 100%;
// display: flex;
// align-items: center;
// justify-content: center;
// & .i-text {
// position: absolute;
// text-align: center;
// color: white;
// text-shadow: 0 0 2px rgba(0, 0, 0, .85);
// }
// & .i-bg {
// position: absolute;
// left: 0;
// top: 0;
// height: 100%;
// background-color: #27b43f;
// border-radius: 0.5rem;
// }
//}
//
//
//:host ::ng-deep .ant-upload {
// display: block;
//}
<div class="content">
<div style="display: flex; margin-bottom: 5px;">
<button nz-button nzType="dashed" (click)="selectSubTemplate()" style=" border-radius: 0.5rem; border: 1px solid #ddd;">
<i nz-icon nzType="appstore" nzTheme="outline"></i>
选择子模板类型
</button>
<h2 *ngIf="_item.template" style="margin-left: 10px; margin-top: 1px;">
{{_item.template.description}}
</h2>
<button nz-button nzType="danger" (click)="deleteSubTemplate()" style="position: absolute; right: 30px; border-radius: 0.5rem; border: 1px solid #ddd;">
<i nz-icon nzType="delete" nzTheme="outline"></i>
删除
</button>
</div>
<iframe #iframe id="iframe" [src]="safeUrl" style="width: 98%; height: 70vh; border: 1px solid #ccc; padding: 5px;" frameborder="0">
</iframe>
<nz-modal [(nzVisible)]="isShowTemplate" (nzAfterClose)="closePanel()" nzTitle="选择子模板" [nzFooter]="null"
(nzOnCancel)="panelCancelClicked()" nzWidth="80%" nzHeight="80%">
<div class="template-container">
<div *ngFor="let template of templateArr" >
<div (click)="templateClick(template)" style="width: 150px; height: 100px; border: 1px solid #ccc; margin: 5px; cursor:pointer; user-select: none;">
<div style="width: 100%; height: 70%; border-bottom: 1px solid #ccc; overflow: hidden;">
<img [src]="template.cover" style="width: 100%; height: auto;">
</div>
<div style="width: 100%; height: 30%; display: flex; align-items: center; justify-content: center; ">
<label style="width: 90%; text-align: center; text-overflow: ellipsis; white-space:nowrap; overflow: hidden; ">{{template.description}}</label>
</div>
</div>
</div>
</div>
</nz-modal>
</div>
\ No newline at end of file
@import '../../style/common_mixin.css';
.content {
// width: 100%;
height: 100%;
border: 2px solid #ccc;
padding: 10px;
border-radius: 5px;
}
.template-container{
width: 100%;
display: flex;
// align-items: center;
// justify-content: space-around;
flex-wrap: wrap;
}
\ No newline at end of file
This diff is collapsed.
<div class="position-relative">
<button nz-button (click)="setAnimaBtnClick()" style=" border-radius: 0.5rem; border: 1px solid #ddd;">
<i nz-icon nzType="tool" nzTheme="outline"></i>
{{btnName}}
</button>
<!--配置龙骨面板-->
<nz-modal [(nzVisible)]="animaPanelVisible" (nzAfterClose)="closePanel()" nzTitle="配置资源文件"
(nzOnCancel)="animaPanelCancel()" (nzOnOk)="animaPanelOk()" nzOkText="保存">
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 ske_json 文件: </span>
<nz-upload [nzShowUploadList]="false" nzAccept="application/json" [nzAction]="uploadUrl" [nzData]="uploadData"
(nzChange)="skeJsonHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isSkeJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="skeJsonData && skeJsonData['name']" style="margin-left: 10px"><u> {{skeJsonData['name']}} </u></span>
</div>
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 tex_json 文件: </span>
<nz-upload [nzShowUploadList]="false" nzAccept="application/json" [nzAction]="uploadUrl" [nzData]="uploadData"
(nzChange)="texJsonHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isTexJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="texJsonData && texJsonData['name']" style="margin-left: 10px"><u> {{texJsonData['name']}} </u></span>
</div>
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 tex_png 文件: </span>
<nz-upload [nzShowUploadList]="false" nzAccept="image/*" [nzAction]="uploadUrl" [nzData]="uploadData"
(nzChange)="texPngHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isTexPngLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="texPngData && texPngData['name']" style="margin-left: 10px"><u> {{texPngData['name']}} </u></span>
</div>
<div class="anima-upload-btn" *ngIf="animaNames && animaNames.length > 0">
提示:需包含动画: {{animaNames.toString()}}.
</div>
</nz-modal>
</div>
\ No newline at end of file
@import '../../style/common_mixin.css';
.p-image-uploader {
position: relative;
display: block;
width: 100%;
height: 0;
padding-bottom: 56.25%;
.p-box {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 2px dashed #ddd;
border-radius: 0.5rem;
background-color: #fafafa;
text-align: center;
color: #aaa;
.p-upload-icon {
text-align: center;
margin: auto;
.anticon-upload {
color: #888;
font-size: 5rem;
}
.p-progress-bar {
position: relative;
width: 20rem;
height: 1.5rem;
border: 1px solid #ccc;
border-radius: 1rem;
.p-progress-bg {
background-color: #1890ff;
border-radius: 1rem;
height: 100%;
}
.p-progress-value {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-shadow: 0 0 4px #000;
color: white;
text-align: center;
font-size: 0.9rem;
line-height: 1.5rem;
}
}
}
.p-preview {
width: 100%;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
background-position: 50% 50%;
//background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png");
}
}
.d-flex{
display: flex;
}
}
.p-btn-delete {
position: absolute;
right: -0.5rem;
top: -0.5rem;
width: 2rem;
height: 2rem;
border: 0.2rem solid white;
border-radius: 50%;
font-size: 1.2rem;
background-color: #fb781a;
color: white;
text-align: center;
}
.p-upload-progress-bg {
position: absolute;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
& .i-text {
position: absolute;
text-align: center;
color: white;
text-shadow: 0 0 2px rgba(0, 0, 0, .85);
}
& .i-bg {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: #27b43f;
border-radius: 0.5rem;
}
}
.anima-upload-btn {
padding: 10px;
}
:host ::ng-deep .ant-upload {
display: block;
}
import {ApplicationRef, Component, EventEmitter, Input, OnChanges, OnDestroy, Output} from '@angular/core';
import { NzMessageService, UploadXHRArgs, UploadFile } from 'ng-zorro-antd';
@Component({
selector: 'app-upload-dragon-bone',
templateUrl: './upload-dragon-bone.component.html',
styleUrls: ['./upload-dragon-bone.component.scss']
})
export class UploadDragonBoneComponent implements OnDestroy, OnChanges {
uploading = false;
progress = 0;
@Input()
btnName = '配置龙骨动画';
@Input()
animaNames = [];
@Input()
skeJsonData = {};
@Input()
texJsonData = {};
@Input()
texPngData = {};
@Output()
save = new EventEmitter();
@Output()
refreshEmitter = new EventEmitter();
// @Input()
// picUrl;
// @Input()
// canDelete = false;
// @Output()
// imageUploaded = new EventEmitter();
// @Output()
// imageUploadFailure = new EventEmitter();
// @Output()
// delete = new EventEmitter();
// @Input()
// picItem = null;
// @Input()
// iconSize = 2;
// @Input()
// TIP = 'Click here to upload image';
// @Input()
// disableUpload = false;
uploadUrl;
uploadData;
animaPanelVisible = false;
isSkeJsonLoading = false;
isTexJsonLoading = false;
isTexPngLoading = false;
constructor(private appRef: ApplicationRef, private nzMessageService: NzMessageService) {
this.uploadUrl = (<any> window).courseware.uploadUrl();
this.uploadData = (<any> window).courseware.uploadData();
window['air'].getUploadCallback = (url, data) => {
this.uploadUrl = url;
this.uploadData = data;
};
}
ngOnChanges() {
}
setAnimaBtnClick() {
this.animaPanelVisible = true;
this.refresh();
}
animaPanelCancel() {
this.animaPanelVisible = false;
this.refresh();
}
animaPanelOk() {
this.sendItemDragonBoneData();
this.animaPanelVisible = false;
this.refresh();
}
sendItemDragonBoneData() {
const data = {};
data['skeJsonData'] = this.skeJsonData;
data['texJsonData'] = this.texJsonData;
data['texPngData'] = this.texPngData;
this.save.emit(data);
}
skeJsonHandleChange(e) {
console.log('e: ', e);
switch (e.type) {
case 'start':
this.isSkeJsonLoading = true;
break;
case 'success':
this.skeJsonData['url'] = e.file.response.url;
this.skeJsonData['name'] = e.file.name;
this.nzMessageService.success('上传成功');
this.isSkeJsonLoading = false;
break;
case 'progress':
break;
}
}
texJsonHandleChange(e) {
console.log('e: ', e);
switch (e.type) {
case 'start':
this.isTexJsonLoading = true;
break;
case 'success':
this.texJsonData['url'] = e.file.response.url;
this.texJsonData['name'] = e.file.name;
this.nzMessageService.success('上传成功');
this.isTexJsonLoading = false;
break;
case 'progress':
break;
}
}
texPngHandleChange(e) {
console.log('e: ', e);
switch (e.type) {
case 'start':
this.isTexPngLoading = true;
break;
case 'success':
this.texPngData['url'] = e.file.response.url;
this.texPngData['name'] = e.file.name;
this.nzMessageService.success('上传成功');
this.isTexPngLoading = false;
break;
case 'progress':
break;
}
}
/**
* 刷新 渲染页面
*/
refresh() {
// this.refreshEmitter.emit();
setTimeout(() => {
this.appRef.tick();
}, 1);
}
closePanel() {
console.log(' in closePanel ');
this.refresh();
}
ngOnDestroy() {
}
}
...@@ -42,7 +42,28 @@ export class UploadImageWithPreviewComponent implements OnDestroy, OnChanges { ...@@ -42,7 +42,28 @@ export class UploadImageWithPreviewComponent implements OnDestroy, OnChanges {
this.uploadData = data; this.uploadData = data;
}; };
this.setUploadUrl();
} }
setUploadUrl() {
if (!this.uploadUrl) {
console.log('this.uploadUrl -=- 1 : ', this.uploadUrl)
this.uploadUrl = (<any> window).courseware.uploadUrl();
this.uploadData = (<any> window).courseware.uploadData();
console.log('this.uploadUrl -=- 2 : ', this.uploadUrl)
setTimeout(() => {
this.setUploadUrl();
}, 500);
}
console.log('this.uploadUrl -=- 3 : ', this.uploadUrl)
}
ngOnChanges() { ngOnChanges() {
if (!this.picItem) { if (!this.picItem) {
return; return;
......
...@@ -81,8 +81,8 @@ ...@@ -81,8 +81,8 @@
</div> </div>
</div> </div>
<div class="p-preview" *ngIf="!uploading && videoUrl " > <div class="p-preview" *ngIf="!uploading && videoUrl " >
<!--<video crossorigin="anonymous" [src]="videoUrl" controls #videoNode></video>--> <video crossorigin="anonymous" [src]="videoUrl" controls #videoNode></video>
<video [src]="safeVideoUrl(videoUrl)" controls #videoNode></video> <!-- <video [src]="safeVideoUrl(videoUrl)" controls #videoNode></video> -->
</div> </div>
</div> </div>
<div [style.display]="!checkVideoExists?'none':''"> <div [style.display]="!checkVideoExists?'none':''">
......
...@@ -6,3 +6,30 @@ ...@@ -6,3 +6,30 @@
height: 100%; height: 100%;
} }
.radioPaire {
float: left;
margin: 3px;
border-style: dashed;
border-color: #000;
border-width: 1px;
}
.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;
}
This diff is collapsed.
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 { JsonPipe } from '@angular/common';
@Component({ @Component({
...@@ -10,47 +10,154 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap ...@@ -10,47 +10,154 @@ 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 = "JM_MATH01";
// 储存对象 // 储存对象
item; item;
customTypeGroupArr = [
{
name: '轮播图片',
audio: true,
pic: true,
// rect: true,
// isShowPos: true,
// isCopy: true,
// label: '比对',
},
{
name: '选择区域',
rect: true,
},
{
name: '简答问题',
pic: true,
},
{
name: '简答填空区',
rect: true,
label: '答案',
},
]
constructor(private appRef: ApplicationRef, private changeDetectorRef: ChangeDetectorRef) {
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) { }
createShell() {
this.item.wordList.push({
word: '',
audio: '',
backWord: '',
backWordAudio: '',
});
this.save();
} }
removeShell(idx) {
this.item.wordList.splice(idx, 1);
this.save();
}
ngOnInit() { ngOnInit() {
this.item = {}; this.item = {};
// 获取存储的数据 // 获取存储的数据
(<any> window).courseware.getData((data) => { (<any>window).courseware.getData((data) => {
if (data) { if (data) {
this.item = data; this.item = data;
} }
console.log('this.item: ', this.item);
this.init(); this.init();
this.changeDetectorRef.markForCheck(); this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges(); this.changeDetectorRef.detectChanges();
this.refresh(); this.refresh();
}, this.saveKey); }, this.saveKey);
} }
ngOnChanges() { ngOnChanges() {
} }
ngOnDestroy() { ngOnDestroy() {
} }
init() {
if (!this.item.sentenceArr) {
this.item.sentenceArr = [];
}
if (!this.item.templateArr) {
this.item.templateArr = [];
}
if (!this.item.optionArr) {
this.item.optionArr = [
{id: 'A', optionArr: [{id: 'A'}, {id: 'B'}]},
{id: 'B', optionArr: [{id: 'A'}, {id: 'B'}]},
{id: 'C', optionArr: [{id: 'A'}, {id: 'B'}]},
{id: 'D', optionArr: [{id: 'A'}, {id: 'B'}]},
];
}
if (!this.item.ques_type) {
this.item.ques_type = 'single_choice'
}
}
addSubTemplate() {
this.item.templateArr.push({
})
this.save();
}
onDeleteTemplate(e, index) {
this.item.templateArr[index] = {};
this.item.templateArr.splice(index, 1);
this.save();
}
onSaveTemplate(e, index) {
this.item.templateArr[index] = e;
this.save();
}
init() {
addBtnClick() {
this.item.sentenceArr.push({});
this.save();
}
deleteBtnClick(index) {
this.item.sentenceArr.splice(index, 1);
this.save();
}
onSaveCustomAction(e) {
console.log('e:', e);
this.item.customAction = e;
this.save();
}
saveHotZone(group, e) {
console.log('e: ', e);
const {bgItem, hotZoneItemArr} = e;
group.bgItem = bgItem;
group.hotZoneItemArr = hotZoneItemArr;
this.save();
} }
...@@ -58,30 +165,55 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -58,30 +165,55 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
* 储存图片数据 * 储存图片数据
* @param e * @param e
*/ */
onImageUploadSuccess(e, key) { onImageUploadSuccess(e, key, item=null) {
if (!item) {
item = this.item;
}
this.item[key] = e.url; item[key] = e.url;
this.save(); this.save();
} }
/** /**
* 储存音频数据 * 储存音频数据
* @param e * @param e
*/ */
onAudioUploadSuccess(e, key) { onAudioUploadSuccess(e, key, item=null) {
if (item == null) {
item = this.item;
}
item[key] = e.url;
this.save();
}
this.item[key] = e.url; onWordAudioUploadSuccess(e, idx) {
this.item.wordList[idx].audio = e.url;
this.save(); this.save();
} }
onBackWordAudioUploadSuccess(e, idx) {
this.item.wordList[idx].backWordAudio = e.url;
this.save();
}
onVideoUploadSuccess(e, item=null) {
console.log(' in onVideoUploadSuccess')
if (!item) {
item = this.item;
}
item.video_url = e.url;
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();
console.log('this.item = ' + JSON.stringify(this.item));
} }
/** /**
...@@ -93,5 +225,4 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -93,5 +225,4 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}, 1); }, 1);
} }
} }
\ No newline at end of file
This diff is collapsed.
export async function loadFonts (fontName, fontFile) {
// const font = new FontFace(
// "DroidSansFallback",
// "url(" + "../../assets/play/font/DroidSansFallback.ttf" + ")"
// );
try {
console.log(location.href.split("#")[0] + "assets/play/font/" + fontFile);
const font = new FontFace(
fontName,
"url(" + location.href.split("#")[0] + "../../assets/play/font/" + fontFile + ")"
);
console.log('start: ', new Date().getTime())
await font.load();
console.log('end: ', new Date().getTime())
document.fonts.add(font);
document.body.classList.add("fonts-loaded");
} catch (error) {
console.log(error);
}
}
// --------------- custom class --------------------
This diff is collapsed.
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
height: 100%; height: 100%;
background: #ffffff; background: #ffffff;
background-size: cover; background-size: cover;
} }
#canvas { #canvas {
...@@ -10,10 +12,28 @@ ...@@ -10,10 +12,28 @@
} }
@font-face @font-face
{ {
font-family: 'BRLNSDB'; font-family: 'BRLNSDB';
src: url("../../assets/font/BRLNSDB.TTF") ; src: url("../../assets/play/font/BRLNSDB_1.TTF")
}
@font-face
{
font-family: 'Aileron-Black';
src: url("../../assets/play/font/Aileron-Black.ttf")
}
@font-face
{
font-family: 'Aileron-Bold';
src: url("../../assets/play/font/Aileron-Bold.ttf")
} }
@font-face
{
font-family: 'DroidSansFallback';
src: url("../../assets/play/font/DroidSansFallback.ttf");
}
\ No newline at end of file
<div class="game-container" #wrap> <span style="font-family:'DroidSansFallback'" ></span>
<canvas id="canvas" #canvas></canvas> <span style="font-family:'Aileron-Black'" ></span>
<span style="font-family:'Aileron-Bold'" ></span>
<ng-template #tpl>
<video></video>
</ng-template>
<div style="display: none" #videoContainer></div>
<div class="game-container" #wrap >
<canvas id="canvas" style="width: 100%; height: 100%;" #canvas></canvas>
</div> </div>
<div id='div_input'>
</div>
<!-- <div style="position: absolute; top: 0">
<label style="font-family: Aileron-Black;"></label>
<label style="font-family: DroidSansFallback;"></label>
</div> -->
This diff is collapsed.
const res = [ const res = [
// ['bg', "assets/play/bg.jpg"], ['op_item', "assets/play/op_item.png"],
['btn_left', "assets/play/btn_left.png"], ['op_item_wrong', "assets/play/op_item_wrong.png"],
['btn_right', "assets/play/btn_right.png"], ['op_item_right', "assets/play/op_item_right.png"],
// ['text_bg', "assets/play/text_bg.png"], ['op_item_normal', "assets/play/op_item_normal.png"],
['btn_close', "assets/play/btn_close.png"],
['bg', "assets/play/bg.jpg"],
['video_bg', "assets/play/video_bg.jpg"],
['btn_replay', "assets/play/btn_replay.png"],
['icon_right', "assets/play/icon_right.png"],
['icon_wrong', "assets/play/icon_wrong.png"],
['answer_normal', "assets/play/answer_normal.png"],
['answer_right', "assets/play/answer_right.png"],
['answer_wrong', "assets/play/answer_wrong.png"],
]; ];
...@@ -12,7 +24,14 @@ const res = [ ...@@ -12,7 +24,14 @@ const res = [
const resAudio = [ const resAudio = [
['click', "assets/play/music/click.mp3"], ['click', "assets/play/music/click.mp3"],
['submit', "assets/play/music/submit.mp3"],
['more', "assets/play/music/more.mp3"],
]; ];
export {res, resAudio}; export {res, resAudio};
This diff is collapsed.
This diff is collapsed.
src/assets/play/bg.jpg

25.8 KB | W: | H:

src/assets/play/bg.jpg

159 KB | W: | H:

src/assets/play/bg.jpg
src/assets/play/bg.jpg
src/assets/play/bg.jpg
src/assets/play/bg.jpg
  • 2-up
  • Swipe
  • Onion skin
...@@ -9,6 +9,12 @@ ...@@ -9,6 +9,12 @@
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
<script type="text/javascript" src="https://staging-teach.cdn.ireadabc.com/h5template/h5-static-lib/js/air.js"></script> <script type="text/javascript" src="https://staging-teach.cdn.ireadabc.com/h5template/h5-static-lib/js/air.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vConsole/3.9.0/vconsole.min.js"></script>
<script>
// init vConsole
// var vConsole = new VConsole();
// console.log('Hello world');
</script>
</head> </head>
<body> <body>
<app-root></app-root> <app-root></app-root>
......
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