Commit 6833a145 authored by 李维's avatar 李维

dev commit

parent 8a51c964
......@@ -128,5 +128,8 @@
}
}
},
"defaultProject": "ng-template-generator"
"defaultProject": "ng-template-generator",
"cli": {
"analytics": "9c6aa33d-85d1-4496-a524-64e708e94e5e"
}
}
\ No newline at end of file
import TWEEN from '@tweenjs/tween.js';
interface AirWindow extends Window {
air: any;
curCtx: any;
}
declare let window: AirWindow;
class Sprite {
x = 0;
......@@ -17,13 +12,9 @@ class Sprite {
angle = 0;
ctx;
constructor(ctx = null) {
if (!ctx) {
this.ctx = window.curCtx;
} else {
constructor(ctx) {
this.ctx = ctx;
}
}
update($event) {
this.draw();
}
......@@ -39,195 +30,80 @@ class Sprite {
export class MySprite extends Sprite {
_width = 0;
_height = 0;
width = 0;
height = 0;
_anchorX = 0;
_anchorY = 0;
_offX = 0;
_offY = 0;
scaleX = 1;
scaleY = 1;
_alpha = 1;
alpha = 1;
rotation = 0;
visible = true;
skewX = 0;
skewY = 0;
_shadowFlag = false;
_shadowColor;
_shadowOffsetX = 0;
_shadowOffsetY = 0;
_shadowBlur = 5;
_radius = 0;
offSetCenter = false;
children = [this];
childDepandVisible = true;
childDepandAlpha = false;
img;
_z = 0;
_showRect;
_bitmapFlag = false;
_offCanvas;
_offCtx;
init(imgObj = null, anchorX: number = 0.5, anchorY: number = 0.5) {
init(imgObj = null, anchorX:number = 0.5, anchorY:number = 0.5) {
if (imgObj) {
this.img = imgObj;
this.width = this.img.width;
this.height = this.img.height;
}
this.anchorX = anchorX;
this.anchorY = anchorY;
}
setShowRect(rect) {
this._showRect = rect;
}
setShadow(offX, offY, blur, color = 'rgba(0, 0, 0, 0.3)') {
this._shadowFlag = true;
this._shadowColor = color;
this._shadowOffsetX = offX;
this._shadowOffsetY = offY;
this._shadowBlur = blur;
}
setRadius(r) {
this._radius = r;
}
update($event = null) {
if (!this.visible && this.childDepandVisible) {
return;
}
if (this.visible) {
this.draw();
}
}
draw() {
this.ctx.save();
this.drawInit();
this.updateChildren();
this.ctx.restore();
}
drawInit() {
this.ctx.translate(this.x, this.y);
this.ctx.rotate(this.rotation * Math.PI / 180);
this.ctx.scale(this.scaleX, this.scaleY);
this.ctx.globalAlpha = this.alpha;
this.ctx.transform(1, this.skewX, this.skewY, 1, 0, 0);
//
// if (this._radius) {
//
// const r = this._radius;
// const w = this.width;
// const h = this.height;
//
// this.ctx.lineTo(-w / 2, h / 2); // 创建水平线
// this.ctx.arcTo(-w / 2, -h / 2, -w / 2 + r, -h / 2, r);
// this.ctx.arcTo(w / 2, -h / 2, w / 2, -h / 2 + r, r);
// this.ctx.arcTo(w / 2, h / 2, w / 2 - r, h / 2, r);
// this.ctx.arcTo(-w / 2, h / 2, -w / 2, h / 2 - r, r);
//
// this.ctx.clip();
// }
if(this.offSetCenter){
this.ctx.translate( -( this.width * this.anchorX ), -( this.height * this.anchorY ) );
}
drawSelf() {
if (this._shadowFlag) {
this.ctx.shadowOffsetX = this._shadowOffsetX;
this.ctx.shadowOffsetY = this._shadowOffsetY;
this.ctx.shadowBlur = this._shadowBlur;
this.ctx.shadowColor = this._shadowColor;
} else {
this.ctx.shadowOffsetX = 0;
this.ctx.shadowOffsetY = 0;
this.ctx.shadowBlur = null;
this.ctx.shadowColor = null;
}
drawSelf() {
if (this.img) {
if (this._showRect) {
const rect = this._showRect;
this.ctx.drawImage(this.img, rect.x, rect.y, rect.width, rect.height, this._offX, this._offY + rect.y, this.width, rect.height);
} else {
this.ctx.drawImage(this.img, this._offX, this._offY);
}
}
}
updateChildren() {
if (this.children.length <= 0) { return; }
for (const child of this.children) {
if (child === this) {
if (this.visible) {
for (let i = 0; i < this.children.length; i++) {
if (this.children[i] === this) {
this.drawSelf();
}
} else {
child.update();
this.children[i].update();
}
}
}
load(url, anchorX = 0.5, anchorY = 0.5) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = url;
}).then(img => {
this.init(img, anchorX, anchorY);
return img;
});
......@@ -239,17 +115,11 @@ export class MySprite extends Sprite {
child._z = z;
child.parent = this;
}
this.children.sort((a, b) => {
return a._z - b._z;
});
if (this.childDepandAlpha) {
child.alpha = this.alpha;
}
}
removeChild(child) {
const index = this.children.indexOf(child);
if (index !== -1) {
......@@ -257,55 +127,6 @@ export class MySprite extends Sprite {
}
}
removeChildren() {
for (let i = 0; i < this.children.length; i++) {
if (this.children[i]) {
if (this.children[i] !== this) {
this.children.splice(i, 1);
i --;
}
}
}
}
_changeChildAlpha(alpha) {
for (const child of this.children) {
if (child !== this) {
child.alpha = alpha;
}
}
}
set btimapFlag(v) {
this._bitmapFlag = v;
}
get btimapFlag() {
return this._bitmapFlag;
}
set alpha(v) {
this._alpha = v;
if (this.childDepandAlpha) {
this._changeChildAlpha(v);
}
}
get alpha() {
return this._alpha;
}
set width(v) {
this._width = v;
this.refreshAnchorOff();
}
get width() {
return this._width;
}
set height(v) {
this._height = v;
this.refreshAnchorOff();
}
get height() {
return this._height;
}
set anchorX(value) {
this._anchorX = value;
this.refreshAnchorOff();
......@@ -321,8 +142,8 @@ export class MySprite extends Sprite {
return this._anchorY;
}
refreshAnchorOff() {
this._offX = -this._width * this.anchorX;
this._offY = -this._height * this.anchorY;
this._offX = -this.width * this.anchorX;
this._offY = -this.height * this.anchorY;
}
setScaleXY(value) {
......@@ -330,1744 +151,486 @@ export class MySprite extends Sprite {
}
getBoundingBox() {
const getParentData = (item) => {
let px = item.x;
let py = item.y;
let sx = item.scaleX;
let sy = item.scaleY;
const parent = item.parent;
if (parent) {
const obj = getParentData(parent);
const _x = obj.px;
const _y = obj.py;
const _sx = obj.sx;
const _sy = obj.sy;
px = _x + item.x * _sx;
py = _y + item.y * _sy;
sx *= _sx;
sy *= _sy;
}
return {px, py, sx, sy};
};
const data = getParentData(this);
const x = data.px + this._offX * Math.abs(data.sx);
const y = data.py + this._offY * Math.abs(data.sy);
const width = this.width * Math.abs(data.sx);
const height = this.height * Math.abs(data.sy);
const x = this.x + this._offX * this.scaleX;
const y = this.y + this._offY * this.scaleY;
const width = this.width * this.scaleX;
const height = this.height * this.scaleY;
return {x, y, width, height};
}
}
export class RoundSprite extends MySprite {
_newCtx;
init(imgObj = null, anchorX: number = 0.5, anchorY: number = 0.5) {
if (imgObj) {
this.img = imgObj;
this.width = this.img.width;
this.height = this.img.height;
export class Item extends MySprite {
baseX;
move(targetY, callBack) {
const self = this;
const tween = new TWEEN.Tween(this)
.to({ y: targetY }, 2500)
.easing(TWEEN.Easing.Quintic.Out)
.onComplete(function() {
self.hide(callBack);
// if (callBack) {
// callBack();
// }
})
.start();
}
this.anchorX = anchorX;
this.anchorY = anchorY;
const canvas = window['curCanvas'];
const w = canvas.nativeElement.width;
const h = canvas.nativeElement.height;
this._offCanvas = document.createElement('canvas');
this._offCanvas.width = w;
this._offCanvas.height = h;
this._offCtx = this._offCanvas.getContext('2d');
// this._newCtx = this.ctx;
// this.ctx = this._offCtx;
show(callBack = null) {
const tween = new TWEEN.Tween(this)
.to({ alpha: 1 }, 800)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(function() {
if (callBack) {
callBack();
}
drawSelf() {
//
// if (this._shadowFlag) {
//
// this.ctx.shadowOffsetX = this._shadowOffsetX;
// this.ctx.shadowOffsetY = this._shadowOffsetY;
// this.ctx.shadowBlur = this._shadowBlur;
// this.ctx.shadowColor = this._shadowColor;
// } else {
// this.ctx.shadowOffsetX = 0;
// this.ctx.shadowOffsetY = 0;
// this.ctx.shadowBlur = null;
// this.ctx.shadowColor = null;
// }
if (this._radius) {
const r = this._radius;
const w = this.width;
const h = this.height;
const x = -this._offX;
const y = -this._offY;
this._offCtx.lineTo(x - w / 2, y + h / 2); // 创建水平线
this._offCtx.arcTo(x - w / 2, y - h / 2, x - w / 2 + r, y - h / 2, r);
this._offCtx.arcTo(x + w / 2, y - h / 2, x + w / 2, y - h / 2 + r, r);
this._offCtx.arcTo(x + w / 2, y + h / 2, x + w / 2 - r, y + h / 2, r);
this._offCtx.arcTo(x - w / 2, y + h / 2, x - w / 2, y + h / 2 - r, r);
this._offCtx.clip();
})
.start(); // Start the tween immediately.
}
if (this.img) {
this._offCtx.drawImage(this.img, 0, 0);
this.ctx.drawImage(this._offCanvas,this._offX, this._offX);
hide(callBack = null) {
const tween = new TWEEN.Tween(this)
.to({ alpha: 0 }, 800)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(function() {
if (callBack) {
callBack();
}
})
.start(); // Start the tween immediately.
}
}
export class ColorSpr extends MySprite {
r = 0;
g = 0;
b = 0;
createGSCanvas() {
if (!this.img) {
return;
shake(id) {
if (!this.baseX) {
this.baseX = this.x;
}
const rect = this.getBoundingBox();
if (rect.width <= 1 || rect.height <= 1) {
return;
const baseX = this.baseX;
const baseTime = 50;
const sequence = [
{target: {x: baseX + 40 * id}, time: baseTime - 25},
{target: {x: baseX - 20 * id}, time: baseTime},
{target: {x: baseX + 10 * id}, time: baseTime},
{target: {x: baseX - 5 * id}, time: baseTime},
{target: {x: baseX + 2 * id}, time: baseTime},
{target: {x: baseX - 1 * id}, time: baseTime},
{target: {x: baseX}, time: baseTime},
];
const self = this;
function runSequence() {
if (self['shakeTween']) {
self['shakeTween'].stop();
}
const tween = new TWEEN.Tween(self);
if (sequence.length > 0) {
const action = sequence.shift();
tween.to(action['target'], action['time']);
tween.onComplete( () => {
runSequence();
});
tween.start();
self['shakeTween'] = tween;
}
const c = this.ctx.getImageData(rect.x, rect.y, rect.width, rect.height);
for ( let i = 0; i < c.height; i++) {
for ( let j = 0; j < c.width; j++) {
const x = (i * 4) * c.width + ( j * 4 );
const r = c.data[x];
const g = c.data[x + 1];
const b = c.data[x + 2];
c.data[x] = this.r;
c.data[x + 1] = this.g;
c.data[x + 2] = this.b;
// c.data[x] = c.data[x + 1] = c.data[x + 2] = (r + g + b) / 3 ;
// // c.data[x + 3] = 255;
}
runSequence();
}
this.ctx.putImageData(c, rect.x, rect.y, 0, 0, rect.width, rect.height);
drop(targetY, callBack = null) {
const self = this;
const time = Math.abs(targetY - this.y) * 2.4;
this.alpha = 1;
const tween = new TWEEN.Tween(this)
.to({ y: targetY }, time)
.easing(TWEEN.Easing.Cubic.In)
.onComplete(function() {
// self.hideItem(callBack);
if (callBack) {
callBack();
}
drawSelf() {
super.drawSelf();
this.createGSCanvas();
})
.start();
}
}
export class GrayscaleSpr extends MySprite {
grayScale = 120;
createGSCanvas() {
export class EndSpr extends MySprite {
show(s) {
this.scaleX = this.scaleY = 0;
this.alpha = 0;
const tween = new TWEEN.Tween(this)
.to({ alpha: 1, scaleX: s, scaleY: s }, 800)
.easing(TWEEN.Easing.Elastic.Out) // Use an easing function to make the animation smooth.
.onComplete(function() {
if (!this.img) {
return;
})
.start(); // Start the tween immediately.
}
}
const rect = this.getBoundingBox();
const c = this.ctx.getImageData(rect.x, rect.y, rect.width, rect.height);
for ( let i = 0; i < c.height; i++) {
for ( let j = 0; j < c.width; j++) {
const x = (i * 4) * c.width + ( j * 4 );
const r = c.data[x];
const g = c.data[x + 1];
const b = c.data[x + 2];
// const a = c.data[x + 3];
c.data[x] = c.data[x + 1] = c.data[x + 2] = this.grayScale; // (r + g + b) / 3;
// c.data[x + 3] = 255;
}
export class ShapeRect extends MySprite {
fillColor = '#FF0000';
setSize(w, h) {
this.width = w;
this.height = h;
}
this.ctx.putImageData(c, rect.x, rect.y, 0, 0, rect.width, rect.height);
drawShape() {
this.ctx.fillStyle = this.fillColor;
this.ctx.fillRect(this._offX, this._offY, this.width, this.height);
}
drawSelf() {
super.drawSelf();
this.createGSCanvas();
this.drawShape();
}
}
export class HotZoneItem extends MySprite {
lineDashFlag = false;
arrow: MySprite;
label: Label;
text;
arrowTop;
arrowRight;
export class BitMapLabel extends MySprite {
labelArr;
baseUrl;
setText(data, text) {
this.labelArr = [];
const labelArr = [];
const tmpArr = text.split('');
let totalW = 0;
let h = 0;
for (const tmp of tmpArr) {
const label = new MySprite(this.ctx);
label.init(data[tmp], 0);
this.addChild(label);
labelArr.push(label);
totalW += label.width;
h = label.height;
}
this.width = totalW;
setSize(w, h) {
this.width = w;
this.height = h;
let offX = -totalW / 2;
for (const label of labelArr) {
label.x = offX;
offX += label.width;
}
this.labelArr = labelArr;
const rect = new ShapeRect(this.ctx);
rect.x = -w / 2;
rect.y = -h / 2;
rect.setSize(w, h);
rect.fillColor = '#FFFFFF';
rect.alpha = 0.2;
this.addChild(rect);
}
}
export class Label extends MySprite {
private _text: string;
// fontSize:String = '40px';
fontName = 'Verdana';
textAlign = 'left';
fontSize = 40;
fontColor = '#000000';
fontWeight = 900;
_maxWidth;
outline = 0;
outlineColor = '#ffffff';
// _shadowFlag = false;
// _shadowColor;
// _shadowOffsetX;
// _shadowOffsetY;
// _shadowBlur;
_outlineFlag = false;
_outLineWidth;
_outLineColor;
constructor(ctx = null) {
super(ctx);
this.init();
}
get text(): string {
return this._text;
}
set text(value: string) {
this._text = value;
this.refreshSize();
}
refreshSize() {
this.ctx.save();
this.ctx.font = `${this.fontSize * this.scaleX}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.fontWeight = this.fontWeight;
this._width = this.ctx.measureText(this.text).width;
this._height = this.fontSize;
this.refreshAnchorOff();
this.ctx.restore();
}
setMaxSize(w) {
this._maxWidth = w;
this.refreshSize();
if (this.width >= w) {
this.scaleX *= w / this.width;
this.scaleY *= w / this.width;
}
}
show(callBack = null) {
this.visible = true;
if (this.alpha >= 1) {
return;
}
const tween = new TWEEN.Tween(this)
.to({ alpha: 1 }, 800)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
if (callBack) {
callBack();
}
})
.start(); // Start the tween immediately.
}
setOutline(width = 5, color = '#ffffff') {
this._outlineFlag = true;
this._outLineWidth = width;
this._outLineColor = color;
}
drawText() {
if (!this.text) { return; }
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.fontWeight = this.fontWeight;
if (this._outlineFlag) {
this.ctx.lineWidth = this._outLineWidth;
this.ctx.strokeStyle = this._outLineColor;
this.ctx.strokeText(this.text, 0, 0);
}
this.ctx.fillStyle = this.fontColor;
if (this.outline > 0) {
this.ctx.lineWidth = this.outline;
this.ctx.strokeStyle = this.outlineColor;
this.ctx.strokeText(this.text, 0, 0);
}
this.ctx.fillText(this.text, 0, 0);
}
drawSelf() {
super.drawSelf();
this.drawText();
}
}
export class RichTextOld extends Label {
textArr = [];
fontSize = 40;
setText(text: string, words) {
let newText = text;
for (const word of words) {
const re = new RegExp(word, 'g');
newText = newText.replace( re, `#${word}#`);
// newText = newText.replace(word, `#${word}#`);
}
this.textArr = newText.split('#');
this.text = newText;
// this.setSize();
showLabel(text = null) {
if (!this.label) {
this.label = new Label(this.ctx);
// this.label.anchorY = 0;
this.label.fontSize = '40px';
this.label.textAlign = 'center';
this.label.color = "#7a4250"
this.addChild(this.label);
this.refreshLabelScale();
}
refreshSize() {
this.ctx.save();
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.fontWeight = this.fontWeight;
let curX = 0;
for (const text of this.textArr) {
const w = this.ctx.measureText(text).width;
curX += w;
if (text) {
this.label.text = text;
} else if (this.text) {
this.label.text = this.text;
}
this.width = curX;
this.height = this.fontSize;
this.refreshAnchorOff();
this.ctx.restore();
this.label.visible = true;
}
show(callBack = null) {
// console.log(' in show ');
this.visible = true;
// this.alpha = 0;
const tween = new TWEEN.Tween(this)
.to({ alpha: 1 }, 800)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
if (callBack) {
callBack();
hideLabel() {
if (!this.label) { return; }
this.label.visible = false;
}
})
.start(); // Start the tween immediately.
refreshLabelScale() {
if (this.scaleX == this.scaleY) {
this.label.setScaleXY(1);
}
drawText() {
// console.log('in drawText', this.text);
if (!this.text) { return; }
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.fontWeight = 900;
this.ctx.lineWidth = 5;
this.ctx.strokeStyle = '#ffffff';
// this.ctx.strokeText(this.text, 0, 0);
this.ctx.fillStyle = '#000000';
// this.ctx.fillText(this.text, 0, 0);
let curX = 0;
for (let i = 0; i < this.textArr.length; i++) {
const w = this.ctx.measureText(this.textArr[i]).width;
if ((i + 1) % 2 === 0) {
this.ctx.fillStyle = '#c8171e';
if (this.scaleX > this.scaleY) {
this.label.scaleX = this.scaleY / this.scaleX;
} else {
this.ctx.fillStyle = '#000000';
}
this.ctx.fillText(this.textArr[i], curX, 0);
curX += w;
}
}
}
export class RichText extends Label {
disH = 30;
constructor(ctx?: any) {
super(ctx);
// this.dataArr = dataArr;
this.label.scaleY = this.scaleX / this.scaleY;
}
drawText() {
if (!this.text) {
return;
}
showLineDash() {
this.lineDashFlag = true;
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.fontWeight = this.fontWeight;
this.ctx.fillStyle = this.fontColor;
const selfW = this.width * this.scaleX;
const chr = this.text.split(' ');
let temp = '';
const row = [];
const w = selfW - 80;
const disH = (this.fontSize + this.disH) * this.scaleY;
for (const c of chr) {
if (this.ctx.measureText(temp).width < w && this.ctx.measureText(temp + (c)).width <= w) {
temp += ' ' + c;
if (this.arrow) {
this.arrow.visible = true;
} else {
row.push(temp);
temp = ' ' + c;
}
}
row.push(temp);
const x = 0;
const y = -row.length * disH / 2;
// for (let b = 0 ; b < row.length; b++) {
// this.ctx.strokeText(row[b], x, y + ( b + 1 ) * disH ); // 每行字体y坐标间隔20
// }
this.arrow = new MySprite(this.ctx);
this.arrow.load('assets/play/common/arrow.png', 1, 0);
this.arrow.setScaleXY(0.06);
this.arrowTop = new MySprite(this.ctx);
this.arrowTop.load('assets/play/common/arrow_top.png', 0.5, 0);
this.arrowTop.setScaleXY(0.06);
if (this._outlineFlag) {
this.ctx.lineWidth = this._outLineWidth;
this.ctx.strokeStyle = this._outLineColor;
for (let b = 0 ; b < row.length; b++) {
this.ctx.strokeText(row[b], x, y + ( b + 1 ) * disH ); // 每行字体y坐标间隔20
}
// this.ctx.strokeText(this.text, 0, 0);
this.arrowRight = new MySprite(this.ctx);
this.arrowRight.load('assets/play/common/arrow_right.png', 1, 0.5);
this.arrowRight.setScaleXY(0.06);
}
// this.ctx.fillStyle = '#ff7600';
for (let b = 0 ; b < row.length; b++) {
this.ctx.fillText(row[b], x, y + ( b + 1 ) * disH ); // 每行字体y坐标间隔20
this.showLabel();
}
hideLineDash() {
this.lineDashFlag = false;
if (this.arrow) {
this.arrow.visible = false;
}
drawSelf() {
super.drawSelf();
this.drawText();
this.hideLabel();
}
}
drawArrow() {
if (!this.arrow) { return; }
const rect = this.getBoundingBox();
this.arrow.x = rect.x + rect.width;
this.arrow.y = rect.y;
this.arrow.update();
export class LineRect extends MySprite {
lineColor = '#ffffff';
lineWidth = 10;
this.arrowTop.x = rect.x + rect.width / 2;
this.arrowTop.y = rect.y;
this.arrowTop.update();
setSize(w, h) {
this.width = w;
this.height = h;
this.arrowRight.x = rect.x + rect.width;
this.arrowRight.y = rect.y + rect.height / 2;
this.arrowRight.update();
}
drawLine() {
drawFrame() {
this.ctx.save();
const rect = this.getBoundingBox();
const w = rect.width;
const h = rect.height;
const x = rect.x + w / 2;
const y = rect.y + h / 2;
this.ctx.setLineDash([5, 5]);
this.ctx.lineWidth = 2;
this.ctx.strokeStyle = '#1bfff7';
this.ctx.beginPath();
this.ctx.moveTo(this._offX, this._offY);
this.ctx.lineTo(this._offX + this.width, this._offY);
this.ctx.lineTo(this._offX + this.width, this._offY + this.height);
this.ctx.lineTo(this._offX, this._offY + this.height);
this.ctx.closePath();
this.ctx.lineWidth = this.lineWidth;
// this.ctx.fillStyle = "rgb(2,33,42)"; //指定填充颜色
// this.ctx.fill(); //对多边形进行填充
this.ctx.strokeStyle = this.lineColor; // "#ffffff";
this.ctx.moveTo( x - w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y - h / 2);
this.ctx.stroke();
this.ctx.restore();
}
drawSelf() {
super.drawSelf();
this.drawLine();
}
}
export class ShapeRect extends MySprite {
fillColor = '#FF0000';
setSize(w, h) {
this.width = w;
this.height = h;
// console.log('w:', w);
// console.log('h:', h);
}
drawShape() {
this.ctx.fillStyle = this.fillColor;
this.ctx.fillRect(this._offX, this._offY, this.width, this.height);
}
drawSelf() {
super.drawSelf();
this.drawShape();
}
}
export class Line extends MySprite {
lineWidth = 5;
lineColor = '#000000';
_pointArr = [];
roundFlag = true;
_pointS = 1;
imgObj;
bitMap;
_offCtx;
_offCanvas;
lastPointIndex = 0;
init() {
const canvas = window['curCanvas'];
const w = canvas.nativeElement.width;
const h = canvas.nativeElement.height;
console.log('w: ', w);
console.log('h: ', h);
this._offCanvas = document.createElement('canvas');
this._offCanvas.width = w;
this._offCanvas.height = h;
// this._offCanvas = _offCanvas;
// this._offCtx = this._offCanvas.getContext('2d');
// this._offCanvas = new OffscreenCanvas(w, h);
this._offCtx = this._offCanvas.getContext('2d');
}
addPoint(x, y) {
this._pointArr.push([x, y]);
if (this._pointArr.length < 2) {
return;
}
//
// const lastP = this._pointArr[this._pointArr.length - 1];
//
//
// const context = this._offCtx;
// context.moveTo (lastP[0], lastP[1]); // 设置起点状态
// context.lineTo (x, y); // 设置末端状态
//
// context.lineWidth = this.lineWidth; //设置线宽状态
// context.strokeStyle = this.lineColor;
// context.stroke();
//
//
// this.bitMap = this._offCanvas.transferToImageBitmap();
// const tmpLine = new MySprite(this._offCtx);
// tmpLine.init(this.imgObj);
// tmpLine.anchorY = 1;
// tmpLine.anchorX = 0.5;
// tmpLine.x = lastP[0];
// tmpLine.y = lastP[1];
//
// const disH = getPosDistance(lastP[0], lastP[1], x, y);
// tmpLine.scaleX = this.lineWidth / tmpLine.width;
// tmpLine.scaleY = disH / tmpLine.height * 1.1;
//
// const angle = getAngleByPos(lastP[0], lastP[1], x, y);
// tmpLine.rotation = angle;
//
// this.addChild(tmpLine);
}
setPointArr(arr, imgObj) {
this.removeChildren();
if (arr.length < 2) {
return;
}
let p1 = arr[0];
let p2;
for (let i = 1; i < arr.length; i++) {
p2 = arr[i];
const tmpLine = new MySprite();
tmpLine.init(imgObj);
tmpLine.anchorY = 1;
tmpLine.anchorX = 0.5;
tmpLine.x = p1[0];
tmpLine.y = p1[1];
const disH = getPosDistance(p1[0], p1[1], p2[0], p2[1]);
tmpLine.scaleX = this.lineWidth / tmpLine.width;
tmpLine.scaleY = disH / tmpLine.height * 1.1;
const angle = getAngleByPos(p1[0], p1[1], p2[0], p2[1]);
tmpLine.rotation = angle;
this.addChild(tmpLine);
p1 = p2;
}
}
drawLine() {
if (this._pointArr.length < 2) {
return;
}
const curMaxPointIndex = this._pointArr.length - 1;
if (curMaxPointIndex > this.lastPointIndex) {
const arr = this._pointArr;
const context = this._offCtx;
context.moveTo (arr[this.lastPointIndex][0] * this._pointS, arr[this.lastPointIndex][1] * this._pointS); // 设置起点状态
for (let i = this.lastPointIndex + 1; i < arr.length; i++) {
context.lineTo (arr[i][0] * this._pointS, arr[i][1] * this._pointS); // 设置末端状态
}
if (this.roundFlag) {
context.lineCap = "round";
}
context.lineWidth = this.lineWidth; //设置线宽状态
context.strokeStyle = this.lineColor;
context.stroke();
this.lastPointIndex = curMaxPointIndex;
// this.bitMap = this._offCanvas.transferToImageBitmap();
}
// this.ctx.drawImage(this.bitMap, this._offX, this._offY);
this.ctx.drawImage(this._offCanvas, this._offX, this._offY);
}
drawSelf() {
super.drawSelf();
this.drawLine();
// if (this.img) {
// this.ctx.drawImage(this._offCanvas, 0, 0, this.width, this.height);
// }
// if (this.bitMap) {
// this.bitMap = this._offCanvas.transferToImageBitmap();
// this.ctx.drawImage(this.bitMap, 0, 0, this.width, this.height);
// }
}
}
export class ShapeCircle extends MySprite {
fillColor = '#FF0000';
radius = 0;
setRadius(r) {
this.anchorX = this.anchorY = 0.5;
this.radius = r;
this.width = r * 2;
this.height = r * 2;
}
drawShape() {
this.ctx.beginPath();
this.ctx.fillStyle = this.fillColor;
this.ctx.arc(0, 0, this.radius, 0, angleToRadian(360));
this.ctx.fill();
}
drawSelf() {
super.drawSelf();
this.drawShape();
}
}
export class ShapeRectNew extends MySprite {
radius = 0;
fillColor = '#ffffff';
strokeColor = '#000000';
fill = true;
stroke = false;
lineWidth = 1;
setSize(w, h, r) {
this.width = w;
this.height = h;
this.radius = r;
}
setOutLine(color, lineWidth) {
this.stroke = true;
this.strokeColor = color;
this.lineWidth = lineWidth;
}
drawShape() {
const ctx = this.ctx;
const width = this.width;
const height = this.height;
const radius = this.radius;
ctx.save();
ctx.beginPath(0);
// 从右下角顺时针绘制,弧度从0到1/2PI
ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
// 矩形下边线
ctx.lineTo(radius, height);
// 左下角圆弧,弧度从1/2PI到PI
ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
// 矩形左边线
ctx.lineTo(0, radius);
// 左上角圆弧,弧度从PI到3/2PI
ctx.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
// 上边线
ctx.lineTo(width - radius, 0);
// 右上角圆弧
ctx.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
// 右边线
ctx.lineTo(width, height - radius);
ctx.closePath();
if (this.fill) {
ctx.fillStyle = this.fillColor;
ctx.fill();
}
if (this.stroke) {
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.strokeColor;
ctx.stroke();
}
ctx.restore();
}
drawSelf() {
super.drawSelf();
this.drawShape();
}
}
export class MyAnimation extends MySprite {
frameArr = [];
frameIndex = 0;
playFlag = false;
lastDateTime;
curDelay = 0;
loop = false;
playEndFunc;
delayPerUnit = 1;
restartFlag = false;
reverseFlag = false;
addFrameByImg(img) {
const spr = new MySprite(this.ctx);
spr.init(img);
this._refreshSize(img);
spr.visible = false;
this.addChild(spr);
this.frameArr.push(spr);
this.frameArr[this.frameIndex].visible = true;
}
addFrameByUrl(url) {
const spr = new MySprite(this.ctx);
spr.load(url).then(img => {
this._refreshSize(img);
});
spr.visible = false;
this.addChild(spr);
this.frameArr.push(spr);
this.frameArr[this.frameIndex].visible = true;
}
_refreshSize(img: any) {
if (this.width < img.width) {
this.width = img.width;
}
if (this.height < img.height) {
this.height = img.height;
}
}
play() {
this.playFlag = true;
this.lastDateTime = new Date().getTime();
}
stop() {
this.playFlag = false;
}
replay() {
this.restartFlag = true;
this.play();
}
reverse() {
this.reverseFlag = !this.reverseFlag;
this.frameArr.reverse();
this.frameIndex = 0;
}
showAllFrame() {
for (const frame of this.frameArr ) {
frame.alpha = 1;
}
}
hideAllFrame() {
for (const frame of this.frameArr) {
frame.alpha = 0;
}
}
playEnd() {
this.playFlag = false;
this.curDelay = 0;
this.frameArr[this.frameIndex].visible = true;
if (this.playEndFunc) {
this.playEndFunc();
this.playEndFunc = null;
}
}
updateFrame() {
if (this.frameArr[this.frameIndex]) {
this.frameArr[this.frameIndex].visible = false;
}
this.frameIndex ++;
if (this.frameIndex >= this.frameArr.length) {
if (this.loop) {
this.frameIndex = 0;
} else if (this.restartFlag) {
this.restartFlag = false;
this.frameIndex = 0;
} else {
this.frameIndex -- ;
this.playEnd();
return;
}
}
this.frameArr[this.frameIndex].visible = true;
}
_updateDelay(delay) {
this.curDelay += delay;
if (this.curDelay < this.delayPerUnit) {
return;
}
this.curDelay -= this.delayPerUnit;
this.updateFrame();
}
_updateLastDate() {
if (!this.playFlag) { return; }
let delay = 0;
if (this.lastDateTime) {
delay = (new Date().getTime() - this.lastDateTime) / 1000;
}
this.lastDateTime = new Date().getTime();
this._updateDelay(delay);
}
update($event: any = null) {
super.update($event);
this._updateLastDate();
}
}
// --------=========== util func =============-------------
export function tweenChange(item, obj, time = 0.8, callBack = null, easing = null, update = null) {
const tween = new TWEEN.Tween(item).to(obj, time * 1000);
if (callBack) {
tween.onComplete(() => {
callBack();
});
}
if (easing) {
tween.easing(easing);
}
if (update) {
tween.onUpdate( (a, b) => {
update(a, b);
});
}
tween.start();
return tween;
}
export function rotateItem(item, rotation, time = 0.8, callBack = null, easing = null) {
const tween = new TWEEN.Tween(item).to({ rotation }, time * 1000);
if (callBack) {
tween.onComplete(() => {
callBack();
});
}
if (easing) {
tween.easing(easing);
}
tween.start();
}
export function scaleItem(item, scale, time = 0.8, callBack = null, easing = null) {
const tween = new TWEEN.Tween(item).to({ scaleX: scale, scaleY: scale}, time * 1000);
if (callBack) {
tween.onComplete(() => {
callBack();
});
}
if (easing) {
tween.easing(easing);
}
tween.start();
return tween;
}
export function moveItem(item, x, y, time = 0.8, callBack = null, easing = null) {
const tween = new TWEEN.Tween(item).to({ x, y}, time * 1000);
if (callBack) {
tween.onComplete(() => {
callBack();
});
}
if (easing) {
tween.easing(easing);
}
tween.start();
return tween;
}
export function endShow(item, s = 1) {
item.scaleX = item.scaleY = 0;
item.alpha = 0;
const tween = new TWEEN.Tween(item)
.to({ alpha: 1, scaleX: s, scaleY: s }, 800)
.easing(TWEEN.Easing.Elastic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
})
.start();
}
export function hideItem(item, time = 0.8, callBack = null, easing = null) {
if (item.alpha === 0) {
return;
}
const tween = new TWEEN.Tween(item)
.to({alpha: 0}, time * 1000)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
if (callBack) {
callBack();
}
});
if (easing) {
tween.easing(easing);
}
tween.start();
}
export function showItem(item, time = 0.8, callBack = null, easing = null) {
if (item.alpha === 1) {
if (callBack) {
callBack();
}
return;
}
item.visible = true;
const tween = new TWEEN.Tween(item)
.to({alpha: 1}, time * 1000)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
if (callBack) {
callBack();
}
});
if (easing) {
tween.easing(easing);
}
tween.start();
}
export function alphaItem(item, alpha, time = 0.8, callBack = null, easing = null) {
const tween = new TWEEN.Tween(item)
.to({alpha}, time * 1000)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
if (callBack) {
callBack();
}
});
if (easing) {
tween.easing(easing);
}
tween.start();
}
export function showStar(item, time = 0.8, callBack = null, easing = null) {
const tween = new TWEEN.Tween(item)
.to({alpha: 1, scale: 1}, time * 1000)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
if (callBack) {
callBack();
}
});
if (easing) {
tween.easing(easing);
}
tween.start();
}
export function randomSortByArr(arr) {
if (!arr) {
return;
}
const newArr = [];
const tmpArr = arr.concat();
while (tmpArr.length > 0) {
const randomIndex = Math.floor( tmpArr.length * Math.random() );
newArr.push(tmpArr[randomIndex]);
tmpArr.splice(randomIndex, 1);
}
return newArr;
}
export function radianToAngle(radian) {
return radian * 180 / Math.PI;
// 角度 = 弧度 * 180 / Math.PI;
}
export function angleToRadian(angle) {
return angle * Math.PI / 180;
// 弧度= 角度 * Math.PI / 180;
}
export function getPosByAngle(angle, len) {
const radian = angle * Math.PI / 180;
const x = Math.sin(radian) * len;
const y = Math.cos(radian) * len;
return {x, y};
}
export function getAngleByPos(px, py, mx, my) {
const x = Math.abs(px - mx);
const y = Math.abs(py - my);
const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
const cos = y / z;
const radina = Math.acos(cos); // 用反三角函数求弧度
let angle = Math.floor(180 / (Math.PI / radina) * 100) / 100; // 将弧度转换成角度
if (mx > px && my > py) {// 鼠标在第四象限
angle = 180 - angle;
}
if (mx === px && my > py) {// 鼠标在y轴负方向上
angle = 180;
}
if (mx > px && my === py) {// 鼠标在x轴正方向上
angle = 90;
}
if (mx < px && my > py) {// 鼠标在第三象限
angle = 180 + angle;
}
if (mx < px && my === py) {// 鼠标在x轴负方向
angle = 270;
}
if (mx < px && my < py) {// 鼠标在第二象限
angle = 360 - angle;
}
// console.log('angle: ', angle);
return angle;
}
export function removeItemFromArr(arr, item) {
const index = arr.indexOf(item);
if (index !== -1) {
arr.splice(index, 1);
}
}
export function circleMove(item, x0, y0, time = 2, addR = 360, xPer = 1, yPer = 1, callBack = null, easing = null) {
const r = getPosDistance(item.x, item.y, x0, y0);
let a = getAngleByPos(item.x, item.y, x0, y0);
a += 90;
const obj = {r, a};
item._circleAngle = a;
const targetA = a + addR;
const tween = new TWEEN.Tween(item).to({_circleAngle: targetA}, time * 1000);
if (callBack) {
tween.onComplete(() => {
callBack();
});
}
if (easing) {
tween.easing(easing);
}
tween.onUpdate( (item, progress) => {
// console.log(item._circleAngle);
const r = obj.r;
const a = item._circleAngle;
const x = x0 + r * xPer * Math.cos(a * Math.PI / 180);
const y = y0 + r * yPer * Math.sin(a * Math.PI / 180);
item.x = x;
item.y = y;
// obj.a ++;
});
tween.start();
}
export function getPosDistance(sx, sy, ex, ey) {
const _x = ex - sx;
const _y = ey - sy;
const len = Math.sqrt( Math.pow(_x, 2) + Math.pow(_y, 2) );
return len;
}
export function delayCall(callback, second) {
const tween = new TWEEN.Tween(this)
.delay(second * 1000)
.onComplete(() => {
if (callback) {
callback();
}
})
.start();
}
export function formatTime(fmt, date) {
// "yyyy-MM-dd HH:mm:ss";
const o = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'h+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
S: date.getMilliseconds() // 毫秒
};
if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); }
for (const k in o) {
if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1)
? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
}
}
return fmt;
}
export function getMinScale(item, maxLen) {
const sx = maxLen / item.width;
const sy = maxLen / item.height;
const minS = Math.min(sx, sy);
return minS;
}
export function jelly(item, time = 0.7) {
if (item.jellyTween) {
TWEEN.remove(item.jellyTween);
}
const t = time / 9;
const baseSX = item.scaleX;
const baseSY = item.scaleY;
let index = 0;
const run = () => {
if (index >= arr.length) {
item.jellyTween = null;
return;
}
const data = arr[index];
const t = tweenChange(item, {scaleX: data[0], scaleY: data[1]}, data[2], () => {
index ++;
run();
}, TWEEN.Easing.Sinusoidal.InOut);
item.jellyTween = t;
};
const arr = [
[baseSX * 1.1, baseSY * 0.9, t],
[baseSX * 0.98, baseSY * 1.02, t * 2],
[baseSX * 1.02, baseSY * 0.98, t * 2],
[baseSX * 0.99, baseSY * 1.01, t * 2],
[baseSX * 1.0, baseSY * 1.0, t * 2],
];
run();
}
export function showPopParticle(img, pos, parent, num = 20, minLen = 40, maxLen = 80, showTime = 0.4) {
for (let i = 0; i < num; i ++) {
const particle = new MySprite();
particle.init(img);
particle.x = pos.x;
particle.y = pos.y;
parent.addChild(particle);
const randomR = 360 * Math.random();
particle.rotation = randomR;
const randomS = 0.3 + Math.random() * 0.7;
particle.setScaleXY(randomS * 0.3);
const randomX = Math.random() * 20 - 10;
particle.x += randomX;
const randomY = Math.random() * 20 - 10;
particle.y += randomY;
const randomL = minLen + Math.random() * (maxLen - minLen);
const randomA = 360 * Math.random();
const randomT = getPosByAngle(randomA, randomL);
moveItem(particle, particle.x + randomT.x, particle.y + randomT.y, showTime, () => {
}, TWEEN.Easing.Exponential.Out);
// scaleItem(particle, 0, 0.6, () => {
//
// });
scaleItem(particle, randomS, 0.6, () => {
}, TWEEN.Easing.Exponential.Out);
setTimeout(() => {
hideItem(particle, 0.4, () => {
}, TWEEN.Easing.Cubic.In);
}, showTime * 0.5 * 1000);
}
}
export function shake(item, time = 0.5, callback = null, rate = 1) {
if (item.shakeTween) {
return;
}
item.shakeTween = true;
const offX = 15 * item.scaleX * rate;
const offY = 15 * item.scaleX * rate;
const baseX = item.x;
const baseY = item.y;
const easing = TWEEN.Easing.Sinusoidal.InOut;
const move4 = () => {
moveItem(item, baseX, baseY, time / 4, () => {
item.shakeTween = false;
if (callback) {
callback();
draw() {
super.draw();
if (this.lineDashFlag) {
this.drawFrame();
this.drawArrow();
}
}
}, easing);
};
const move3 = () => {
moveItem(item, baseX + offX / 4, baseY + offY / 4, time / 4, () => {
move4();
}, easing);
};
const move2 = () => {
moveItem(item, baseX - offX / 4 * 3, baseY - offY / 4 * 3, time / 4, () => {
move3();
}, easing);
};
const move1 = () => {
moveItem(item, baseX + offX, baseY + offY, time / 7.5, () => {
move2();
}, easing);
};
move1();
}
// --------------- custom class --------------------
export class HotZoneItem extends MySprite {
export class HotZoneImageItem extends MySprite {
index
lineDashFlag = false;
arrow: MySprite;
label: Label;
title;
image: MySprite;
image_url: String;
labelBox: MySprite;
audio_url: String;
attImage_url: String;
text = "";
type = "text";
card_audio_url: String
scale
arrowTop;
arrowRight;
audio_url;
pic_url;
text;
private _itemType;
private shapeRect: ShapeRect;
init(image_url = null, text?, type?, callback?, handleSave?){
let change = true;
if(type == this.type){
change = false
}
if(type && type=="Text"){
image_url = "assets/play/default/images/bg_50_50.png";
this.type = "Text"
}else if(!type){
this.type = "Text"
}
if(text){
this.text = text
}else{
this.text = ""
}
this.showImage(image_url, (img)=>{
callback && callback(img.width, img.height)
if(type == "Text"){
this.scaleX = 104 / img.width
this.scaleY = 78 / img.height
this.setSize(img.width*this.scaleX, img.height*this.scaleY)
}else{
this.setSize(img.width*this.image.scaleX, img.height*this.image.scaleY)
}
handleSave && handleSave()
this.lineDashFlag = true;
if(type == "Text"){
this.showLabel(text);
// this.arrow.visible = false
}else{
if(this.label){
this.removeChild(this.label)
}
this.drawArrow()
}
if(change){
this.showLineDash()
}
})
}
get itemType() {
return this._itemType;
initNew(callback?, handleSave?){
if(this.type && this.type=="Text"){
this.image_url = "assets/play/default/images/bg_50_50.png";
}
this.showImage(this.image_url, (img)=>{
callback && callback(img.width, img.height)
if(this.type == "Text"){
this.scaleX = 104 / img.width
this.scaleY = 78 / img.height
this.setSize(104, 78)
}else{
this.setSize(img.width*this.image.scaleX, img.height*this.image.scaleY)
}
handleSave && handleSave()
this.lineDashFlag = true;
if(this.type == "Text"){
this.showLabel(this.text);
}else{
this.showLabel(this.index);
}
set itemType(value) {
this._itemType = value;
this.drawArrow()
this.showLineDash()
})
}
setSize(w, h) {
this.width = w;
this.height = h;
const rect = new ShapeRect(this.ctx);
rect.x = -w / 2;
rect.y = -h / 2;
rect.setSize(w, h);
rect.fillColor = '#ffffff';
rect.alpha = 0.2;
this.addChild(rect);
}
showLabel(text = null) {
if (!this.label) {
this.labelBox = new MySprite(this.ctx);
this.labelBox.load('assets/play/default/images/bg_50_50.png').then(()=>{
this.labelBox.x = this.width/2;
this.labelBox.y = this.height/2;
});
this.label = new Label(this.ctx);
this.label.anchorY = 0;
this.label.fontSize = 40;
this.label.fontSize = "45";
this.label.textAlign = 'center';
this.addChild(this.label);
// this.label.scaleX = 1 / this.scaleX;
// this.label.scaleY = 1 / this.scaleY;
this.label.color = "#7A4250"
if(this.type == "Text"){
this.labelBox.visible = true
}else{
this.labelBox.visible = false
}
this.labelBox.addChild(this.label);
this.addChild(this.labelBox);
this.refreshLabelScale();
}
if (text) {
this.label.text = text;
} else if (this.title) {
this.label.text = this.title;
} else if (this.text) {
this.label.text = this.text;
}
this.label.visible = true;
}
hideLabel() {
if (!this.label) { return; }
this.label.visible = false;
}
refreshLabelScale() {
if (this.scaleX == this.scaleY) {
this.label.setScaleXY(1);
showImage(image_url = null, callback) {
this.loadImage(image_url).then((img)=>{
if(this.image){
this.removeChild(this.image)
}
this.image = new MySprite(this.ctx);
this.image.init(img)
this.image.x = this.image.width/2
this.image.y = this.image.height/2
this.image.alpha = 0.7;
this.image_url = image_url;
this.addChild(this.image,-1);
callback && callback(this.image)
})
}
if (this.scaleX > this.scaleY) {
this.label.scaleX = this.scaleY / this.scaleX;
} else {
this.label.scaleY = this.scaleX / this.scaleY;
loadImage(image_url = null){
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = image_url;
})
}
hideImage() {
if (!this.image) { return; }
this.image.visible = false;
}
refreshLabelScale() {
this.labelBox.scaleX = 75 / (this.labelBox.width*this.image.scaleX)
}
showLineDash() {
this.lineDashFlag = true;
if (this.arrow) {
this.arrow.visible = true;
} else {
this.arrow = new MySprite(this.ctx);
this.arrow.load('assets/common/arrow.png', 1, 0);
this.arrow.load('assets/play/common/arrow.png', 1, 0);
this.arrow.setScaleXY(0.06);
this.arrowTop = new MySprite(this.ctx);
this.arrowTop.load('assets/common/arrow_top.png', 0.5, 0);
this.arrowTop.load('assets/play/common/arrow_top.png', 0.5, 0);
this.arrowTop.setScaleXY(0.06);
this.arrowRight = new MySprite(this.ctx);
this.arrowRight.load('assets/common/arrow_right.png', 1, 0.5);
this.arrowRight.load('assets/play/common/arrow_right.png', 1, 0.5);
this.arrowRight.setScaleXY(0.06);
}
this.showLabel();
}
hideLineDash() {
this.lineDashFlag = false;
if (this.arrow) {
this.arrow.visible = false;
}
this.hideLabel();
}
drawArrow() {
if(this.offSetCenter){
if (!this.arrow) { return; }
const rect = this.getBoundingBox();
this.arrow.x = rect.x + rect.width / 2;
this.arrow.y = rect.y - rect.height / 2;
this.arrow.update();
this.arrowTop.x = rect.x
this.arrowTop.y = rect.y - rect.height / 2;
this.arrowTop.update();
this.arrowRight.x = rect.x + rect.width / 2;
this.arrowRight.y = rect.y //+ rect.height / 2;
this.arrowRight.update();
}else{
if (!this.arrow) { return; }
const rect = this.getBoundingBox();
this.arrow.x = rect.x + rect.width;
this.arrow.y = rect.y;
this.arrow.update();
this.arrowTop.x = rect.x + rect.width / 2;
this.arrowTop.y = rect.y;
this.arrowTop.update();
......@@ -2076,178 +639,92 @@ export class HotZoneItem extends MySprite {
this.arrowRight.y = rect.y + rect.height / 2;
this.arrowRight.update();
}
}
drawFrame() {
if(this.offSetCenter){
this.ctx.save();
const rect = this.getBoundingBox();
const w = rect.width;
const h = rect.height;
const x = rect.x + w / 2;
const y = rect.y + h / 2;
const x = rect.x// + w / 2;
const y = rect.y// + h / 2;
this.ctx.setLineDash([5, 5]);
this.ctx.lineWidth = 2;
this.ctx.strokeStyle = '#1bfff7';
// this.ctx.fillStyle = '#ffffff';
this.ctx.beginPath();
this.ctx.moveTo( x - w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y - h / 2);
// this.ctx.fill();
this.ctx.stroke();
this.ctx.restore();
}
draw() {
super.draw();
if (this.lineDashFlag) {
this.drawFrame();
this.drawArrow();
}
}
}
export class HotZoneImg extends MySprite {
drawFrame() {
}else{
this.ctx.save();
const rect = this.getBoundingBox();
const w = rect.width;
const h = rect.height;
const x = rect.x + w / 2;
const y = rect.y + h / 2;
this.ctx.setLineDash([5, 5]);
this.ctx.lineWidth = 2;
this.ctx.strokeStyle = '#1bfff7';
this.ctx.beginPath();
this.ctx.moveTo( x - w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y - h / 2);
// this.ctx.fill();
this.ctx.stroke();
this.ctx.restore();
}
draw() {
super.draw();
this.drawFrame();
}
}
export class HotZoneLabel extends Label {
drawFrame() {
this.ctx.save();
const rect = this.getBoundingBox();
const w = rect.width / this.scaleX;
const h = this.height * this.scaleY;
const x = this.x;
const y = this.y;
this.ctx.setLineDash([5, 5]);
this.ctx.lineWidth = 2;
this.ctx.strokeStyle = '#1bfff7';
this.ctx.beginPath();
this.ctx.moveTo( x - w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y - h / 2);
// this.ctx.fill();
this.ctx.stroke();
this.ctx.restore();
}
draw() {
super.draw();
if (this.lineDashFlag) {
this.drawFrame();
this.drawArrow();
}
}
}
export class EditorItem extends MySprite {
lineDashFlag = false;
arrow: MySprite;
label: Label;
label:Label;
text;
showLabel(text = null) {
if (!this.label) {
this.label = new Label(this.ctx);
this.label.anchorY = 0;
this.label.fontSize = 50;
this.label.fontSize = '50px';
this.label.textAlign = 'center';
this.addChild(this.label);
this.label.setScaleXY(1 / this.scaleX);
}
if (text) {
this.label.text = text;
} else if (this.text) {
this.label.text = this.text;
}
this.label.visible = true;
}
hideLabel() {
if (!this.label) { return; }
this.label.visible = false;
}
showLineDash() {
this.lineDashFlag = true;
if (this.arrow) {
this.arrow.visible = true;
} else {
this.arrow = new MySprite(this.ctx);
this.arrow.load('assets/common/arrow.png', 1, 0);
this.arrow.load('assets/play/common/arrow.png', 1, 0);
this.arrow.setScaleXY(0.06);
}
this.showLabel();
}
......@@ -2326,783 +803,89 @@ export class EditorItem extends MySprite {
//
//
// import TWEEN from '@tweenjs/tween.js';
//
//
// class Sprite {
// x = 0;
// y = 0;
// color = '';
// radius = 0;
// alive = false;
// margin = 0;
// angle = 0;
// ctx;
//
// constructor(ctx) {
// this.ctx = ctx;
// }
// update($event) {
// this.draw();
// }
// draw() {
//
// }
//
// }
//
//
//
//
//
// export class MySprite extends Sprite {
//
// width = 0;
// height = 0;
// _anchorX = 0;
// _anchorY = 0;
// _offX = 0;
// _offY = 0;
// scaleX = 1;
// scaleY = 1;
// alpha = 1;
// rotation = 0;
// visible = true;
//
// children = [this];
//
// img;
// _z = 0;
//
//
// init(imgObj = null, anchorX:number = 0.5, anchorY:number = 0.5) {
//
// if (imgObj) {
//
// this.img = imgObj;
//
// this.width = this.img.width;
// this.height = this.img.height;
// }
//
// this.anchorX = anchorX;
// this.anchorY = anchorY;
// }
//
//
//
// update($event = null) {
// if (this.visible) {
// this.draw();
// }
// }
// draw() {
//
// this.ctx.save();
//
// this.drawInit();
//
// this.updateChildren();
//
// this.ctx.restore();
// }
//
// drawInit() {
//
// this.ctx.translate(this.x, this.y);
//
// this.ctx.rotate(this.rotation * Math.PI / 180);
//
// this.ctx.scale(this.scaleX, this.scaleY);
//
// this.ctx.globalAlpha = this.alpha;
//
// }
//
// drawSelf() {
// if (this.img) {
// this.ctx.drawImage(this.img, this._offX, this._offY);
// }
// }
//
// updateChildren() {
//
// if (this.children.length <= 0) { return; }
//
// for (let i = 0; i < this.children.length; i++) {
//
// if (this.children[i] === this) {
//
// this.drawSelf();
// } else {
//
// this.children[i].update();
// }
// }
// }
//
//
// load(url, anchorX = 0.5, anchorY = 0.5) {
//
// return new Promise((resolve, reject) => {
// const img = new Image();
// img.onload = () => resolve(img);
// img.onerror = reject;
// img.src = url;
// }).then(img => {
//
// this.init(img, anchorX, anchorY);
// return img;
// });
// }
//
// addChild(child, z = 1) {
// if (this.children.indexOf(child) === -1) {
// this.children.push(child);
// child._z = z;
// child.parent = this;
// }
//
// this.children.sort((a, b) => {
// return a._z - b._z;
// });
//
// }
// removeChild(child) {
// const index = this.children.indexOf(child);
// if (index !== -1) {
// this.children.splice(index, 1);
// }
// }
//
// set anchorX(value) {
// this._anchorX = value;
// this.refreshAnchorOff();
// }
// get anchorX() {
// return this._anchorX;
// }
// set anchorY(value) {
// this._anchorY = value;
// this.refreshAnchorOff();
// }
// get anchorY() {
// return this._anchorY;
// }
// refreshAnchorOff() {
// this._offX = -this.width * this.anchorX;
// this._offY = -this.height * this.anchorY;
// }
//
// setScaleXY(value) {
// this.scaleX = this.scaleY = value;
// }
//
// getBoundingBox() {
//
// const x = this.x + this._offX * this.scaleX;
// const y = this.y + this._offY * this.scaleY;
// const width = this.width * this.scaleX;
// const height = this.height * this.scaleY;
//
// return {x, y, width, height};
// }
//
// }
//
//
//
//
//
// export class Item extends MySprite {
//
// baseX;
//
// move(targetY, callBack) {
//
// const self = this;
//
// const tween = new TWEEN.Tween(this)
// .to({ y: targetY }, 2500)
// .easing(TWEEN.Easing.Quintic.Out)
// .onComplete(function() {
//
// self.hide(callBack);
// // if (callBack) {
// // callBack();
// // }
// })
// .start();
//
// }
//
// show(callBack = null) {
//
// const tween = new TWEEN.Tween(this)
// .to({ alpha: 1 }, 800)
// // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
// .onComplete(function() {
// if (callBack) {
// callBack();
// }
// })
// .start(); // Start the tween immediately.
//
// }
//
// hide(callBack = null) {
//
// const tween = new TWEEN.Tween(this)
// .to({ alpha: 0 }, 800)
// // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
// .onComplete(function() {
// if (callBack) {
// callBack();
// }
// })
// .start(); // Start the tween immediately.
// }
//
//
// shake(id) {
//
//
// if (!this.baseX) {
// this.baseX = this.x;
// }
//
// const baseX = this.baseX;
// const baseTime = 50;
// const sequence = [
// {target: {x: baseX + 40 * id}, time: baseTime - 25},
// {target: {x: baseX - 20 * id}, time: baseTime},
// {target: {x: baseX + 10 * id}, time: baseTime},
// {target: {x: baseX - 5 * id}, time: baseTime},
// {target: {x: baseX + 2 * id}, time: baseTime},
// {target: {x: baseX - 1 * id}, time: baseTime},
// {target: {x: baseX}, time: baseTime},
//
// ];
//
//
// const self = this;
//
// function runSequence() {
//
// if (self['shakeTween']) {
// self['shakeTween'].stop();
// }
//
// const tween = new TWEEN.Tween(self);
//
// if (sequence.length > 0) {
// // console.log('sequence.length: ', sequence.length);
// const action = sequence.shift();
// tween.to(action['target'], action['time']);
// tween.onComplete( () => {
// runSequence();
// });
// tween.start();
//
// self['shakeTween'] = tween;
// }
// }
//
// runSequence();
//
// }
//
//
//
// drop(targetY, callBack = null) {
//
// const self = this;
//
// const time = Math.abs(targetY - this.y) * 2.4;
//
// this.alpha = 1;
//
// const tween = new TWEEN.Tween(this)
// .to({ y: targetY }, time)
// .easing(TWEEN.Easing.Cubic.In)
// .onComplete(function() {
//
// // self.hideItem(callBack);
// if (callBack) {
// callBack();
// }
// })
// .start();
//
//
// }
//
//
// }
//
//
// export class EndSpr extends MySprite {
//
// show(s) {
//
// this.scaleX = this.scaleY = 0;
// this.alpha = 0;
//
// const tween = new TWEEN.Tween(this)
// .to({ alpha: 1, scaleX: s, scaleY: s }, 800)
// .easing(TWEEN.Easing.Elastic.Out) // Use an easing function to make the animation smooth.
// .onComplete(function() {
//
// })
// .start(); // Start the tween immediately.
//
// }
// }
//
//
//
// export class ShapeRect extends MySprite {
//
// fillColor = '#FF0000';
//
// setSize(w, h) {
// this.width = w;
// this.height = h;
//
// console.log('w:', w);
// console.log('h:', h);
// }
//
// drawShape() {
//
// this.ctx.fillStyle = this.fillColor;
// this.ctx.fillRect(this._offX, this._offY, this.width, this.height);
//
// }
//
//
// drawSelf() {
// super.drawSelf();
// this.drawShape();
// }
// }
//
//
// export class HotZoneItem extends MySprite {
//
//
// lineDashFlag = false;
// arrow: MySprite;
// label: Label;
// title;
//
// arrowTop;
// arrowRight;
//
// audio_url;
// pic_url;
// text;
// private _itemType;
// private shapeRect: ShapeRect;
//
// get itemType() {
// return this._itemType;
// }
// set itemType(value) {
// this._itemType = value;
// }
//
// setSize(w, h) {
// this.width = w;
// this.height = h;
//
//
// const rect = new ShapeRect(this.ctx);
// rect.x = -w / 2;
// rect.y = -h / 2;
// rect.setSize(w, h);
// rect.fillColor = '#ffffff';
// rect.alpha = 0.2;
// this.addChild(rect);
// }
//
// showLabel(text = null) {
//
//
// if (!this.label) {
// this.label = new Label(this.ctx);
// this.label.anchorY = 0;
// this.label.fontSize = '40px';
// this.label.textAlign = 'center';
// this.addChild(this.label);
// // this.label.scaleX = 1 / this.scaleX;
// // this.label.scaleY = 1 / this.scaleY;
//
// this.refreshLabelScale();
//
// }
//
// if (text) {
// this.label.text = text;
// } else if (this.title) {
// this.label.text = this.title;
// }
// this.label.visible = true;
//
// }
//
// hideLabel() {
// if (!this.label) { return; }
//
// this.label.visible = false;
// }
//
// refreshLabelScale() {
// if (this.scaleX == this.scaleY) {
// this.label.setScaleXY(1);
// }
//
// if (this.scaleX > this.scaleY) {
// this.label.scaleX = this.scaleY / this.scaleX;
// } else {
// this.label.scaleY = this.scaleX / this.scaleY;
// }
// }
//
// showLineDash() {
// this.lineDashFlag = true;
//
// if (this.arrow) {
// this.arrow.visible = true;
// } else {
// this.arrow = new MySprite(this.ctx);
// this.arrow.load('assets/common/arrow.png', 1, 0);
// this.arrow.setScaleXY(0.06);
//
// this.arrowTop = new MySprite(this.ctx);
// this.arrowTop.load('assets/common/arrow_top.png', 0.5, 0);
// this.arrowTop.setScaleXY(0.06);
//
// this.arrowRight = new MySprite(this.ctx);
// this.arrowRight.load('assets/common/arrow_right.png', 1, 0.5);
// this.arrowRight.setScaleXY(0.06);
// }
//
// this.showLabel();
// }
//
// hideLineDash() {
//
// this.lineDashFlag = false;
//
// if (this.arrow) {
// this.arrow.visible = false;
// }
//
// this.hideLabel();
// }
//
//
//
// drawArrow() {
// if (!this.arrow) { return; }
//
// const rect = this.getBoundingBox();
// this.arrow.x = rect.x + rect.width;
// this.arrow.y = rect.y;
//
// this.arrow.update();
//
//
// this.arrowTop.x = rect.x + rect.width / 2;
// this.arrowTop.y = rect.y;
// this.arrowTop.update();
//
// this.arrowRight.x = rect.x + rect.width;
// this.arrowRight.y = rect.y + rect.height / 2;
// this.arrowRight.update();
// }
//
// drawFrame() {
//
//
// this.ctx.save();
//
//
// const rect = this.getBoundingBox();
//
// const w = rect.width;
// const h = rect.height;
// const x = rect.x + w / 2;
// const y = rect.y + h / 2;
//
// this.ctx.setLineDash([5, 5]);
// this.ctx.lineWidth = 2;
// this.ctx.strokeStyle = '#1bfff7';
// // this.ctx.fillStyle = '#ffffff';
//
// this.ctx.beginPath();
//
// this.ctx.moveTo( x - w / 2, y - h / 2);
//
// this.ctx.lineTo(x + w / 2, y - h / 2);
//
// this.ctx.lineTo(x + w / 2, y + h / 2);
//
// this.ctx.lineTo(x - w / 2, y + h / 2);
//
// this.ctx.lineTo(x - w / 2, y - h / 2);
//
// // this.ctx.fill();
// this.ctx.stroke();
//
//
//
//
// this.ctx.restore();
//
// }
//
// draw() {
// super.draw();
//
// if (this.lineDashFlag) {
// this.drawFrame();
// this.drawArrow();
// }
// }
// }
//
//
// export class EditorItem extends MySprite {
//
// lineDashFlag = false;
// arrow: MySprite;
// label:Label;
// text;
//
// showLabel(text = null) {
//
//
// if (!this.label) {
// this.label = new Label(this.ctx);
// this.label.anchorY = 0;
// this.label.fontSize = '50px';
// this.label.textAlign = 'center';
// this.addChild(this.label);
// this.label.setScaleXY(1 / this.scaleX);
// }
//
// if (text) {
// this.label.text = text;
// } else if (this.text) {
// this.label.text = this.text;
// }
// this.label.visible = true;
//
// }
//
// hideLabel() {
// if (!this.label) { return; }
//
// this.label.visible = false;
// }
//
// showLineDash() {
// this.lineDashFlag = true;
//
// if (this.arrow) {
// this.arrow.visible = true;
// } else {
// this.arrow = new MySprite(this.ctx);
// this.arrow.load('assets/common/arrow.png', 1, 0);
// this.arrow.setScaleXY(0.06);
//
// }
//
// this.showLabel();
// }
//
// hideLineDash() {
//
// this.lineDashFlag = false;
//
// if (this.arrow) {
// this.arrow.visible = false;
// }
//
// this.hideLabel();
// }
//
//
//
// drawArrow() {
// if (!this.arrow) { return; }
//
// const rect = this.getBoundingBox();
// this.arrow.x = rect.x + rect.width;
// this.arrow.y = rect.y;
//
// this.arrow.update();
// }
//
// drawFrame() {
//
//
// this.ctx.save();
//
//
// const rect = this.getBoundingBox();
//
// const w = rect.width;
// const h = rect.height;
// const x = rect.x + w / 2;
// const y = rect.y + h / 2;
//
// this.ctx.setLineDash([5, 5]);
// this.ctx.lineWidth = 2;
// this.ctx.strokeStyle = '#1bfff7';
// // this.ctx.fillStyle = '#ffffff';
//
// this.ctx.beginPath();
//
// this.ctx.moveTo( x - w / 2, y - h / 2);
//
// this.ctx.lineTo(x + w / 2, y - h / 2);
//
// this.ctx.lineTo(x + w / 2, y + h / 2);
//
// this.ctx.lineTo(x - w / 2, y + h / 2);
//
// this.ctx.lineTo(x - w / 2, y - h / 2);
//
// // this.ctx.fill();
// this.ctx.stroke();
//
//
//
//
// this.ctx.restore();
//
// }
//
// draw() {
// super.draw();
//
// if (this.lineDashFlag) {
// this.drawFrame();
// this.drawArrow();
// }
// }
// }
//
//
//
// export class Label extends MySprite {
//
// text:String;
// fontSize:String = '40px';
// fontName:String = 'Verdana';
// textAlign:String = 'left';
//
//
// constructor(ctx) {
// super(ctx);
// this.init();
// }
//
// drawText() {
//
// // console.log('in drawText', this.text);
//
// if (!this.text) { return; }
//
// this.ctx.font = `${this.fontSize} ${this.fontName}`;
// this.ctx.textAlign = this.textAlign;
// this.ctx.textBaseline = 'middle';
// this.ctx.fontWeight = 900;
//
// this.ctx.lineWidth = 5;
// this.ctx.strokeStyle = '#ffffff';
// this.ctx.strokeText(this.text, 0, 0);
//
// this.ctx.fillStyle = '#000000';
// this.ctx.fillText(this.text, 0, 0);
//
//
// }
//
//
// drawSelf() {
// super.drawSelf();
// this.drawText();
// }
//
// }
//
//
//
// export function getPosByAngle(angle, len) {
//
// const radian = angle * Math.PI / 180;
// const x = Math.sin(radian) * len;
// const y = Math.cos(radian) * len;
//
// return {x, y};
//
// }
//
// export function getAngleByPos(px, py, mx, my) {
//
// // const _x = p2x - p1x;
// // const _y = p2y - p1y;
// // const tan = _y / _x;
// //
// // const radina = Math.atan(tan); // 用反三角函数求弧度
// // const angle = Math.floor(180 / (Math.PI / radina)); //
// //
// // console.log('r: ' , angle);
// // return angle;
// //
//
//
//
// const x = Math.abs(px - mx);
// const y = Math.abs(py - my);
// // const x = Math.abs(mx - px);
// // const y = Math.abs(my - py);
// const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
// const cos = y / z;
// const radina = Math.acos(cos); // 用反三角函数求弧度
// let angle = Math.floor(180 / (Math.PI / radina) * 100) / 100; // 将弧度转换成角度
//
// if(mx > px && my > py) {// 鼠标在第四象限
// angle = 180 - angle;
// }
//
// if(mx === px && my > py) {// 鼠标在y轴负方向上
// angle = 180;
// }
//
// if(mx > px && my === py) {// 鼠标在x轴正方向上
// angle = 90;
// }
//
// if(mx < px && my > py) {// 鼠标在第三象限
// angle = 180 + angle;
// }
//
// if(mx < px && my === py) {// 鼠标在x轴负方向
// angle = 270;
// }
//
// if(mx < px && my < py) {// 鼠标在第二象限
// angle = 360 - angle;
// }
//
// // console.log('angle: ', angle);
// return angle;
//
// }
export class Label extends MySprite {
text:String;
fontSize:String = '40px';
fontName:String = 'Verdana';
textAlign:String = 'left';
constructor(ctx) {
super(ctx);
this.init();
}
drawText() {
if (!this.text) { return; }
this.ctx.font = `${this.fontSize} ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.fontWeight = 900;
// this.ctx.lineWidth = 5;
// this.ctx.strokeStyle = '#ffffff';
// this.ctx.strokeText(this.text, 0, 0);
this.ctx.fillStyle = '#7a4250';
this.ctx.fillText(this.text, 0, 0);
}
drawSelf() {
super.drawSelf();
this.drawText();
}
}
export function getPosByAngle(angle, len) {
const radian = angle * Math.PI / 180;
const x = Math.sin(radian) * len;
const y = Math.cos(radian) * len;
return {x, y};
}
export function getAngleByPos(px, py, mx, my) {
const x = Math.abs(px - mx);
const y = Math.abs(py - my);
const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
const cos = y / z;
const radina = Math.acos(cos); // 用反三角函数求弧度
let angle = Math.floor(180 / (Math.PI / radina) * 100) / 100; // 将弧度转换成角度
if(mx > px && my > py) {// 鼠标在第四象限
angle = 180 - angle;
}
if(mx === px && my > py) {// 鼠标在y轴负方向上
angle = 180;
}
if(mx > px && my === py) {// 鼠标在x轴正方向上
angle = 90;
}
if(mx < px && my > py) {// 鼠标在第三象限
angle = 180 + angle;
}
if(mx < px && my === py) {// 鼠标在x轴负方向
angle = 270;
}
if(mx < px && my < py) {// 鼠标在第二象限
angle = 360 - angle;
}
return angle;
}
<div class="p-image-children-editor">
<h5 style="margin-left: 2.5%;"> preview: </h5>
<div class="preview-box" #wrap>
<div style=" margin: 0 auto; width: 800px;">
<h5 style="margin-left: 2.5%;">预览:</h5>
<div id="canvas-container" style="margin:5px;">
<div class="preview-box" #wrap style="margin-bottom: 20px">
<canvas id="canvas" #canvas></canvas>
</div>
</div>
<div nz-row nzType="flex" nzAlign="middle">
<div nz-col nzSpan="5" nzOffset="1">
<h5> add background: </h5>
<div class="bg-box">
<app-upload-image-with-preview
[picUrl]="bgItem?.url"
(imageUploaded)="onBackgroundUploadSuccess($event)">
<div style="width: 100%;">
<!-- <div class="bg-box">
<app-upload-image-with-preview [picUrl]="bgItem.url" (imageUploaded)="onBackgroundUploadSuccess($event)">
</app-upload-image-with-preview>
</div> -->
<div style="display: flex; margin-bottom: 28px;">
<div style="flex: 1;" >
旋转:
</div>
<div style="flex: 5;" >
<nz-select [(ngModel)]="currentSelected" nzAllowClear style="min-width: 200px;" >
<nz-option *ngFor="let it of hotZoneArr; let i = index" [nzValue]="it" [nzLabel]="(i+1) + ' - ' + it.text"></nz-option>
</nz-select>
</div>
</div>
<div nz-col nzSpan="5" nzOffset="1" class="img-box"
*ngFor="let it of hotZoneArr; let i = index">
<div
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>
<button style="float: right;" nz-button nzType="danger" nzSize="small" (click)="deleteBtnClick(i)">
X
<div *ngIf="currentSelected" style="display: flex; margin-bottom: 28px;">
<div style="flex: 5; display: flex;" >
<div style="flex:2; margin-right: 5px;">
<nz-input-group nzAddOnBefore="X:">
<nz-input-number [(ngModel)]="currentSelected.x" (ngModelChange)="autoSave()" ></nz-input-number>
</nz-input-group>
</div>
<div style="flex:2; margin-right: 5px;">
<nz-input-group nzAddOnBefore="Y:">
<nz-input-number [(ngModel)]="currentSelected.y" (ngModelChange)="autoSave()" ></nz-input-number>
</nz-input-group>
</div>
<div style="flex:2; margin-right: 10px;">
<nz-input-group nzAddOnBefore="Rotation:" >
<nz-input-number [nzMin]="-180" [nzMax]="180" [(ngModel)]="currentSelected.rotation" (ngModelChange)="autoSave()" ></nz-input-number>
</nz-input-group>
</div>
<div style="flex:4;">
<nz-slider [nzMin]="-180" [nzMax]="180" [(ngModel)]="currentSelected.rotation" (nzOnAfterChange)="autoSave()" ></nz-slider>
</div>
</div>
</div>
<div style="text-align: center;">
<button nz-button nzType="primary" [nzSize]="'small'" nzShape="round" (click)="saveClick()"
[disabled]="!hotZoneChanged">
<i nz-icon type="save"></i>
Save
</button>
<nz-divider style="margin-top: 10px;"></nz-divider>
<div style="margin-top: -20px; margin-bottom: 5px">
<nz-radio-group [ngModel]="it.itemType" (ngModelChange)="radioChange($event, 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 nzAlign="middle">
<div class="img-box clearfix" style="border-bottom: 1px solid #DDD; padding-bottom: 10px;">
<div style="float: left; width: 100px;">
<h3>题号</h3>
<input type="text" nz-input placeholder="" [(ngModel)]="bgItem.title.NO" (blur)="autoSave()" />
</div>
<div style="float: left; width: 300px; margin-left: 50px;">
<h3>课件标题</h3>
<input type="text" nz-input placeholder="" [(ngModel)]="bgItem.title.mainText" (blur)="autoSave()" />
</div>
<div style="float: left; width: 300px; margin-left: 50px;">
<h3>标题发音</h3>
<app-audio-recorder id="index_audio_1" [audioUrl]="bgItem.title.mainTitleAudio" (audioUploaded)="onUploadSuccessByItem($event, bgItem.title,'mainTitleAudio', 'audio')" > </app-audio-recorder>
</div>
<div style="float: left; width: 300px;">
<h3>白板标题</h3>
<input type="text" nz-input placeholder="" [(ngModel)]="bgItem.title.boardTitle" (blur)="autoSave()" />
</div>
<div style="float: left; width: 300px; margin-left: 50px;">
<h3>白板标题发音</h3>
<app-audio-recorder id="index_audio_1" [audioUrl]="bgItem.title.boardTitleAudio" (audioUploaded)="onUploadSuccessByItem($event, bgItem.title,'boardTitleAudio', 'audio')" > </app-audio-recorder>
</div>
<!-- <div style="float: left; width: 300px; margin-left: 50px;">
<h3>题目长音频</h3>
<app-audio-recorder id="index_audio_1" [audioUrl]="bgItem.title.mainAudio" (audioUploaded)="onUploadSuccessByItem($event, bgItem.title,'mainAudio', 'audio')" > </app-audio-recorder>
</div> -->
</div>
</div>
<div style="border-right: 1px solid #DDD; display: flex; flex-direction: column;" >
<div class="img-box clearfix" *ngFor="let it of hotZoneArr; let i = index" style="border-bottom: 1px solid #DDD; padding-bottom: 10px; flex: 1; min-width: 800px;">
<div>
<h2> 词组-{{ i + 1 }}</h2>
</div>
<div style="position: relative; display: flex; ">
<div style="flex: 6; display: flex; flex-direction: column;">
<div style="flex: 1; display: flex; margin-bottom: 28px;" >
<div style="flex: 1;" >
文字:
</div>
<div style="flex: 5;" >
<input type="text" nz-input placeholder="" [(ngModel)]="it.text" (blur)="autoSave()" />
</div>
</div>
<div style="flex: 1; display: flex; margin-bottom: 28px;">
<div style="flex: 1;" >
音频:
</div>
<div style="flex: 5;" >
<app-audio-recorder [audioUrl]="it.audio_url" (audioUploaded)="onUploadSuccessByItem($event, it, 'audio_url', 'audio')" ></app-audio-recorder>
</div>
</div>
</div>
<div style="flex:1; margin-left: 10px;">
图片:
</div>
<div style="flex:4">
<div style="width:200px">
<app-upload-image-with-preview [picUrl]="it.image_url" (imageUploaded)="onUploadSuccessByItem($event, it, 'image_url', 'image')"></app-upload-image-with-preview>
</div>
</div>
<div style="flex:1; margin-left: 10px;">
附图:
</div>
<div style="flex:4">
<div style="width:200px">
<app-upload-image-with-preview [picUrl]="it.attImage_url" (imageUploaded)="onUploadSuccessByItem($event, it, 'attImage_url', 'image')"></app-upload-image-with-preview>
</div>
</div>
</div>
<div nz-col nzSpan="5" nzOffset="1">
<div style="flex: 1; margin-bottom: 28px;">
<div style="float: left; width: 650px; display: flex;" >
<div style="flex:2; margin-right: 5px;">
<nz-input-group nzAddOnBefore="X:">
<nz-input-number [(ngModel)]="it.x" (ngModelChange)="autoSave()" ></nz-input-number>
</nz-input-group>
</div>
<div style="flex:2; margin-right: 5px;">
<nz-input-group nzAddOnBefore="Y:">
<nz-input-number [(ngModel)]="it.y" (ngModelChange)="autoSave()" ></nz-input-number>
</nz-input-group>
</div>
<div style="flex:2; margin-right: 10px;">
<nz-input-group nzAddOnBefore="Rotation:" >
<nz-input-number [nzMin]="-180" [nzMax]="180" [(ngModel)]="it.rotation" (ngModelChange)="autoSave()" ></nz-input-number>
</nz-input-group>
</div>
<div style="flex:1;">
<button style="flex:1; margin-bottom: 5px;" nz-button (click)="copyPositionData(it)">
<i nz-icon nzType="copy" nzTheme="outline"></i>
复制
</button>
</div>
<div style="flex:1;">
<button style="flex:1; margin-bottom: 5px;" (click)="showPasteModal(it)" nz-button>
<i nz-icon nzType="form" nzTheme="outline"></i>
黏贴
</button>
</div>
</div>
<div style="flex: 1 ; display: flex;" ></div>
</div>
<div class="bg-box">
<button nz-button nzType="dashed" (click)="addBtnClick()"
class="add-btn">
<div style="float: right; display: flex; margin-top: 5px; margin-right: 40px; ">
<!-- <button style="flex:1; margin-bottom: 5px;" nz-button nzType="dashed" (click)="handleMoveItemUp($event, i)"
[disabled]="i==0">
<i nz-icon nzType="up" nzTheme="outline"></i>
上移
</button>
<button style="flex:1; margin-bottom: 5px;" nz-button nzType="dashed" (click)="handleMoveItemDown($event, i)"
[disabled]="i==hotZoneArr.length-1">
<i nz-icon nzType="down" nzTheme="outline"></i>
下移
</button> -->
<button style="flex:1; margin-bottom: 5px;" nz-button nzType="danger" (click)="deleteItem(hotZoneArr, i)">
<i nz-icon nzType="delete" nzTheme="outline"></i>
删除
</button>
</div>
</div>
<div *ngIf="hotZoneArr.length<8">
<button nz-button nzType="dashed" (click)="addBtnClick(hotZoneArr)" class="add-btn" style="margin:0 auto" >
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>
<!--Add Image-->
Add hot zone
新建词组
</button>
</div>
</div>
</div>
<nz-divider></nz-divider>
<div class="save-box">
<button class="save-btn" nz-button nzType="primary" [nzSize]="'large'" nzShape="round"
(click)="saveClick()" >
<i nz-icon nzType="save"></i>
Save
</button>
</div>
<nz-modal [(nzVisible)]="showModalWindow" nzTitle="坐标粘贴" (nzOnCancel)="handlePasteCancle()" (nzOnOk)="handlePasteOk()" ng-paste="alert('d')">
<textarea #pasteDataContainer rows="4" nz-input [(ngModel)]="pasteData"></textarea>
</nz-modal>
</div>
\ No newline at end of file
<label style="opacity: 0; position: absolute; top: 0px; font-family: 'BRLNSR_1'">1</label>
.p-image-children-editor {
width: 100%;
height: 100%;
border-radius: 0.5rem;
min-width: 1200px;
border: 2px solid #ddd;
.preview-box {
margin: auto;
width: 95%;
height: 35vw;
width: 100%;
// height: 35vw;
border: 2px dashed #ddd;
border-radius: 0.5rem;
background-color: #fafafa;
text-align: center;
color: #aaa;
.preview-img {
height: 100%;
width: auto;
}
}
.bg-box{
//width: 100%;
.bg-box {
margin-bottom: 1rem;
}
.clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.img-box {
margin-bottom: 1rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 1rem;
}
.img-box-upload{
width: 80%;
.img-box-upload {
width: 120px;
height: 80px;
}
.add-btn {
margin-top: 1rem;
width: 200px;
height: 90px;
display: flex;
align-items: center;
justify-content: center;
}
}
.save-box {
width: 100%;
......@@ -85,28 +72,6 @@ h5 {
margin-top: 1rem;
}
@font-face
{
font-family: 'BRLNSR_1';
src: url("/assets/font/BRLNSR_1.TTF") ;
}
//@import '../../../style/common_mixin';
//
//.p-image-uploader {
......
import {
Component,
ElementRef,
EventEmitter,
HostListener,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
ViewChild
} from '@angular/core';
import {Subject} from 'rxjs';
import {debounceTime} from 'rxjs/operators';
import {EditorItem, HotZoneImg, HotZoneItem, HotZoneLabel, Label, MySprite, removeItemFromArr} from './Unit';
import { Component, ElementRef, EventEmitter, HostListener, Input, OnChanges, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
import {NzMessageService, NzNotificationService, UploadFile} from 'ng-zorro-antd';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { EditorItem, HotZoneImageItem, Label, MySprite } from './Unit';
import TWEEN from '@tweenjs/tween.js';
import {getMinScale} from "../../play/Unit";
import {tar} from "compressing";
@Component({
......@@ -25,280 +13,304 @@ import {tar} from "compressing";
})
export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
_bgItem = null;
@Input()
set bgItem(v) {
this._bgItem = v;
this.init();
}
get bgItem() {
return this._bgItem;
}
@Input()
imgItemArr = null;
@Input()
hotZoneItemArr = null;
@Input()
hotZoneArr = null;
@Output()
save = new EventEmitter();
@ViewChild('canvas', {static: true}) canvas: ElementRef;
@ViewChild('wrap', {static: true}) wrap: ElementRef;
@Input()
isHasRect = true;
@Input()
isHasPic = true;
@Input()
isHasText = true;
@Input()
hotZoneFontObj = {
size: 50,
name: 'BRLNSR_1',
color: '#8f3758'
}
@Input()
defaultItemType = 'text';
@ViewChild('canvas', { static: true }) canvas: ElementRef;
@ViewChild('wrap', { static: true }) wrap: ElementRef;
@ViewChild('pasteDataContainer', { static: true }) pasteDataContainer: ElementRef;
@Input()
hotZoneImgSize = 190;
@HostListener('window:resize', ['$event'])
onResize(event) {
this.g_winResizeEventStream.next();
}
saveDisabled = true;
g_winResizeEventStream = new Subject();
firstTouch = true;
canvasWidth = 1280;
canvasHeight = 720;
canvasBaseW = 1280;
// @HostListener('window:resize', ['$event'])
canvasBaseH = 720;
mapScale = 1;
currentSelected = null
ctx;
mx;
my; // 点击坐标
// 声音
bgAudio = new Audio();
images = new Map();
animationId: any;
// 资源
// rawImages = new Map(res);
winResizeEventStream = new Subject();
// 声音
bgAudio = new Audio();
images = new Map();
animationId: any;
// winResizeEventStream = new Subject();
canvasLeft;
canvasTop;
renderArr;
imgArr = [];
oldPos;
radioValue;
curItem;
bg: MySprite;
changeSizeFlag = false;
changeTopSizeFlag = false;
changeRightSizeFlag = false;
hotZoneChanged = false;
showModalWindow = false;
currentPasteItem = null
copyData = ""
pasteData = ""
scale = 1;
constructor() {
}
_bgItem = null;
get bgItem() {
return this._bgItem;
}
@Input()
set bgItem(v) {
this._bgItem = v;
constructor( private nzMessageService: NzMessageService, private el: ElementRef) {
this.init();
}
onResize(event) {
this.winResizeEventStream.next();
}
ngOnInit() {
if(!this.bgItem.url){
this.bgItem.url = "assets/play/hot-zoo-bg.png"
}
this.initListener();
// this.init();
this.update();
}
ngOnDestroy() {
window.cancelAnimationFrame(this.animationId);
}
ngOnChanges() {
}
onBackgroundUploadSuccess(e) {
console.log('e: ', e);
this.bgItem.url = e.url;
this.refreshBackground();
}
onItemImgUploadSuccess(e, item) {
item.pic_url = e.url;
this.loadHotZonePic(item.pic, e.url);
}
onItemAudioUploadSuccess(e, item) {
item.audio_url = e.url;
this.refreshBackground(() => {
this.autoSave()
});
}
refreshBackground(callBack = null) {
if (!this.bg) {
this.bg = new MySprite(this.ctx);
this.renderArr.push(this.bg);
}
const bg = this.bg;
if (this.bgItem.url) {
bg.load(this.bgItem.url).then(() => {
bg.load("assets/play/hot-zoo-bg.png").then(() => {
const rate1 = this.canvasWidth / bg.width;
const rate2 = this.canvasHeight / bg.height;
const rate = Math.min(rate1, rate2);
bg.setScaleXY(rate);
bg.x = this.canvasWidth / 2;
bg.y = this.canvasHeight / 2;
if (callBack) {
callBack();
}
});
}).catch((error) => {
console.log(error)
})
}
addBtnClick(array) {
const item = this.getHotZoneItem(null, null, true);
item.type = "Image"
array.push(item);
this.refreshHotZoneId();
this.autoSave()
}
deleteItem(array, i) {
array.splice(i, 1);
this.refreshHotZoneId();
this.autoSave()
}
addBtnClick() {
// this.imgArr.push({});
// this.hotZoneArr.push({});
handleMoveItemUp(items, index) {
if (index != 0) {
items[index] =items.splice(index - 1, 1,items[index])[0];
} else {
items.push(this.hotZoneArr.shift());
}
this.autoSave()
}
const item = this.getHotZoneItem();
this.hotZoneArr.push(item);
handleMoveItemDown(items, index) {
if (index != items.length - 1) {
items[index] = items.splice(index + 1, 1, items[index])[0];
} else {
items.unshift(items.splice(index, 1)[0]);
}
this.autoSave()
}
this.refreshItem(item);
onImgUploadSuccessByImg(e, item) {
item.pic_url = e.url;
item.image_url = e.url;
item.initNew((w, h) => {
item.setScaleXY(Math.min(100 / w, 150 / h))
})
this.refreshImage(item);
this.autoSave()
}
this.refreshHotZoneId();
onUploadSuccessByItem(e, items, key, type){
items[key] = e.url;
let textSaved = items.text
if(type == "image"){
items.initNew((w, h) => {
items.text = textSaved
items.setScaleXY(Math.min(100 / w, 150 / h))
})
this.refreshImage(items)
}
this.autoSave()
}
deleteBtnClick(index) {
const item = this.hotZoneArr.splice(index, 1)[0];
removeItemFromArr(this.renderArr, item.pic);
removeItemFromArr(this.renderArr, item.textLabel);
showPasteModal(it): void {
this.currentPasteItem = it
this.showModalWindow = true;
setTimeout(() => {
this.pasteDataContainer.nativeElement.focus();
}, 10);
}
this.refreshHotZoneId();
handlePasteOk(){
if(this.pasteData && this.currentPasteItem){
let pos = this.pasteData.split(";")
if(pos.length == 5){
let result = true;
let reg = /^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$/
pos.forEach(item=>{
if(!reg.test(item)){
result = false;
}
})
if(result){
this.currentPasteItem.x = Number(pos[0])
this.currentPasteItem.y = Number(pos[1])
this.currentPasteItem.width = Number(pos[2]) / this.currentPasteItem.scaleX
this.currentPasteItem.height = Number(pos[3]) / this.currentPasteItem.scaleY
this.currentPasteItem.rotation = Number(pos[4])
this.autoSave()
this.init()
}
}
}
this.pasteData = ""
this.currentPasteItem = null
this.showModalWindow = false;
}
handlePasteCancle(){
this.pasteData = ""
this.currentPasteItem = null
this.showModalWindow = false;
}
onImgUploadSuccessByImg(e, img) {
img.pic_url = e.url;
this.refreshImage(img);
copyPositionData(item){
this.nzMessageService.info('Copied');
document.addEventListener('copy', handleData);
document.execCommand('copy');
document.removeEventListener('copy', handleData);
function handleData(e) {
let bb = item.getBoundingBox()
e.clipboardData.setData('text/plain', `${Math.round(item.x*100)/100};${Math.round(item.y*100)/100};${Math.round(bb.width*100)/100};${Math.round(bb.height*100)/100};${Math.round(item.rotation*100)/100}`);
e.preventDefault();
}
}
refreshImage(img) {
this.hideAllLineDash();
img.picItem = this.getPicItem(img);
this.refreshImageId();
}
refreshHotZoneId() {
for (let i = 0; i < this.hotZoneArr.length; i++) {
this.hotZoneArr[i].index = i;
if (this.hotZoneArr[i]) {
this.hotZoneArr[i].title = 'item-' + (i + 1);
}
}
}
refreshHotZoneText(item) {
item.initNew()
}
refreshImageId() {
for (let i = 0; i < this.imgArr.length; i++) {
this.imgArr[i].id = i;
if (this.imgArr[i].picItem) {
this.imgArr[i].picItem.text = 'Image-' + (i + 1);
}
}
}
getHotZoneItem(saveData = null) {
getHotZoneItem(saveData = null, newRect?, offSetCenter=false) {
const itemW = 200;
const itemH = 200;
const item = new HotZoneItem(this.ctx);
item.setSize(itemW, itemH);
item.anchorX = 0.5;
item.anchorY = 0.5;
item.x = this.canvasWidth / 2;
item.y = this.canvasHeight / 2;
item.itemType = this.defaultItemType;
const item = new HotZoneImageItem(this.ctx);
item.offSetCenter = offSetCenter
if (saveData) {
item.init(saveData.media.image_url, saveData.media.text, saveData.media.type, (w, h) => {
const saveRect = saveData.rect;
item.scaleX = saveRect.width / item.width;
item.scaleY = saveRect.height / item.height;
item.x = saveRect.x + saveRect.width / 2;
item.y = saveRect.y + saveRect.height / 2;
item.scaleX = (saveData.rect.width / saveData.scale) / w;
item.scaleY = (saveData.rect.height / saveData.scale) / h;
if(item.offSetCenter){
item.x = (saveRect.x + saveRect.width/2) / saveData.scale + newRect.x
item.y = (saveRect.y + saveRect.height/2) / saveData.scale + newRect.y
}else{
item.x = saveRect.x / saveData.scale + newRect.x
item.y = saveRect.y / saveData.scale + newRect.y
}
});
item.rotation = saveData.rect.rotation
item.image_url = saveData.media.image_url
item.attImage_url = saveData.media.attImage_url
item.audio_url = saveData.media.audio_url
item.text = saveData.media.text
item.type = saveData.media.type
item.showLineDash();
const pic = new HotZoneImg(this.ctx);
pic.visible = false;
item['pic'] = pic;
if (saveData && saveData.pic_url) {
this.loadHotZonePic(pic, saveData.pic_url);
}
pic.x = item.x;
pic.y = item.y;
this.renderArr.push(pic);
const textLabel = new HotZoneLabel(this.ctx);
textLabel.fontSize = this.hotZoneFontObj.size;
textLabel.fontName = this.hotZoneFontObj.name;
textLabel.fontColor = this.hotZoneFontObj.color;
textLabel.textAlign = 'center';
// textLabel.setOutline();
// console.log('saveData:', saveData);
item['textLabel'] = textLabel;
textLabel.setScaleXY(this.mapScale);
if (saveData && saveData.text) {
textLabel.text = saveData.text;
textLabel.refreshSize();
}
textLabel.x = item.x;
textLabel.y = item.y;
this.renderArr.push(textLabel);
} else {
item.init("assets/play/bg_sentence.png", null, "Image", () => {
item.image_url = "assets/play/bg_sentence.png"
item.x = this.canvasWidth / 2 - 142;
item.y = this.canvasHeight / 2 - 15;
}, () => this.autoSave());
}
item.anchorX = 0.5;
item.anchorY = 0.5;
return item;
}
getPicItem(img, saveData = null) {
const item = new EditorItem(this.ctx);
item.load(img.pic_url).then(img => {
item.load(img.image_url).then(img => {
let maxW, maxH;
if (this.bg) {
maxW = this.bg.width * this.bg.scaleX;
......@@ -307,10 +319,8 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
maxW = this.canvasWidth;
maxH = this.canvasHeight;
}
let scaleX = maxW / 3 / item.width;
let scaleY = maxH / 3 / item.height;
if (item.height * scaleX < this.canvasHeight) {
item.setScaleXY(scaleX);
} else {
......@@ -318,159 +328,84 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
}
item.x = this.canvasWidth / 2;
item.y = this.canvasHeight / 2;
if (saveData) {
const saveRect = saveData.rect;
item.setScaleXY(saveRect.width / item.width);
item.x = saveRect.x + saveRect.width / 2;
item.y = saveRect.y + saveRect.height / 2;
} else {
item.showLineDash();
}
});
this.autoSave()
})
return item;
}
onAudioUploadSuccessByImg(e, img) {
img.audio_url = e.url;
}
deleteItem(e, i) {
// this.imgArr.splice(i , 1);
// this.refreshImageId();
this.hotZoneArr.splice(i, 1);
this.refreshHotZoneId();
}
radioChange(e, item) {
item.itemType = e;
this.refreshItem(item);
// console.log(' in radioChange e: ', e);
}
refreshItem(item) {
switch (item.itemType) {
case 'rect':
this.setRectState(item);
break;
case 'pic':
this.setPicState(item);
break;
case 'text':
this.setTextState(item);
break;
default:
}
}
init() {
this.initData();
this.initCtx();
this.initItem();
}
initItem() {
if (!this.bgItem) {
this.bgItem = {};
this.bgItem = {
title: {
mainText: "Read then write a rhyme.",
mainTitleAudio: "",
boardTitle: "Make rhymes",
boardTitleAudio: "",
mainAudio: "",
leftText: "Rhyme 2",
rightText: "Rhyme 1",
leftAudio: "",
rightAudio: ""
}
};
} else {
this.refreshBackground(() => {
// if (!this.imgItemArr) {
// this.imgItemArr = [];
// } else {
// this.initImgArr();
// }
// console.log('aaaaa');
if (!this.hotZoneItemArr) {
this.hotZoneItemArr = [];
} else {
this.initHotZoneArr();
}
});
}
}
initHotZoneArr() {
// console.log('this.hotZoneArr: ', this.hotZoneArr);
let curBgRect;
if (this.bg) {
curBgRect = this.bg.getBoundingBox();
} else {
curBgRect = {x: 0, y: 0, width: this.canvasWidth, height: this.canvasHeight};
curBgRect = { x: 0, y: 0, width: this.canvasWidth, height: this.canvasHeight };
}
let oldBgRect = this.bgItem.rect;
if (!oldBgRect) {
oldBgRect = curBgRect;
}
const rate = curBgRect.width / oldBgRect.width;
console.log('rate: ', rate);
this.hotZoneArr = [];
const arr = this.hotZoneItemArr.concat();
for (let i = 0; i < arr.length; i++) {
const data = JSON.parse(JSON.stringify(arr[i]));
// const img = {pic_url: data.pic_url};
data.rect.x *= rate;
data.rect.y *= rate;
data.rect.width *= rate;
data.rect.height *= rate;
data.rect.x += curBgRect.x;
data.rect.y += curBgRect.y;
// img['picItem'] = this.getPicItem(img, data);
// img['audio_url'] = arr[i].audio_url;
// this.imgArr.push(img);
const item = this.getHotZoneItem(data);
item.audio_url = data.audio_url;
item.pic_url = data.pic_url;
item.text = data.text;
item.itemType = data.itemType;
this.refreshItem(item);
console.log('item: ', item);
const item = this.getHotZoneItem(data, { x: curBgRect.x, y: curBgRect.y }, true);
this.hotZoneArr.push(item);
}
this.refreshHotZoneId();
// this.refreshImageId();
}
initImgArr() {
console.log('this.imgItemArr: ', this.imgItemArr);
let curBgRect;
if (this.bg) {
curBgRect = this.bg.getBoundingBox();
} else {
curBgRect = {x: 0, y: 0, width: this.canvasWidth, height: this.canvasHeight};
curBgRect = { x: 0, y: 0, width: this.canvasWidth, height: this.canvasHeight };
}
let oldBgRect = this.bgItem.rect;
......@@ -479,15 +414,12 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
}
const rate = curBgRect.width / oldBgRect.width;
console.log('rate: ', rate);
this.imgArr = [];
const arr = this.imgItemArr.concat();
for (let i = 0; i < arr.length; i++) {
const data = JSON.parse(JSON.stringify(arr[i]));
const img = {pic_url: data.pic_url};
const img = { pic_url: data.pic_url };
data.rect.x *= rate;
data.rect.y *= rate;
......@@ -506,13 +438,12 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
initData() {
this.canvasWidth = this.wrap.nativeElement.clientWidth;
this.canvasHeight = this.wrap.nativeElement.clientHeight;
this.canvasHeight = this.wrap.nativeElement.clientWidth * (555 / 1070);
this.scale = 1070 / this.wrap.nativeElement.clientWidth
this.mapScale = this.canvasWidth / this.canvasBaseW;
this.renderArr = [];
this.bg = null;
this.imgArr = [];
this.hotZoneArr = [];
}
......@@ -523,45 +454,41 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
this.canvas.nativeElement.height = this.canvasHeight;
}
mapDown(event) {
this.oldPos = {x: this.mx, y: this.my};
for (let i = 0; i < this.hotZoneArr.length; i++) {
const item = this.hotZoneArr[i];
let callback;
let target;
switch (item.itemType) {
case 'rect':
target = item;
callback = this.clickedHotZoneRect.bind(this);
break;
case 'pic':
target = item.pic;
callback = this.clickedHotZonePic.bind(this);
break;
case 'text':
target = item.textLabel;
callback = this.clickedHotZoneText.bind(this);
break;
}
if (this.checkClickTarget(target)) {
callback(target);
return;
this.oldPos = { x: this.mx, y: this.my };
const arr = this.hotZoneArr.concat();
for (let i = arr.length - 1; i >= 0; i--) {
const item = arr[i];
if (item) {
if (this.checkClickTarget(item)) {
if (item.lineDashFlag && this.checkClickTarget(item.arrow)) {
if(item.type == "Text"){
return
}
this.changeItemSize(item);
} else if (item.lineDashFlag && this.checkClickTarget(item.arrowTop)) {
if(item.type == "Text"){
return
}
this.changeItemTopSize(item);
} else if (item.lineDashFlag && this.checkClickTarget(item.arrowRight)) {
if(item.type == "Text"){
return
}
this.changeItemRightSize(item);
} else {
this.changeCurItem(item);
}
this.hotZoneChanged = true;
return;
}
}
}
}
mapMove(event) {
if (!this.curItem) {
return;
}
if (!this.curItem) { return; }
if (this.changeSizeFlag) {
this.changeSize();
......@@ -571,19 +498,14 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
} else if (this.changeRightSizeFlag) {
this.changeRightSize();
} else {
const addX = this.mx - this.oldPos.x;
const addY = this.my - this.oldPos.y;
let addX = this.mx - this.oldPos.x;
let addY = this.my - this.oldPos.y;
this.curItem.x += addX;
this.curItem.y += addY;
}
this.oldPos = {x: this.mx, y: this.my};
this.saveDisabled = true;
this.oldPos = { x: this.mx, y: this.my };
}
mapUp(event) {
......@@ -593,79 +515,68 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
this.changeRightSizeFlag = false;
}
changeSize() {
const rect = this.curItem.getBoundingBox();
let lenW = (this.mx - (rect.x + rect.width / 2)) * 2;
let lenH = ((rect.y + rect.height / 2) - this.my) * 2;
let distance = null;
let lenW = null;
if(this.curItem.offSetCenter){
distance = (this.my + rect.height/2) - rect.y
lenW = (this.mx + rect.width/2) - rect.x;
}else{
distance = this.my - rect.y;
lenW = this.mx - rect.x;
}
let lenH = rect.height - distance
let minLen = 20;
let s;
if (lenW < lenH) {
let sx, sy;
if (lenW < minLen) {
lenW = minLen;
}
s = lenW / this.curItem.width;
} else {
sx = lenW / this.curItem.width;
if (lenH < minLen) {
lenH = minLen;
}
s = lenH / this.curItem.height;
}
// console.log('s: ', s);
this.curItem.setScaleXY(s);
this.curItem.refreshLabelScale();
sy = lenH / this.curItem.height;
this.curItem.y = this.curItem.y + distance
this.curItem.scaleX = sx;
this.curItem.scaleY = sy;
}
changeTopSize() {
const rect = this.curItem.getBoundingBox();
// let lenW = ( this.mx - (rect.x + rect.width / 2) ) * 2;
let lenH = ((rect.y + rect.height / 2) - this.my) * 2;
let lenH = null
if(this.curItem.offSetCenter){
lenH = rect.y - (this.my + rect.height/2) + rect.height;
this.curItem.y = this.my + rect.height/2
}else{
lenH = rect.y - this.my + rect.height;
this.curItem.y = this.my
}
let minLen = 20;
let s;
// if (lenW < lenH) {
// if (lenW < minLen) {
// lenW = minLen;
// }
// s = lenW / this.curItem.width;
//
// } else {
if (lenH < minLen) {
lenH = minLen;
}
s = lenH / this.curItem.height;
// }
// console.log('s: ', s);
this.curItem.scaleY = s;
this.curItem.refreshLabelScale();
this.curItem.setScaleXY(s);
}
changeRightSize() {
const rect = this.curItem.getBoundingBox();
let lenW = (this.mx - (rect.x + rect.width / 2)) * 2;
// let lenH = ( (rect.y + rect.height / 2) - this.my ) * 2;
let lenW = null
if(this.curItem.offSetCenter){
lenW = this.mx - rect.x + rect.width/2;
}else{
lenW = this.mx - rect.x;
}
let minLen = 20;
let s;
if (lenW < minLen) {
lenW = minLen;
}
s = lenW / this.curItem.width;
this.curItem.scaleX = s;
this.curItem.refreshLabelScale();
this.curItem.setScaleXY(s);
}
changeItemSize(item) {
......@@ -692,7 +603,6 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
}
hideAllLineDash() {
for (let i = 0; i < this.imgArr.length; i++) {
if (this.imgArr[i].picItem) {
this.imgArr[i].picItem.hideLineDash();
......@@ -700,32 +610,14 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
}
}
update() {
if (!this.ctx) {
return;
}
this.animationId = window.requestAnimationFrame(this.update.bind(this));
// 清除画布内容
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
for (let i = 0; i < this.renderArr.length; i++) {
this.renderArr[i].update(this);
}
// for (let i = 0; i < this.imgArr.length; i++) {
// const picItem = this.imgArr[i].picItem;
// if (picItem) {
// picItem.update(this);
// }
// }
this.updateArr(this.hotZoneArr);
this.updatePos()
TWEEN.update();
}
......@@ -737,7 +629,6 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
}
}
renderAfterResize() {
this.canvasWidth = this.wrap.nativeElement.clientWidth;
this.canvasHeight = this.wrap.nativeElement.clientHeight;
......@@ -745,79 +636,94 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
}
initListener() {
this.winResizeEventStream
.pipe(debounceTime(500))
.subscribe(data => {
const element = this.canvas.nativeElement;
this.g_winResizeEventStream.pipe(debounceTime(500)).subscribe(data => {
this.renderAfterResize();
});
if (this.IsPC()) {
this.canvas.nativeElement.addEventListener('mousedown', (event) => {
setMxMyByMouse(event);
this.mapDown(event);
});
this.canvas.nativeElement.addEventListener('mousemove', (event) => {
setMxMyByMouse(event);
this.mapMove(event);
});
this.canvas.nativeElement.addEventListener('mouseup', (event) => {
setMxMyByMouse(event);
this.mapUp(event);
});
const setMxMyByMouse = (event) => {
this.mx = event.offsetX;
this.my = event.offsetY;
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);
};
} else {
this.canvas.nativeElement.addEventListener('touchstart', (event) => {
setMxMyByTouch(event);
this.mapDown(event);
});
this.canvas.nativeElement.addEventListener('touchmove', (event) => {
setMxMyByTouch(event);
this.mapMove(event);
});
this.canvas.nativeElement.addEventListener('touchend', (event) => {
setMxMyByTouch(event);
this.mapUp(event);
});
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);
};
this.canvas.nativeElement.addEventListener('touchcancel', (event) => {
setMxMyByTouch(event);
this.mapUp(event);
});
const touchDownFunc = (e) => {
if (this.firstTouch) {
this.firstTouch = false;
removeMouseListener();
}
setMxMyByTouch(e);
this.mapDown(e);
};
const touchMoveFunc = (e) => {
setMxMyByTouch(e);
this.mapMove(e);
};
const touchUpFunc = (e) => {
setMxMyByTouch(e);
this.mapUp(e);
};
const mouseDownFunc = (e) => {
if (this.firstTouch) {
this.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 setMxMyByTouch = (event) => {
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;
};
const setParentOffset = () => {
const rect = this.canvas.nativeElement.getBoundingClientRect();
this.canvasLeft = rect.left;
this.canvasTop = rect.top;
};
}
const setMxMyByMouse = (event) => {
this.mx = event.offsetX;
this.my = event.offsetY;
};
addMouseListener();
addTouchListener();
}
IsPC() {
......@@ -833,11 +739,16 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
checkClickTarget(target) {
const rect = target.getBoundingBox();
if(target.offSetCenter){
if (this.checkPointInRectOffSetCenter(this.mx, this.my, rect)) {
return true;
}
}else{
if (this.checkPointInRect(this.mx, this.my, rect)) {
return true;
}
}
return false;
}
......@@ -850,137 +761,60 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
return false;
}
checkPointInRectOffSetCenter(x, y, rect) {
if (x >= rect.x - rect.width/2 && x <= rect.x + rect.width/2) {
if (y >= rect.y - rect.height/2 && y <= rect.y + rect.height/2) {
return true;
}
}
return false;
}
saveClick() {
autoSave() {
// console.log("Auto save")
const bgItem = this.bgItem;
if (this.bg) {
bgItem['rect'] = this.bg.getBoundingBox();
} else {
bgItem['rect'] = {
x: 0,
y: 0,
width: Math.round(this.canvasWidth * 100) / 100,
height: Math.round(this.canvasHeight * 100) / 100
};
bgItem['rect'] = { x: 0, y: 0, width: Math.round(this.canvasWidth * 100) / 100, height: Math.round(this.canvasHeight * 100) / 100 };
}
const hotZoneItemArr = [];
const hotZoneArr = this.hotZoneArr;
for (let i = 0; i < hotZoneArr.length; i++) {
const hotZoneItem = {
index: hotZoneArr[i].index,
pic_url: hotZoneArr[i].pic_url,
text: hotZoneArr[i].text,
audio_url: hotZoneArr[i].audio_url,
itemType: hotZoneArr[i].itemType,
fontSize: this.hotZoneFontObj.size,
fontName: this.hotZoneFontObj.name,
fontColor: this.hotZoneFontObj.color,
fontScale: hotZoneArr[i].textLabel ? hotZoneArr[i].textLabel.scaleX : 1,
imgScale: hotZoneArr[i].pic ? hotZoneArr[i].pic.scaleX : 1,
mapScale: this.mapScale
};
hotZoneItem['rect'] = hotZoneArr[i].getBoundingBox();
hotZoneItem['rect'].x = Math.round((hotZoneItem['rect'].x - bgItem['rect'].x) * 100) / 100;
hotZoneItem['rect'].y = Math.round((hotZoneItem['rect'].y - bgItem['rect'].y) * 100) / 100;
hotZoneItem['rect'].width = Math.round((hotZoneItem['rect'].width) * 100) / 100;
hotZoneItem['rect'].height = Math.round((hotZoneItem['rect'].height) * 100) / 100;
const currentX = hotZoneItem['rect'].x
const currentY = hotZoneItem['rect'].y
hotZoneItem['media'] = {}
hotZoneItem['scale'] = this.scale
if(hotZoneArr[i].offSetCenter){
hotZoneItem['rect'].x = (Math.round((currentX - bgItem['rect'].x - hotZoneItem['rect'].width / 2) * 100) / 100) * this.scale;
hotZoneItem['rect'].y = (Math.round((currentY - bgItem['rect'].y - hotZoneItem['rect'].height /2) * 100) / 100) * this.scale;
}else{
hotZoneItem['rect'].x = (Math.round((currentX - bgItem['rect'].x) * 100) / 100) * this.scale;
hotZoneItem['rect'].y = (Math.round((currentY - bgItem['rect'].y) * 100) / 100) * this.scale;
}
hotZoneItem['rect'].width = (Math.round((hotZoneItem['rect'].width) * 100) / 100) * this.scale;
hotZoneItem['rect'].height = (Math.round((hotZoneItem['rect'].height) * 100) / 100) * this.scale;
hotZoneItem['rect'].rotation = hotZoneArr[i].rotation
hotZoneItem['media'].image_url = hotZoneArr[i].image_url
hotZoneItem['media'].attImage_url = hotZoneArr[i].attImage_url
hotZoneItem['media'].audio_url = hotZoneArr[i].audio_url
hotZoneItem['media'].text = hotZoneArr[i].text
hotZoneItem['media'].type = hotZoneArr[i].type
hotZoneItemArr.push(hotZoneItem);
}
console.log('hotZoneItemArr: ', hotZoneItemArr);
this.save.emit({bgItem, hotZoneItemArr});
}
private updatePos() {
this.hotZoneArr.forEach((item) => {
let x, y;
switch (item.itemType) {
case 'rect':
x = item.x;
y = item.y;
break;
case 'pic':
x = item.pic.x;
y = item.pic.y;
break;
case 'text':
x = item.textLabel.x;
y = item.textLabel.y;
break;
}
item.x = x;
item.y = y;
item.pic.x = x;
item.pic.y = y;
item.textLabel.x = x;
item.textLabel.y = y;
});
}
private setPicState(item: any) {
item.visible = false;
item.textLabel.visible = false;
item.pic.visible = true;
}
private setRectState(item: any) {
item.visible = true;
item.textLabel.visible = false;
item.pic.visible = false;
}
private setTextState(item: any) {
item.visible = false;
item.pic.visible = false;
item.textLabel.visible = true;
this.save.emit({ bgItem, hotZoneItemArr });
this.hotZoneChanged = false;
}
private clickedHotZoneRect(item: any) {
if (this.checkClickTarget(item)) {
if (item.lineDashFlag && this.checkClickTarget(item.arrow)) {
this.changeItemSize(item);
} else if (item.lineDashFlag && this.checkClickTarget(item.arrowTop)) {
this.changeItemTopSize(item);
} else if (item.lineDashFlag && this.checkClickTarget(item.arrowRight)) {
this.changeItemRightSize(item);
} else {
this.changeCurItem(item);
}
return;
}
}
private clickedHotZonePic(item: any) {
if (this.checkClickTarget(item)) {
this.curItem = item;
}
}
private clickedHotZoneText(item: any) {
if (this.checkClickTarget(item)) {
this.curItem = item;
}
}
saveText(item) {
item.textLabel.text = item.text;
}
private loadHotZonePic(pic: HotZoneImg, url) {
const baseLen = this.hotZoneImgSize * this.mapScale;
pic.load(url).then(() => {
const s = getMinScale(pic, baseLen);
pic.setScaleXY(s);
});
saveClick() {
// console.log("Saved")
this.autoSave()
}
}
@import '../style/common_mixin.css';
.model-content {
width: 100%;
height: 100%;
}
<div class="model-content">
<div class="card-config">
<div *ngFor="let item of contentObj.dataArray; let i = index" class="card-item" style="padding: 0.5vw; min-width: 900px;" >
<div class="card-item-content border">
<div class="card-item-content">
<div class="title" >
第-<strong>{{ i + 1 }}</strong>-题
</div>
<div class="section" >
<div class="section-title" >
题干
</div>
<div class="section-content">
<div style="flex:1">
<div style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
<span>音频</span>
</div>
<div style="flex:11">
<app-audio-recorder [audioUrl]="item.audio_url1" (audioUploaded)="onAudioUploadSuccessByItem($event, item, 'audio_url1')" ></app-audio-recorder>
</div>
</div>
</div>
</div>
</div>
<div style="position: absolute; left: 200px; top: 100px; width: 800px;">
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()">
<!-- <div class="section" >
<div class="section-title" >
正确选项
</div>
<div style="display: flex;">
<div style="float: left;border:1px solid #CCC; padding:5px; border-radius: 5px; margin: 10px; width: 300px; height: 250px; position: relative;">
<div style="display: flex; margin-bottom: 10px;">
<div style="flex:2">
显示选项
</div>
<div style="flex:4">
<nz-radio-group [(ngModel)]="item.type" (ngModelChange)="saveItem()" >
<label nz-radio [nzValue]="'Text'">文字</label>
<label nz-radio [nzValue]="'Image'">图片</label>
</nz-radio-group>
</div>
</div>
<div *ngIf="item.type=='Text'" style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
文字
</div>
<div style="flex:5">
<input type="text" nz-input placeholder="" [(ngModel)]="item.text" (blur)="saveItem()" />
</div>
</div>
<div *ngIf="item.type=='Image'" style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
图片
</div>
<div style="flex:5">
<div style="width: 200px;">
<app-upload-image-with-preview style="width: 100%;" [picUrl]="item.image_url" (imageUploaded)="onImageUploadSuccessByItem($event, item, 'image_url')"></app-upload-image-with-preview>
</div>
</div>
</div>
<div style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
音频
</div>
<div style="flex:5">
<app-audio-recorder [audioUrl]="item.audio_url2" (audioUploaded)="onUploadSuccessByItem($event, item, 'audio_url2')" ></app-audio-recorder>
</div>
</div>
</div>
</div>
</div> -->
<app-upload-image-with-preview
[picUrl]="item.pic_url"
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')"
></app-upload-image-with-preview>
<div class="section" >
<div class="section-title" >
正确选项
<div style="text-align: center; float: right;">
<button nz-button nzType="primary" (click)="addChoice(item.correct)" >
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>
添加
</button>
</div>
</div>
<div class="section-content clearfix" style="display: block;">
<div *ngFor="let choiceItem of item.correct; let choiceIndex = index" style="float: left;border:1px solid #CCC; padding:5px; border-radius: 5px; margin: 10px; width: 300px; height: 250px; position: relative;">
<div style="display: flex; margin-bottom: 10px;">
<div style="flex:2">
显示选项
</div>
<div style="flex:4">
<nz-radio-group [(ngModel)]="choiceItem.type" (ngModelChange)="saveItem()" >
<label nz-radio [nzValue]="'Text'">文字</label>
<label nz-radio [nzValue]="'Image'">图片</label>
</nz-radio-group>
</div>
</div>
<div *ngIf="choiceItem.type=='Text'" style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
文字
</div>
<div style="flex:5">
<input type="text" nz-input placeholder="" [(ngModel)]="choiceItem.text" (blur)="saveItem()" />
</div>
</div>
<div *ngIf="choiceItem.type=='Image'" style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
图片
</div>
<div style="flex:5">
<div style="width: 200px;">
<app-upload-image-with-preview style="width: 100%;" [picUrl]="choiceItem.image_url" (imageUploaded)="onImageUploadSuccessByItem($event, choiceItem, 'image_url')"></app-upload-image-with-preview>
</div>
</div>
</div>
<div style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
音频
</div>
<div style="flex:5">
<app-audio-recorder [audioUrl]="choiceItem.audio_url" (audioUploaded)="onUploadSuccessByItem($event, choiceItem, 'audio_url')" ></app-audio-recorder>
</div>
</div>
<button *ngIf="item.correct.length>1" style="margin-top: 10px; position: absolute; bottom: 10px; right: 10px;;" nz-button nzType="danger" (click)="deleteChoice(item.correct, choiceIndex)" >
<span>删除此选项</span>
</button>
</div>
</div>
</div>
<app-audio-recorder
[audioUrl]="item.audio_url"
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url')"
></app-audio-recorder>
<app-custom-hot-zone></app-custom-hot-zone>
<app-upload-video></app-upload-video>
<app-lesson-title-config></app-lesson-title-config>
<div class="section" >
<div class="section-title" >
错误选项
<div style="text-align: center; float: right;">
<button nz-button nzType="primary" (click)="addChoice(item.incorrect)" >
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>
添加
</button>
</div>
</div>
<div class="section-content clearfix" style="display: block;">
<div *ngFor="let choiceItem of item.incorrect; let choiceIndex = index" style="float: left;border:1px solid #CCC; padding:5px; border-radius: 5px; margin: 10px; width: 300px; height: 250px; position: relative;">
<div style="display: flex; margin-bottom: 10px;">
<div style="flex:2">
显示选项
</div>
<div style="flex:4">
<nz-radio-group [(ngModel)]="choiceItem.type" (ngModelChange)="saveItem()" >
<label nz-radio [nzValue]="'Text'">文字</label>
<label nz-radio [nzValue]="'Image'">图片</label>
</nz-radio-group>
</div>
</div>
<div *ngIf="choiceItem.type=='Text'" style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
文字
</div>
<div style="flex:5">
<input type="text" nz-input placeholder="" [(ngModel)]="choiceItem.text" (blur)="saveItem()" />
</div>
</div>
<div *ngIf="choiceItem.type=='Image'" style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
图片
</div>
<div style="flex:5">
<div style="width: 200px;">
<app-upload-image-with-preview style="width: 100%;" [picUrl]="choiceItem.image_url" (imageUploaded)="onImageUploadSuccessByItem($event, choiceItem, 'image_url')"></app-upload-image-with-preview>
</div>
</div>
</div>
<button style="margin-top: 10px; position: absolute; bottom: 10px; right: 10px;;" nz-button nzType="danger" (click)="deleteChoice(item.incorrect, choiceIndex)" >
<span>删除此选项</span>
</button>
</div>
</div>
</div>
<div class="section" >
<div style="float:right; text-align: left; padding-left: 20px;">
<button style="flex:1;" nz-button nzType="default" (click)="handleMoveItemUp('dataArray', i)" [disabled]="i==0">
<i nz-icon nzType="up" nzTheme="outline" style="float: left; margin-top: 4px;"></i>
<span style="float: right;">上移</span>
</button>
<button style="flex:1; margin-left: 10px; vertical-align:baseline;" nz-button nzType="default" (click)="handleMoveItemDown('dataArray', i)" [disabled]="i==contentObj.dataArray.length-1">
<i nz-icon nzType="down" nzTheme="outline" style="float: left; margin-top: 4px;"></i>
<span style="float: right;">下移</span>
</button>
</div>
<div style="text-align: right; padding-right: 20px;">
<button style="margin-bottom: 10px;" nz-button nzType="danger" (click)="deleteItem('dataArray', i)" >
<span>删除本题</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="contentObj.dataArray.length<26" class="card-item" style="padding: 0.5vw; width: 500px;" >
<button nz-button nzType="primary" class="add-btn" (click)="addItem('dataArray')">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>
新建题目
</button>
</div>
</div>
\ No newline at end of file
@import "../style/common_mixin";
.model-content {
margin: 10px;
.card-config {
// width: 100%;
height: 100%;
// display: flex;
flex-wrap: wrap;
box-sizing: border-box;
// width: 500px;
.card-item{
margin-bottom: 40px;
.border {
border-radius: 20px;
border-style: dashed;
padding:20px;
width: 100%;
}
.card-item-content{
.title {
font-size: 24px;
width: 100%;
text-align: center;
}
.section{
border-top: 1px solid ;
padding: 10px 0;
.section-title{
font-size: 24px;
width: 100%;
}
.section-content{
display: flex;
flex-direction: row;
margin: 5px 0 10px 0;
}
}
.pic-sound-box {
width: 50%;
display: flex;
flex-direction: column;
}
.add-btn-box {
display: flex;
align-items: center;
justify-content: center;
height: 20vw;
padding: 10px;
padding-top: 5vw;
}
}
}
}
}
.hidden{
display: none;
}
.clearfix:before,.clearfix:after {
content: "";
display: block;
clear: both;
}
import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef, ChangeDetectorRef} from '@angular/core';
import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef} from '@angular/core';
import defauleFormData from '../../assets/default/formData/defaultData_LST08.js'
@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";
// 储存对象
item;
_item: any;
dataArray: Array<Object> = [];
contentObj = {
dataArray: [],
}
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) {
KEY = 'DataKey_LST08';
set item(item) {
this._item = item;
}
get item() {
return this._item;
}
@Output()
update = new EventEmitter();
constructor(private appRef: ApplicationRef) {
ngOnInit() {
}
ngOnInit() {
this.item = {};
// 获取存储的数据
(<any> window).courseware.getData((data) => {
this.item.contentObj = {};
const getData = (<any> window).courseware.getData;
getData((data) => {
// console.log("读取数据", data)
if (data) {
this.item = data;
} else {
this.item = {};
}
if ( !this.item.contentObj ) {
this.item.contentObj = {};
}
this.init();
this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges();
this.refresh();
this.save()
}, this.KEY);
}
ngOnChanges() {
}, this.saveKey);
}
ngOnDestroy() {
}
saveData(e){
this.save();
}
ngOnChanges() {
init() {
if (Object.keys(this.item.contentObj).length != 0 && this.item.contentObj.version && this.item.contentObj.version==defauleFormData.version) {
// console.log("使用默认数据", this.item.contentObj)
this.contentObj = this.item.contentObj;
this.dataArray = this.item.contentObj.dataArray;
} else {
this.contentObj = defauleFormData;
this.dataArray = defauleFormData.dataArray
// console.log("使用默认数据", this.contentObj)
this.item.contentObj = this.contentObj;
this.item.contentObj.dataArray = this.dataArray;
this.item.contentObj.question = defauleFormData.question;
}
}
ngOnDestroy() {
cardItemData(){
return {
correct: [
{
type: "Text",
text: "",
audio_url: "",
image_url: "",
}
],
incorrect: [
]
}
}
cardChoiceData(){
return { type:"Text", image_url:"", text:"", audio_url:"" }
}
addChoice(item) {
console.log(item)
item.push(this.cardChoiceData());
this.saveItem();
}
init() {
deleteChoice(item, index){
item.splice(index,1)
this.save()
}
getDefaultPicArr() {
let arr = [];
return arr;
}
initData() {
/**
* 储存图片数据
* @param e
*/
onImageUploadSuccess(e, key) {
}
this.item[key] = e.url;
onUploadSuccessByItem(e, item, key) {
item[key] = e.url;
this.save();
}
/**
* 储存音频数据
* @param e
*/
onAudioUploadSuccess(e, key) {
onImageUploadSuccessByItem(e, item, key) {
item[key] = e.url
this.save();
}
this.item[key] = e.url;
onAudioUploadSuccessByItem(e, item, key) {
item[key] = e.url;
this.save();
}
onTitleAudioUploadSuccess(e) {
this.item.contentObj.titleAudio_url = e.url;
this.save();
}
addItem(type) {
let item = this.cardItemData();
this[type].push(item);
this.saveItem();
}
deleteItem(type, index){
this[type].splice(index,1)
this.save()
}
handleMoveItemUp(key, index){
if(index!=0){
this[key][index] = this[key].splice(index-1, 1, this[key][index])[0];
}else{
this[key].push(this[key].shift());
}
this.save()
}
handleMoveItemDown(key, index){
if(index!=this[key].length-1){
this[key][index] = this[key].splice(index+1, 1, this[key][index])[0];
}else{
this[key].unshift( this[key].splice(index,1)[0]);
}
this.save()
}
radioClick(it, radioValue) {
it.radioValue = radioValue;
this.saveItem();
}
clickCheckBox() {
this.saveItem();
}
saveItem() {
this.save();
}
/**
* 储存数据
*/
save() {
(<any> window).courseware.setData(this.item, null, this.saveKey);
(<any> window).courseware.setData(this.item, null, this.KEY);
this.refresh();
console.log("保存", this.item)
}
/**
* 刷新 渲染页面
*/
refresh() {
setTimeout(() => {
this.appRef.tick();
}, 1);
}
}
import {
MySprite,
getMinScale,
ShapeRect,
tweenChange,
randomSortByArr,
Label,
showPopParticle,
moveItem,
removeItemFromArr,
rotateItem,
ShapeRectNew,
waterWave,
ShapeCircle,
MyAnimation
} from "./Unit";
export class Cartoon {
// 系统缩放比例
mapScale = 1;
stageWidth;
stageHeight;
clientWidth;
clientHeight;
// 音乐 和 图片的缓冲区
audio = new Map();
images = new Map();
imagesOriginSize = new Map();
// 坐标原点 包含缩放
originX = 0;
originY = 0;
setOrigin = (x, y) => {
this.originX = x;
this.originY = y;
}
getOrigin = () => {
return {
x: this.originX,
y: this.originY
}
}
// 相对坐标原点 包含缩放 用于添加孩子动画元素
relativeOriginX = 0;
relativeOriginY = 0;
setRelativeOrigin = (x, y) => {
this.relativeOriginX = x;
this.relativeOriginY = y;
}
getRelativeOrigin = () => {
return {
x: this.relativeOriginX,
y: this.relativeOriginY
}
}
// 存放音乐和图片的地址
audioObj = {}
imageObj = {}
_currentPlayAudio;
// 添加音乐
addAudio = (key, url) => {
this.audioObj[key] = url
};
// 添加音乐
addImage = (key, url) => {
this.imageObj[key] = url
};
// 播放音乐
_playingNow = []
audioCallback = {}
playAudio = function (key, now = false, callback = null, loop?, onplayingCallback?) {
const audio = this.audio.get(key);
if (audio) {
if (now) {
audio.pause();
audio.currentTime = 0;
}
this.audioCallback[key] = {}
if (callback) {
this.audioCallback[key]["onended"] = () => {
callback && callback()
}
audio.onended = () => {
let index = this._playingNow.indexOf(audio)
if (index != -1) {
this._playingNow.splice(index, 1)
}
callback();
};
}
if (onplayingCallback) {
this.audioCallback[key]["onplaying"] = () => {
onplayingCallback && onplayingCallback(audio)
}
audio.onplaying = () => {
onplayingCallback && onplayingCallback(audio)
}
}
audio.play();
audio.callback = callback
audio.loop = loop ? true : false
this._playingNow.push(audio)
this._currentPlayAudio = audio;
}
return audio
}
setAudioVolume(key, volume) {
if (volume < 0 || volume > 1) {
return
}
const audio = this.audio.get(key);
audio.volume = volume
}
stopAllAudio(audioAll?) {
if (!audioAll) {
audioAll = this._playingNow
}
audioAll.forEach(audio => {
if (audio) {
const audio_URL = audio.src
try {
if (audio) {
audio.onended && audio.onended()
audio.pause && audio.pause();
audio.currentTime = 0;
} else {
if (this.audioCallback[audio_URL] && this.audioCallback[audio_URL]["onended"]) {
this.audioCallback[audio_URL]["onended"]()
}
}
} catch (err) {
console.log(err)
}
}
else if (this._currentPlayAudio) {
this._currentPlayAudio.pause();
this._currentPlayAudio.currentTime = 0;
}
})
this._playingNow = []
}
stopAudio(audio_URL?) {
if (audio_URL) {
const audio = this.audio.get(audio_URL);
try {
if (audio) {
audio.onended && audio.onended()
audio.pause();
audio.currentTime = 0;
} else {
if (this.audioCallback[audio_URL] && this.audioCallback[audio_URL]["onended"]) {
this.audioCallback[audio_URL]["onended"]()
}
}
} catch (err) {
console.log(err)
}
}
else if (this._currentPlayAudio) {
this._currentPlayAudio.pause();
this._currentPlayAudio.currentTime = 0;
}
}
pauseAudio(key) {
const audio = this.audio.get(key);
audio.pause()
}
// 异步加载图片 音频资源
loadResources = () => {
const pr = [];
for (let key in this.imageObj) {
const p = this.preloadImage(this.imageObj[key]).then((img: any) => {
this.images.set(key, img);
this.imagesOriginSize.set(key, { width: img.width, height: img.height });
}).catch(err => console.log(key));
pr.push(p);
};
for (let key in this.audioObj) {
const a = this.preloadAudio(this.audioObj[key]).then((audio: any) => {
this.audio.set(key, audio);
}).catch(err => console.log(key));
pr.push(a);
};
return Promise.all(pr);
}
// 预加载图片
preloadImage = (url) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.src = url;
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);
};
audio.onerror = () => {
reject();
};
audio.src = url;
audio.load();
});
}
// 缓存页面元素
cartoonElementsBuffer = {}
createCartoonElement = (key, type) => {
this.cartoonElementsBuffer[key] = {
ref: null,
get boundingBox(){
return this.ref.getBoundingBox()
}
}
this.cartoonElementsBuffer[key].id = key;
switch (type) {
case "MySprite": this.cartoonElementsBuffer[key].ref = new MySprite(); break;
case "ShapeRect": this.cartoonElementsBuffer[key].ref = new ShapeRect(); break;
case "ShapeRectNew": this.cartoonElementsBuffer[key].ref = new ShapeRectNew(); break;
case "Label": this.cartoonElementsBuffer[key].ref = new Label(); break;
case "waterWave": this.cartoonElementsBuffer[key].ref = new waterWave(); break;
case "ShapeCircle": this.cartoonElementsBuffer[key].ref = new ShapeCircle(); break;
default: this.cartoonElementsBuffer[key].ref = new MySprite(); break;
}
this.cartoonElementsBuffer[key].ref.id = key;
return this.cartoonElementsBuffer[key]
}
deleteCartoonElement = (key) => {
if(this.cartoonElementsBuffer[key]){
this.cartoonElementsBuffer[key] = null
}
}
// 创建图片
createCartoonElementImage(id: string, image: string, width: number, height: number, initX: number, initY: number, withScale?: boolean) {
let element = this.createCartoonElement(id, "MySprite")
element.ref.init(this.images.get(image))
element.initX = initX
element.initY = initY
if (withScale) {
element.initScaleX = width * this.mapScale / element.ref.width
element.initScaleY = height * this.mapScale / element.ref.height
} else {
element.initScaleX = width / element.ref.width
element.initScaleY = height / element.ref.height
}
element.ref.scaleX = element.initScaleX
element.ref.scaleY = element.initScaleY
element.ref.x = element.initX
element.ref.y = element.initY
this.attachProperties(element)
return this.cartoonElementsBuffer[id]
}
// 创建图片(回调方式)
createCartoonElementImageFunc(id: string, image: string, callbackScale: Function, callbackPosition: Function) {
let element = this.createCartoonElement(id, "MySprite")
element.ref.init(this.images.get(image))
element.rePosition = () => {
let scale = callbackScale(element.ref.width, element.ref.height)
let position = callbackPosition(element.ref.width, element.ref.height)
// save initScale
element.ref.initScaleX = scale.sx
element.ref.initScaleY = scale.sy
element.initScaleX = scale.sx
element.initScaleY = scale.sy
// save initX_Y
element.ref.initX = position.x
element.ref.initY = position.y
element.initX = position.x
element.initY = position.y
// save initRotation
element.ref.initRotation = element.rotation ? element.rotation : 0
element.initRotation = element.rotation ? element.rotation : 0
element.ref.scaleX = scale.sx
element.ref.scaleY = scale.sy
element.ref.x = element.initX
element.ref.y = element.initY
}
element.rePosition()
this.attachProperties(element)
return this.cartoonElementsBuffer[id]
}
createCartoonElementLabel(id: string, text: string, fontName?: string, fontColor?: string, fontSize?: number, initX?: number, initY?: number) {
if (!fontName) {
fontName = "BRLNSDB"
}
if (!fontColor) {
fontColor = "#000000"
}
if (!fontSize) {
fontSize = 20
}
if (!initX) {
initX = 0
}
if (!initY) {
initY = 0
}
let element = this.createCartoonElement(id, "Label")
element.ref.text = text
element.ref.fontName = fontName
element.ref.fontColor = fontColor
element.ref.fontSize = fontSize
element.ref.x = initX
element.ref.y = initY
element.ref.textAlign = "center"
element.ref.refreshSize();
this.attachProperties(element)
return element
}
createCartoonElementLabelFunc(id: string, text: string, fontName?: string, fontColor?: string, fontSize?: number, callback?) {
let element = this.createCartoonElement(id, "Label")
element.ref.text = text
element.ref.fontName = fontName
element.ref.fontColor = fontColor
element.ref.fontSize = fontSize
element.ref.textAlign = "center"
element.ref.refreshSize();
if (callback) {
let size = callback(element.ref.width, element.ref.height)
element.ref.x = size.x
element.ref.y = size.y
}
return element
}
createLabel = (text, fontName, fontColor, fontSize, initX?, initY?) => {
let element = new Label()
element.text = text;
if (fontName) {
element.fontName = fontName;
}
if (fontColor) {
element.fontColor = fontColor;
}
if (fontSize) {
element.fontSize = fontSize;
}
element.textAlign = "center";
element.x = initX;
element.y = initY;
return element
}
createImage(image, callbackScale, callbackPosition) {
let element = new MySprite()
element.init(this.images.get(image))
let scale = callbackScale(element.width, element.height)
let position = callbackPosition(element.width, element.height)
element.scaleX = scale.sx
element.scaleY = scale.sy
element.x = position.x
element.y = position.y
element.initScaleX = scale.sx
element.initScaleY = scale.sy
element.initX = position.x
element.initY = position.y
return element
}
createBorder(config) {
let element = new ShapeRectNew()
if(config.width) element.width = config.width
if(config.height) element.height = config.height
if(config.x) element.x = config.x
if(config.y) element.y =config.y
if(config.borderColor && config.lineWidth) element.setOutLine(config.borderColor, config.lineWidth)
if(config.fill){
element.fill = true
}else{
element.fill = false
}
if(config.radius) element.radius = config.radius
return element
}
createRectangula(config) {
let element = new ShapeRectNew()
element.fill = true
if(config.width) element.width = config.width
if(config.height) element.height = config.height
if(config.x) element.x = config.x
if(config.y) element.y = config.y
if(config.fillColor) element.fillColor = config.fillColor
if(config.radius) element.radius = config.radius
return element
}
createAnimation(imageKey, length, runTime, endCallback?, order?:boolean) {
let element = new MyAnimation()
element.id = "ANI-" + imageKey + "-" + Math.floor(Math.random()*10000)
if(order){
for (let index = length; index > 0; index--) {
element.addFrameByImg(this.images.get(`${imageKey} (${index})`))
}
}else{
for (let index = 0; index < length; index++) {
element.addFrameByImg(this.images.get(`${imageKey} (${index + 1})`))
}
}
element.delayPerUnit = (runTime / length) / 1000
if (element.delayPerUnit > 1) {
element.delayPerUnit = 1
} else if (element.delayPerUnit < 0.01) {
element.delayPerUnit = 0.01;
}
element.playEndFunc = () => {
endCallback && endCallback()
}
return element
}
attachProperties(cartoonElement){
// cartoonElement.updateBoundingBox = ()=>{
// cartoonElement.boundingBox = cartoonElement.ref.getBoundingBox()
// }
// cartoonElement.boundingBox = cartoonElement.ref.getBoundingBox()
}
getCartoonElementRef = (key) => {
if (this.cartoonElementsBuffer[key]) {
return this.cartoonElementsBuffer[key].ref;
} else {
return undefined
}
}
getCartoonElement = (key) => {
return this.cartoonElementsBuffer[key]
}
getCartoonElementsRef = (keys) => {
let allElelemts = []
keys.forEach(id => {
if (this.cartoonElementsBuffer[id]) {
allElelemts.push(this.cartoonElementsBuffer[id].ref)
}
});
return allElelemts
}
getCartoonElements = (keys) => {
let allElelemts = []
keys.forEach(id => {
if (this.cartoonElementsBuffer[id]) {
allElelemts.push(this.cartoonElementsBuffer[id])
}
});
return allElelemts
}
getAllCartoonElement = () => {
return this.cartoonElementsBuffer
}
setCartoonElementPosition = (key, posi) => {
this.cartoonElementsBuffer[key].ref.x = posi.x
this.cartoonElementsBuffer[key].ref.y = posi.y
this.cartoonElementsBuffer[key].x = posi.x
this.cartoonElementsBuffer[key].y = posi.y
}
setCartoonElementPositionX = (key, x) => {
this.cartoonElementsBuffer[key].ref.x = x
this.cartoonElementsBuffer[key].x = x
}
setCartoonElementRelativePositionX = (key, x) => {
this.cartoonElementsBuffer[key].relativeX = x
}
setCartoonElementPositionY = (key, y) => {
this.cartoonElementsBuffer[key].ref.y = y
this.cartoonElementsBuffer[key].y = y
}
setCartoonElementRelativePositionY = (key, y) => {
this.cartoonElementsBuffer[key].relativeY = y
}
getCartoonElementPosition = (key) => {
return {
x: this.cartoonElementsBuffer[key].x,
y: this.cartoonElementsBuffer[key].y
}
}
getCartoonElementRelativePosition = (key) => {
return {
x: this.cartoonElementsBuffer[key].relativeX,
y: this.cartoonElementsBuffer[key].relativeY
}
}
saveSize(key){
this.cartoonElementsBuffer[key].initX = this.cartoonElementsBuffer[key].ref.x
this.cartoonElementsBuffer[key].initY = this.cartoonElementsBuffer[key].ref.y
this.cartoonElementsBuffer[key].initScaleX = this.cartoonElementsBuffer[key].ref.scaleX
this.cartoonElementsBuffer[key].initScaleY = this.cartoonElementsBuffer[key].ref.scaleX
this.cartoonElementsBuffer[key].ref.initX = this.cartoonElementsBuffer[key].ref.x
this.cartoonElementsBuffer[key].ref.initY = this.cartoonElementsBuffer[key].ref.y
this.cartoonElementsBuffer[key].ref.initScaleX = this.cartoonElementsBuffer[key].ref.scaleX
this.cartoonElementsBuffer[key].ref.initScaleY = this.cartoonElementsBuffer[key].ref.scaleX
}
resetAll = () => {
this.cartoonElementsBuffer = {}
}
}
\ No newline at end of file
import TWEEN from '@tweenjs/tween.js';
interface AirWindow extends Window {
air: any;
curCtx: any;
}
declare let window: AirWindow;
import TWEEN from "@tweenjs/tween.js";
import simplexNoise from "../../assets/libs/simplex-noise/simplex-noise.min.js"
import { del } from "selenium-webdriver/http";
import construct = Reflect.construct;
class Sprite {
x = 0;
y = 0;
color = '';
color = "";
radius = 0;
alive = false;
margin = 0;
angle = 0;
ctx;
id;
constructor(ctx = null) {
if (!ctx) {
this.ctx = window.curCtx;
this.ctx = window["curCtx"];
} else {
this.ctx = ctx;
}
......@@ -27,18 +23,10 @@ class Sprite {
update($event) {
this.draw();
}
draw() {
}
draw() { }
}
export class MySprite extends Sprite {
_width = 0;
_height = 0;
_anchorX = 0;
......@@ -53,162 +41,81 @@ export class MySprite extends Sprite {
skewX = 0;
skewY = 0;
_shadowFlag = false;
_shadowColor;
_shadowOffsetX = 0;
_shadowOffsetY = 0;
_shadowBlur = 5;
_radius = 0;
children = [this];
childDepandVisible = true;
childDepandAlpha = false;
initScaleX;
initScaleY;
initX;
initY;
img;
_z = 0;
init(imgObj = null, anchorX: number = 0.5, anchorY: number = 0.5) {
if (imgObj) {
this.img = imgObj;
this.width = this.img.width;
this.height = this.img.height;
}
this.anchorX = anchorX;
this.anchorY = anchorY;
}
setShadow(offX, offY, blur, color = 'rgba(0, 0, 0, 0.3)') {
this._shadowFlag = true;
this._shadowColor = color;
this._shadowOffsetX = offX;
this._shadowOffsetY = offY;
this._shadowBlur = blur;
}
setRadius(r) {
this._radius = r;
}
update($event = null) {
if (!this.visible && this.childDepandVisible) {
return;
}
this.draw();
}
draw() {
draw() {
this.ctx.save();
this.drawInit();
this.updateChildren();
this.ctx.restore();
}
drawInit() {
this.ctx.translate(this.x, this.y);
this.ctx.rotate(this.rotation * Math.PI / 180);
this.ctx.rotate((this.rotation * Math.PI) / 180);
this.ctx.scale(this.scaleX, this.scaleY);
this.ctx.globalAlpha = this.alpha;
this.ctx.transform(1, this.skewX, this.skewY, 1, 0, 0);
if (this._radius) {
const r = this._radius;
const w = this.width;
const h = this.height;
this.ctx.lineTo(-w / 2, h / 2); // 创建水平线
this.ctx.arcTo(-w / 2, -h / 2, -w / 2 + r, -h / 2, r);
this.ctx.arcTo(w / 2, -h / 2, w / 2, -h / 2 + r, r);
this.ctx.arcTo(w / 2, h / 2, w / 2 - r, h / 2, r);
this.ctx.arcTo(-w / 2, h / 2, -w / 2, h / 2 - r, r);
this.ctx.clip();
}
}
drawSelf() {
if (this._shadowFlag) {
this.ctx.shadowOffsetX = this._shadowOffsetX;
this.ctx.shadowOffsetY = this._shadowOffsetY;
this.ctx.shadowBlur = this._shadowBlur;
this.ctx.shadowColor = this._shadowColor;
} else {
this.ctx.shadowOffsetX = 0;
this.ctx.shadowOffsetY = 0;
this.ctx.shadowBlur = null;
this.ctx.shadowColor = null;
}
if (this.img) {
this.ctx.drawImage(this.img, this._offX, this._offY);
}
}
updateChildren() {
if (this.children.length <= 0) {
return;
}
if (this.children.length <= 0) { return; }
for (const child of this.children) {
if (child === this) {
for (let i = 0; i < this.children.length; i++) {
if (this.children[i] === this) {
if (this.visible) {
this.drawSelf();
}
} else {
child.update();
this.children[i].update();
}
}
}
load(url, anchorX = 0.5, anchorY = 0.5) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = url;
}).then(img => {
this.init(img, anchorX, anchorY);
return img;
});
......@@ -225,36 +132,77 @@ export class MySprite extends Sprite {
return a._z - b._z;
});
if (this.childDepandAlpha) {
child.alpha = this.alpha;
}
}
removeChild(child) {
const index = this.children.indexOf(child);
if (index !== -1) {
this.children.splice(index, 1);
}else{
console.warn("Can not delete child!")
}
}
removeChildren() {
for (let i = 0; i < this.children.length; i++) {
if (this.children[i]) {
if (this.children[i] !== this) {
if (this.children[i] != this) {
this.children.splice(i, 1);
i --;
i--;
}
}
}
}
_changeChildAlpha(alpha) {
for (const child of this.children) {
if (child !== this) {
child.alpha = alpha;
for (let i = 0; i < this.children.length; i++) {
if (this.children[i] != this) {
this.children[i].alpha = alpha;
}
}
}
refreshAnchorOff() {
this._offX = -this._width * this.anchorX;
this._offY = -this._height * this.anchorY;
}
setScaleXY(value) {
this.scaleX = this.scaleY = value;
}
getBoundingBox() {
const getParentData = item => {
let px = item.x;
let py = item.y;
let sx = item.scaleX;
let sy = item.scaleY;
const parent = item.parent;
if (parent) {
const obj = getParentData(parent);
const _x = obj.px;
const _y = obj.py;
const _sx = obj.sx;
const _sy = obj.sy;
px = _x + item.x * _sx;
py = _y + item.y * _sy;
sx *= _sx;
sy *= _sy;
}
return { px, py, sx, sy };
};
const data = getParentData(this);
const x = data.px + this._offX * Math.abs(data.sx);
const y = data.py + this._offY * Math.abs(data.sy);
const width = this.width * Math.abs(data.sx);
const height = this.height * Math.abs(data.sy);
return { x, y, width, height };
}
set alpha(v) {
......@@ -294,94 +242,83 @@ export class MySprite extends Sprite {
get anchorY() {
return this._anchorY;
}
refreshAnchorOff() {
this._offX = -this._width * this.anchorX;
this._offY = -this._height * this.anchorY;
}
}
setScaleXY(value) {
this.scaleX = this.scaleY = value;
export class waterWave extends MySprite {
bottole_r = 100;
bottole_x0 = 100;
bottole_y0 = 100;
simplex = new simplexNoise()
amp = 10; //波浪幅度 可以通过函数传递参数更改不同的幅度
count = 80;
speedY = 0;
speedX = 0;
height = this.bottole_r
water_color = "red"
per = 1.5
_runTimeCtl = new Date().getTime()
draw_self(color, comp, height) {
this.ctx.beginPath();
let r = this.bottole_r
let a = this.bottole_x0 // this.bottole_r*2
let b = this.bottole_y0 // this.bottole_r*2
for (var i = 0; i <= this.count; i++) {
this.speedX += 0.05;
var x = a - r + i * (r * 2 / this.count);
var y = b + r - height + this.simplex.noise2D(this.speedX, this.speedY) * this.amp;
if (x > (a + r)) {
x = a + r
}
getBoundingBox() {
const getParentData = (item) => {
let px = item.x;
let py = item.y;
let sx = item.scaleX;
let sy = item.scaleY;
const parent = item.parent;
if (parent) {
const obj = getParentData(parent);
const _x = obj.px;
const _y = obj.py;
const _sx = obj.sx;
const _sy = obj.sy;
px = _x + item.x * _sx;
py = _y + item.y * _sy;
sx *= _sx;
sy *= _sy;
if (x < (a - r)) {
x = a - r
}
return {px, py, sx, sy};
};
const data = getParentData(this);
const x = data.px + this._offX * Math.abs(data.sx);
const y = data.py + this._offY * Math.abs(data.sy);
const width = this.width * Math.abs(data.sx);
const height = this.height * Math.abs(data.sy);
// const x = this.x + this._offX * Math.abs(this.scaleX);
// const y = this.y + this._offY * Math.abs(this.scaleY);
// const width = this.width * Math.abs(this.scaleX);
// const height = this.height * Math.abs(this.scaleY);
return {x, y, width, height};
let c_y1 = Math.sqrt(r * r - (x - a) * (x - a)) + b
let c_y2 = -Math.sqrt(r * r - (x - a) * (x - a)) + b
if (y > c_y1) {
y = c_y1
}
if (y < c_y2) {
y = c_y2
}
this.ctx[i === 0 ? "moveTo" : "lineTo"](x, y);
}
this.ctx.arc(a, b, r, 0, Math.PI);
this.ctx.closePath();
this.ctx.fillStyle = color;
this.ctx.fill();
}
drawSelf() {
super.drawSelf();
this.speedX = 0;
if (new Date().getTime() - this._runTimeCtl > 10) {
this.speedY += 0.02; //每次渲染需要更新波峰波谷值
}
this._runTimeCtl = new Date().getTime()
this.draw_self(this.water_color, "screen", this.height);
}
}
export class ColorSpr extends MySprite {
r = 0;
g = 0;
b = 0;
createGSCanvas() {
if (!this.img) {
return;
}
const rect = this.getBoundingBox();
if (rect.width <= 1 || rect.height <= 1) {
return;
}
const c = this.ctx.getImageData(rect.x, rect.y, rect.width, rect.height);
for ( let i = 0; i < c.height; i++) {
for ( let j = 0; j < c.width; j++) {
const x = (i * 4) * c.width + ( j * 4 );
for (let i = 0; i < c.height; i++) {
for (let j = 0; j < c.width; j++) {
const x = i * 4 * c.width + j * 4;
const r = c.data[x];
const g = c.data[x + 1];
const b = c.data[x + 2];
......@@ -390,88 +327,61 @@ export class ColorSpr extends MySprite {
c.data[x + 1] = this.g;
c.data[x + 2] = this.b;
// c.data[x] = c.data[x + 1] = c.data[x + 2] = (r + g + b) / 3 ;
// // c.data[x + 3] = 255;
}
}
this.ctx.putImageData(c, rect.x, rect.y, 0, 0, rect.width, rect.height);
}
drawSelf() {
super.drawSelf();
this.createGSCanvas();
}
}
export class GrayscaleSpr extends MySprite {
grayScale = 120;
createGSCanvas() {
if (!this.img) {
return;
}
const rect = this.getBoundingBox();
const c = this.ctx.getImageData(rect.x, rect.y, rect.width, rect.height);
for ( let i = 0; i < c.height; i++) {
for ( let j = 0; j < c.width; j++) {
const x = (i * 4) * c.width + ( j * 4 );
for (let i = 0; i < c.height; i++) {
for (let j = 0; j < c.width; j++) {
const x = i * 4 * c.width + j * 4;
const r = c.data[x];
const g = c.data[x + 1];
const b = c.data[x + 2];
// const a = c.data[x + 3];
c.data[x] = c.data[x + 1] = c.data[x + 2] = this.grayScale; // (r + g + b) / 3;
// c.data[x + 3] = 255;
}
}
this.ctx.putImageData(c, rect.x, rect.y, 0, 0, rect.width, rect.height);
}
drawSelf() {
super.drawSelf();
this.createGSCanvas();
}
}
export class BitMapLabel extends MySprite {
labelArr;
baseUrl;
setText(data, text) {
this.labelArr = [];
const labelArr = [];
const tmpArr = text.split('');
const tmpArr = text.split("");
let totalW = 0;
let h = 0;
for (const tmp of tmpArr) {
for (let i = 0; i < tmpArr.length; i++) {
const label = new MySprite(this.ctx);
label.init(data[tmp], 0);
label.init(data[tmpArr[i]], 0);
this.addChild(label);
labelArr.push(label);
......@@ -479,47 +389,44 @@ export class BitMapLabel extends MySprite {
h = label.height;
}
this.width = totalW;
this.height = h;
let offX = -totalW / 2;
for (const label of labelArr) {
label.x = offX;
offX += label.width;
for (let i = 0; i < labelArr.length; i++) {
labelArr[i].x = offX;
offX += labelArr[i].width;
}
this.labelArr = labelArr;
}
}
export class Label extends MySprite {
text: string;
text: String;
// fontSize:String = '40px';
fontName = 'Verdana';
textAlign = 'left';
fontName: String = "Verdana";
textAlign: String = "left";
fontSize = 40;
fontColor = '#000000';
fontColor = "#000000";
fontWeight = 900;
_maxWidth;
maxWidth;
outline = 0;
outlineColor = '#ffffff';
outlineColor = "#ffffff";
// _shadowFlag = false;
// _shadowColor;
// _shadowOffsetX;
// _shadowOffsetY;
// _shadowBlur;
maxSingalLineWidth = 0;
baseY = 0
warpLineHeight = 0;
_shadowFlag = false;
_shadowColor;
_shadowOffsetX;
_shadowOffsetY;
_shadowBlur;
_outlineFlag = false;
_outLineWidth;
_outLineColor;
_warpLineY = 0;
constructor(ctx = null) {
super(ctx);
......@@ -527,25 +434,47 @@ export class Label extends MySprite {
}
refreshSize() {
this.ctx.save();
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.textBaseline = "middle";
this.ctx.fontWeight = this.fontWeight;
this._width = this.ctx.measureText(this.text).width;
this._height = this.fontSize;
let height = this.fontSize
if (this.maxSingalLineWidth !== 0) {
var words = this.text.split(' ');
var line = '';
let index = 0;
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = this.ctx.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > this.maxSingalLineWidth && n > 0) {
// this.ctx.fillText(line, 0, this._warpLineY);
line = words[n] + ' ';
// this._warpLineY += this.fontSize;
index++
console.log(index)
height += this.fontSize;
}else {
line = testLine;
}
}
this._height = height;
}else{
this.height = this.fontSize;
}
this.refreshAnchorOff();
this.ctx.restore();
}
setMaxSize(w) {
this._maxWidth = w;
this.maxWidth = w;
this.refreshSize();
if (this.width >= w) {
this.scaleX *= w / this.width;
......@@ -554,7 +483,6 @@ export class Label extends MySprite {
}
show(callBack = null) {
this.visible = true;
if (this.alpha >= 1) {
......@@ -564,7 +492,7 @@ export class Label extends MySprite {
const tween = new TWEEN.Tween(this)
.to({ alpha: 1 }, 800)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
.onComplete(function () {
if (callBack) {
callBack();
}
......@@ -572,47 +500,41 @@ export class Label extends MySprite {
.start(); // Start the tween immediately.
}
// setShadow(offX = 0, offY = 2, blur = 2, color = 'rgba(0, 0, 0, 0.2)') {
//
// this._shadowFlag = true;
// this._shadowColor = color;
// // 将阴影向右移动15px,向上移动10px
// this._shadowOffsetX = 5;
// this._shadowOffsetY = 5;
// // 轻微模糊阴影
// this._shadowBlur = 5;
// }
setOutline(width = 5, color = '#ffffff') {
setShadow(offX = 2, offY = 2, blur = 2, color = "rgba(0, 0, 0, 0.2)") {
this._shadowFlag = true;
this._shadowColor = color;
// 将阴影向右移动15px,向上移动10px
this._shadowOffsetX = offX;
this._shadowOffsetY = offY;
// 轻微模糊阴影
this._shadowBlur = blur;
}
setOutline(width = 5, color = "#ffffff") {
this._outlineFlag = true;
this._outLineWidth = width;
this._outLineColor = color;
}
drawText() {
// console.log('in drawText', this.text);
if (!this.text) { return; }
// if (this._shadowFlag) {
//
// this.ctx.shadowColor = this._shadowColor;
// // 将阴影向右移动15px,向上移动10px
// this.ctx.shadowOffsetX = this._shadowOffsetX;
// this.ctx.shadowOffsetY = this._shadowOffsetY;
// // 轻微模糊阴影
// this.ctx.shadowBlur = this._shadowBlur;
// }
if (!this.text) {
return;
}
if (this._shadowFlag) {
this.ctx.shadowColor = this._shadowColor;
// 将阴影向右移动15px,向上移动10px
this.ctx.shadowOffsetX = this._shadowOffsetX;
this.ctx.shadowOffsetY = this._shadowOffsetY;
// 轻微模糊阴影
this.ctx.shadowBlur = this._shadowBlur;
}
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.textBaseline = "middle";
this.ctx.fontWeight = this.fontWeight;
if (this._outlineFlag) {
......@@ -623,61 +545,152 @@ export class Label extends MySprite {
this.ctx.fillStyle = this.fontColor;
if (this.outline > 0) {
this.ctx.lineWidth = this.outline;
this.ctx.strokeStyle = this.outlineColor;
this.ctx.strokeText(this.text, 0, 0);
}
// 当maxSingalLineWidth不为0时,对数据进行换行处理
if (this.maxSingalLineWidth !== 0) {
var words = this.text.split(' ');
var line = '';
this._warpLineY = 0;
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = this.ctx.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > this.maxSingalLineWidth && n > 0) {
this.ctx.fillText(line, 0, this._warpLineY);
line = words[n] + ' ';
this._warpLineY += this.fontSize;
}
else {
line = testLine;
}
}
this.y = this.baseY // + this._warpLineY
this.ctx.fillText(line, 0, this._warpLineY);
} else {
this.ctx.fillText(this.text, 0, 0);
}
}
drawSelf() {
super.drawSelf();
this.drawText();
}
}
export class ShapeRectNew extends MySprite {
radius = 0;
fillColor = '#ffffff';
strokeColor = '#000000';
fill = true;
stroke = false;
lineWidth = 1;
setSize(w, h, r) {
this.width = w;
this.height = h;
this.radius = r;
}
setOutLine(color, lineWidth) {
this.stroke = true;
this.strokeColor = color;
this.lineWidth = lineWidth;
}
drawShape() {
const ctx = this.ctx;
const width = this.width;
const height = this.height;
const radius = this.radius;
ctx.save();
ctx.beginPath(0);
// 从右下角顺时针绘制,弧度从0到1/2PI
ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
// 矩形下边线
ctx.lineTo(radius, height);
// 左下角圆弧,弧度从1/2PI到PI
ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
// 矩形左边线
ctx.lineTo(0, radius);
// 左上角圆弧,弧度从PI到3/2PI
ctx.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
// 上边线
ctx.lineTo(width - radius, 0);
// 右上角圆弧
ctx.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
// 右边线
ctx.lineTo(width, height - radius);
ctx.closePath();
if (this.fill) {
ctx.fillStyle = this.fillColor;
ctx.fill();
}
if (this.stroke) {
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.strokeColor;
ctx.stroke();
}
ctx.restore();
}
drawSelf() {
super.drawSelf();
this.drawText();
this.drawShape();
}
}
export class RichTextOld extends Label {
textArr = [];
fontSize = 40;
setText(text: string, words) {
let newText = text;
for (const word of words) {
for (let i = 0; i < words.length; i++) {
const word = words[i];
const re = new RegExp(word, 'g');
newText = newText.replace( re, `#${word}#`);
const re = new RegExp(word, "g");
newText = newText.replace(re, `#${word}#`);
// newText = newText.replace(word, `#${word}#`);
}
this.textArr = newText.split('#');
this.textArr = newText.split("#");
this.text = newText;
// this.setSize();
}
refreshSize() {
this.ctx.save();
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.textBaseline = "middle";
this.ctx.fontWeight = this.fontWeight;
let curX = 0;
for (const text of this.textArr) {
const w = this.ctx.measureText(text).width;
for (let i = 0; i < this.textArr.length; i++) {
const w = this.ctx.measureText(this.textArr[i]).width;
curX += w;
}
......@@ -686,12 +699,9 @@ export class RichTextOld extends Label {
this.refreshAnchorOff();
this.ctx.restore();
}
show(callBack = null) {
// console.log(' in show ');
this.visible = true;
// this.alpha = 0;
......@@ -699,185 +709,119 @@ export class RichTextOld extends Label {
const tween = new TWEEN.Tween(this)
.to({ alpha: 1 }, 800)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
.onComplete(function () {
if (callBack) {
callBack();
}
})
.start(); // Start the tween immediately.
}
drawText() {
// console.log('in drawText', this.text);
if (!this.text) { return; }
if (!this.text) {
return;
}
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.textBaseline = "middle";
this.ctx.fontWeight = 900;
this.ctx.lineWidth = 5;
this.ctx.strokeStyle = '#ffffff';
this.ctx.strokeStyle = "#ffffff";
// this.ctx.strokeText(this.text, 0, 0);
this.ctx.fillStyle = '#000000';
this.ctx.fillStyle = "#000000";
// this.ctx.fillText(this.text, 0, 0);
let curX = 0;
for (let i = 0; i < this.textArr.length; i++) {
const w = this.ctx.measureText(this.textArr[i]).width;
if ((i + 1) % 2 === 0) {
this.ctx.fillStyle = '#c8171e';
if ((i + 1) % 2 == 0) {
this.ctx.fillStyle = "#c8171e";
} else {
this.ctx.fillStyle = '#000000';
this.ctx.fillStyle = "#000000";
}
this.ctx.fillText(this.textArr[i], curX, 0);
curX += w;
}
}
}
export class RichText extends Label {
disH = 30;
constructor(ctx?: any) {
constructor(ctx = null) {
super(ctx);
// this.dataArr = dataArr;
}
drawText() {
if (!this.text) {
return;
}
this.ctx.font = `${this.fontSize}px ${this.fontName}`;
this.ctx.textAlign = this.textAlign;
this.ctx.textBaseline = 'middle';
this.ctx.textBaseline = "middle";
this.ctx.fontWeight = this.fontWeight;
this.ctx.fillStyle = this.fontColor;
const selfW = this.width * this.scaleX;
const chr = this.text.split(' ');
let temp = '';
const chr = this.text.split(" ");
let temp = "";
const row = [];
const w = selfW - 80;
const disH = (this.fontSize + this.disH) * this.scaleY;
for (const c of chr) {
if (this.ctx.measureText(temp).width < w && this.ctx.measureText(temp + (c)).width <= w) {
temp += ' ' + c;
for (let a = 0; a < chr.length; a++) {
if (
this.ctx.measureText(temp).width < w &&
this.ctx.measureText(temp + chr[a]).width <= w
) {
temp += " " + chr[a];
} else {
row.push(temp);
temp = ' ' + c;
temp = " " + chr[a];
}
}
row.push(temp);
const x = 0;
const y = -row.length * disH / 2;
const y = (-row.length * disH) / 2;
// for (let b = 0 ; b < row.length; b++) {
// this.ctx.strokeText(row[b], x, y + ( b + 1 ) * disH ); // 每行字体y坐标间隔20
// }
if (this._outlineFlag) {
this.ctx.lineWidth = this._outLineWidth;
this.ctx.strokeStyle = this._outLineColor;
for (let b = 0 ; b < row.length; b++) {
this.ctx.strokeText(row[b], x, y + ( b + 1 ) * disH ); // 每行字体y坐标间隔20
for (let b = 0; b < row.length; b++) {
this.ctx.strokeText(row[b], x, y + (b + 1) * disH); // 每行字体y坐标间隔20
}
// this.ctx.strokeText(this.text, 0, 0);
}
// this.ctx.fillStyle = '#ff7600';
for (let b = 0 ; b < row.length; b++) {
this.ctx.fillText(row[b], x, y + ( b + 1 ) * disH ); // 每行字体y坐标间隔20
for (let b = 0; b < row.length; b++) {
this.ctx.fillText(row[b], x, y + (b + 1) * disH); // 每行字体y坐标间隔20
}
}
drawSelf() {
super.drawSelf();
this.drawText();
}
}
export class LineRect extends MySprite {
lineColor = '#ffffff';
lineWidth = 10;
setSize(w, h) {
this.width = w;
this.height = h;
}
drawLine() {
this.ctx.beginPath();
this.ctx.moveTo(this._offX, this._offY);
this.ctx.lineTo(this._offX + this.width, this._offY);
this.ctx.lineTo(this._offX + this.width, this._offY + this.height);
this.ctx.lineTo(this._offX, this._offY + this.height);
this.ctx.closePath();
this.ctx.lineWidth = this.lineWidth;
// this.ctx.fillStyle = "rgb(2,33,42)"; //指定填充颜色
// this.ctx.fill(); //对多边形进行填充
this.ctx.strokeStyle = this.lineColor; // "#ffffff";
this.ctx.stroke();
}
drawSelf() {
super.drawSelf();
this.drawLine();
}
}
export class ShapeRect extends MySprite {
fillColor = '#FF0000';
fillColor = "#FF0000";
setSize(w, h) {
this.width = w;
......@@ -888,136 +832,71 @@ export class ShapeRect extends MySprite {
}
drawShape() {
this.ctx.fillStyle = this.fillColor;
this.ctx.fillRect(this._offX, this._offY, this.width, this.height);
}
drawSelf() {
super.drawSelf();
this.drawShape();
}
}
export class ShapeCircle extends MySprite {
fillColor = '#FF0000';
fillColor = "#FFFF00";
radius = 0;
startRadian = 0;
endRadian = 180;
strokeLineWidth = 5;
strokeColor = "#702dee";
drawType = "fill"
counterclockwise = false; // false 逆时针 true 顺时针
shadowColor = "rgba(0,0,0,0)"
shadowOffsetX = 0;
shadowOffsetY = 0;
setRadius(r) {
this.anchorX = this.anchorY = 0.5;
this.radius = r;
this.width = r * 2;
this.height = r * 2;
}
drawShape() {
switch (this.drawType) {
case "stroke":
this.ctx.beginPath();
this.ctx.strokeStyle = this.strokeColor;
this.ctx.lineWidth = this.strokeLineWidth
this.ctx.arc(0, 0, this.radius, this.startRadian, this.endRadian, this.counterclockwise);
this.ctx.stroke()
break;
default:
this.ctx.beginPath();
this.ctx.fillStyle = this.fillColor;
this.ctx.arc(0, 0, this.radius, 0, angleToRadian(360));
this.ctx.arc(0, 0, this.radius, this.startRadian, this.endRadian);
this.ctx.shadowColor = this.shadowColor
this.ctx.shadowOffsetX = this.shadowOffsetX
this.ctx.shadowOffsetY = this.shadowOffsetY
this.ctx.fill();
break;
}
drawSelf() {
super.drawSelf();
this.drawShape();
}
}
export class ShapeRectNew extends MySprite {
radius = 0;
fillColor = '#ffffff';
strokeColor = '#000000';
fill = true;
stroke = false;
lineWidth = 1;
setSize(w, h, r) {
this.width = w;
this.height = h;
this.radius = r;
}
setOutLine(color, lineWidth) {
this.stroke = true;
this.strokeColor = color;
this.lineWidth = lineWidth;
}
drawShape() {
const ctx = this.ctx;
const width = this.width;
const height = this.height;
const radius = this.radius;
ctx.save();
ctx.beginPath(0);
// 从右下角顺时针绘制,弧度从0到1/2PI
ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
// 矩形下边线
ctx.lineTo(radius, height);
// 左下角圆弧,弧度从1/2PI到PI
ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
// 矩形左边线
ctx.lineTo(0, radius);
// 左上角圆弧,弧度从PI到3/2PI
ctx.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
// 上边线
ctx.lineTo(width - radius, 0);
// 右上角圆弧
ctx.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
// 右边线
ctx.lineTo(width, height - radius);
ctx.closePath();
if (this.fill) {
ctx.fillStyle = this.fillColor;
ctx.fill();
}
if (this.stroke) {
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.strokeColor;
ctx.stroke();
}
ctx.restore();
}
drawSelf() {
super.drawSelf();
this.drawShape();
}
}
export class MyAnimation extends MySprite {
export class MyAnimation extends MySprite {
frameArr = [];
frameIndex = 0;
playFlag = false;
lastDateTime;
curDelay = 0;
loop = false;
playEndFunc;
delayPerUnit = 1;
......@@ -1026,7 +905,6 @@ export class MyAnimation extends MySprite {
reverseFlag = false;
addFrameByImg(img) {
const spr = new MySprite(this.ctx);
spr.init(img);
this._refreshSize(img);
......@@ -1040,10 +918,8 @@ export class MyAnimation extends MySprite {
}
addFrameByUrl(url) {
const spr = new MySprite(this.ctx);
spr.load(url).then(img => {
this._refreshSize(img);
});
spr.visible = false;
......@@ -1054,18 +930,15 @@ export class MyAnimation extends MySprite {
this.frameArr[this.frameIndex].visible = true;
}
_refreshSize(img: any) {
if (this.width < img.width) {
this.width = img.width;
_refreshSize(img) {
if (this.width < img["width"]) {
this.width = img["width"];
}
if (this.height < img.height) {
this.height = img.height;
if (this.height < img["height"]) {
this.height = img["height"];
}
}
play() {
this.playFlag = true;
this.lastDateTime = new Date().getTime();
......@@ -1075,13 +948,11 @@ export class MyAnimation extends MySprite {
this.playFlag = false;
}
replay() {
this.restartFlag = true;
this.play();
}
reverse() {
this.reverseFlag = !this.reverseFlag;
this.frameArr.reverse();
......@@ -1089,20 +960,18 @@ export class MyAnimation extends MySprite {
}
showAllFrame() {
for (const frame of this.frameArr ) {
frame.alpha = 1;
for (let i = 0; i < this.frameArr.length; i++) {
this.frameArr[i].alpha = 1;
}
}
hideAllFrame() {
for (const frame of this.frameArr) {
frame.alpha = 0;
for (let i = 0; i < this.frameArr.length; i++) {
this.frameArr[i].alpha = 0;
}
}
playEnd() {
this.playFlag = false;
this.curDelay = 0;
......@@ -1119,7 +988,7 @@ export class MyAnimation extends MySprite {
this.frameArr[this.frameIndex].visible = false;
}
this.frameIndex ++;
this.frameIndex++;
if (this.frameIndex >= this.frameArr.length) {
if (this.loop) {
this.frameIndex = 0;
......@@ -1127,21 +996,16 @@ export class MyAnimation extends MySprite {
this.restartFlag = false;
this.frameIndex = 0;
} else {
this.frameIndex -- ;
this.frameIndex--;
this.playEnd();
return;
}
}
this.frameArr[this.frameIndex].visible = true;
}
_updateDelay(delay) {
this.curDelay += delay;
if (this.curDelay < this.delayPerUnit) {
return;
......@@ -1151,7 +1015,9 @@ export class MyAnimation extends MySprite {
}
_updateLastDate() {
if (!this.playFlag) { return; }
if (!this.playFlag) {
return;
}
let delay = 0;
if (this.lastDateTime) {
......@@ -1165,18 +1031,18 @@ export class MyAnimation extends MySprite {
super.update($event);
this._updateLastDate();
}
}
// --------=========== util func =============-------------
export function tweenChange(item, obj, time = 0.8, callBack = null, easing = null, update = null) {
export function tweenChange(
item,
obj,
time = 0.8,
callBack = null,
easing = null,
update = null
) {
const tween = new TWEEN.Tween(item).to(obj, time * 1000);
if (callBack) {
......@@ -1188,7 +1054,7 @@ export function tweenChange(item, obj, time = 0.8, callBack = null, easing = nul
tween.easing(easing);
}
if (update) {
tween.onUpdate( (a, b) => {
tween.onUpdate((a, b) => {
update(a, b);
});
}
......@@ -1197,11 +1063,13 @@ export function tweenChange(item, obj, time = 0.8, callBack = null, easing = nul
return tween;
}
export function rotateItem(item, rotation, time = 0.8, callBack = null, easing = null) {
export function rotateItem(
item,
rotation,
time = 0.8,
callBack = null,
easing = null
) {
const tween = new TWEEN.Tween(item).to({ rotation }, time * 1000);
if (callBack) {
......@@ -1216,11 +1084,17 @@ export function rotateItem(item, rotation, time = 0.8, callBack = null, easing =
tween.start();
}
export function scaleItem(item, scale, time = 0.8, callBack = null, easing = null) {
const tween = new TWEEN.Tween(item).to({ scaleX: scale, scaleY: scale}, time * 1000);
export function scaleItem(
item,
scale,
time = 0.8,
callBack = null,
easing = null
) {
const tween = new TWEEN.Tween(item).to(
{ scaleX: scale, scaleY: scale },
time * 1000
);
if (callBack) {
tween.onComplete(() => {
......@@ -1235,10 +1109,15 @@ export function scaleItem(item, scale, time = 0.8, callBack = null, easing = nul
return tween;
}
export function moveItem(item, x, y, time = 0.8, callBack = null, easing = null) {
const tween = new TWEEN.Tween(item).to({ x, y}, time * 1000);
export function moveItem(
item,
x,
y,
time = 0.8,
callBack = null,
easing = null
) {
const tween = new TWEEN.Tween(item).to({ x, y }, time * 1000);
if (callBack) {
tween.onComplete(() => {
......@@ -1254,36 +1133,26 @@ export function moveItem(item, x, y, time = 0.8, callBack = null, easing = null)
return tween;
}
export function endShow(item, s = 1) {
item.scaleX = item.scaleY = 0;
item.alpha = 0;
const tween = new TWEEN.Tween(item)
.to({ alpha: 1, scaleX: s, scaleY: s }, 800)
.easing(TWEEN.Easing.Elastic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
})
.onComplete(function () { })
.start();
}
export function hideItem(item, time = 0.8, callBack = null, easing = null) {
if (item.alpha === 0) {
if (item.alpha == 0) {
return;
}
const tween = new TWEEN.Tween(item)
.to({alpha: 0}, time * 1000)
.to({ alpha: 0 }, time * 1000)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
.onComplete(function () {
if (callBack) {
callBack();
}
......@@ -1296,10 +1165,8 @@ export function hideItem(item, time = 0.8, callBack = null, easing = null) {
tween.start();
}
export function showItem(item, time = 0.8, callBack = null, easing = null) {
if (item.alpha === 1) {
if (item.alpha == 1) {
if (callBack) {
callBack();
}
......@@ -1308,9 +1175,9 @@ export function showItem(item, time = 0.8, callBack = null, easing = null) {
item.visible = true;
const tween = new TWEEN.Tween(item)
.to({alpha: 1}, time * 1000)
.to({ alpha: 1 }, time * 1000)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
.onComplete(function () {
if (callBack) {
callBack();
}
......@@ -1323,14 +1190,17 @@ export function showItem(item, time = 0.8, callBack = null, easing = null) {
tween.start();
}
export function alphaItem(item, alpha, time = 0.8, callBack = null, easing = null) {
export function alphaItem(
item,
alpha,
time = 0.8,
callBack = null,
easing = null
) {
const tween = new TWEEN.Tween(item)
.to({alpha}, time * 1000)
.to({ alpha: alpha }, time * 1000)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
.onComplete(function () {
if (callBack) {
callBack();
}
......@@ -1343,14 +1213,11 @@ export function alphaItem(item, alpha, time = 0.8, callBack = null, easing = nul
tween.start();
}
export function showStar(item, time = 0.8, callBack = null, easing = null) {
const tween = new TWEEN.Tween(item)
.to({alpha: 1, scale: 1}, time * 1000)
.to({ alpha: 1, scale: 1 }, time * 1000)
// .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
.onComplete(() => {
.onComplete(function () {
if (callBack) {
callBack();
}
......@@ -1363,97 +1230,103 @@ export function showStar(item, time = 0.8, callBack = null, easing = null) {
tween.start();
}
export function randomSortByArr(arr) {
const newArr = [];
const tmpArr = arr.concat();
while (tmpArr.length > 0) {
const randomIndex = Math.floor( tmpArr.length * Math.random() );
const randomIndex = Math.floor(tmpArr.length * Math.random());
newArr.push(tmpArr[randomIndex]);
tmpArr.splice(randomIndex, 1);
}
return newArr;
}
export function radianToAngle(radian) {
return radian * 180 / Math.PI;
return (radian * 180) / Math.PI;
// 角度 = 弧度 * 180 / Math.PI;
}
export function angleToRadian(angle) {
return angle * Math.PI / 180;
return (angle * Math.PI) / 180;
// 弧度= 角度 * Math.PI / 180;
}
export function getPosByAngle(angle, len) {
const radian = angle * Math.PI / 180;
const radian = (angle * Math.PI) / 180;
const x = Math.sin(radian) * len;
const y = Math.cos(radian) * len;
return {x, y};
return { x, y };
}
export function getAngleByPos(px, py, mx, my) {
const x = Math.abs(px - mx);
const y = Math.abs(py - my);
const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
const cos = y / z;
const radina = Math.acos(cos); // 用反三角函数求弧度
let angle = Math.floor(180 / (Math.PI / radina) * 100) / 100; // 将弧度转换成角度
let angle = Math.floor((180 / (Math.PI / radina)) * 100) / 100; // 将弧度转换成角度
if (mx > px && my > py) {// 鼠标在第四象限
if (mx > px && my > py) {
// 鼠标在第四象限
angle = 180 - angle;
}
if (mx === px && my > py) {// 鼠标在y轴负方向上
if (mx === px && my > py) {
// 鼠标在y轴负方向上
angle = 180;
}
if (mx > px && my === py) {// 鼠标在x轴正方向上
if (mx > px && my === py) {
// 鼠标在x轴正方向上
angle = 90;
}
if (mx < px && my > py) {// 鼠标在第三象限
if (mx < px && my > py) {
// 鼠标在第三象限
angle = 180 + angle;
}
if (mx < px && my === py) {// 鼠标在x轴负方向
if (mx < px && my === py) {
// 鼠标在x轴负方向
angle = 270;
}
if (mx < px && my < py) {// 鼠标在第二象限
if (mx < px && my < py) {
// 鼠标在第二象限
angle = 360 - angle;
}
// console.log('angle: ', angle);
return angle;
}
export function removeItemFromArr(arr, item) {
const index = arr.indexOf(item);
if (index !== -1) {
if (index != -1) {
arr.splice(index, 1);
}
}
export function circleMove(item, x0, y0, time = 2, addR = 360, xPer = 1, yPer = 1, callBack = null, easing = null) {
export function circleMove(
item,
x0,
y0,
time = 2,
addR = 360,
xPer = 1,
yPer = 1,
callBack = null,
easing = null
) {
const r = getPosDistance(item.x, item.y, x0, y0);
let a = getAngleByPos(item.x, item.y, x0, y0);
a += 90;
const obj = {r, a};
const obj = { r, a };
item._circleAngle = a;
const targetA = a + addR;
const tween = new TWEEN.Tween(item).to({_circleAngle: targetA}, time * 1000);
const tween = new TWEEN.Tween(item).to(
{ _circleAngle: targetA },
time * 1000
);
if (callBack) {
tween.onComplete(() => {
......@@ -1464,14 +1337,13 @@ export function circleMove(item, x0, y0, time = 2, addR = 360, xPer = 1, yPer =
tween.easing(easing);
}
tween.onUpdate( (item, progress) => {
tween.onUpdate((item, progress) => {
// console.log(item._circleAngle);
const r = obj.r;
const a = item._circleAngle;
const x = x0 + r * xPer * Math.cos(a * Math.PI / 180);
const y = y0 + r * yPer * Math.sin(a * Math.PI / 180);
const x = x0 + r * xPer * Math.cos((a * Math.PI) / 180);
const y = y0 + r * yPer * Math.sin((a * Math.PI) / 180);
item.x = x;
item.y = y;
......@@ -1482,12 +1354,10 @@ export function circleMove(item, x0, y0, time = 2, addR = 360, xPer = 1, yPer =
tween.start();
}
export function getPosDistance(sx, sy, ex, ey) {
const _x = ex - sx;
const _y = ey - sy;
const len = Math.sqrt( Math.pow(_x, 2) + Math.pow(_y, 2) );
const len = Math.sqrt(Math.pow(_x, 2) + Math.pow(_y, 2));
return len;
}
......@@ -1502,29 +1372,6 @@ export function delayCall(callback, second) {
.start();
}
export function formatTime(fmt, date) {
// "yyyy-MM-dd HH:mm:ss";
const o = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'h+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
S: date.getMilliseconds() // 毫秒
};
if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); }
for (const k in o) {
if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1)
? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
}
}
return fmt;
}
export function getMinScale(item, maxLen) {
const sx = maxLen / item.width;
const sy = maxLen / item.height;
......@@ -1532,11 +1379,7 @@ export function getMinScale(item, maxLen) {
return minS;
}
export function jelly(item, time = 0.7) {
if (item.jellyTween) {
TWEEN.remove(item.jellyTween);
}
......@@ -1552,10 +1395,16 @@ export function jelly(item, time = 0.7) {
return;
}
const data = arr[index];
const t = tweenChange(item, {scaleX: data[0], scaleY: data[1]}, data[2], () => {
index ++;
const t = tweenChange(
item,
{ scaleX: data[0], scaleY: data[1] },
data[2],
() => {
index++;
run();
}, TWEEN.Easing.Sinusoidal.InOut);
},
TWEEN.Easing.Sinusoidal.InOut
);
item.jellyTween = t;
};
......@@ -1564,20 +1413,24 @@ export function jelly(item, time = 0.7) {
[baseSX * 0.98, baseSY * 1.02, t * 2],
[baseSX * 1.02, baseSY * 0.98, t * 2],
[baseSX * 0.99, baseSY * 1.01, t * 2],
[baseSX * 1.0, baseSY * 1.0, t * 2],
[baseSX * 1.0, baseSY * 1.0, t * 2]
];
run();
}
export function showPopParticle(img, pos, parent, num = 20, minLen = 40, maxLen = 80, showTime = 0.4) {
for (let i = 0; i < num; i ++) {
/**
* 烟花爆炸效果动画
* @param img 颗粒的图片
* @param pos 爆点的坐标
* @param parent 必须传一个父类
*/
export function showPopParticle(img, pos, parent) {
const num = 20;
const maxLen = 100;
const minLen = 40;
for (let i = 0; i < num; i++) {
const particle = new MySprite();
particle.init(img);
particle.x = pos.x;
......@@ -1587,8 +1440,8 @@ export function showPopParticle(img, pos, parent, num = 20, minLen = 40, maxLen
const randomR = 360 * Math.random();
particle.rotation = randomR;
const randomS = 0.3 + Math.random() * 0.7;
particle.setScaleXY(randomS * 0.3);
const randomS = 0.5 + Math.random() * 0.5;
particle.setScaleXY(randomS);
const randomX = Math.random() * 20 - 10;
particle.x += randomX;
......@@ -1596,39 +1449,23 @@ export function showPopParticle(img, pos, parent, num = 20, minLen = 40, maxLen
const randomY = Math.random() * 20 - 10;
particle.y += randomY;
const randomL = minLen + Math.random() * (maxLen - minLen);
const randomL = minLen + Math.random() * maxLen;
const randomA = 360 * Math.random();
const randomT = getPosByAngle(randomA, randomL);
moveItem(particle, particle.x + randomT.x, particle.y + randomT.y, showTime, () => {
}, TWEEN.Easing.Exponential.Out);
// scaleItem(particle, 0, 0.6, () => {
//
// });
scaleItem(particle, randomS, 0.6, () => {
}, TWEEN.Easing.Exponential.Out);
setTimeout(() => {
hideItem(particle, 0.4, () => {
}, TWEEN.Easing.Cubic.In);
}, showTime * 0.5 * 1000);
moveItem(
particle,
particle.x + randomT.x,
particle.y + randomT.y,
0.4,
() => { },
TWEEN.Easing.Exponential.Out
);
scaleItem(particle, 0, 0.6, () => { });
}
}
export function shake(item, time = 0.5, callback = null, rate = 1) {
if (item.shakeTween) {
return;
}
......@@ -1640,37 +1477,104 @@ export function shake(item, time = 0.5, callback = null, rate = 1) {
const baseY = item.y;
const easing = TWEEN.Easing.Sinusoidal.InOut;
const move4 = () => {
moveItem(item, baseX, baseY, time / 4, () => {
moveItem(
item,
baseX,
baseY,
time / 4,
() => {
item.shakeTween = false;
if (callback) {
callback();
}
}, easing);
},
easing
);
};
const move3 = () => {
moveItem(item, baseX + offX / 4, baseY + offY / 4, time / 4, () => {
moveItem(
item,
baseX + offX / 4,
baseY + offY / 4,
time / 4,
() => {
move4();
}, easing);
},
easing
);
};
const move2 = () => {
moveItem(item, baseX - offX / 4 * 3, baseY - offY / 4 * 3, time / 4, () => {
moveItem(
item,
baseX - (offX / 4) * 3,
baseY - (offY / 4) * 3,
time / 4,
() => {
move3();
}, easing);
},
easing
);
};
const move1 = () => {
moveItem(item, baseX + offX, baseY + offY, time / 7.5, () => {
moveItem(
item,
baseX + offX,
baseY + offY,
time / 8,
() => {
move2();
}, easing);
},
easing
);
};
move1();
}
// --------------- custom class --------------------
export function showBlingBling(starImg, rectArea, parent, mapScale = 1, num = 30, disTime = 0.1, showTime = 3) {
const timeId = setInterval(() => {
showBlingStar(starImg, num, rectArea, parent, mapScale);
}, disTime * 1000);
setTimeout(() => {
clearInterval(timeId);
}, showTime * 1000);
}
function showBlingStar(starImg, num, rectArea, parent, mapScale) {
for (let i = 0; i < num; i++) {
const star = new MySprite();
star.init(starImg);
const px = -parent.width / 2 + Math.random() * parent.width;
const py = -parent.height / 2 + Math.random() * parent.height;
star.x = px;
star.y = py;
const randomS = (0.1 + Math.random() * 0.8) * mapScale;
star.setScaleXY(1);
parent.addChild(star);
scaleItem(star, randomS, 0.3, () => {
setTimeout(() => {
scaleItem(star, 0, 0.3, () => {
parent.removeChild(star);
});
}, 100 + Math.random() * 200);
});
}
}
\ No newline at end of file
.game-container {
width: 100%;
height: 100%;
background: #ffffff;
background-size: cover;
}
#canvas {
}
@font-face
{
font-family: 'BRLNSDB';
src: url("../../assets/font/BRLNSDB.TTF") ;
}
.game-container {
width: 100%;
height: 100%;
//background-image: url("/assets/play/listen-read-circle/bg.jpg");
background: #ffffff;
background-repeat: no-repeat;
background-size: cover;
}
.read-and-point-copy {
width: 500px;
height: 85px;
object-fit: contain;
text-shadow: 0 6px 4px rgba(0, 0, 0, 0.5), 0 3px 0 #fffecc;
font-family: Questrian;
font-size: 72px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
color: #f8e424;
}
.read-and-point-copy .text-style-1 {
font-size: 48px;
}
.read-and-point-copy .text-style-2 {
font-size: 64px;
}
@font-face
{
font-family: 'BRLNSDB';
src: url("../../assets/play/font/BRLNSDB.TTF") ;
}
@font-face
{
font-family: 'RoundedBold';
src: url("../../assets/play/font/ArialRoundedBold.otf") ;
}
@font-face{
font-family: 'BRLNSB_1';
src: url("../../assets/play/font/BerlinSansFB/BRLNSB_1.TTF") ;
}
@font-face{
font-family: 'BerlinSansFBDemi-Bold';
src: url("../../assets/play/font/BerlinSansFB/BRLNSDB_1.TTF") ;
}
@font-face{
font-family: 'BRLNSR_1';
src: url("../../assets/play/font/BerlinSansFB/BRLNSR_1.TTF") ;
}
@font-face{
font-family: 'GOTHIC_1';
src: url("../../assets/play/font/CenturyGothic/GOTHIC_1.TTF") ;
}
@font-face{
font-family: 'GOTHICB_1';
src: url("../../assets/play/font/CenturyGothic/GOTHICB_1.TTF") ;
}
@font-face{
font-family: 'GOTHICBI_1';
src: url("../../assets/play/font/CenturyGothic/GOTHICBI_1.TTF") ;
}
@font-face{
font-family: 'GOTHICI_1';
src: url("../../assets/play/font/CenturyGothic/GOTHICI_1.TTF") ;
}
@font-face{
font-family: 'MMTextBook';
src: url("../../assets/play/font/MMTextBook/MMTextBook.otf") ;
}
@font-face{
font-family: 'MMTextBook-Bold';
src: url("../../assets/play/font/MMTextBook/MMTextBook-Bold.otf") ;
}
@font-face{
font-family: 'MMTextBook-BoldItalic';
src: url("../../assets/play/font/MMTextBook/MMTextBook-BoldItalic.otf") ;
}
@font-face{
font-family: 'MMTextBook-Italic';
src: url("../../assets/play/font/MMTextBook/MMTextBook-Italic.otf") ;
}
@font-face{
font-family: 'FuturaBT-Bold';
src: url("../../assets/play/font/FUTURAB.ttf") ;
}
\ No newline at end of file
import {Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener} from '@angular/core';
import {
Component,
ElementRef,
ViewChild,
OnInit,
Input,
OnDestroy,
HostListener
} from "@angular/core";
import {
MySprite,
RichText,
getMinScale,
ShapeRect,
ShapeCircle,
tweenChange,
randomSortByArr,
Label,
MySprite, tweenChange,
showPopParticle,
moveItem,
removeItemFromArr,
rotateItem,
hideItem,
showItem,
ShapeRectNew,
scaleItem,
showBlingBling,
waterWave,
jelly,
getAngleByPos,
getPosDistance,
shake
} from "./Unit";
import { localImages, localAudios, multiSizeBackground} from "./resources";
import { Cartoon } from './Cartoon'
import { Subject } from "rxjs";
import { debounceTime, map, takeWhile, retry } from "rxjs/operators";
import * as _ from "lodash";
import TWEEN from "@tweenjs/tween.js";
import defauleFormData from '../../assets/default/formData/defaultData_LST08.js'
import { v4 as uuidv4 } from 'uuid';
const zIndexMap = {
mainBackground: 0,
shazi: 10,
beike: 20,
haixing: 20,
shitou: 20,
bgBubble: 3,
bgBubbleFront: 30,
button: 200,
finalPannel: 195,
scroePannel: 150,
breakLine: 150,
answerBall: 40,
maskLayout: 190,
audioPlayer: 160
}
} from './Unit';
import {res, resAudio} from './resources';
@Component({
selector: "app-play",
templateUrl: "./play.component.html",
styleUrls: ["./play.component.scss"]
})
import {Subject} from 'rxjs';
import {debounceTime} from 'rxjs/operators';
export class PlayComponent implements OnInit, OnDestroy {
import TWEEN from '@tweenjs/tween.js';
g_cartoon = new Cartoon()
// ------------ 全局数据 ------------
g_stage; //中心舞台
// g_background_color = "#rgb(0,0,0,0)"
g_background_color = "#ffe197"
g_enableMapDown = true; // 触摸使能
g_enableMapUp = true; // 抬起使能
g_enableMapMove = true; // 移动ss使能
g_canvasLeft;
g_canvasTop;
g_animationId: any;
g_mapScale = 1; // 缩放比例
g_KEY = "DataKey_LST08";
g_canvasWidth = 1280;
g_canvasHeight = 720;
g_canvasBaseW = 1280;
g_canvasBaseH = 720;
g_winResizeEventStream = new Subject();
g_clickX; // 点击坐标 X
g_clickY; // 点击坐标 Y
g_ctx; // canvas 实例
g_data; // 数据
g_formData; // 核心表单数据
g_teacherFlag = false; // 默认角色
g_currentUser;
g_firstTouch = true;
g_partTitle_x = null;
g_mainTitle_x = null;
// ------------------------------------
// ------------ 私有数据 ------------
m_mapDownQueue = {} //按下事件处理队列
m_mapDownArray = [] //按下事件处理队列
m_mapDownObject = []
m_mapDownBuffer = []
m_mapDownEventCount = 0;
m_mapUpQueue = {} //抬起事件处理队列
m_mapUpArray = [] //抬起事件处理队列
m_mapUpObject = []
m_mapDragQueue = {} //拖拽事件处理队列
m_mapDragArray = [] //拖拽事件处理队列
m_mapDragObject = []
m_mapMoveArray = [] //移动事件处理队列
m_mapMoveObject = []
m_endPageArr;
m_showPetalFlag;
m_elementPetalArr;
m_showElementPetalFlag;
m_PetalImage = "_scrap-pic-" // 飘落动画
m_renderArr // 渲染队列
m_renderObject = [];
m_frontCurtainArr = []; // 前置幕布
m_defaultZindex = 0;
m_setTimeoutIDs = [];
m_setIntervalIDs = [];
m_moveAsstantIntervalId = null;
g_currentDragElementID: any = null; // 当前拖动的动画元件
g_dragFirstClickY: any;
g_dragFirstClickX: any;
g_enableDragDistance: number = 20 * this.g_mapScale;
g_enableDragging: any;
// ------------------------------------
// ------------ 游戏逻辑数据 ------------
m_allAnswerBubble = {
left: [],
right: []
}
m_score = {
left: 0,
right: 0
}
m_startGame = false;
m_currentQuestionIndex = -1;
m_lastBubbleX = {
left: 0,
right: 0
}
m_scoreLine = {
left: 0,
right: 0
}
// ------------------------------------
// ------------ 消息 ------------
@Component({
selector: 'app-play',
templateUrl: './play.component.html',
styleUrls: ['./play.component.css']
})
export class PlayComponent implements OnInit, OnDestroy {
// ------------------------------------
@ViewChild('canvas', {static: true }) canvas: ElementRef;
@ViewChild('wrap', {static: true }) wrap: ElementRef;
// 数据
data;
// ------------ 调试变量 ------------
g_EnableStageRuler = false; // 使能舞台背景格尺
g_ForceChangeDefaultRole = false // 强制当前角色为默认角色
g_EnableTestSendEvent = false // 发送模拟Web数据
g_showLeftCornerTest= false // 测试左上角图标
// ------------------------------------
ctx;
canvasWidth = 1280; // canvas实际宽度
canvasHeight = 720; // canvas实际高度
// 当数据加载完毕后,执行
systemReady(){
this.setLeftCornerTest()
this.initGame()
}
canvasBaseW = 1280; // canvas 资源预设宽度
canvasBaseH = 720; // canvas 资源预设高度
// 屏幕尺寸变化后执行
handleScreenResize(){
this.initSystem();
this.cleanSystemVar()
this.cleanGameVar();
this.setLeftCornerTest()
this.initGame()
}
mx; // 点击x坐标
my; // 点击y坐标
// 映射预加载图片[网路]资源 返回包含图片路径的数组
mapToImageArray(contentObj){
let array = []
this.g_formData.dataArray.forEach(element => {
if(element.image_url){
array.push(element.image_url)
}
element.correct.forEach(element => {
if(element.image_url){
array.push(element.image_url)
}
});
element.incorrect.forEach(element => {
if(element.image_url){
array.push(element.image_url)
}
});
});
return array
}
// 资源
rawImages = new Map(res);
rawAudios = new Map(resAudio);
// 映射预加载音频[网路]资源 返回包含音频路径的数组
mapToAduioArray(contentObj){
let array = []
images = new Map();
this.g_formData.dataArray.forEach(element => {
if(element.audio_url1){
array.push(element.audio_url1)
}
if(element.audio_url2){
array.push(element.audio_url2)
}
element.correct.forEach(element => {
if(element.audio_url){
array.push(element.audio_url)
}
});
// element.incorrect.forEach(element => {
// if(element.audio_url){
// array.push(element.audio_url)
// }
// });
});
animationId: any;
winResizeEventStream = new Subject();
return array
}
audioObj = {};
// ------------------------------------------------------------------------------
// 游戏核心处理区
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
//
//
//
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
initGame(){
console.log(this.g_formData);
this.initBackground();
this.initButtons();
this.initScorePannel();
this.initBreakLine();
this.initBlackMask();
this.initHand();
this.initSpeaker();
this.initFinal();
}
renderArr;
mapScale = 1;
cleanGameVar(){
this.m_allAnswerBubble = {
left: [],
right: []
}
this.m_score = {
left: 0,
right: 0
}
this.m_currentQuestionIndex = -1;
this.m_allAnswerBubble.left.forEach(item=>{
this.g_cartoon.getCartoonElement(item).delete()
this.deleteElementInRender(item)
})
this.m_allAnswerBubble.right.forEach(item=>{
this.g_cartoon.getCartoonElement(item).delete()
this.deleteElementInRender(item)
})
this.m_allAnswerBubble = {
left: [],
right: []
}
this.m_startGame = false;
this.setScore("left", 0)
this.setScore("right", 0)
this.m_lastBubbleX = {
left: 0,
right: 0
}
// this.initAnswerBubble();
this.g_cartoon.getCartoonElement("play-audio").stop()
this.m_scoreLine = {
left: 0,
right: 0
}
}
canvasLeft;
canvasTop;
startGame(callback?){
this.g_cartoon.playAudio("open")
this.g_cartoon.getCartoonElement("score-pannel-left").in()
this.g_cartoon.getCartoonElement("score-pannel-right").in()
this.g_cartoon.getCartoonElement("breakLine-line").in()
this.m_setTimeoutIDs.push(setTimeout(() => {
this.m_startGame = true;
this.loadNextQuestion()
callback && callback()
}, 1000))
}
saveKey = 'test_0011';
restartGame(callback?){
this.cleanGameVar();
this.stopEndPatal();
this.stopClapHand(()=>{
this.g_cartoon.getCartoonElement("mask-layer").out(()=>{
callback && callback()
this.startGame()
})
})
}
endGame(callback?){
this.g_cartoon.getCartoonElement("play-audio").stop()
this.g_cartoon.getCartoonElement("play-audio").setAudio(null)
this.m_allAnswerBubble.left.forEach(item=>{
this.deleteElementInRender(item)
})
this.m_allAnswerBubble.right.forEach(item=>{
this.deleteElementInRender(item)
})
this.g_cartoon.playAudio("win")
this.m_startGame = false;
this.g_cartoon.getCartoonElement("mask-layer").in(()=>{
let showType = "final-win"
if(this.m_score["left"] == this.m_score["right"]){
showType = "final-pingju";
this.showEndPatal()
}
btnLeft;
btnRight;
pic1;
pic2;
if(this.m_score["left"] > this.m_score["right"]){
this.showEndPatal("left")
}
canTouch = true;
if(this.m_score["left"] < this.m_score["right"]){
this.showEndPatal("right")
}
this.g_cartoon.getCartoonElement(showType).in()
this.g_cartoon.playAudio("guzhang", false, ()=>{
this.stopEndPatal()
this.g_cartoon.getCartoonElement(showType).out(()=>{
this.g_cartoon.getCartoonElement("replay-button").in(()=>{
callback && callback()
})
})
})
})
}
curPic;
initBackground(){
let mainBG = this.g_cartoon.createCartoonElementImageFunc("main-background", "bg_bg", (w ,h)=>{
return {
sx: this.g_canvasWidth / w,
sy: this.g_canvasHeight / h
}
}, (w, h)=>{
return {
x: this.g_canvasWidth / 2,
y: this.g_canvasHeight / 2,
}
})
this.render(mainBG.ref, zIndexMap.mainBackground)
@HostListener('window:resize', ['$event'])
onResize(event) {
this.winResizeEventStream.next();
let left = this.g_cartoon.createCartoonElementImageFunc("main-background-left", "bg_zuo", (w ,h)=>{
return {
sx: 181 * this.g_mapScale / w,
sy: this.g_canvasHeight / h
}
}, (w, h)=>{
return {
x: 40 * this.g_mapScale,
y: this.g_canvasHeight / 2,
}
})
this.render(left.ref, zIndexMap.mainBackground + 1)
let right = this.g_cartoon.createCartoonElementImageFunc("main-background-right", "bg_you", (w ,h)=>{
return {
sx: 181 * this.g_mapScale/ w,
sy: this.g_canvasHeight / h
}
}, (w, h)=>{
return {
x: this.g_canvasWidth - 40 * this.g_mapScale,
y: this.g_canvasHeight / 2,
}
})
this.render(right.ref, zIndexMap.mainBackground + 1)
ngOnInit() {
let yeZiLeft = this.g_cartoon.createCartoonElementImageFunc("main-background-yeZiLeft", "bg_yezi1", (w ,h)=>{
return {
sx: 277 * this.g_mapScale / w,
sy: 213 * this.g_mapScale / h
}
}, (w, h)=>{
return {
x: 60 * this.g_mapScale,
y: this.g_canvasHeight - 20 * this.g_mapScale,
}
})
this.render(yeZiLeft.ref,zIndexMap.mainBackground + 2)
this.data = {};
let yeZiRight = this.g_cartoon.createCartoonElementImageFunc("main-background-yeZiRight", "bg_yezi2", (w ,h)=>{
return {
sx: 273 * this.g_mapScale / w,
sy: 215 * this.g_mapScale / h
}
}, (w, h)=>{
return {
x: this.g_canvasWidth,
y: this.g_canvasHeight - 50 * this.g_mapScale,
}
})
this.render(yeZiRight.ref, zIndexMap.mainBackground + 2)
// 获取数据
const getData = (<any> window).courseware.getData;
getData((data) => {
}
if (data && typeof data == 'object') {
this.data = data;
initButtons(){
let startButton = this.g_cartoon.createCartoonElementImageFunc("start-button", "btn_start", (w ,h)=>{
return {
sx: 577 * this.g_mapScale / w,
sy: 164 * this.g_mapScale / h
}
// console.log('data:' , data);
}, (w, h)=>{
return {
x: this.g_canvasWidth / 2,
y: this.g_canvasHeight / 2,
}
})
this.render(startButton.ref, zIndexMap.button)
// 初始化 各事件监听
this.initListener();
this.subscribeMapDownEvent(startButton.id, ()=>{
this.showJellyAnimation(startButton.id, ()=>{
tweenChange(startButton.ref, {x: this.g_canvasWidth + 500 * this.g_mapScale}, 0.2, ()=>{
this.startGame()
this.g_enableMapDown = true;
})
})
})
// 若无数据 则为预览模式 需要填充一些默认数据用来显示
this.initDefaultData();
let replayButton = this.g_cartoon.createCartoonElementImageFunc("replay-button", "btn_restart", (w ,h)=>{
return {
sx: 577 * this.g_mapScale / w,
sy: 164 * this.g_mapScale / h
}
}, (w, h)=>{
return {
x: this.g_canvasWidth + 500 * this.g_mapScale,
y: this.g_canvasHeight / 2,
}
})
// 初始化 音频资源
this.initAudio();
// 初始化 图片资源
this.initImg();
// 开始预加载资源
this.load();
replayButton.in = (calback?)=>{
tweenChange(replayButton.ref, {x: this.g_canvasWidth / 2}, 0.2, ()=>{
calback && calback()
})
}
}, this.saveKey);
this.subscribeMapDownEvent(replayButton.id, ()=>{
this.showJellyAnimation(replayButton.id, ()=>{
this.restartGame(()=>{
this.g_enableMapDown = true;
})
tweenChange(replayButton.ref, {x: replayButton.initX}, 0.2)
})
})
this.render(replayButton.ref, zIndexMap.button)
}
initScorePannel(){
let scorePannelLeft = this.g_cartoon.createCartoonElementImageFunc("score-pannel-left", "score", (w ,h)=>{
return {
sx: 76 * this.g_mapScale / w,
sy: 284 * this.g_mapScale / h
}
}, (w, h)=>{
return {
x: (76 / 2 + 58) * this.g_mapScale,
y: this.g_canvasHeight / 2,
}
})
scorePannelLeft.ref.alpha = 0;
scorePannelLeft.ref.x = - (76 / 2 + 58) * this.g_mapScale
scorePannelLeft.in = ()=>{
tweenChange(scorePannelLeft.ref, {x: scorePannelLeft.initX}, 0.1)
}
this.render(scorePannelLeft.ref, zIndexMap.scroePannel)
let scorePannelRight = this.g_cartoon.createCartoonElementImageFunc("score-pannel-right", "score", (w ,h)=>{
return {
sx: 76 * this.g_mapScale / w,
sy: 284 * this.g_mapScale / h
}
}, (w, h)=>{
return {
x: this.g_canvasWidth - (76 / 2 + 58) * this.g_mapScale,
y: this.g_canvasHeight / 2,
}
})
scorePannelRight.ref.alpha = 0;
scorePannelRight.ref.x = this.g_canvasWidth + (76 / 2 + 58) * this.g_mapScale;
scorePannelRight.in = ()=>{
tweenChange(scorePannelRight.ref, {x: scorePannelRight.initX}, 0.1)
}
this.render(scorePannelRight.ref, zIndexMap.scroePannel)
let allPannel = [scorePannelLeft, scorePannelRight]
let baseY = (284 - 53) / 2 - 10
allPannel.forEach((element, index) => {
let newId = "score-ball-left-"
if(index==1){
newId = "score-ball-right-"
}
for(let i=0; i<6; i++){
let scoreBall = this.g_cartoon.createCartoonElementImageFunc(newId + i, "bg_star", (w ,h)=>{
return {
sx: 68 / w,
sy: 70 / h
}
}, (w, h)=>{
return {
x: 0,
y: baseY - 70 * i,
}
})
scoreBall.ref.alpha = 1;
scoreBall.ref.visible = true
element.ref.addChild(scoreBall.ref)
let scoreBall_Light = this.g_cartoon.createCartoonElementImageFunc(newId + i + "-light", "icon_star", (w ,h)=>{
return {
sx: 68 / w,
sy: 70 / h
}
}, (w, h)=>{
return {
x: 0,
y: baseY - 70 * i,
}
})
scoreBall_Light.ref.alpha = 0;
scoreBall_Light.ref.visible = false
element.ref.addChild(scoreBall_Light.ref)
}
});
}
setScore(side, score, callback?){
for(let index = 0; index<5; index++){
let ball = this.g_cartoon.getCartoonElement(`score-ball-${side}-${index}`)
let ballLight = this.g_cartoon.getCartoonElement(`score-ball-${side}-${index}-light`)
if(ball){
console.log(index, score)
if(index >= score){
ball.ref.visible = true;
ball.ref.alpha = 1
ballLight.ref.visible = false;
ballLight.ref.alpha = 0
}else{
ball.ref.visible = false;
tweenChange(ball.ref, {alpha: 0}, 0.2)
ballLight.ref.visible = true;
tweenChange(ballLight.ref, {alpha: 1}, 0.2)
}
}
}
this.m_setIntervalIDs.push(setTimeout(() => {
callback && callback()
}, 210))
}
initBreakLine(){
let line = this.g_cartoon.createCartoonElementImageFunc("breakLine-line", "bg_eyu", (w ,h)=>{
return {
sx: 163 * this.g_mapScale / w,
sy: (this.g_canvasHeight - 78 * this.g_mapScale) / h
}
}, (w, h)=>{
return {
x: this.g_canvasWidth / 2 ,
y: this.g_canvasHeight / 2 + 50 * this.g_mapScale
}
})
line.ref.y = line.ref.y + this.g_canvasHeight;
line.in = ()=>{
tweenChange(line.ref, {y: line.initY}, 0.5)
}
this.render(line.ref, zIndexMap.breakLine - 1)
}
initAnswerBubble(){
let bubbleAll = []
this.m_scoreLine = {
left: this.g_formData.dataArray[this.m_currentQuestionIndex].correct.length,
right: this.g_formData.dataArray[this.m_currentQuestionIndex].correct.length
}
this.g_formData.dataArray[this.m_currentQuestionIndex].correct.forEach(element => {
element.isAnswer= true;
element.index = this.m_currentQuestionIndex;
bubbleAll.push(element)
});
this.g_formData.dataArray[this.m_currentQuestionIndex].incorrect.forEach(element => {
element.isAnswer= false;
bubbleAll.push(element)
});
this.m_allAnswerBubble["left"] = []
this.m_allAnswerBubble["right"] = []
bubbleAll = this.randomArray_shuffle(bubbleAll)
bubbleAll.forEach((data, index)=>{
this.createPopUpBubble("left", index, data)
})
bubbleAll = this.randomArray_shuffle(bubbleAll)
bubbleAll.forEach((data, index)=>{
this.createPopUpBubble("right", index, data)
})
}
createPopUpBubble(side, index, data){
let container = this.g_cartoon.createCartoonElementImageFunc(`answer-bubble-${side}-${index}`, "bg_pao", (w ,h)=>{
return {
sx: 151 * this.g_mapScale / w,
sy: 151 * this.g_mapScale / h
}
}, (w, h)=>{
let width = 151 * this.g_mapScale
let x = 0
if( side=="right" ){
do{
x = this.g_canvasWidth / 2 + ( Math.ceil(Math.random()*400) + 80 ) * this.g_mapScale
}while(this.m_lastBubbleX[side] != -1 && x <= (this.m_lastBubbleX[side] + width) && x >= (this.m_lastBubbleX[side] - width))
}else{
do{
x = 150 * this.g_mapScale + Math.ceil(Math.random()*400) * this.g_mapScale
}while(this.m_lastBubbleX[side] != -1 && x <= (this.m_lastBubbleX[side] + width) && x >= (this.m_lastBubbleX[side] - width))
}
this.m_lastBubbleX[side] = x
return {
x: x,
y: this.g_canvasHeight + (151 / 2 + Math.ceil(Math.random() * this.g_formData.dataArray[this.m_currentQuestionIndex].incorrect.length) * 157) * this.g_mapScale
}
})
container.side = side;
if(data.isAnswer){
container.index = data.index!=undefined?data.index:-1;
}else{
container.index = -1;
}
container.text = data.text
container.in = (callback)=>{
tweenChange(container.ref, {y: container.initY}, 2, ()=>{
callback && callback()
})
}
this.m_allAnswerBubble[side].push(container.id)
if(data.type == "Image"){
let image = this.g_cartoon.createImage(data.image_url, (w, h)=>{
let sx = 138 * 0.7 / w
let sy = 138 * 0.7 / h
let s = Math.min(sx, sy)
return {
sx: s,
sy: s
}
}, (w, h)=>{
return {
x: 0,
y: 0
}
})
container.ref.addChild(image)
}else{
let text = this.g_cartoon.createLabel(data.text, "BerlinSansFBDemi-Bold", "#FFFFFF", 24);
container.ref.addChild(text)
}
container.ball_highlight = this.g_cartoon.createImage("ball_highlight", (w, h)=>{
return {
sx: 164 * 1.1 / w,
sy: 152 * 1.1 / h
}
}, (w, h)=>{
return {
x: -2,
y: -5
}
})
container.ref.addChild(container.ball_highlight)
container.ball_highlight.visible = false;
container.ballYeah = this.g_cartoon.createImage("bg_graet", (w, h)=>{
return {
sx: 357 / w,
sy: 226 / h
}
}, (w, h)=>{
return {
x: -2,
y: -5
}
})
container.ref.addChild(container.ballYeah)
container.ballYeah.visible = false;
container.bubbleAni = this.g_cartoon.createAnimation("bg_star", 18, 900)
container.bubbleAni.x = 0;
container.bubbleAni.y = 0;
container.bubbleAni.visible = false;
container.ref.addChild(container.bubbleAni)
container.correct = (score = false, callback?) => {
this.topOfRenderArray(container.ref)
this.g_cartoon.getCartoonElement("play-audio").stop()
this.g_cartoon.playAudio("polie", false, ()=>{
if(data.audio_url){
this.g_cartoon.playAudio(data.audio_url)
}
})
container.bubbleAni.playEndFunc = ()=>{
container.bubbleAni.visible = false;
if(score){
this.topOfRenderArray(container.ref)
container.ballYeah.visible = true;
let x = this.g_canvasWidth / 4
if(side == "right"){
x = this.g_canvasWidth / 4 * 3
}
tweenChange(container.ref, {x: x, y: this.g_canvasHeight / 2}, 0.2, ()=>{
let x = this.g_cartoon.getCartoonElement(`score-pannel-${side}`).ref.x
let y = this.g_cartoon.getCartoonElement(`score-pannel-${side}`).ref.y
this.m_setTimeoutIDs.push(setTimeout(() => {
tweenChange(container.ref, {scaleX: 0, scaleY: 0, x: x, y: y}, 0.2, ()=>{
callback && callback()
container.ballYeah.visible = false;
container.ref.visible = false;
})
}, 2000))
})
}else{
container.ref.setScaleXY(0)
container.ref.visible = false;
callback && callback()
}
}
container.bubbleAni.visible = true;
container.ref.alpha = 0;
container.bubbleAni.play()
}
container.inCorrect = (callback?) => {
this.g_cartoon.playAudio("cuowu")
container.ball_highlight.visible = true;
this.showShakeAnimation(container.id, ()=>{
container.ball_highlight.visible = false;
callback && callback()
})
}
container.tween = null
container.move = () => {
this.topOfDownEventArray(container.id)
let time = 10000 + Math.ceil(Math.random() * 7000)
setTimeout(() => {
container.tween = tweenChange(container.ref, {y: -200 * this.g_mapScale}, time / 1000, ()=>{
let width = 159 * this.g_mapScale
let x = 0
if( side=="right" ){
let time = 0;
do{
x = this.g_canvasWidth / 2 + ( Math.ceil(Math.random()*400) + 80 ) * this.g_mapScale
}while(x <= (this.m_lastBubbleX[side] + width) && x >= (this.m_lastBubbleX[side] - width))
}else{
let time = 0;
do{
x = 150 * this.g_mapScale + Math.ceil(Math.random()*400) * this.g_mapScale
}while( x <= (this.m_lastBubbleX[side] + width) && x >= (this.m_lastBubbleX[side] - width))
}
this.m_lastBubbleX[side] = x
container.ref.x = x
container.ref.y = this.g_canvasHeight + (157/2) * this.g_mapScale //container.initY
container.move()
})
}, 0);
}
container.stopMove = () => {
if(container.tween){
container.tween.stop()
}
}
container.delete = () => {
this.deleteElementInRender(container.id)
this.g_cartoon.deleteCartoonElement(container.id)
}
this.subscribeMapDownEvent(container.id, ()=>{
if(!this.m_startGame){
this.g_enableMapDown = true;
return
}
container.tween.stop()
if(container.index == this.m_currentQuestionIndex){
this.m_scoreLine[side]--
if( this.m_scoreLine[side]==0 ){
this.m_score[side]++
container.correct(true, ()=>{
if( (this.m_currentQuestionIndex+1) == this.g_formData.dataArray.length){
this.endGame(()=>{
this.g_enableMapDown = true;
})
}else{
this.loadNextQuestion(true)
this.g_enableMapDown = true;
}
this.setScore(side, this.m_score[side])
})
}else{
container.correct(false, ()=>{
this.g_enableMapDown = true;
})
}
}else{
container.inCorrect(()=>{
this.g_enableMapDown = true;
container.tween.start()
})
}
return true;
}, 0, true)
if(data.isAnswer){
this.render(container.ref, zIndexMap.scroePannel - 1)
}else{
this.render(container.ref, zIndexMap.answerBall + index)
}
return container
}
loadNextQuestion(mute=false){
if(mute){
this.g_cartoon.stopAllAudio()
}
this.m_currentQuestionIndex++;
this.m_allAnswerBubble["left"].forEach(item=>{
this.g_cartoon.getCartoonElement(item).delete()
})
this.m_allAnswerBubble["right"].forEach(item=>{
this.g_cartoon.getCartoonElement(item).delete()
})
this.initAnswerBubble()
if(!this.g_formData.dataArray[this.m_currentQuestionIndex].audio_url1){
// 升起泡泡
this.m_allAnswerBubble["left"].forEach(item=>{
this.g_cartoon.getCartoonElement(item).move()
})
this.m_allAnswerBubble["right"].forEach(item=>{
this.g_cartoon.getCartoonElement(item).move()
})
}
this.g_cartoon.getCartoonElement("play-audio").setAudio(this.g_formData.dataArray[this.m_currentQuestionIndex].audio_url1)
}
initSpeaker(){
let element = this.g_cartoon.createCartoonElementImageFunc(`play-audio`, "btn_laba1", (w,h)=>{
return {
sx: 95*this.g_mapScale / w,
sy: 100*this.g_mapScale / h
}
}, (w,h)=>{
return{
x: this.g_canvasWidth - (20 + 95 / 2) * this.g_mapScale,
y: this.g_canvasHeight - (20 + 100 / 2) * this.g_mapScale,
}
})
element.ref.setScaleXY(0)
element.playAni = this.g_cartoon.createAnimation("btn_laba", 4, 500)
// element.playAni.setScaleXY(this.g_mapScale)
element.playAni.x = 0;
element.playAni.y = 0;
element.playAni.visible = false;
element.ref.addChild(element.playAni)
element.playAni.loop = true;
element.isPlay = false;
element.isTriggerBubble = false;
element.setAudio = (url) => {
element.audio_url = url;
element.audio = null
if(element.audio_url){
element.isTriggerBubble = true;
element.audio = this.g_cartoon.audio.get(element.audio_url)
element.audio.onended = ()=>{
element.pause()
}
tweenChange(element.ref, {scaleX: element.initScaleX, scaleY: element.initScaleY}, 0.2)
}else{
tweenChange(element.ref, {scaleX: 0, scaleY: 0}, 0.2)
}
}
element.in = () => {
if(element.audio_url){
tweenChange(element.ref, {scaleX: element.initScaleX, scaleY: element.initScaleY}, 0.2)
}
}
element.play = ()=> {
if(element.audio_url && !element.isPlay){
element.isPlay = true;
element.playAni.play()
if(element.audio){
element.audio.play()
}
element.playAni.visible = true;
}
}
element.pause = ()=> {
if(element.audio_url && element.isPlay){
element.isPlay = false;
element.playAni.stop()
element.audio.pause()
element.playAni.visible = false;
}
}
element.stop = ()=> {
if(element.audio_url && element.isPlay){
element.isPlay = false;
element.playAni.stop()
element.audio.pause()
element.audio.currentTime = 0;
element.playAni.visible = false;
}
}
this.subscribeMapDownEvent(element.id, ()=>{
if(element.isPlay){
element.pause()
}else{
if(element.isTriggerBubble){
element.isTriggerBubble = false;
// 升起泡泡
this.m_allAnswerBubble["left"].forEach(item=>{
this.g_cartoon.getCartoonElement(item).move()
})
this.m_allAnswerBubble["right"].forEach(item=>{
this.g_cartoon.getCartoonElement(item).move()
})
}
element.play()
}
this.g_enableMapDown = true;
})
this.render(element.ref, zIndexMap.audioPlayer)
}
initFinal(){
let element = this.g_cartoon.createCartoonElementImageFunc(`final-win`, "bg_new_smiling_face", (w,h)=>{
return {
sx: 700*this.g_mapScale / w,
sy: 560*this.g_mapScale / h
}
}, (w,h)=>{
return{
x: this.g_canvasWidth / 2,
y: this.g_canvasHeight / 2,
}
})
element.ref.y = - (560*this.g_mapScale) * this.g_mapScale
// element.smilingAni = this.g_cartoon.createAnimation("smiling_face", 10, 500)
// element.smilingAni.setScaleXY(0.5)
// element.smilingAni.x = 0;
// element.smilingAni.y = 0;
// element.smilingAni.loop = true;
// element.smilingAni.visible = true;
// element.ref.addChild(element.smilingAni)
element.in = (callback?)=>{
tweenChange(element.ref, {y: element.initY}, 0.2, ()=>{
// element.smilingAni.play()
callback && callback()
})
}
element.out = (callback?)=>{
light.out()
tweenChange(element.ref, {y: - 176 * this.g_mapScale}, 0.2, ()=>{
callback && callback()
})
}
let pingju = this.g_cartoon.createCartoonElementImageFunc(`final-pingju`, "bg_shake_hand", (w,h)=>{
return {
sx: 560*this.g_mapScale / w,
sy: 419*this.g_mapScale / h
}
}, (w,h)=>{
return{
x: this.g_canvasWidth / 2,
y: this.g_canvasHeight / 2,
}
})
pingju.ref.y = - 419 * this.g_mapScale
// pingju.eyeAni = this.g_cartoon.createAnimation("shake_hand", 25, 1500)
// pingju.eyeAni.x = 0;
// pingju.eyeAni.y = 0;
// pingju.eyeAni.loop = true;
// pingju.eyeAni.visible = true;
// pingju.ref.addChild(pingju.eyeAni)
pingju.in = (callback?)=>{
tweenChange(pingju.ref, {y: pingju.initY}, 0.2, ()=>{
// pingju.eyeAni.play()
callback && callback()
})
}
pingju.out = (callback?)=>{
light.out()
tweenChange(pingju.ref, {y: - 176 * this.g_mapScale}, 0.2, ()=>{
callback && callback()
})
}
let light = this.g_cartoon.createCartoonElementImageFunc(`final-guang`, "guang", (w,h)=>{
return {
sx: 675*this.g_mapScale / w,
sy: 588*this.g_mapScale / h
}
}, (w,h)=>{
return{
x: this.g_canvasWidth / 2,
y: this.g_canvasHeight / 2 - 100 * this.g_mapScale,
}
})
light.ref.setScaleXY(0)
light.in = (callback?)=>{
tweenChange(light.ref, {scaleX: light.initScaleX, scaleY: light.initScaleY}, 0.2, ()=>{
callback && callback()
})
}
light.out = (callback?)=>{
light.ref.setScaleXY(0)
}
this.render(light.ref, zIndexMap.finalPannel-1)
this.render(element.ref, zIndexMap.finalPannel)
this.render(pingju.ref, zIndexMap.finalPannel)
}
initBlackMask(callback?){
let element = this.g_cartoon.createCartoonElementImage("mask-layer", "_mask_layer_1280_720", this.g_canvasWidth, this.g_canvasHeight, this.g_canvasWidth/2, this.g_canvasHeight/2)
element.ref.visible = false;
element.ref.alpha = 0;
element.in = (callback?)=>{
element.ref.visible = true;
tweenChange(element.ref, {alpha:1}, 0.1, ()=>{
callback && callback()
})
}
element.out = (callback?)=>{
tweenChange(element.ref, {alpha:0}, 0.1, ()=>{
element.ref.visible = false;
callback && callback()
})
}
this.render(element.ref, zIndexMap.maskLayout)
}
initHand(){
let basePos = {
x: this.g_canvasWidth / 2,
y: this.g_canvasHeight / 2
}
let elementLeft = this.g_cartoon.createCartoonElementImage("hand-left", "hand-left", 265, 310, basePos.x - 120*this.g_mapScale, basePos.y, true)
elementLeft.pos_1 = {
x: basePos.x,
y: basePos.y
}
elementLeft.pos_2 = {
x: basePos.x - 120*this.g_mapScale,
y: basePos.y
}
elementLeft.ref.y += this.g_canvasHeight
let elementRight = this.g_cartoon.createCartoonElementImage("hand-right", "hand-right", 247, 322, basePos.x + 120*this.g_mapScale, basePos.y, true)
elementRight.pos_1 = {
x: basePos.x,
y: basePos.y
}
elementRight.pos_2 = {
x: basePos.x + 120*this.g_mapScale,
y: basePos.y
}
elementRight.ref.y += this.g_canvasHeight
elementLeft.clap = (callback?)=>{
tweenChange(elementLeft.ref, {y:elementLeft.initY}, 1, ()=>{
this.m_setIntervalIDs.push(setInterval(()=>{
tweenChange(elementLeft.ref, elementLeft.pos_2, 0.2, ()=>{
tweenChange(elementLeft.ref, elementLeft.pos_1, 0.2)
})
}, 410))
})
callback && callback()
}
elementRight.clap = (callback?)=>{
tweenChange(elementRight.ref, {y:elementRight.initY}, 1, ()=>{
this.m_setIntervalIDs.push(setInterval(()=>{
tweenChange(elementRight.ref, elementRight.pos_2, 0.2, ()=>{
tweenChange(elementRight.ref, elementRight.pos_1, 0.2)
})
}, 410))
callback && callback()
})
}
this.render(elementLeft.ref, 9999)
this.render(elementRight.ref, 9990)
}
clapHand(callback?){
this.g_cartoon.getCartoonElement("hand-left").clap()
this.g_cartoon.getCartoonElement("hand-right").clap(()=>{
callback && callback()
})
}
stopClapHand(callback?){
this.stopAllInterval()
let handLeft = this.g_cartoon.getCartoonElement("hand-left")
let handRight = this.g_cartoon.getCartoonElement("hand-right")
tweenChange(handLeft.ref, {y: handLeft.ref.y + 1000 * this.g_mapScale}, 1)
tweenChange(handRight.ref, {y: handRight.ref.y + 1000 * this.g_mapScale}, 1, ()=>{
callback && callback()
})
}
// --------------------------------------------------
// -------------- Template function ---------------
// --------------------------------------------------
// --------------------------------------------------
// --------------------------------------------------
//
// _________
// / /.
// .-------------. /_________/ |
// / / | | | |
// /+============+\ | | |====| | |
// ||C:\> || | | | |
// || || | | |====| | |
// || || | | ___ | |
// || || | | |166| | |
// || ||/@@@ | --- | |
// \+============+/ @ |_________|./.
// @ .. ....'
// ..................@ __.'.' ''
// /oooooooooooooooo// ///
// /................// /_/
// ------------------
//
// --------------------------------------------------
@ViewChild("canvas", { static: true }) canvas: ElementRef;
@ViewChild("wrap", { static: true }) wrap: ElementRef;
@HostListener("window:resize", ["$event"])
onResize(event) {
this.g_winResizeEventStream.next();
}
ngOnDestroy() {
window['curCtx'] = null;
window.cancelAnimationFrame(this.animationId);
window["curCtx"] = null;
window.cancelAnimationFrame(this.g_animationId);
this.g_cartoon.audio.forEach(audio=>{
audio.pause()
})
}
ngOnInit() {
const getData = (<any>window).courseware.getData;
getData(data => {
// if (window['air'].airClassInfo.user.classRole == 'tea') {
// if(!this.g_ForceChangeDefaultRole){
// this.g_teacherFlag = true;
// }
// }
// this.g_currentUser = window['air'].airClassInfo.user;
if (data && typeof data == "object") {
this.g_data = data;
this.g_formData = data.contentObj;
} else {
this.g_data = {};
}
load() {
if (!this.g_data.contentObj) {
this.g_data.contentObj = {};
this.g_formData = {};
}
this.initDefaultData();
this.initAudio();
this.initImg();
// 预加载资源
this.loadResources().then(() => {
window["air"].hideAirClassLoading(this.saveKey, this.data);
this.init();
this.g_cartoon.loadResources().then(() => {
window["air"].hideAirClassLoading(this.g_KEY, this.g_data);
this.initSystem();
this.update();
this.systemReady()
});
this.initListener();
}, this.g_KEY);
}
// ----------------------------------
// 初始化默认数据
// ----------------------------------
initDefaultData() {
if ( Object.keys(this.g_formData).length===0 || this.g_formData.version != defauleFormData.version ) {
this.g_formData = defauleFormData;
}
}
init() {
this.initCtx();
this.initData();
this.initView();
// ----------------------------------
// 初始化音乐
// ----------------------------------
initAudio() {
const contentObj = this.g_formData;
if (!contentObj) {
return;
}
// 添加用户上传音效
let images:Array<string> = this.mapToAduioArray(contentObj)
images.forEach(image => {
this.g_cartoon.addAudio( image, image );
});
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;
// 添加本地音效
for( var key in localAudios ){
this.g_cartoon.addAudio( key, localAudios[key] );
}
}
// ----------------------------------
// 初始化图片
// ----------------------------------
initImg() {
const contentObj = this.g_formData;
if (contentObj) {
const addPicUrl = url => {
if (url) {
this.g_cartoon.addImage(url, url);
}
};
let images:Array<string> = this.mapToImageArray(contentObj)
images.forEach(image => {
addPicUrl(image)
});
}
// 添加本地图片
for( var key in localImages ){
this.g_cartoon.addImage( key, localImages[key] );
}
}
this.ctx = this.canvas.nativeElement.getContext('2d');
this.canvas.nativeElement.width = this.canvasWidth;
this.canvas.nativeElement.height = this.canvasHeight;
window['curCtx'] = this.ctx;
mapDown(event) {
let myStopPropagation = false;
if (!this.g_enableMapDown) {
return;
}
let eventBuffer = []
this.m_mapDownArray.forEach((item)=>{
if(!myStopPropagation){
if (this.checkClickTarget(this.g_cartoon.getCartoonElementRef(item.id))) {
if(this.m_mapDownBuffer.indexOf(item.id) != -1){
this.g_enableMapDown = false;
eventBuffer.push({id: item.id, callback: item.callback, eventIndex: this.g_cartoon.getCartoonElementRef(item.id).eventIndex?this.g_cartoon.getCartoonElementRef(item.id).eventIndex:0, text: this.g_cartoon.getCartoonElement(item.id).text})
}else{
this.g_enableMapDown = false;
if(this.m_mapDragObject[item.id]){
this.m_mapDragObject[item.id].trigger()
let dragElement = this.g_cartoon.getCartoonElement(item.id)
if(dragElement){
this.g_currentDragElementID = item.id
this.g_dragFirstClickX = this.g_clickX
this.g_dragFirstClickY = this.g_clickY
this.enableMoveAsstant(()=>{
this.m_mapDragObject[item.id].move(dragElement)
})
}
myStopPropagation = true;
}else{
if(item.callback()){
myStopPropagation = true;
}
eventBuffer = []
}
}
}
}
})
if(eventBuffer.length>0){
eventBuffer.sort((a,b)=>{
return b.eventIndex - a.eventIndex
})
eventBuffer[0].callback()
}
}
mapMove(event) {
let myStopPropagation = false;
if (!this.g_enableMapMove) {
return;
}
this.m_mapMoveArray.forEach((item)=>{
if(!myStopPropagation){
if (this.checkClickTarget(this.g_cartoon.getCartoonElementRef(item.id))) {
this.g_enableMapMove = false;
if(item.callback()){
myStopPropagation = true;
}
}
}
})
}
mapUp(event) {
let myStopPropagation = false;
if (!this.g_enableMapUp) {
return;
}
this.m_mapUpArray.forEach((item)=>{
if(!myStopPropagation){
if (this.checkClickTarget(this.g_cartoon.getCartoonElementRef(item.id))) {
this.g_enableMapUp = false;
if(item.callback()){
myStopPropagation = true;
}
this.g_currentDragElementID = null;
this.disableMoveAsstant();
}
}
})
}
update() {
this.g_animationId = window.requestAnimationFrame(this.update.bind(this));
// 清除画布内容
this.g_ctx.clearRect(0, 0, this.g_canvasWidth, this.g_canvasHeight);
TWEEN.update();
this.updateArr(this.m_renderArr);
this.updateArr(this.m_endPageArr);
this.updateArr(this.m_elementPetalArr);
this.updateArr(this.m_frontCurtainArr)
}
updateItem(item) {
if (item) {
......@@ -163,50 +1427,39 @@ export class PlayComponent implements OnInit, OnDestroy {
}
}
initListener() {
this.winResizeEventStream
.pipe(debounceTime(500))
.subscribe(data => {
const element = this.canvas.nativeElement;
this.g_winResizeEventStream.pipe(debounceTime(500)).subscribe(data => {
this.renderAfterResize();
});
// ---------------------------------------------
const setParentOffset = () => {
const rect = this.canvas.nativeElement.getBoundingClientRect();
this.canvasLeft = rect.left;
this.canvasTop = rect.top;
const addTouchListener = () => {
element.addEventListener('touchstart', touchDownFunc);
element.addEventListener('touchmove', touchMoveFunc);
element.addEventListener('touchend', touchUpFunc);
element.addEventListener('touchcancel', touchUpFunc);
};
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;
const removeTouchListener = () => {
element.removeEventListener('touchstart', touchDownFunc);
element.removeEventListener('touchmove', touchMoveFunc);
element.removeEventListener('touchend', touchUpFunc);
element.removeEventListener('touchcancel', touchUpFunc);
};
const setMxMyByMouse = (event) => {
this.mx = event.offsetX;
this.my = event.offsetY;
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);
};
// ---------------------------------------------
let firstTouch = true;
const touchDownFunc = (e) => {
if (firstTouch) {
firstTouch = false;
if (this.g_firstTouch) {
this.g_firstTouch = false;
removeMouseListener();
}
setMxMyByTouch(e);
......@@ -222,8 +1475,8 @@ export class PlayComponent implements OnInit, OnDestroy {
};
const mouseDownFunc = (e) => {
if (firstTouch) {
firstTouch = false;
if (this.g_firstTouch) {
this.g_firstTouch = false;
removeTouchListener();
}
setMxMyByMouse(e);
......@@ -238,135 +1491,85 @@ export class PlayComponent implements OnInit, OnDestroy {
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 setMxMyByTouch = event => {
if (event.touches.length <= 0) {
return;
}
if (this.g_canvasLeft == null) {
setParentOffset();
}
this.g_clickX = event.touches[0].pageX - this.g_canvasLeft;
this.g_clickY = event.touches[0].pageY - this.g_canvasTop;
};
const addMouseListener = () => {
element.addEventListener('mousedown', mouseDownFunc);
element.addEventListener('mousemove', mouseMoveFunc);
element.addEventListener('mouseup', mouseUpFunc);
const setParentOffset = () => {
const rect = this.canvas.nativeElement.getBoundingClientRect();
this.g_canvasLeft = rect.left;
this.g_canvasTop = rect.top;
};
const removeMouseListener = () => {
element.removeEventListener('mousedown', mouseDownFunc);
element.removeEventListener('mousemove', mouseMoveFunc);
element.removeEventListener('mouseup', mouseUpFunc);
const setMxMyByMouse = (event) => {
this.g_clickX = event.offsetX;
this.g_clickY = event.offsetY;
};
addMouseListener();
addTouchListener();
}
playAudio(key, now = false, callback = null) {
const audio = this.audioObj[key];
if (audio) {
if (now) {
audio.pause();
audio.currentTime = 0;
showArr(arr) {
if (!arr) {
return;
}
for (let i = 0; i < arr.length; i++) {
arr[i].visible = true;
}
}
if (callback) {
audio.onended = () => {
callback();
};
hideArr(arr) {
if (!arr) {
return;
}
audio.play();
for (let i = 0; i < arr.length; i++) {
arr[i].visible = false;
}
}
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);
IsPC() {
if (window["ELECTRON"]) {
return false; // 封装客户端标记
}
preload(url) {
return new Promise((resolve, reject) => {
const img = new Image();
// img.crossOrigin = "anonymous";
img.onload = () => resolve(img);
img.onerror = reject;
img.src = url;
});
if (
document.body.ontouchmove !== undefined &&
document.body.ontouchmove !== undefined
) {
return false;
} else {
return true;
}
preloadAudio(url) {
return new Promise((resolve, reject) => {
const audio = new Audio();
audio.oncanplay = (a) => {
resolve();
};
audio.onerror = () => {
reject();
};
audio.src = url;
audio.load();
});
}
renderAfterResize() {
this.canvasWidth = this.wrap.nativeElement.clientWidth;
this.canvasHeight = this.wrap.nativeElement.clientHeight;
this.init();
this.g_canvasWidth = this.wrap.nativeElement.clientWidth;
this.g_canvasHeight = this.wrap.nativeElement.clientHeight;
this.update();
this.handleScreenResize()
}
checkClickTarget(target) {
if (!target) {
return false;
}
const rect = target.getBoundingBox();
if (this.checkPointInRect(this.mx, this.my, rect)) {
if (this.checkPointInRect(this.g_clickX, this.g_clickY, 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;
......@@ -383,297 +1586,700 @@ export class PlayComponent implements OnInit, OnDestroy {
return false;
}
getPosByAngle(angle, len) {
const radian = (angle * Math.PI) / 180;
const x = Math.sin(radian) * len;
const y = Math.cos(radian) * len;
return { x, y };
}
getPosDistance(sx, sy, ex, ey) {
const _x = ex - sx;
const _y = ey - sy;
const len = Math.sqrt(Math.pow(_x, 2) + Math.pow(_y, 2));
return len;
}
subscribeMapDownEvent(id,callback, zIndex = 0, buffer = false){
let isExist = false
if(buffer){
if(this.m_mapDownBuffer.indexOf(id) == -1){
this.m_mapDownBuffer.push(id)
}
}
this.m_mapDownObject.forEach(item=>{
if(item.id==id){
item.callback = callback
isExist = true;
}
})
if(!isExist){
this.m_mapDownObject.push({id:id, zIndex:zIndex?zIndex:1, callback:callback})
this.m_mapDownObject.sort((a,b)=>{
return b.zIndex-a.zIndex
})
}
this.m_mapDownArray = []
this.m_mapDownObject.forEach(item=>{
this.m_mapDownArray.push(item)
})
}
addUrlToAudioObj(key, url = null, vlomue = 1, loop = false, callback = null) {
const audioObj = this.audioObj;
if (url == null) {
url = key;
topOfDownEventArray(id){
let index = -1
this.m_mapDownArray.forEach((item, i)=>{
if(item.id == id){
index = i
}
})
this.rawAudios.set(key, url);
if(index !=- 1){
let item = this.m_mapDownArray.splice(index, 1)
this.m_mapDownArray.push(item[0])
}
}
const audio = new Audio();
audio.src = url;
audio.load();
audio.loop = loop;
audio.volume = vlomue;
subscribeMapUpEvent(id,callback, zIndex?){
zIndex = zIndex?zIndex:0
this.m_mapUpObject.push({id:id, zIndex:zIndex?zIndex:1, callback:callback})
this.m_mapUpObject.sort((a,b)=>{
return b.zIndex-a.zIndex
})
this.m_mapUpArray = []
this.m_mapUpObject.forEach(item=>{
this.m_mapUpArray.push(item)
})
}
audioObj[key] = audio;
subscribeMapMoveEvent(id, callback, zIndex?){
zIndex = zIndex?zIndex:0
this.m_mapMoveObject.push({id:id, zIndex:zIndex?zIndex:1, callback:callback})
this.m_mapMoveObject.sort((a,b)=>{
return a.zIndex - b.zIndex
})
this.m_mapMoveArray = []
this.m_mapMoveObject.forEach(item=>{
this.m_mapMoveArray.push(item)
})
}
if (callback) {
audio.onended = () => {
callback();
subscribeMapDragEvent(id, trigger, move, release){
this.subscribeMapDownEvent(id,()=>{})
this.m_mapDragObject[id] = {
trigger,
move,
release
};
}
}
addUrlToImages(url) {
this.rawImages.set(url, url);
releaseDragElement(){
if(this.g_currentDragElementID){
this.m_mapDragObject[this.g_currentDragElementID].release()
}
}
// 全局初始化入口,当资源加载完毕后执行
initSystem() {
this.g_canvasWidth = this.wrap.nativeElement.clientWidth;
this.g_canvasHeight = this.wrap.nativeElement.clientHeight;
const sx = this.g_canvasWidth / this.g_canvasBaseW;
const sy = this.g_canvasHeight / this.g_canvasBaseH;
const s = Math.min(sx, sy);
this.g_mapScale = s;
this.g_cartoon.mapScale = this.g_mapScale;
this.g_cartoon.clientWidth = this.wrap.nativeElement.clientWidth;
this.g_cartoon.clientHeight = this.wrap.nativeElement.clientHeight;
this.m_renderArr = [];
this.m_frontCurtainArr = [];
this.m_renderObject = [];
this.g_enableMapDown = true;
// ======================================================编写区域==========================================================================
this.g_ctx = this.canvas.nativeElement.getContext("2d");
this.canvas.nativeElement.width = this.g_canvasWidth;
this.canvas.nativeElement.height = this.g_canvasHeight;
window["curCtx"] = this.g_ctx;
// 初始化舞台
this.initStage();
this.update();
}
initStage() {
const bgWidth = 1280;
const bgHeight = 720;
this.g_cartoon.stageWidth = bgWidth*this.g_mapScale;
this.g_cartoon.stageHeight= bgHeight*this.g_mapScale;
const imageColor = this.g_cartoon.createCartoonElement("g-ackground-color", "ShapeRect").ref;
// console.log( "stageWidth: " + this.g_cartoon.stageWidth + " stageHeight" + this.g_cartoon.stageHeight)
// console.log( "clientWidth: " + this.g_cartoon.clientWidth + " clientHeight" + this.g_cartoon.clientHeight)
// console.log( "canvasWidth: " + this.g_canvasWidth + " canvasHeight" + this.g_canvasHeight)
// console.log( "mapScale: " + this.g_mapScale )
imageColor.x = this.g_cartoon.clientWidth / 2 ;
imageColor.y = this.g_cartoon.clientHeight / 2 ;
imageColor.setSize(this.g_cartoon.clientWidth, this.g_cartoon.clientHeight);
imageColor.init();
imageColor.fillColor = this.g_background_color;
this.render(imageColor, -999999)
const image = this.g_cartoon.createCartoonElement("bg_1280_720_Ruler", "MySprite").ref;
image.init(this.g_cartoon.images.get("_bg_1280_720_Ruler"));
image.x = this.g_canvasWidth / 2;
image.y = this.g_canvasHeight /2;
image.visible = this.g_EnableStageRuler
this.g_cartoon.setOrigin( image.x-(bgWidth/2*this.g_mapScale), image.y-(bgHeight/2*this.g_mapScale) )
this.g_cartoon.setRelativeOrigin( -bgWidth/2, -bgHeight/2)
image.setScaleXY(this.g_mapScale);
this.render(image, -999)
this.g_stage = image
this.subscribeMapUpEvent("g-ackground-color", ()=>{
if(this.g_currentDragElementID){
// let dragElement = this.g_cartoon.getCartoonElement(this.g_currentDragElementID)
this.releaseDragElement()
this.g_currentDragElementID = null;
}else{
this.g_enableMapUp = true;
}
})
}
/**
* 添加默认数据 便于无数据时的展示
*/
initDefaultData() {
render(ele, zIndex:number = 0){
ele.eventIndex = zIndex
this.m_renderObject.push({element:ele, zIndex:zIndex?zIndex:1})
this.m_renderObject.sort((a,b)=>{
return a.zIndex - b.zIndex
})
this.m_renderArr = []
this.m_renderObject.forEach(item=>{
this.m_renderArr.push(item.element)
})
}
if (!this.data.pic_url) {
this.data.pic_url = 'assets/play/default/pic.jpg';
this.data.pic_url_2 = 'assets/play/default/pic.jpg';
sendServerEvent(key, data) {
const c = (<any> window).courseware;
c.sendEvent(key, JSON.stringify(data));
}
addServerListener(msg_key, callback) {
const c = (<any> window).courseware;
c.onEvent(msg_key, (data,next) => {
callback(JSON.parse(data))
next && next();
});
}
randomArray_shuffle(array) {
var input = array;
for (var i = input.length-1; i >=0; i--) {
var randomIndex = Math.floor(Math.random()*(i+1));
var itemAtIndex = input[randomIndex];
input[randomIndex] = input[i];
input[i] = itemAtIndex;
}
return input;
}
/**
* 添加预加载图片
*/
initImg() {
paginationArray(pageNo, pageSize, array) {
var offset = (pageNo - 1) * pageSize;
return (offset + pageSize >= array.length) ? array.slice(offset, array.length) : array.slice(offset, offset + pageSize);
}
this.addUrlToImages(this.data.pic_url);
this.addUrlToImages(this.data.pic_url_2);
stopAllTimeout(){
this.m_setTimeoutIDs.forEach(id=>clearTimeout(id))
this.m_setTimeoutIDs = []
}
stopAllInterval(){
this.m_setIntervalIDs.forEach(id=>clearInterval(id))
this.m_setIntervalIDs = []
}
/**
* 添加预加载音频
*/
initAudio() {
topOfRenderArray(element){
let index = this.m_renderArr.indexOf(element)
if(index !=-1){
this.m_renderArr.splice(index, 1)
this.m_renderArr.push(element)
}
}
// 音频资源
this.addUrlToAudioObj(this.data.audio_url);
this.addUrlToAudioObj(this.data.audio_url_2);
setRenderZIndex(element, zIndex){
let index = null;
for(let i=0; i<this.m_renderObject.length; i++){
if( this.m_renderObject[i].element.id == element.id ){
index = i
}
}
if(index){
this.m_renderObject.splice(index, 1)
this.m_renderObject.push({element:element, zIndex:zIndex?zIndex:1})
this.m_renderObject.sort((a,b)=>{
return a.zIndex - b.zIndex
})
// 音效
this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3);
this.m_renderArr = []
this.m_renderObject.forEach(item=>{
this.m_renderArr.push(item.element)
})
}
}
deleteElementInRender(id){
let index = null;
for(let i=0; i<this.m_renderObject.length; i++){
if( this.m_renderObject[i].element.id == id ){
index = i
}
}
if(index){
this.m_renderObject.splice(index, 1)
this.m_renderObject.sort((a,b)=>{
return a.zIndex - b.zIndex
})
this.m_renderArr = []
this.m_renderObject.forEach(item=>{
this.m_renderArr.push(item.element)
})
}else{
console.warn("Can not found element id:" + id)
}
}
enableMoveAsstant(callback){
if (this.m_moveAsstantIntervalId) {
this.g_enableDragging = false;
clearInterval(this.m_moveAsstantIntervalId)
}
this.m_moveAsstantIntervalId = setInterval(() => {
if(this.g_enableDragging){
callback()
}else{
let moveX = Math.abs(this.g_dragFirstClickX - this.g_clickX)
let moveY = Math.abs(this.g_dragFirstClickY - this.g_clickY)
if (moveX > this.g_enableDragDistance || moveY > this.g_enableDragDistance) {
this.g_enableDragging = true;
}
}
}, 50)
}
disableMoveAsstant(){
this.g_enableDragging = false;
clearInterval(this.m_moveAsstantIntervalId)
}
/**
* 初始化数据
*/
initData() {
cleanSystemVar(){
this.m_mapDownQueue = {}
this.m_mapDownArray = []
this.m_mapDownObject = []
this.m_mapDownBuffer = []
this.m_mapDownEventCount = 0;
this.m_mapMoveArray = []
this.m_mapMoveObject = []
this.m_mapUpQueue = {}
this.m_mapUpArray = []
this.m_mapUpObject = []
this.stopAllInterval();
this.stopAllTimeout()
this.g_cartoon.stopAllAudio()
}
const sx = this.canvasWidth / this.canvasBaseW;
const sy = this.canvasHeight / this.canvasBaseH;
const s = Math.min(sx, sy);
this.mapScale = s;
getMaxSubstringLength(str){
let maxLength = 0;
let subSubstring = str.split(" ")
for (let index=0; index<subSubstring.length; index++) {
if(subSubstring[index].length > maxLength){
maxLength = subSubstring[index].length;
}
}
return maxLength
}
// this.mapScale = sx;
// this.mapScale = sy;
setLeftCornerTest(){
const bgRect = new ShapeRect();
bgRect.setSize(57, 65);
bgRect.fillColor = '#f8c224';
const sx = this.g_canvasWidth / this.g_canvasBaseW;
bgRect.setScaleXY(sx);
bgRect.x = 65 * sx;
this.g_partTitle_x = bgRect.x
this.g_mainTitle_x = bgRect.x + 80 * sx
bgRect.alpha = 0.5
bgRect.visible = this.g_showLeftCornerTest
this.render(bgRect, 9999);
}
alignCenter(elementArray, spacing, withAni?, callback?){
let totlaWidth = 0
let length = elementArray.length
elementArray.forEach(element => {
let bd = element.ref.getBoundingBox()
totlaWidth += bd.width
});
totlaWidth += (elementArray.length-1) * spacing
let laseX = this.g_canvasWidth / 2 - totlaWidth/2;
elementArray.forEach((element, index) => {
let bd = element.ref.getBoundingBox()
if(withAni){
tweenChange(element.ref, {x: laseX + bd.width / 2}, 0.2, ()=>{
this.g_cartoon.saveSize(element.id)
if(length == (index+1)){
callback && callback()
}
})
}else{
element.ref.x = laseX + bd.width / 2
this.g_cartoon.saveSize(element.id)
if(length == (index+1)){
callback && callback()
}
}
this.renderArr = [];
laseX = (laseX + bd.width + spacing)
});
}
alignLeft(elementArray, spacing, startX = 0, withAni?, callback?){
let laseX = startX;
elementArray.forEach((element, index) => {
let bd = element.ref.getBoundingBox()
if(withAni){
tweenChange(element.ref, {x: laseX + bd.width / 2}, 0.2, ()=>{
this.g_cartoon.saveSize(element.id)
if(length == (index+1)){
callback && callback()
}
})
}else{
element.ref.x = laseX + bd.width / 2
this.g_cartoon.saveSize(element.id)
if(length == (index+1)){
callback && callback()
}
}
laseX = (laseX + bd.width + spacing)
});
}
createTestLine(x, y, height, color?){
var colorAll = ['#ff0000','#eb4310','#f6941d','#fbb417','#ffff00','#cdd541','#99cc33','#3f9337','#219167','#239676','#24998d','#1f9baa','#0080ff','#3366cc','#333399','#003366','#800080','#a1488e','#c71585','#bd2158'];
color = color ? color : colorAll[Math.floor(Math.random()*20)]
this.render(this.g_cartoon.createRectangula({
width: 5,
height: height,
x: x,
y: y,
fillColor: color
}), 9999)
}
getSuitSizeBackground(key, width){
let bgAll = multiSizeBackground[key]
if(!bgAll){
return ""
}
let suitFileName = ""
for(let fileName in bgAll){
if( Number(fileName) >= width){
suitFileName = bgAll[fileName]
break
}
}
return suitFileName
}
getMapDownEventCount(){
return this.m_mapDownEventCount++
}
/**
* 初始化试图
*/
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() {
this.nextPage();
}
lastPage() {
if (this.curPic == this.pic1) {
return;
}
this.canTouch = false;
// --------------------------------------------------
// -------------- Template function ---------------
// --------------------------------------------------
// --------------------------------------------------
// --------------------------------------------------
//
// .-~~~~~~~~~-._ _.-~~~~~~~~~-.
// __.' ~. .~ `.__
// .'// \./ \\`.
// .'// | \\`.
// .'// .-~"""""""~~~~-._ | _,-~~~~"""""""~-. \\`.
// .'//.-" `-. | .-' "-.\\`.
// .'//______.============-.. \ | / ..-============.______\\`.
//.'______________________________\|/______________________________`.
//
// --------------------------------------------------
// showParticle( element_id ) 泡泡效果
// --------------------------------------------------
// showEndPatal() / stopEndPatal() 花瓣飘落结束动画
// --------------------------------------------------
// showCorrectPatal() 指定元素上面飘花
// --------------------------------------------------
// convertPercentToRadian() 将百分比转换为弧长 第一个参数是百分比,第二个参数是方向 true为逆时针,false为顺时针。用于ShapeCircle换圆弧
// --------------------------------------------------
// movePaoWuxian() 元素抛物线跳
// --------------------------------------------------
// showJellyAnimation()------------------------------
// showBlingStar()----------------------显示星星效果--
// --------------------------------------------------
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;
});
}
nextPage() {
if (this.curPic == this.pic2) {
return;
// 泡泡
showParticle(card) {
let myCard = this.g_cartoon.getCartoonElementRelativePosition(card.id)
showPopParticle(this.g_cartoon.images.get("_bubble"), { x: myCard.x , y: myCard.y }, this.g_stage);
}
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;
});
// 选择正确动画
showCorrectPatal(card_id, showTime, callback?) {
this.m_elementPetalArr = [];
this.m_showElementPetalFlag = true;
this.addCorrectPetal(card_id);
setTimeout(()=>{
this.m_elementPetalArr = [];
this.m_showElementPetalFlag = false;
callback && callback()
},showTime)
}
pic1Clicked() {
this.playAudio(this.data.audio_url);
stopAllCorrectPatal(){
this.m_elementPetalArr = [];
this.m_showElementPetalFlag = false;
}
pic2Clicked() {
this.playAudio(this.data.audio_url_2);
addCorrectPetal(card_id) {
if (!this.m_showElementPetalFlag) {
return;
}
let element = this.g_cartoon.getCartoonElement(card_id)
const petal = new MySprite(this.g_ctx);
const id = Math.ceil(Math.random() * 3);
petal.init(this.g_cartoon.images.get(this.m_PetalImage + id));
const randomS = (Math.random() * 0.4 + 0.6) * this.g_mapScale * 0.5;
petal.setScaleXY(randomS);
const randomR = Math.random() * 360;
petal.rotation = randomR;
mapDown(event) {
const randomX = Math.random() * element.ref.width * this.g_mapScale;
if (!this.canTouch) {
return;
}
petal.x = element.ref.x - (element.ref.width * this.g_mapScale / 2) + randomX;
petal.y = element.ref.y - (element.ref.height * this.g_mapScale / 2);
if ( this.checkClickTarget(this.btnLeft) ) {
this.btnLeftClicked();
return;
const randomT = 1 + Math.random() * 2;
petal["time"] = randomT;
let randomTR = 360 * Math.random(); // - 180;
if (Math.random() < 0.5) {
randomTR *= -1;
}
petal["tr"] = randomTR;
this.m_elementPetalArr.push(petal);
moveItem(
petal,
petal.x,
element.ref.y + (element.ref.height * this.g_mapScale / 2),
petal["time"],
() => {
removeItemFromArr(this.m_elementPetalArr, petal);
}
);
rotateItem(petal, petal["tr"], petal["time"]);
setTimeout(() => {
this.addCorrectPetal(card_id);
}, 200);
}
if ( this.checkClickTarget(this.btnRight) ) {
this.btnRightClicked();
return;
// 结束动画花瓣飘落
showEndPatal(side = "all") {
this.m_endPageArr = [];
this.m_showPetalFlag = true;
this.addPetal(side);
}
if ( this.checkClickTarget(this.pic1) ) {
this.pic1Clicked();
return;
stopEndPatal() {
this.m_endPageArr = [];
this.m_showPetalFlag = false;
}
if ( this.checkClickTarget(this.pic2) ) {
this.pic2Clicked();
addPetal(side) {
if (!this.m_showPetalFlag) {
return;
}
const petal = this.getPetal(side);
this.m_endPageArr.push(petal);
moveItem(
petal,
petal.x,
this.g_canvasHeight + petal.height * petal.scaleY,
petal["time"],
() => {
removeItemFromArr(this.m_endPageArr, petal);
}
mapMove(event) {
);
rotateItem(petal, petal["tr"], petal["time"]);
setTimeout(() => {
this.addPetal(side);
}, 100);
}
mapUp(event) {
getPetal(side) {
const petal = new MySprite(this.g_ctx);
}
const id = Math.ceil(Math.random() * 3);
petal.init(this.g_cartoon.images.get(this.m_PetalImage + id));
const randomS = (Math.random() * 0.4 + 0.6) * this.g_mapScale;
petal.setScaleXY(randomS);
const randomR = Math.random() * 360;
petal.rotation = randomR;
update() {
let randomX = null;
switch(side) {
case "left":
randomX = Math.random() * this.g_canvasWidth / 2;
break;
case "right":
randomX = this.g_canvasWidth / 2 + Math.random() * this.g_canvasWidth / 2;
break;
default:
randomX = Math.random() * this.g_canvasWidth;
}
petal.x = randomX;
petal.y = (-petal.height / 2) * petal.scaleY;
// ----------------------------------------------------------
this.animationId = window.requestAnimationFrame(this.update.bind(this));
// 清除画布内容
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
// tween 更新动画
TWEEN.update();
// ----------------------------------------------------------
const randomT = 2 + Math.random() * 5;
petal["time"] = randomT;
let randomTR = 360 * Math.random(); // - 180;
if (Math.random() < 0.5) {
randomTR *= -1;
}
petal["tr"] = randomTR;
return petal;
}
this.updateArr(this.renderArr);
showJellyAnimation(element_id, callback?){
let element = this.g_cartoon.getCartoonElement(element_id).ref
tweenChange(element,{ scaleX: this.g_mapScale * 1.2 , scaleY: this.g_mapScale * 1.1 }, 0.1, ()=>{
tweenChange(element,{ scaleX: this.g_mapScale * 0.8 , scaleY: this.g_mapScale * 0.9 }, 0.1, ()=>{
tweenChange(element,{ scaleX: this.g_mapScale , scaleY: this.g_mapScale }, 0.1, ()=>{
callback && callback()
})
})
})
}
showShakeAnimation(element_id, callback?){
let element = this.g_cartoon.getCartoonElement(element_id).ref
let originX = element.x
tweenChange(element,{ x: originX - 10*this.g_mapScale }, 0.1, ()=>{
tweenChange(element,{ x: originX + 10*this.g_mapScale }, 0.1, ()=>{
tweenChange(element,{ x: originX }, 0.1, ()=>{
callback && callback()
})
})
})
}
convertPercentToRadian(per, direction){
let radian = 0;
if(direction) { //逆时针
if(per*360 > 270){
radian = 361 - (per*360 - 270)
}else{
radian = 270 - per*360
}
}else{ //顺时针
if(per*360 > 90){
radian = per*360 - 90
}else{
radian = 270 + per*360
}
}
return (radian * Math.PI) / 180;
}
showBlingStar(element, callback?){
let rect = element.getBoundingBox()
showBlingBling(this.g_cartoon.images.get('icon_star'), rect, element, 0.5, 1, 0.08, 0.5);
this.m_setTimeoutIDs.push(setTimeout(() => {
callback && callback()
}, 2000))
// setTimeout(()=>{
// showBlingBling(this.g_cartoon.images.get('icon_star'), rect, element, 0.5, 1, 0.08, 1.8);
// },200)
// setTimeout(()=>{
// showBlingBling(this.g_cartoon.images.get('icon_star'), rect, element, 0.5, 1, 0.08, 1.6);
// },400)
}
movePaoWuxian(element,dis,time,callback?){
let disX = dis.x - element.x
let disY = (element.y - dis.y)
let count = 0
let runTime = time/5
let vx = disX/runTime
let a = -0.05
let vy0 = disY/runTime - 0.5*a*runTime
let id = setInterval(()=>{
element.x += vx
element.y -= vy0 + a*count
count++;
if(count>runTime){
clearInterval(id)
callback && callback()
}
}, 5);
}
}
const res = [
const localImages = {
'_bg_1280_720_Ruler': 'assets/default/images/1280_720_Ruler.png',
'_mask_layer_1280_720': 'assets/default/images/mask_layer_1280_720.png',
'_bg_240_180': 'assets/default/images/bg_240_180.png',
'_bg_453_251': 'assets/default/images/bg_453_251.png',
'_bg_1280_222': 'assets/default/images/bg_1280_222.png',
'_bg_1280_720': 'assets/default/images/bg_1280_720.png',
'_bg_200_200': 'assets/default/images/bg_200_200.png',
'_bg_30_30': 'assets/default/images/bg_30_30.png',
'_bg_500_600': 'assets/default/images/bg_500_600.png',
'_bg_50_50': 'assets/default/images/bg_50_50.png',
'_bg_75_50': 'assets/default/images/bg_75_50.png',
'_bg_75_50_black': 'assets/default/images/bg_75_50_black.png',
'_flag': 'assets/default/images/flag.png',
'_go': 'assets/default/images/go.png',
'_header': 'assets/default/images/header.png',
'_ready': 'assets/default/images/ready.png',
'_replay': 'assets/default/images/replay.png',
'_scrap-pic-1': 'assets/default/images/scrap-pic-1.png',
'_scrap-pic-2': 'assets/default/images/scrap-pic-2.png',
'_scrap-pic-3': 'assets/default/images/scrap-pic-3.png',
'_sm-pic-1': 'assets/default/images/sm-pic-1.png',
'_sm-pic-2': 'assets/default/images/sm-pic-2.png',
'_sm-pic-3': 'assets/default/images/sm-pic-3.png',
'_sm-pic-4': 'assets/default/images/sm-pic-4.png',
'_star': 'assets/default/images/star.png',
'_bubble': 'assets/default/images/bubble.png',
'_image_none': 'assets/default/images/image_none.png',
// ['bg', "assets/play/bg.jpg"],
['btn_left', "assets/play/btn_left.png"],
['btn_right', "assets/play/btn_right.png"],
// ['text_bg', "assets/play/text_bg.png"],
'audio': 'assets/play/audio.png',
'background': 'assets/play/background.png',
'ball': 'assets/play/ball.png',
'beike': 'assets/play/beike.png',
'button_replay': 'assets/play/button_replay.png',
'button_start': 'assets/play/button_start.png',
'correct': 'assets/play/correct.png',
'gb_ball_1': 'assets/play/gb_ball_2.png',
'gb_ball_2': 'assets/play/gb_ball_2.png',
'gb_ball_3': 'assets/play/gb_ball_3.png',
'gb_ball_4': 'assets/play/gb_ball_4.png',
'haixing': 'assets/play/haixing.png',
'line': 'assets/play/line.png',
'score': 'assets/play/score.png',
'score_ball': 'assets/play/score_ball.png',
'shatu': 'assets/play/shatu.png',
'shitou': 'assets/play/shitou.png',
'breakLineTop': 'assets/play/breakLineTop.png',
'hand-left': 'assets/play/hand-left.png',
'hand-right': 'assets/play/hand-right.png',
'play_audio': 'assets/play/play_audio.png',
'ball_highlight': 'assets/play/ball_highlight.png',
'bg_shake_hand': 'assets/play/bg_shake_hand.png',
'bg_new_smiling_face': 'assets/play/bg_new_smiling_face.png',
];
'guang': 'assets/play/guang.png',
'shengli': 'assets/play/shengli.png',
'pingju': 'assets/play/pingju.png',
'play_audio (1)': 'assets/play/frame/play_audio (1).png',
'play_audio (2)': 'assets/play/frame/play_audio (2).png',
'play_audio (3)': 'assets/play/frame/play_audio (3).png',
'bubble_ani (1)': 'assets/play/frame/bubble_ani (1).png',
'bubble_ani (2)': 'assets/play/frame/bubble_ani (2).png',
'bubble_ani (3)': 'assets/play/frame/bubble_ani (3).png',
'bubble_ani (4)': 'assets/play/frame/bubble_ani (4).png',
'bubble_ani (5)': 'assets/play/frame/bubble_ani (5).png',
'bubble_ani (6)': 'assets/play/frame/bubble_ani (6).png',
'bubble_ani (7)': 'assets/play/frame/bubble_ani (7).png',
'bubble_ani (8)': 'assets/play/frame/bubble_ani (8).png',
'bubble_ani (9)': 'assets/play/frame/bubble_ani (9).png',
const resAudio = [
'shake_hand (1)': 'assets/play/frame/shake_hand (1).png',
'shake_hand (10)': 'assets/play/frame/shake_hand (10).png',
'shake_hand (11)': 'assets/play/frame/shake_hand (11).png',
'shake_hand (12)': 'assets/play/frame/shake_hand (12).png',
'shake_hand (13)': 'assets/play/frame/shake_hand (13).png',
'shake_hand (14)': 'assets/play/frame/shake_hand (14).png',
'shake_hand (15)': 'assets/play/frame/shake_hand (15).png',
'shake_hand (16)': 'assets/play/frame/shake_hand (16).png',
'shake_hand (17)': 'assets/play/frame/shake_hand (17).png',
'shake_hand (18)': 'assets/play/frame/shake_hand (18).png',
'shake_hand (19)': 'assets/play/frame/shake_hand (19).png',
'shake_hand (2)': 'assets/play/frame/shake_hand (2).png',
'shake_hand (20)': 'assets/play/frame/shake_hand (20).png',
'shake_hand (21)': 'assets/play/frame/shake_hand (21).png',
'shake_hand (22)': 'assets/play/frame/shake_hand (22).png',
'shake_hand (23)': 'assets/play/frame/shake_hand (23).png',
'shake_hand (24)': 'assets/play/frame/shake_hand (24).png',
'shake_hand (25)': 'assets/play/frame/shake_hand (25).png',
'shake_hand (3)': 'assets/play/frame/shake_hand (3).png',
'shake_hand (4)': 'assets/play/frame/shake_hand (4).png',
'shake_hand (5)': 'assets/play/frame/shake_hand (5).png',
'shake_hand (6)': 'assets/play/frame/shake_hand (6).png',
'shake_hand (7)': 'assets/play/frame/shake_hand (7).png',
'shake_hand (8)': 'assets/play/frame/shake_hand (8).png',
'shake_hand (9)': 'assets/play/frame/shake_hand (9).png',
['click', "assets/play/music/click.mp3"],
'smiling_face (1)': 'assets/play/frame/new_smiling_face (1).png',
'smiling_face (2)': 'assets/play/frame/new_smiling_face (2).png',
'smiling_face (3)': 'assets/play/frame/new_smiling_face (3).png',
'smiling_face (4)': 'assets/play/frame/new_smiling_face (4).png',
'smiling_face (5)': 'assets/play/frame/new_smiling_face (5).png',
'smiling_face (6)': 'assets/play/frame/new_smiling_face (6).png',
'smiling_face (7)': 'assets/play/frame/new_smiling_face (7).png',
'smiling_face (8)': 'assets/play/frame/new_smiling_face (8).png',
'smiling_face (9)': 'assets/play/frame/new_smiling_face (9).png',
'smiling_face (10)': 'assets/play/frame/new_smiling_face (10).png',
];
'bg_star (1)': 'assets/play/frame/bg_star (1).png',
'bg_star (10)': 'assets/play/frame/bg_star (10).png',
'bg_star (11)': 'assets/play/frame/bg_star (11).png',
'bg_star (12)': 'assets/play/frame/bg_star (12).png',
'bg_star (13)': 'assets/play/frame/bg_star (13).png',
'bg_star (14)': 'assets/play/frame/bg_star (14).png',
'bg_star (15)': 'assets/play/frame/bg_star (15).png',
'bg_star (16)': 'assets/play/frame/bg_star (16).png',
'bg_star (17)': 'assets/play/frame/bg_star (17).png',
'bg_star (18)': 'assets/play/frame/bg_star (18).png',
'bg_star (2)': 'assets/play/frame/bg_star (2).png',
'bg_star (3)': 'assets/play/frame/bg_star (3).png',
'bg_star (4)': 'assets/play/frame/bg_star (4).png',
'bg_star (5)': 'assets/play/frame/bg_star (5).png',
'bg_star (6)': 'assets/play/frame/bg_star (6).png',
'bg_star (7)': 'assets/play/frame/bg_star (7).png',
'bg_star (8)': 'assets/play/frame/bg_star (8).png',
'bg_star (9)': 'assets/play/frame/bg_star (9).png',
export {res, resAudio};
'btn_laba (1)': 'assets/play/frame/btn_laba (1).png',
'btn_laba (2)': 'assets/play/frame/btn_laba (2).png',
'btn_laba (3)': 'assets/play/frame/btn_laba (3).png',
'btn_laba (4)': 'assets/play/frame/btn_laba (4).png',
'bg_bg': 'assets/play/new/bg_bg.png',
'bg_eyu': 'assets/play/new/bg_eyu.png',
'bg_graet': 'assets/play/new/bg_graet.png',
'bg_pao': 'assets/play/new/bg_pao.png',
'bg_picdi': 'assets/play/new/bg_picdi.png',
'bg_star': 'assets/play/new/bg_star.png',
'bg_yezi1': 'assets/play/new/bg_yezi1.png',
'bg_yezi2': 'assets/play/new/bg_yezi2.png',
'bg_you': 'assets/play/new/bg_you.png',
'bg_zuo': 'assets/play/new/bg_zuo.png',
'btn_laba1': 'assets/play/new/btn_laba1.png',
'btn_laba2': 'assets/play/new/btn_laba2.png',
'btn_laba3': 'assets/play/new/btn_laba3.png',
'btn_laba4': 'assets/play/new/btn_laba4.png',
'btn_restart': 'assets/play/new/btn_restart.png',
'btn_start': 'assets/play/new/btn_start.png',
'icon_star': 'assets/play/new/icon_star.png',
};
const localAudios = {
'sm-back': "assets/default/audio/sm-back.mp3",
'sm-display': "assets/default/audio/sm-display.mp3",
'sm-wrong': "assets/default/audio/sm-wrong.mp3",
'sm-win': "assets/default/audio/sm-win.mp3",
'sm-in': "assets/default/audio/sm-in.mp3",
'sm-out': "assets/default/audio/sm-out.mp3",
'sm-click': "assets/default/audio/sm-click.mp3",
'sm-start': "assets/default/audio/sm-start.mp3",
'sm-correct': 'assets/default/audio/sm-correct.mp3',
'sm-star': "assets/default/audio/sm-star.mp3",
'sm-choice-complete': 'assets/default/audio/sm-choice-complete.mp3',
'sm-choice-correct': 'assets/default/audio/sm-choice-correct.mp3',
'sm-choice-error': 'assets/default/audio/sm-choice-error.mp3',
'sm-choice-in': 'assets/default/audio/sm-choice-in.mp3',
'sm-choice-show-answer': 'assets/default/audio/sm-choice-show-answer.mp3',
'sm-choice-timeup-0': 'assets/default/audio/sm-choice-timeup-0.mp3',
'sm-choice-timeup-3': 'assets/default/audio/sm-choice-timeup-3.mp3',
'sm-go': 'assets/default/audio/sm-go.mp3',
'sm-ready': 'assets/default/audio/sm-ready.mp3',
'cuowu': 'assets/play/sound/cuowu.mp3',
'guzhang': 'assets/play/sound/guzhang.mp3',
'open': 'assets/play/sound/open.mp3',
'polie': 'assets/play/sound/polie.mp3',
'win': 'assets/play/sound/win.mp3',
};
const multiSizeBackground = {
}
export {localImages, localAudios, multiSizeBackground};
export default {
version: "1.0",
key: "DataKey_LST08",
dataArray: [
{
correct: [
{
type: "Text",
text: "",
audio_url: "",
image_url: "",
}
],
incorrect: [
]
}
]
}
\ No newline at end of file
!function(){"use strict";function r(r){r||(r=Math.random),this.p=e(r),this.perm=new Uint8Array(512),this.permMod12=new Uint8Array(512);for(var t=0;t<512;t++)this.perm[t]=this.p[255&t],this.permMod12[t]=this.perm[t]%12}function e(r){var e,t=new Uint8Array(256);for(e=0;e<256;e++)t[e]=e;for(e=0;e<255;e++){var a=e+1+~~(r()*(255-e)),i=t[e];t[e]=t[a],t[a]=i}return t}var t=.5*(Math.sqrt(3)-1),a=(3-Math.sqrt(3))/6,i=1/3,o=1/6,n=(Math.sqrt(5)-1)/4,f=(5-Math.sqrt(5))/20;r.prototype={grad3:new Float32Array([1,1,0,-1,1,0,1,-1,0,-1,-1,0,1,0,1,-1,0,1,1,0,-1,-1,0,-1,0,1,1,0,-1,1,0,1,-1,0,-1,-1]),grad4:new Float32Array([0,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,1,0,1,1,1,0,1,-1,1,0,-1,1,1,0,-1,-1,-1,0,1,1,-1,0,1,-1,-1,0,-1,1,-1,0,-1,-1,1,1,0,1,1,1,0,-1,1,-1,0,1,1,-1,0,-1,-1,1,0,1,-1,1,0,-1,-1,-1,0,1,-1,-1,0,-1,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,0]),noise2D:function(r,e){var i,o,n=this.permMod12,f=this.perm,s=this.grad3,v=0,h=0,d=0,l=(r+e)*t,p=Math.floor(r+l),u=Math.floor(e+l),M=(p+u)*a,m=p-M,y=u-M,w=r-m,c=e-y;w>c?(i=1,o=0):(i=0,o=1);var g=w-i+a,x=c-o+a,A=w-1+2*a,q=c-1+2*a,D=255&p,U=255&u,b=.5-w*w-c*c;if(b>=0){var F=3*n[D+f[U]];b*=b,v=b*b*(s[F]*w+s[F+1]*c)}var N=.5-g*g-x*x;if(N>=0){var S=3*n[D+i+f[U+o]];N*=N,h=N*N*(s[S]*g+s[S+1]*x)}var P=.5-A*A-q*q;if(P>=0){var T=3*n[D+1+f[U+1]];P*=P,d=P*P*(s[T]*A+s[T+1]*q)}return 70*(v+h+d)},noise3D:function(r,e,t){var a,n,f,s,v,h,d,l,p,u,M=this.permMod12,m=this.perm,y=this.grad3,w=(r+e+t)*i,c=Math.floor(r+w),g=Math.floor(e+w),x=Math.floor(t+w),A=(c+g+x)*o,q=c-A,D=g-A,U=x-A,b=r-q,F=e-D,N=t-U;b>=F?F>=N?(v=1,h=0,d=0,l=1,p=1,u=0):b>=N?(v=1,h=0,d=0,l=1,p=0,u=1):(v=0,h=0,d=1,l=1,p=0,u=1):F<N?(v=0,h=0,d=1,l=0,p=1,u=1):b<N?(v=0,h=1,d=0,l=0,p=1,u=1):(v=0,h=1,d=0,l=1,p=1,u=0);var S=b-v+o,P=F-h+o,T=N-d+o,_=b-l+2*o,j=F-p+2*o,k=N-u+2*o,z=b-1+3*o,B=F-1+3*o,C=N-1+3*o,E=255&c,G=255&g,H=255&x,I=.6-b*b-F*F-N*N;if(I<0)a=0;else{var J=3*M[E+m[G+m[H]]];I*=I,a=I*I*(y[J]*b+y[J+1]*F+y[J+2]*N)}var K=.6-S*S-P*P-T*T;if(K<0)n=0;else{var L=3*M[E+v+m[G+h+m[H+d]]];K*=K,n=K*K*(y[L]*S+y[L+1]*P+y[L+2]*T)}var O=.6-_*_-j*j-k*k;if(O<0)f=0;else{var Q=3*M[E+l+m[G+p+m[H+u]]];O*=O,f=O*O*(y[Q]*_+y[Q+1]*j+y[Q+2]*k)}var R=.6-z*z-B*B-C*C;if(R<0)s=0;else{var V=3*M[E+1+m[G+1+m[H+1]]];R*=R,s=R*R*(y[V]*z+y[V+1]*B+y[V+2]*C)}return 32*(a+n+f+s)},noise4D:function(r,e,t,a){var i,o,s,v,h,d=(this.permMod12,this.perm),l=this.grad4,p=(r+e+t+a)*n,u=Math.floor(r+p),M=Math.floor(e+p),m=Math.floor(t+p),y=Math.floor(a+p),w=(u+M+m+y)*f,c=u-w,g=M-w,x=m-w,A=y-w,q=r-c,D=e-g,U=t-x,b=a-A,F=0,N=0,S=0,P=0;q>D?F++:N++,q>U?F++:S++,q>b?F++:P++,D>U?N++:S++,D>b?N++:P++,U>b?S++:P++;var T,_,j,k,z,B,C,E,G,H,I,J;T=F>=3?1:0,_=N>=3?1:0,j=S>=3?1:0,k=P>=3?1:0,z=F>=2?1:0,B=N>=2?1:0,C=S>=2?1:0,E=P>=2?1:0,G=F>=1?1:0,H=N>=1?1:0,I=S>=1?1:0,J=P>=1?1:0;var K=q-T+f,L=D-_+f,O=U-j+f,Q=b-k+f,R=q-z+2*f,V=D-B+2*f,W=U-C+2*f,X=b-E+2*f,Y=q-G+3*f,Z=D-H+3*f,$=U-I+3*f,rr=b-J+3*f,er=q-1+4*f,tr=D-1+4*f,ar=U-1+4*f,ir=b-1+4*f,or=255&u,nr=255&M,fr=255&m,sr=255&y,vr=.6-q*q-D*D-U*U-b*b;if(vr<0)i=0;else{var hr=d[or+d[nr+d[fr+d[sr]]]]%32*4;vr*=vr,i=vr*vr*(l[hr]*q+l[hr+1]*D+l[hr+2]*U+l[hr+3]*b)}var dr=.6-K*K-L*L-O*O-Q*Q;if(dr<0)o=0;else{var lr=d[or+T+d[nr+_+d[fr+j+d[sr+k]]]]%32*4;dr*=dr,o=dr*dr*(l[lr]*K+l[lr+1]*L+l[lr+2]*O+l[lr+3]*Q)}var pr=.6-R*R-V*V-W*W-X*X;if(pr<0)s=0;else{var ur=d[or+z+d[nr+B+d[fr+C+d[sr+E]]]]%32*4;pr*=pr,s=pr*pr*(l[ur]*R+l[ur+1]*V+l[ur+2]*W+l[ur+3]*X)}var Mr=.6-Y*Y-Z*Z-$*$-rr*rr;if(Mr<0)v=0;else{var mr=d[or+G+d[nr+H+d[fr+I+d[sr+J]]]]%32*4;Mr*=Mr,v=Mr*Mr*(l[mr]*Y+l[mr+1]*Z+l[mr+2]*$+l[mr+3]*rr)}var yr=.6-er*er-tr*tr-ar*ar-ir*ir;if(yr<0)h=0;else{var wr=d[or+1+d[nr+1+d[fr+1+d[sr+1]]]]%32*4;yr*=yr,h=yr*yr*(l[wr]*er+l[wr+1]*tr+l[wr+2]*ar+l[wr+3]*ir)}return 27*(i+o+s+v+h)}},r._buildPermutationTable=e,"undefined"!=typeof define&&define.amd&&define(function(){return r}),"undefined"!=typeof exports?exports.SimplexNoise=r:"undefined"!=typeof window&&(window.SimplexNoise=r),"undefined"!=typeof module&&(module.exports=r)}();
//# sourceMappingURL=simplex-noise.min.js.map
\ No newline at end of file
import os
import json
def file_name(file_dir):
fileList =["bg_kuang", "bg_kuang2", "bg_light"]
f = open('filename.txt', 'w');
blank = False
for root, dirs, files in os.walk(file_dir):
for fileName in files:
if root.split("\\")[-1]=="new" or root.split("\\")[-1]=="frame" or root.split("\\")[-1]=="sound" or root.split("\\")[-1]=="play" or (root.split("\\")[-1] in fileList):
blank = True
if root.split("\\")[-1] != "play":
f.write("'" + fileName.split(".")[0] + "': 'assets/play/" + root.split("\\")[-1] + "/" + fileName + "',\n")
else:
f.write("'" + fileName.split(".")[0] + "': 'assets/" + root.split("\\")[-1] + "/" + fileName + "',\n")
if blank:
f.write("\n")
blank = False
f.close()
fileList = file_name(os.path.abspath('.'))
'audio': 'assets/play/audio.png',
'background': 'assets/play/background.png',
'ball': 'assets/play/ball.png',
'ball_highlight': 'assets/play/ball_highlight.png',
'beike': 'assets/play/beike.png',
'bg_new_smiling_face': 'assets/play/bg_new_smiling_face.png',
'bg_shake_hand': 'assets/play/bg_shake_hand.png',
'breakLineTop': 'assets/play/breakLineTop.png',
'button_replay': 'assets/play/button_replay.png',
'button_start': 'assets/play/button_start.png',
'correct': 'assets/play/correct.png',
'creatJsonProfile': 'assets/play/creatJsonProfile.py',
'filename': 'assets/play/filename.txt',
'gb_ball_2': 'assets/play/gb_ball_2.png',
'gb_ball_3': 'assets/play/gb_ball_3.png',
'gb_ball_4': 'assets/play/gb_ball_4.png',
'guang': 'assets/play/guang.png',
'haixing': 'assets/play/haixing.png',
'hand-left': 'assets/play/hand-left.png',
'hand-right': 'assets/play/hand-right.png',
'line': 'assets/play/line.png',
'pingju': 'assets/play/pingju.png',
'play_audio': 'assets/play/play_audio.png',
'resizeImg': 'assets/play/resizeImg.py',
'reversalImg': 'assets/play/reversalImg.py',
'score': 'assets/play/score.png',
'score_ball': 'assets/play/score_ball.png',
'shatu': 'assets/play/shatu.png',
'shengli': 'assets/play/shengli.png',
'shitou': 'assets/play/shitou.png',
'bg_star (1)': 'assets/play/frame/bg_star (1).png',
'bg_star (10)': 'assets/play/frame/bg_star (10).png',
'bg_star (11)': 'assets/play/frame/bg_star (11).png',
'bg_star (12)': 'assets/play/frame/bg_star (12).png',
'bg_star (13)': 'assets/play/frame/bg_star (13).png',
'bg_star (14)': 'assets/play/frame/bg_star (14).png',
'bg_star (15)': 'assets/play/frame/bg_star (15).png',
'bg_star (16)': 'assets/play/frame/bg_star (16).png',
'bg_star (17)': 'assets/play/frame/bg_star (17).png',
'bg_star (18)': 'assets/play/frame/bg_star (18).png',
'bg_star (2)': 'assets/play/frame/bg_star (2).png',
'bg_star (3)': 'assets/play/frame/bg_star (3).png',
'bg_star (4)': 'assets/play/frame/bg_star (4).png',
'bg_star (5)': 'assets/play/frame/bg_star (5).png',
'bg_star (6)': 'assets/play/frame/bg_star (6).png',
'bg_star (7)': 'assets/play/frame/bg_star (7).png',
'bg_star (8)': 'assets/play/frame/bg_star (8).png',
'bg_star (9)': 'assets/play/frame/bg_star (9).png',
'btn_laba (1)': 'assets/play/frame/btn_laba (1).png',
'btn_laba (2)': 'assets/play/frame/btn_laba (2).png',
'btn_laba (3)': 'assets/play/frame/btn_laba (3).png',
'btn_laba (4)': 'assets/play/frame/btn_laba (4).png',
'bubble_ani (1)': 'assets/play/frame/bubble_ani (1).png',
'bubble_ani (2)': 'assets/play/frame/bubble_ani (2).png',
'bubble_ani (3)': 'assets/play/frame/bubble_ani (3).png',
'bubble_ani (4)': 'assets/play/frame/bubble_ani (4).png',
'bubble_ani (5)': 'assets/play/frame/bubble_ani (5).png',
'bubble_ani (6)': 'assets/play/frame/bubble_ani (6).png',
'bubble_ani (7)': 'assets/play/frame/bubble_ani (7).png',
'bubble_ani (8)': 'assets/play/frame/bubble_ani (8).png',
'bubble_ani (9)': 'assets/play/frame/bubble_ani (9).png',
'new_smiling_face (1)': 'assets/play/frame/new_smiling_face (1).png',
'new_smiling_face (10)': 'assets/play/frame/new_smiling_face (10).png',
'new_smiling_face (2)': 'assets/play/frame/new_smiling_face (2).png',
'new_smiling_face (3)': 'assets/play/frame/new_smiling_face (3).png',
'new_smiling_face (4)': 'assets/play/frame/new_smiling_face (4).png',
'new_smiling_face (5)': 'assets/play/frame/new_smiling_face (5).png',
'new_smiling_face (6)': 'assets/play/frame/new_smiling_face (6).png',
'new_smiling_face (7)': 'assets/play/frame/new_smiling_face (7).png',
'new_smiling_face (8)': 'assets/play/frame/new_smiling_face (8).png',
'new_smiling_face (9)': 'assets/play/frame/new_smiling_face (9).png',
'play_audio (1)': 'assets/play/frame/play_audio (1).png',
'play_audio (2)': 'assets/play/frame/play_audio (2).png',
'play_audio (3)': 'assets/play/frame/play_audio (3).png',
'shake_hand (1)': 'assets/play/frame/shake_hand (1).png',
'shake_hand (10)': 'assets/play/frame/shake_hand (10).png',
'shake_hand (11)': 'assets/play/frame/shake_hand (11).png',
'shake_hand (12)': 'assets/play/frame/shake_hand (12).png',
'shake_hand (13)': 'assets/play/frame/shake_hand (13).png',
'shake_hand (14)': 'assets/play/frame/shake_hand (14).png',
'shake_hand (15)': 'assets/play/frame/shake_hand (15).png',
'shake_hand (16)': 'assets/play/frame/shake_hand (16).png',
'shake_hand (17)': 'assets/play/frame/shake_hand (17).png',
'shake_hand (18)': 'assets/play/frame/shake_hand (18).png',
'shake_hand (19)': 'assets/play/frame/shake_hand (19).png',
'shake_hand (2)': 'assets/play/frame/shake_hand (2).png',
'shake_hand (20)': 'assets/play/frame/shake_hand (20).png',
'shake_hand (21)': 'assets/play/frame/shake_hand (21).png',
'shake_hand (22)': 'assets/play/frame/shake_hand (22).png',
'shake_hand (23)': 'assets/play/frame/shake_hand (23).png',
'shake_hand (24)': 'assets/play/frame/shake_hand (24).png',
'shake_hand (25)': 'assets/play/frame/shake_hand (25).png',
'shake_hand (3)': 'assets/play/frame/shake_hand (3).png',
'shake_hand (4)': 'assets/play/frame/shake_hand (4).png',
'shake_hand (5)': 'assets/play/frame/shake_hand (5).png',
'shake_hand (6)': 'assets/play/frame/shake_hand (6).png',
'shake_hand (7)': 'assets/play/frame/shake_hand (7).png',
'shake_hand (8)': 'assets/play/frame/shake_hand (8).png',
'shake_hand (9)': 'assets/play/frame/shake_hand (9).png',
'bg_bg': 'assets/play/new/bg_bg.png',
'bg_eyu': 'assets/play/new/bg_eyu.png',
'bg_graet': 'assets/play/new/bg_graet.png',
'bg_pao': 'assets/play/new/bg_pao.png',
'bg_picdi': 'assets/play/new/bg_picdi.png',
'bg_star': 'assets/play/new/bg_star.png',
'bg_yezi1': 'assets/play/new/bg_yezi1.png',
'bg_yezi2': 'assets/play/new/bg_yezi2.png',
'bg_you': 'assets/play/new/bg_you.png',
'bg_zuo': 'assets/play/new/bg_zuo.png',
'btn_laba1': 'assets/play/new/btn_laba1.png',
'btn_laba2': 'assets/play/new/btn_laba2.png',
'btn_laba3': 'assets/play/new/btn_laba3.png',
'btn_laba4': 'assets/play/new/btn_laba4.png',
'btn_restart': 'assets/play/new/btn_restart.png',
'btn_start': 'assets/play/new/btn_start.png',
'icon_star': 'assets/play/new/icon_star.png',
'cuowu': 'assets/play/sound/cuowu.mp3',
'guzhang': 'assets/play/sound/guzhang.mp3',
'open': 'assets/play/sound/open.mp3',
'polie': 'assets/play/sound/polie.mp3',
'win': 'assets/play/sound/win.mp3',
import os
import shutil
from PIL import Image
fileName = os.listdir('./')
withBorder = False
border_left = ""
border_right = ""
imageName = input("图片名:")
if input("是否包含边框? (y/n):")=="y":
withBorder = True
if withBorder:
border_left = input("左边框文件名:")
border_right = input("右边框文件名:")
number = int(input("数量:"))
if os.path.exists('./' + imageName + '/'):
shutil.rmtree('./' + imageName + '/')
os.mkdir('./' + imageName + '/')
pic = Image.open('./' + imageName + '.PNG')
width = pic.width
height = pic.height
f = open('./' + imageName + '/' + imageName + '_map.txt', 'w')
if withBorder:
borderImg_left, borderImg_right = Image.open('./' + border_left + '.PNG'), Image.open('./' + border_right + '.PNG')
for index in range(1, number):
newpic = pic.resize((width*index, height),Image.ANTIALIAS)
loc1, loc2, loc3 = (0, 0), (borderImg_left.width, 0), (borderImg_left.width +newpic.width, 0)
join_pic = Image.new('RGBA', (borderImg_left.width + newpic.width + borderImg_right.width, newpic.height))
join_pic.paste(borderImg_left, loc1)
join_pic.paste(newpic, loc2)
join_pic.paste(borderImg_right, loc3)
join_pic.save('./' + imageName + '/' + imageName + '_' + str(index) + 'x.PNG')
f.write('"' + str(width*index) + '": "' + imageName + '_' + str(index) + 'x",\n')
f.close()
else:
for index in range(1, number):
newpic = pic.resize((width*index, height),Image.ANTIALIAS)
newpic.save('./' + imageName + '/' + imageName + '_' + str(index) + 'x.PNG')
f.write('"' + str(width*index) + '": "' + imageName + '_' + str(index) + 'x",\n')
f.close()
\ No newline at end of file
import os
import shutil
from PIL import Image
imageName = input("图片名:")
number = int(input("数量:"))
newImageName = input("新图片名:")
if os.path.exists('./' + imageName + '/'):
shutil.rmtree('./' + imageName + '/')
os.mkdir('./' + newImageName + '/')
for index in range(1, number):
pic = Image.open('./beat_left (' + str(index) + ').PNG')
newpic = pic.transpose(Image.FLIP_LEFT_RIGHT)
newpic.save('./' + newImageName + '/' + newImageName + ' (' + str(index) + ').PNG')
\ No newline at end of file
......@@ -4,6 +4,12 @@
<meta charset="utf-8">
<title>NgOne</title>
<base href="/">
<style>
html, body{
width: 100%;
height: 100%;
}
</style>
<!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
......
/* You can add global styles to this file, and also import other style files */
@import "~ng-zorro-antd/ng-zorro-antd.min.css";
\ No newline at end of file
......@@ -21,6 +21,7 @@
]
},
"angularCompilerOptions": {
"enableIvy": false,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
......
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