Commit cb437e73 authored by liujiangnan's avatar liujiangnan

feat: 迁移完成

parent 8a51c964
......@@ -30,7 +30,10 @@
],
"styles": [
"./node_modules/ng-zorro-antd/ng-zorro-antd.min.css",
"src/styles.css"
"./node_modules/font-awesome/css/font-awesome.css",
"./node_modules/bootstrap/dist/css/bootstrap.min.css",
"./node_modules/animate.css/animate.min.css",
"src/styles.scss"
],
"scripts": []
},
......@@ -128,5 +131,8 @@
}
}
},
"defaultProject": "ng-template-generator"
"defaultProject": "ng-template-generator",
"cli": {
"analytics": "4ac5015e-c397-4a11-92f8-d88d5163f352"
}
}
\ No newline at end of file
......@@ -24,6 +24,7 @@ import {AudioRecorderComponent} from './common/audio-recorder/audio-recorder.com
import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome';
import { fas } from '@fortawesome/free-solid-svg-icons';
import { far } from '@fortawesome/free-regular-svg-icons';
import { BrLineBreakerPipe } from './pipes/br-line-breaker.pipe';
registerLocaleData(zh);
......@@ -36,6 +37,7 @@ registerLocaleData(zh);
AudioRecorderComponent,
UploadImageWithPreviewComponent,
BackgroundImagePipe,
BrLineBreakerPipe,
ResourcePipe,
TimePipe,
UploadVideoComponent,
......
@import '../style/common_mixin.css';
.model-content {
width: 100%;
height: 100%;
}
<div class="model-content">
<div style="position: absolute; left: 200px; top: 100px; width: 800px;">
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()">
<app-upload-image-with-preview
[picUrl]="item.pic_url"
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')"
></app-upload-image-with-preview>
<nz-form-item>
<nz-form-label [nzSpan]="4">Vocabulary</nz-form-label>
<nz-form-control [nzSpan]="8">
<input type="text" nz-input placeholder="Please input Vocabulary" [(ngModel)]="item.contentObj.vocabulary" (blur)="updateVocabulary()">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzSpan]="8" [nzOffset]="4">
<app-audio-recorder
[audioUrl]="item.contentObj.vocabulary_audio"
(audioUploaded)="onVocabularyAudioUploadSuccess($event)"
></app-audio-recorder>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="4">Part of Speech</nz-form-label>
<nz-form-control [nzSpan]="8">
<input type="text" nz-input [(ngModel)]="item.contentObj.vocabularyType" (blur)="updatePartOfSpeech()" placeholder="Please Input Part of Speech">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="4">Definition</nz-form-label>
<nz-form-control [nzSpan]="8">
<textarea nz-input rows="2" placeholder="Please Input Definition" [(ngModel)]="item.contentObj.definition" (blur)="updateDefinition()"></textarea>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzSpan]="8" [nzOffset]="4">
<app-audio-recorder
[audioUrl]="item.audio_url"
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url')"
[audioUrl]="item.contentObj.definition_audio"
(audioUploaded)="onDefinitionAudioUploadSuccess($event)"
></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>
\ No newline at end of file
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="4">Definition Picture</nz-form-label>
<nz-form-control [nzSpan]="8">
<app-upload-image-with-preview
[picUrl]="item.contentObj.pic_id"
(imageUploaded)="onImageUploadSuccess($event)"
></app-upload-image-with-preview>
</nz-form-control>
</nz-form-item>
import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef, ChangeDetectorRef} from '@angular/core';
import _ from 'lodash';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css']
styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit, OnChanges, OnDestroy {
// 储存数据用
saveKey = "test_0011";
saveKey = 'ww_vocabulary';
// 储存对象
item;
originContent;
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) {
constructor(private appRef: ApplicationRef,
private changeDetectorRef: ChangeDetectorRef) {
}
ngOnInit() {
this.item = {};
this.item = {
contentObj: {
vocabulary: "",
vocabularyType: "",
definition: "",
definition_audio: "",
pic_id: "",
vocabulary_audio: ""
}
};
// 获取存储的数据
(<any> window).courseware.getData((data) => {
(window as any).courseware.getData((data) => {
if (data) {
this.item = data;
}
this.init();
this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges();
this.refresh();
......@@ -47,33 +55,50 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
ngOnDestroy() {
}
init() {
onImageUploadSuccess(e) {
this.item.contentObj.pic_id = e.url;
this.save();
}
/**
* 储存图片数据
* @param e
*/
onImageUploadSuccess(e, key) {
this.item[key] = e.url;
updateVocabulary() {
const temp = this.item.contentObj.vocabulary ? this.item.contentObj.vocabulary.trim() : '';
if (temp) {
this.item.contentObj.vocabulary = this.item.contentObj.vocabulary.trim();
}
if (temp !== this.originContent.vocabulary) {
this.originContent.vocabulary = temp;
this.save();
}
/**
* 储存音频数据
* @param e
*/
onAudioUploadSuccess(e, key) {
this.item[key] = e.url;
}
updatePartOfSpeech() {
const temp = this.item.contentObj.vocabularyType ? this.item.contentObj.vocabularyType.trim() : '';
if (temp) {
this.item.contentObj.vocabularyType = this.item.contentObj.vocabularyType.trim();
}
if (temp !== this.originContent.vocabularyType) {
this.originContent.vocabularyType = temp;
this.save();
}
}
updateDefinition() {
const temp = this.item.contentObj.definition ? this.item.contentObj.definition.trim() : '';
if (temp) {
this.item.contentObj.definition = this.item.contentObj.definition.trim();
}
if (temp !== this.originContent.definition) {
this.originContent.definition = temp;
this.save();
}
}
onVocabularyAudioUploadSuccess(e) {
this.item.contentObj.vocabulary_audio = e.url;
this.save();
}
onDefinitionAudioUploadSuccess(e) {
this.item.contentObj.definition_audio = e.url;
this.save();
}
/**
......
import {Pipe, PipeTransform} from '@angular/core';
// import {ElectronUtil} from '../util/ElectronUtil';
declare const APP_PATH;
// const isInElectron = localStorage.getItem('electron');
@Pipe({
name: 'backgroundImage'
})
export class BackgroundImagePipe implements PipeTransform {
transform(value: any, coursewareSid?: string) {
// const ret = value ? `url(${value})` : '';
const ret = value ? `url(${value})` : '';
return ret;
// let ret = value > 0 ? `url(/api/media-resource/${value}/file)` : '';
// if (isInElectron && ElectronUtil.hasCached(coursewareSid, value)) {
// ret = `url(file://${APP_PATH}/courseware_cache/${coursewareSid}/${value})`;
// }
// return ret;
transform(value: any) {
return `url(${value})`;
}
}
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'brLineBreaker'
})
export class BrLineBreakerPipe implements PipeTransform {
transform(value: any, args?: any): any {
return value ? value.replace(/\n/g, '<br />') : '';
}
}
......@@ -2,25 +2,17 @@ import {Pipe, PipeTransform} from '@angular/core';
// import {ElectronUtil} from '../util/ElectronUtil';
declare const APP_PATH;
// const isInElectron = localStorage.getItem('electron');
const isInElectron = localStorage.getItem('electron');
@Pipe({
name: 'resource'
})
export class ResourcePipe implements PipeTransform {
transform(pic_url: any, coursewareSid?: string): string {
// return pic_url;
if (pic_url && typeof pic_url === 'object') {
return pic_url;
}
// console.log('resource', pic_url)
return `${pic_url}?t=${Math.random()}`;
// let ret = value ? `/api/resource/${value}/file` : '';
// let ret = res_id ? `/resource/audio/${res_id}` : '';
// if (isInElectron && ElectronUtil.hasCached(coursewareSid, res_id)) {
// ret = `file://${APP_PATH}/courseware_cache/${coursewareSid}/${res_id}`;
transform(value: any, coursewareSid?: string): string {
return value ? `/api/media-resource/${value}/file` : '';
// if (isInElectron && ElectronUtil.hasCached(coursewareSid, value)) {
// ret = `file://${APP_PATH}/courseware_cache/${coursewareSid}/${value}`;
// }
// return ret;
}
......
.game-container {
width: 100%;
height: 100%;
background: #ffffff;
background-size: cover;
}
#canvas {
}
@font-face
{
font-family: 'BRLNSDB';
src: url("../../assets/font/BRLNSDB.TTF") ;
}
<div class="game-container" #wrap>
<canvas id="canvas" #canvas></canvas>
<div class="vocabulary-container">
<div class="content-wrap">
<div class="top-line">
<img class="star" src="../../assets/vocabulary/star.png" alt="" size="20">
<h1 class="vocabulary" [ngClass]="{'animated bounce infinite': vocabularyPlaying}"
(click)="playVocabularyAudio()">
<span class="star"></span>{{data.contentObj.vocabulary}}
</h1>
<h2 class="type">
{{data.contentObj.vocabularyType}}
</h2>
<div class="audio-button" [ngClass]="{'animated zoomIn slow infinite': definitionPlaying}"
(click)="playDefinitionAudio()"></div>
<div class="show-text" (click)="showSentence()"></div>
</div>
<div class="sentence" [style.visibility]="show">
{{data.contentObj.definition}}
</div>
<div class="img-wrap">
<img [src]="data.contentObj.pic_id" alt="" (dragstart)="false;$event.preventDefault();"/>
</div>
</div>
</div>
.vocabulary-container {
text-align: left;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: #fff;
font-family: 'ChalkboardSE-Regular';
.content-wrap {
display: flex;
flex-direction: column;
width: 90%;
height: 90%;
padding: 1rem 10vh;
.top-line {
display: flex;
align-items: center;
.star {
width: 1.5rem;
height: 1.5rem;
margin-right: 0.6rem;
object-fit: contain;
}
.vocabulary {
display: inline-block;
}
.audio-button {
display: inline-block;
width: 2.5rem;
height: 2.5rem;
margin: 0 0.5rem;
background-image: url("../../assets/vocabulary/1.png");
background-repeat: no-repeat;
background-size: contain;
}
.show-text {
display: inline-block;
width: 2.5rem;
height: 2.5rem;
margin: 0 0.5rem;
background-image: url("../../assets/vocabulary/2.png");
background-repeat: no-repeat;
background-size: contain;
}
.type {
display: inline-block;
font-weight: 300;
margin: 0 0 0 2rem;
color: #444;
}
}
.sentence {
color: #000;// #FF960B;
font-size: 24px;
min-height: 4rem;
max-height: 7rem;
margin: 1rem 0;
overflow-y: auto;
}
.img-wrap {
width: 60%;
height: 60%;
border: .8vh solid rgb(255, 150, 11);
border-radius: 2.4vh;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
}
import {Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener} from '@angular/core';
import {
Label,
MySprite, tweenChange,
} from './Unit';
import {res, resAudio} from './resources';
import {Subject} from 'rxjs';
import {debounceTime} from 'rxjs/operators';
import TWEEN from '@tweenjs/tween.js';
import { Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener, OnChanges, AfterViewInit } from '@angular/core';
import * as _ from 'lodash';
import { animate, state, style, transition, trigger } from '@angular/animations';
......@@ -18,662 +8,124 @@ import TWEEN from '@tweenjs/tween.js';
@Component({
selector: 'app-play',
templateUrl: './play.component.html',
styleUrls: ['./play.component.css']
styleUrls: ['./play.component.scss'],
})
export class PlayComponent implements OnInit, OnDestroy {
@ViewChild('canvas', {static: true }) canvas: ElementRef;
@ViewChild('wrap', {static: true }) wrap: ElementRef;
export class PlayComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
// 数据
data;
saveKey = 'ww_vocabulary';
ctx;
canvasWidth = 1280; // canvas实际宽度
canvasHeight = 720; // canvas实际高度
canvasBaseW = 1280; // canvas 资源预设宽度
canvasBaseH = 720; // canvas 资源预设高度
mx; // 点击x坐标
my; // 点击y坐标
// 资源
rawImages = new Map(res);
rawAudios = new Map(resAudio);
images = new Map();
animationId: any;
winResizeEventStream = new Subject();
audioObj = {};
renderArr;
mapScale = 1;
canvasLeft;
canvasTop;
saveKey = 'test_0011';
btnLeft;
btnRight;
pic1;
pic2;
canTouch = true;
curPic;
@HostListener('window:resize', ['$event'])
onResize(event) {
this.winResizeEventStream.next();
}
ngOnInit() {
this.data = {};
// 获取数据
const getData = (<any> window).courseware.getData;
getData((data) => {
if (data && typeof data == 'object') {
this.data = data;
}
// console.log('data:' , data);
// 初始化 各事件监听
this.initListener();
// 若无数据 则为预览模式 需要填充一些默认数据用来显示
this.initDefaultData();
show = 'hidden';
// 初始化 音频资源
this.initAudio();
// 初始化 图片资源
this.initImg();
// 开始预加载资源
this.load();
vocabulary_audio = new Audio();
definition_audio = new Audio();
vocabularyPlaying = false;
definitionPlaying = false;
}, this.saveKey);
}
ngOnDestroy() {
window['curCtx'] = null;
window.cancelAnimationFrame(this.animationId);
}
load() {
// 预加载资源
this.loadResources().then(() => {
window["air"].hideAirClassLoading(this.saveKey, this.data);
this.init();
this.update();
});
}
init() {
this.initCtx();
this.initData();
this.initView();
}
initCtx() {
this.canvasWidth = this.wrap.nativeElement.clientWidth;
this.canvasHeight = this.wrap.nativeElement.clientHeight;
this.canvas.nativeElement.width = this.wrap.nativeElement.clientWidth;
this.canvas.nativeElement.height = this.wrap.nativeElement.clientHeight;
this.ctx = this.canvas.nativeElement.getContext('2d');
this.canvas.nativeElement.width = this.canvasWidth;
this.canvas.nativeElement.height = this.canvasHeight;
window['curCtx'] = this.ctx;
}
updateItem(item) {
if (item) {
item.update();
}
}
updateArr(arr) {
if (!arr) {
return;
}
for (let i = 0; i < arr.length; i++) {
arr[i].update(this);
}
}
initListener() {
this.winResizeEventStream
.pipe(debounceTime(500))
.subscribe(data => {
this.renderAfterResize();
});
// ---------------------------------------------
const setParentOffset = () => {
const rect = this.canvas.nativeElement.getBoundingClientRect();
this.canvasLeft = rect.left;
this.canvasTop = rect.top;
constructor() {
this.vocabulary_audio.onplay = () => {
this.vocabularyPlaying = true;
};
const setMxMyByTouch = (event) => {
if (event.touches.length <= 0) {
return;
}
if (this.canvasLeft == null) {
setParentOffset();
}
this.mx = event.touches[0].pageX - this.canvasLeft;
this.my = event.touches[0].pageY - this.canvasTop;
this.vocabulary_audio.onpause = () => {
this.vocabularyPlaying = false;
};
const setMxMyByMouse = (event) => {
this.mx = event.offsetX;
this.my = event.offsetY;
this.vocabulary_audio.onended = () => {
this.vocabularyPlaying = false;
};
// ---------------------------------------------
let firstTouch = true;
const touchDownFunc = (e) => {
if (firstTouch) {
firstTouch = false;
removeMouseListener();
}
setMxMyByTouch(e);
this.mapDown(e);
this.definition_audio.onplay = () => {
this.definitionPlaying = true;
};
const touchMoveFunc = (e) => {
setMxMyByTouch(e);
this.mapMove(e);
this.definition_audio.onpause = () => {
this.definitionPlaying = false;
};
const touchUpFunc = (e) => {
setMxMyByTouch(e);
this.mapUp(e);
this.definition_audio.onended = () => {
this.definitionPlaying = false;
};
const mouseDownFunc = (e) => {
if (firstTouch) {
firstTouch = false;
removeTouchListener();
}
setMxMyByMouse(e);
this.mapDown(e);
};
const mouseMoveFunc = (e) => {
setMxMyByMouse(e);
this.mapMove(e);
};
const mouseUpFunc = (e) => {
setMxMyByMouse(e);
this.mapUp(e);
};
const element = this.canvas.nativeElement;
const addTouchListener = () => {
element.addEventListener('touchstart', touchDownFunc);
element.addEventListener('touchmove', touchMoveFunc);
element.addEventListener('touchend', touchUpFunc);
element.addEventListener('touchcancel', touchUpFunc);
};
const removeTouchListener = () => {
element.removeEventListener('touchstart', touchDownFunc);
element.removeEventListener('touchmove', touchMoveFunc);
element.removeEventListener('touchend', touchUpFunc);
element.removeEventListener('touchcancel', touchUpFunc);
};
const addMouseListener = () => {
element.addEventListener('mousedown', mouseDownFunc);
element.addEventListener('mousemove', mouseMoveFunc);
element.addEventListener('mouseup', mouseUpFunc);
};
const removeMouseListener = () => {
element.removeEventListener('mousedown', mouseDownFunc);
element.removeEventListener('mousemove', mouseMoveFunc);
element.removeEventListener('mouseup', mouseUpFunc);
};
addMouseListener();
addTouchListener();
}
playAudio(key, now = false, callback = null) {
const audio = this.audioObj[key];
if (audio) {
if (now) {
audio.pause();
audio.currentTime = 0;
ngOnInit() {
this.data = {
contentObj: {
vocabulary: "aaaaaa",
vocabularyType: "bbbbbbb",
definition: "ccccccc",
definition_audio: "assets/right.mp3",
pic_id: "assets/vocabulary/9.png",
vocabulary_audio: "assets/wrong.mp3"
}
if (callback) {
audio.onended = () => {
callback();
};
}
audio.play();
}
}
loadResources() {
const pr = [];
this.rawImages.forEach((value, key) => {// 预加载图片
const p = this.preload(value)
.then(img => {
this.images.set(key, img);
})
.catch(err => console.log(err));
pr.push(p);
});
this.rawAudios.forEach((value, key) => {// 预加载音频
const a = this.preloadAudio(value)
.then(() => {
// this.images.set(key, img);
})
.catch(err => console.log(err));
pr.push(a);
});
return Promise.all(pr);
}
preload(url) {
return new Promise((resolve, reject) => {
const img = new Image();
// img.crossOrigin = "anonymous";
img.onload = () => resolve(img);
img.onerror = reject;
img.src = url;
});
}
preloadAudio(url) {
return new Promise((resolve, reject) => {
const audio = new Audio();
audio.oncanplay = (a) => {
resolve();
};
audio.onerror = () => {
reject();
};
audio.src = url;
audio.load();
});
// 获取数据
const getData = ( window as any).courseware.getData;
getData((data) => {
if (data && typeof data === 'object') {
this.data = data;
}
renderAfterResize() {
this.canvasWidth = this.wrap.nativeElement.clientWidth;
this.canvasHeight = this.wrap.nativeElement.clientHeight;
this.init();
}
checkClickTarget(target) {
const rect = target.getBoundingBox();
if (this.checkPointInRect(this.mx, this.my, rect)) {
return true;
}
return false;
}
getWorlRect(target) {
let rect = target.getBoundingBox();
if (target.parent) {
const pRect = this.getWorlRect(target.parent);
rect.x += pRect.x;
rect.y += pRect.y;
}
return rect;
}
checkPointInRect(x, y, rect) {
if (x >= rect.x && x <= rect.x + rect.width) {
if (y >= rect.y && y <= rect.y + rect.height) {
return true;
}
}
return false;
}
addUrlToAudioObj(key, url = null, vlomue = 1, loop = false, callback = null) {
const audioObj = this.audioObj;
if (url == null) {
url = key;
}
this.rawAudios.set(key, url);
const audio = new Audio();
audio.src = url;
audio.load();
audio.loop = loop;
audio.volume = vlomue;
audioObj[key] = audio;
if (callback) {
audio.onended = () => {
callback();
};
}
}
addUrlToImages(url) {
this.rawImages.set(url, url);
}
// ======================================================编写区域==========================================================================
/**
* 添加默认数据 便于无数据时的展示
*/
initDefaultData() {
if (!this.data.pic_url) {
this.data.pic_url = 'assets/play/default/pic.jpg';
this.data.pic_url_2 = 'assets/play/default/pic.jpg';
}
}
/**
* 添加预加载图片
*/
initImg() {
this.addUrlToImages(this.data.pic_url);
this.addUrlToImages(this.data.pic_url_2);
}
/**
* 添加预加载音频
*/
initAudio() {
// 音频资源
this.addUrlToAudioObj(this.data.audio_url);
this.addUrlToAudioObj(this.data.audio_url_2);
// 音效
this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3);
}
/**
* 初始化数据
*/
initData() {
const sx = this.canvasWidth / this.canvasBaseW;
const sy = this.canvasHeight / this.canvasBaseH;
const s = Math.min(sx, sy);
this.mapScale = s;
// this.mapScale = sx;
// this.mapScale = sy;
this.renderArr = [];
}
/**
* 初始化试图
*/
initView() {
this.initPic();
this.initBottomPart();
}
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;
btnLeft.setScaleXY(this.mapScale);
this.renderArr.push(btnLeft);
this.btnLeft = btnLeft;
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);
this.renderArr.push(btnRight);
this.btnRight = btnRight;
}
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);
this.renderArr.push(pic1);
this.pic1 = pic1;
const label1 = new Label();
label1.text = this.data.text;
label1.textAlign = 'center';
label1.fontSize = 50;
label1.fontName = 'BRLNSDB';
label1.fontColor = '#ffffff';
pic1.addChild(label1);
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;
}
btnLeftClicked() {
this.lastPage();
}
btnRightClicked() {
window["air"].hideAirClassLoading(this.saveKey, this.data);
}, this.saveKey);
this.nextPage();
}
lastPage() {
init(){
this.show = 'hidden';
this.vocabularyPlaying = false;
this.definitionPlaying = false;
this.vocabulary_audio.pause();
this.definition_audio.pause();
this.vocabulary_audio.currentTime = 0;
this.definition_audio.currentTime = 0;
if (this.curPic == this.pic1) {
return;
if (this.data.contentObj && this.data.contentObj.vocabulary_audio) {
this.vocabulary_audio.src = this.data.contentObj.vocabulary_audio;
this.vocabulary_audio.load();
}
this.canTouch = 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;
});
if (this.data.contentObj && this.data.contentObj.definition_audio) {
this.definition_audio.src = this.data.contentObj.definition_audio;
this.definition_audio.load();
}
nextPage() {
if (this.curPic == this.pic2) {
return;
}
this.canTouch = 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.pic2;
});
ngOnDestroy() {
this.vocabulary_audio.pause();
this.definition_audio.pause();
this.vocabulary_audio = null;
this.definition_audio = null;
}
pic1Clicked() {
this.playAudio(this.data.audio_url);
}
ngOnChanges(data) {
pic2Clicked() {
this.playAudio(this.data.audio_url_2);
}
mapDown(event) {
if (!this.canTouch) {
return;
ngAfterViewInit() {
}
if ( this.checkClickTarget(this.btnLeft) ) {
this.btnLeftClicked();
return;
showSentence() {
this.show = this.show === 'hidden' ? 'visible' : 'hidden';
}
if ( this.checkClickTarget(this.btnRight) ) {
this.btnRightClicked();
return;
playVocabularyAudio() {
if (this.data.contentObj && this.data.contentObj.vocabulary_audio) {
if (!this.vocabularyPlaying && this.vocabulary_audio.src) {
this.vocabulary_audio.play();
this.definition_audio.pause();
} else {
this.vocabulary_audio.pause();
}
if ( this.checkClickTarget(this.pic1) ) {
this.pic1Clicked();
return;
}
if ( this.checkClickTarget(this.pic2) ) {
this.pic2Clicked();
return;
}
}
mapMove(event) {
playDefinitionAudio() {
if (this.data.contentObj && this.data.contentObj.definition_audio) {
if (!this.definitionPlaying && this.definition_audio.src) {
this.definition_audio.play();
this.vocabulary_audio.pause();
} else {
this.definition_audio.pause();
}
mapUp(event) {
}
update() {
// ----------------------------------------------------------
this.animationId = window.requestAnimationFrame(this.update.bind(this));
// 清除画布内容
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
// tween 更新动画
TWEEN.update();
// ----------------------------------------------------------
this.updateArr(this.renderArr);
}
}
@mixin hide-overflow-text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
@mixin k-no-select {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@mixin k-img-bg {
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
@mixin hide-overflow-text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
@mixin k-no-select {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@mixin k-img-bg {
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
......@@ -3,6 +3,8 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
if (environment.production) {
enableProdMode();
......
/* You can add global styles to this file, and also import other style files */
/* You can add global styles to this file, and also import other style files */
@mixin hide-overflow-text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
@mixin k-no-select {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@mixin k-img-bg {
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
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