diff --git a/form_angular/src/app/common/audio-recorder/audio-recorder.component.html b/form_angular/src/app/common/audio-recorder/audio-recorder.component.html index c871e7672817c7dea89bc069c62ab50924e3bc7e..b9bff999d8c8de539f89a996a55ba1ccfb634fb6 100644 --- a/form_angular/src/app/common/audio-recorder/audio-recorder.component.html +++ b/form_angular/src/app/common/audio-recorder/audio-recorder.component.html @@ -1,4 +1,4 @@ -<div class="d-flex"> +<div class="d-flex" (drop)="handle_drop($event)" (dragover)="handle_dragover($event)"> <div class="p-btn-record d-flex"> <div class="btn-clear" style="cursor: pointer" (click)="onBtnClearAudio()" *ngIf="withRmBtn && (audioUrl || audioBlob)"> <fa-icon icon="times"></fa-icon> diff --git a/form_angular/src/app/common/audio-recorder/audio-recorder.component.ts b/form_angular/src/app/common/audio-recorder/audio-recorder.component.ts index 4af32f165cb18541775c443231c942019da569a3..d6ce89ae6730edb74362a05571b779f0c45228f2 100644 --- a/form_angular/src/app/common/audio-recorder/audio-recorder.component.ts +++ b/form_angular/src/app/common/audio-recorder/audio-recorder.component.ts @@ -276,6 +276,39 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { this.progress = Math.floor(p * 100); } + linkInputed (url, name) { + url = url.substring(0, url.lastIndexOf(".")) + "_l.mp3"; + this.audioUrl = url; + this.audioUploaded.emit({url}); + this.audioName.emit(name); + } + + handle_dragover(e) { + e.preventDefault(); + } + + handle_drop(e) { + const dt = e.dataTransfer.getData("text/plain"); + console.log("handle_drop===", dt); + if (!dt) { + return; + } + try { + const {url, name} = JSON.parse(dt); + if (url.indexOf("teach")<0 || url.indexOf("cdn")<0) { + return; + } + const white = [".mp3"]; + if (!white.includes(url.substr(url.lastIndexOf(".")))) { + return; + } + + this.linkInputed(url, name); + } catch (error) { + console.warn("handle_dropæ‹–æ‹½åœ¨çº¿éŸ³é¢‘ä¼ é€’å‚æ•°ä¸åˆæ³•,应该是{url:'', name:''}"); + } + } + } enum Type { diff --git a/form_angular/src/app/common/custom-hot-zone/Unit.ts b/form_angular/src/app/common/custom-hot-zone/Unit.ts index 7b99189ae1e79f71bf621d6c98beff55cb7df827..3345e2404d2ab972fd91322dec9d33410cf69f50 100644 --- a/form_angular/src/app/common/custom-hot-zone/Unit.ts +++ b/form_angular/src/app/common/custom-hot-zone/Unit.ts @@ -329,6 +329,7 @@ export class MySprite extends Sprite { this.scaleX = this.scaleY = value; } + getBoundingBox() { const getParentData = (item) => { @@ -1956,6 +1957,10 @@ export class HotZoneItem extends MySprite { audio_url; pic_url; text; + gIdx; + + isAnimaStyle = false; + private _itemType; private shapeRect: ShapeRect; @@ -2056,7 +2061,10 @@ export class HotZoneItem extends MySprite { this.hideLabel(); } - + setAnimaStyle(isAnimaStyle) { + this.isAnimaStyle = isAnimaStyle; + console.log('in setAnimaStyle ') + } drawArrow() { if (!this.arrow) { return; } @@ -2068,13 +2076,16 @@ export class HotZoneItem extends MySprite { 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(); + if (!this.isAnimaStyle) { + 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() { @@ -2197,10 +2208,155 @@ export class HotZoneLabel extends Label { this.drawFrame(); } + + + getLabelRect() { + + + const rect = this.getBoundingBox(); + const width = rect.width / this.scaleX; + const height = this.height * this.scaleY; + const x = this.x - width / 2; + const y = this.y - height / 2; + + return {width, height, x, y}; + } + } +export class HotZoneAction extends MySprite { + + +} + +export class DragItem extends MySprite { + + lineDashFlag = true; + item; + + init() { + this.anchorX = 0.5; + this.anchorY = 0.5; + + this.initCenterCircle(); + + } + + setSize(w, h) { + + this.anchorX = 0.5; + this.anchorY = 0.5; + + 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 = '#000000'; + // rect.alpha = 0.1; + // this.addChild(rect); + + + } + + initCenterCircle() { + const circle = new ShapeCircle(this.ctx); + circle.setRadius(10); + circle.fillColor = '#ffa568' + this.addChild(circle); + + this.width = circle.width; + this.height = circle.height; + } + + getPosition() { + return {x: this.x, y: this.y}; + } + + drawLine() { + if (!this.item) { + return; + } + + + 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([4, 4]); + this.ctx.lineWidth = 1; + this.ctx.strokeStyle = '#ffa568'; + + this.ctx.beginPath(); + + this.ctx.moveTo( x + w / 2 , y + h / 2 ); + + this.ctx.lineTo(this.item.x, this.item.y); + + // this.ctx.fill(); + this.ctx.stroke(); + + + this.ctx.restore(); + } + + 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([4, 4]); + this.ctx.lineWidth = 2; + this.ctx.strokeStyle = '#ffa568'; + // 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.drawLine(); + // this.drawFrame(); + // this.drawArrow(); + } + } +} export class EditorItem extends MySprite { @@ -2208,6 +2364,8 @@ export class EditorItem extends MySprite { arrow: MySprite; label: Label; text; + arrowTop; + arrowRight; showLabel(text = null) { @@ -2246,6 +2404,13 @@ export class EditorItem extends MySprite { 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(); @@ -2262,16 +2427,25 @@ export class EditorItem extends MySprite { this.hideLabel(); } - + refreshLabelScale() {} 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() { @@ -2325,784 +2499,3 @@ 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; -// -// } diff --git a/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.html b/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.html index 9028527061890eefb1557c53f49394c7ea827b11..72de6c46de4475a4b0c9469ac50113b8931d7863 100644 --- a/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.html +++ b/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.html @@ -32,33 +32,143 @@ <nz-divider style="margin-top: 10px;"></nz-divider> + <div style="margin-top: -20px; margin-bottom: 5px; width: 100%;"> - <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="customTypeGroupArr"> + <nz-radio-group [ngModel]="it.gIdx" (ngModelChange)="customRadioChange($event, it)" style="display: flex; align-items: center; justify-content: center; flex-wrap: wrap;"> + <div *ngFor="let group of customTypeGroupArr; let gIdx = index" style="display: flex; "> + <label nz-radio nzValue="{{gIdx}}">{{group.name}}</label> + </div> + </nz-radio-group> - <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> + + <!-- <div *ngIf="!customTypeGroupArr"> + <nz-radio-group [ngModel]="it.itemType" (ngModelChange)="radioChange($event, it)" style="display: flex; align-items: center; justify-content: center"> + + <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 == '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 *ngIf="customTypeGroupArr && customTypeGroupArr[it.gIdx]"> + + <div *ngIf="customTypeGroupArr[it.gIdx].pic"> + <app-upload-image-with-preview + [picUrl]="it?.pic_url" + (imageUploaded)="onItemImgUploadSuccess($event, it)"> + </app-upload-image-with-preview> + </div> + + <div *ngIf="customTypeGroupArr[it.gIdx].text" style="margin-top: 5px"> + <input type="text" nz-input [(ngModel)]="it.text" (blur)="saveText(it)"> + </div> + + <div *ngIf="customTypeGroupArr[it.gIdx].anima" align="center" style="margin-top: 5px"> + <button nz-button (click)="setAnimaBtnClick(i)" > + <i nz-icon nzType="tool" nzTheme="outline"></i> + é…置龙骨动画 + </button> + </div> + + <div *ngIf="customTypeGroupArr[it.gIdx].animaSmall" align="center" style="margin-top: 5px"> + <button nz-button (click)="setAnimaSmallBtnClick(i)" > + <i nz-icon nzType="tool" nzTheme="outline"></i> + é…置龙骨动画(å°) + </button> + </div> + + + <div *ngIf="customTypeGroupArr[it.gIdx].audio" style="display: flex;align-items: center; margin-top: 5px"> + <app-audio-recorder + style="margin: auto" + [audioUrl]="it.audio_url" + (audioUploaded)="onItemAudioUploadSuccess($event, it)" + ></app-audio-recorder> + </div> + +<!-- <div *ngIf="customTypeGroupArr[it.gIdx]?.action" style="display: flex;align-items: center; margin-top: 5px">--> +<!-- <app-custom-action--> +<!-- style="margin: auto"--> +<!-- [item]="it ? it['actionData_' + it.gIdx] : {}"--> +<!-- [type]="customTypeGroupArr[it.gIdx].action.type"--> +<!-- [option]="customTypeGroupArr[it.gIdx].action.option"--> +<!-- (save)="onSaveCustomAction($event, it)">--> +<!-- ></app-custom-action>--> +<!-- </div>--> + + <div *ngIf="customTypeGroupArr[it.gIdx]?.isShowPos" style="display: flex; align-items: center; justify-content: center; margin-top: 5px;"> + x: <input type="text" nz-input [(ngModel)]="it.posX" style="width: 50px; margin-right: 15px;" (blur)="saveItemPos(it)"> + y: <input type="text" nz-input [(ngModel)]="it.posY" style="width: 50px" (blur)="saveItemPos(it)"> + </div> + + <div *ngIf="customTypeGroupArr[it.gIdx]?.select" align="center" > + <nz-select [(ngModel)]="it.selectType" nzAllowClear nzPlaceHolder="Choose" style="width: 70%; margin-top: 5px;"> + <nz-option *ngFor="let s of customTypeGroupArr[it.gIdx]?.select" [nzValue]="s.value" [nzLabel]="s.label"> + </nz-option> + </nz-select> + </div> + + <div *ngIf="customTypeGroupArr[it.gIdx]?.label" align="center" style="margin-top: 5px; display: flex; align-items: center; justify-content: center;"> + <span style="width: 30%;">{{customTypeGroupArr[it.gIdx].label + ':'}}</span> + <input type="text" nz-input [(ngModel)]="it.labelText" (blur)="saveText(it)"> + </div> + +<!-- <div *ngIf="customTypeGroupArr[it.gIdx]?.mathLabel" align="center" style="margin-top: 5px; display: flex; align-items: center; justify-content: center;">--> +<!-- <span style="width: 30%;">{{customTypeGroupArr[it.gIdx].mathLabel + ':'}}</span>--> +<!-- <app-formula-input [(ngfModel)]="it.mathLabel" ></app-formula-input>--> + +<!-- </div>--> + + + <div *ngIf="customTypeGroupArr[it.gIdx]?.isCopy" align="center" style="margin-top: 5px; display: flex; align-items: center; justify-content: center;"> + <button nz-button (click)="copyItem(it)" > + <i nz-icon nzType="copy" nzTheme="outline"></i> + å¤åˆ¶ç²˜è´´ + </button> + </div> + </div> + + + <!-- <div *ngIf="!customTypeGroupArr"> + + <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 *ngIf="isHasAudio" + style="width: 100%; margin-top: 5px; display: flex; align-items: center; justify-items: center;"> + <app-audio-recorder + style="margin: auto" + [audioUrl]="it.audio_url" + (audioUploaded)="onItemAudioUploadSuccess($event, it)" + ></app-audio-recorder> + </div> + + <div *ngIf="it.itemType == 'rect' && isHasAnima" align="center" style="margin-bottom: 5px"> + <button nz-button (click)="setAnimaBtnClick(i)" > + <i nz-icon nzType="tool" nzTheme="outline"></i> + é…置龙骨动画 + </button> + </div> + + </div> --> + + + </div> </div> @@ -83,12 +193,29 @@ <div class="save-box"> - <button class="save-btn" nz-button nzType="primary" [nzSize]="'large'" nzShape="round" + <button style="margin-left: 200px" class="save-btn" nz-button nzType="primary" [nzSize]="'large'" nzShape="round" (click)="saveClick()" > <i nz-icon nzType="save"></i> Save </button> + <div *ngIf="isCopyData" style="height: 40px; display: flex; justify-items: center;" > + + <label style="margin-left: 40px" nz-checkbox [(ngModel)]="bgItem.isShowDebugLine">显示辅助框</label> + + <button style="margin-left: 20px; margin-top: -5px" nz-button (click)="copyHotZoneData()"> å¤åˆ¶åŸºç¡€æ•°æ® </button> + <div style="margin-left: 10px; margin-top: -5px" > + + <span>粘贴数æ®: </span> + <input style="width: 100px;" type="text" nz-input [(ngModel)]="pasteData" > + <button style="margin-left: 5px;" nz-button [disabled]="pasteData==''" nzType="primary" (click)="importData()">导入</button> + + </div> + + + </div> + + </div> @@ -98,3 +225,52 @@ <label style="opacity: 0; position: absolute; top: 0px; font-family: 'BRLNSR_1'">1</label> +<!--é¾™éª¨é¢æ¿--> +<nz-modal [(nzVisible)]="animaPanelVisible" nzTitle="é…ç½®èµ„æºæ–‡ä»¶" (nzAfterClose)="closeAfterPanel()" (nzOnCancel)="animaPanelCancel()" (nzOnOk)="animaPanelOk()" nzOkText="ä¿å˜"> + + <div class="anima-upload-btn"> + <span style="margin-right: 10px">ä¸Šä¼ ske_json 文件: </span> + <nz-upload [nzShowUploadList]="false" + nzAccept="application/json" + [nzAction]="uploadUrl" + [nzData]="uploadData" + (nzChange)="skeJsonHandleChange($event)"> + <button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button> + </nz-upload> + <i *ngIf="isSkeJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i> + <span *ngIf="skeJsonData['name']" style="margin-left: 10px"><u> {{skeJsonData['name']}} </u></span> + </div> + + <div class="anima-upload-btn"> + <span style="margin-right: 10px">ä¸Šä¼ tex_json 文件: </span> + <nz-upload [nzShowUploadList]="false" + nzAccept="application/json" + [nzAction]="uploadUrl" + [nzData]="uploadData" + (nzChange)="texJsonHandleChange($event)"> + <button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button> + </nz-upload> + <i *ngIf="isTexJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i> + <span *ngIf="texJsonData['name']" style="margin-left: 10px"><u> {{texJsonData['name']}} </u></span> + </div> + + <div class="anima-upload-btn"> + <span style="margin-right: 10px">ä¸Šä¼ tex_png 文件: </span> + <nz-upload [nzShowUploadList]="false" + nzAccept = "image/*" + [nzAction]="uploadUrl" + [nzData]="uploadData" + (nzChange)="texPngHandleChange($event)"> + <button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button> + </nz-upload> + <i *ngIf="isTexPngLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i> + <span *ngIf="texPngData['name']" style="margin-left: 10px"><u> {{texPngData['name']}} </u></span> + </div> + + <div class="anima-upload-btn" *ngIf="customTypeGroupArr && customTypeGroupArr[curDragonBoneGIdx] && customTypeGroupArr[curDragonBoneGIdx].animaNames"> + æç¤ºï¼šéœ€åŒ…å«ä»¥ä¸‹åŠ¨ç”»: {{customTypeGroupArr[curDragonBoneGIdx].animaNames.toString()}} + </div> + +</nz-modal> + + diff --git a/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.scss b/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.scss index 9e2c2bf053571db2d78708132b23fe87e0acc9b2..a8f75bfa284d09475309022adfcd8552a212cea4 100644 --- a/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.scss +++ b/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.scss @@ -81,6 +81,10 @@ } } +.anima-upload-btn { + padding: 10px; +} + h5 { margin-top: 1rem; } @@ -89,8 +93,8 @@ h5 { @font-face { - font-family: 'BRLNSR_1'; - src: url("/assets/font/BRLNSR_1.TTF") ; + font-family: 'ahronbd-1'; + src: url("/assets/font/ahronbd-1.ttf") ; } @@ -105,106 +109,3 @@ h5 { - - -//@import '../../../style/common_mixin'; -// -//.p-image-uploader { -// position: relative; -// display: block; -// width: 100%; -// height: 0; -// padding-bottom: 56.25%; -// .p-box { -// position: absolute; -// left: 0; -// top: 0; -// right: 0; -// bottom: 0; -// border: 2px dashed #ddd; -// border-radius: 0.5rem; -// background-color: #fafafa; -// text-align: center; -// color: #aaa; -// .p-upload-icon { -// text-align: center; -// margin: auto; -// .anticon-upload { -// color: #888; -// font-size: 5rem; -// } -// .p-progress-bar { -// position: relative; -// width: 20rem; -// height: 1.5rem; -// border: 1px solid #ccc; -// border-radius: 1rem; -// .p-progress-bg { -// background-color: #1890ff; -// border-radius: 1rem; -// height: 100%; -// } -// .p-progress-value { -// position: absolute; -// top: 0; -// left: 0; -// width: 100%; -// height: 100%; -// text-shadow: 0 0 4px #000; -// color: white; -// text-align: center; -// font-size: 0.9rem; -// line-height: 1.5rem; -// } -// } -// } -// .p-preview { -// width: 100%; -// height: 100%; -// //background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"); -// @include k-img-bg(); -// } -// } -//} -// -//.p-btn-delete { -// position: absolute; -// right: -0.5rem; -// top: -0.5rem; -// width: 2rem; -// height: 2rem; -// border: 0.2rem solid white; -// border-radius: 50%; -// font-size: 1.2rem; -// background-color: #fb781a; -// color: white; -// text-align: center; -//} -// -//.p-upload-progress-bg { -// position: absolute; -// width: 100%; -// height: 100%; -// display: flex; -// align-items: center; -// justify-content: center; -// & .i-text { -// position: absolute; -// text-align: center; -// color: white; -// text-shadow: 0 0 2px rgba(0, 0, 0, .85); -// } -// & .i-bg { -// position: absolute; -// left: 0; -// top: 0; -// height: 100%; -// background-color: #27b43f; -// border-radius: 0.5rem; -// } -//} -// -// -//:host ::ng-deep .ant-upload { -// display: block; -//} diff --git a/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.ts b/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.ts index dc2a4cf04d4592cc6a399cf5708c713dbb3439fd..f6e01c38dcb9a59cfc50cf9cb13be60afe312284 100644 --- a/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.ts +++ b/form_angular/src/app/common/custom-hot-zone/custom-hot-zone.component.ts @@ -1,4 +1,6 @@ import { + ApplicationRef, + ChangeDetectorRef, Component, ElementRef, EventEmitter, @@ -12,10 +14,11 @@ import { } from '@angular/core'; import {Subject} from 'rxjs'; import {debounceTime} from 'rxjs/operators'; -import {EditorItem, HotZoneImg, HotZoneItem, HotZoneLabel, Label, MySprite, removeItemFromArr} from './Unit'; +import {DragItem, EditorItem, HotZoneImg, HotZoneItem, HotZoneLabel, Label, MySprite, removeItemFromArr, ShapeRect, ShapeRectNew} from './Unit'; import TWEEN from '@tweenjs/tween.js'; -import {getMinScale} from "../../play/Unit"; -import {tar} from "compressing"; +import {getMinScale} from '../../play/Unit'; +import {tar} from 'compressing'; +import {NzMessageService} from 'ng-zorro-antd'; @Component({ @@ -25,18 +28,14 @@ import {tar} from "compressing"; }) export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { + @ViewChild('canvas', {static: true}) canvas: ElementRef; + @ViewChild('wrap', {static: true}) wrap: ElementRef; + - @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() @@ -44,16 +43,31 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { @Input() isHasText = true; @Input() - hotZoneFontObj = { - size: 50, - name: 'BRLNSR_1', - color: '#8f3758' - } + isHasAudio = true; + @Input() + isHasAnima = false; + @Input() + customTypeGroupArr; // [{name:string, rect:boolean, pic:boolean, text:boolean, audio:boolean, anima:boolean, animaNames:['name1', ..]}, ...] + @Input() + // hotZoneFontObj; + @Input() + isCopyData = false; + + hotZoneFontObj; + // hotZoneFontObj = { + // size: 50, + // name: 'ahronbd-1', + // color: '#8f3758' + // } @Input() defaultItemType = 'text'; - @Input() - hotZoneImgSize = 190; + hotZoneImgSize = 0; + + + @Output() + save = new EventEmitter(); + saveDisabled = true; @@ -86,8 +100,43 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { changeSizeFlag = false; changeTopSizeFlag = false; changeRightSizeFlag = false; - - constructor() { + animaPanelVisible = false; + + uploadUrl; + uploadData; + skeJsonData = {}; + texJsonData = {}; + texPngData = {}; + animaName = ''; + curDragonBoneIndex; + curDragonBoneGIdx; + pasteData = ''; + + isSkeJsonLoading = false; + isTexJsonLoading = false; + isTexPngLoading = false; + + isAnimaSmall = false; + + savePropertyArr = [ + 'id', + 'gIdx', + 'selectType', + 'labelText', + 'posX', + 'posY', + 'mathLabel', + ] + + + constructor(private nzMessageService: NzMessageService, private appRef: ApplicationRef, private changeDetectorRef: ChangeDetectorRef) { + this.uploadUrl = (<any> window).courseware.uploadUrl(); + this.uploadData = (<any> window).courseware.uploadData(); + + window['air'].getUploadCallback = (url, data) => { + this.uploadUrl = url; + this.uploadData = data; + }; } _bgItem = null; @@ -110,11 +159,14 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { ngOnInit() { + this.initListener(); // this.init(); this.update(); + this.refresh(); + } ngOnDestroy() { @@ -136,10 +188,12 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { onItemImgUploadSuccess(e, item) { item.pic_url = e.url; this.loadHotZonePic(item.pic, e.url); + this.refresh(); } onItemAudioUploadSuccess(e, item) { item.audio_url = e.url; + this.refresh(); } @@ -150,37 +204,61 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { this.renderArr.push(this.bg); } + if (!this.bgItem.url) { + this.bgItem.url = 'http://teach.cdn.ireadabc.com/8ebb1858564340ea0936b83e3280ad7d.jpg'; + } + const bg = this.bg; - if (this.bgItem.url) { + // if (this.bgItem.url) { - bg.load(this.bgItem.url).then(() => { - const rate1 = this.canvasWidth / bg.width; - const rate2 = this.canvasHeight / bg.height; + bg.load(this.bgItem.url).then(() => { + const rate1 = this.canvasWidth / bg.width; + const rate2 = this.canvasHeight / bg.height; - const rate = Math.min(rate1, rate2); - bg.setScaleXY(rate); + const rate = Math.min(rate1, rate2); + bg.setScaleXY(rate); + + bg.x = this.canvasWidth / 2; + bg.y = this.canvasHeight / 2; + bg.removeChildren(); - bg.x = this.canvasWidth / 2; - bg.y = this.canvasHeight / 2; + const bgBorder = new ShapeRectNew(this.ctx); + bgBorder.setSize(bg.width, bg.height, 0); + bgBorder.fillColor = '#ff0000'; + bgBorder.fill = false; + bgBorder.stroke = true; + bgBorder.x = -bg.width / 2; + bgBorder.y = -bg.height / 2; + bgBorder.lineWidth = 0.5; + bg.addChild(bgBorder); - if (callBack) { - callBack(); - } - }); - } + + if (callBack) { + callBack(); + } + + this.refresh(); + + }); + // } } - addBtnClick() { + addBtnClick(data=null) { // this.imgArr.push({}); // this.hotZoneArr.push({}); - const item = this.getHotZoneItem(); + const item = this.getHotZoneItem(data); this.hotZoneArr.push(item); - this.refreshItem(item); + + if (this.customTypeGroupArr) { + this.refreshCustomItem(item); + } else { + this.refreshItem(item); + } this.refreshHotZoneId(); @@ -191,6 +269,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { const item = this.hotZoneArr.splice(index, 1)[0]; removeItemFromArr(this.renderArr, item.pic); removeItemFromArr(this.renderArr, item.textLabel); + removeItemFromArr(this.renderArr, item.drag); this.refreshHotZoneId(); @@ -199,6 +278,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { onImgUploadSuccessByImg(e, img) { img.pic_url = e.url; this.refreshImage(img); + this.refresh(); } refreshImage(img) { @@ -221,6 +301,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { } } + this.refresh(); } @@ -245,10 +326,18 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { item.anchorX = 0.5; item.anchorY = 0.5; + item.x = this.canvasWidth / 2; item.y = this.canvasHeight / 2; - item.itemType = this.defaultItemType; + item.itemType = this.getDefaultItemType(); + item.gIdx = '0'; + + + item['id'] = this.createItemId() // new Date().getTime().toString(); + item['data'] = saveData; + + console.log('item.x: ', item.x); if (saveData) { @@ -257,41 +346,203 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { item.scaleY = saveRect.height / item.height; item.x = saveRect.x + saveRect.width / 2; item.y = saveRect.y + saveRect.height / 2; + item.gIdx = saveData.gIdx; + + item['id'] = saveData.id; + item['skeJsonData'] = saveData.skeJsonData; + item['texJsonData'] = saveData.texJsonData; + item['texPngData'] = saveData.texPngData; + + + item['actionData_' + item.gIdx] = saveData['actionData_' + item.gIdx]; + + this.savePropertyArr.forEach((key) => { + if (saveData[key]) { + item[key] = saveData[key]; + } + }) + } + console.log('item.x:~~ ', item.x); + item.showLineDash(); - const pic = new HotZoneImg(this.ctx); + // const pic = new HotZoneImg(this.ctx); + + + this.setItemPic(item, saveData); + + this.setItemLabel(item, saveData); + + this.setItemAnima(item, saveData); + + this.setItemDrag(item, saveData); + + + return item; + } + + setItemPic(item, saveData) { + + console.log('in setItemPic ', saveData); + const pic = new EditorItem(this.ctx); pic.visible = false; item['pic'] = pic; - if (saveData && saveData.pic_url) { - this.loadHotZonePic(pic, saveData.pic_url); + if (saveData) { + + let picUrl = saveData.pic_url; + const actionData = saveData['actionData_' + item.gIdx]; + if (actionData && actionData.type == 'pic') { + picUrl = actionData.pic_url; + } + + console.log('saveData: ', saveData); + console.log('picUrl: ', picUrl); + + if (picUrl) { + this.loadHotZonePic(pic, picUrl, saveData.imgScale); + } } + pic.x = item.x; pic.y = item.y; this.renderArr.push(pic); + } + + + setItemDrag(item, saveData) { + + console.log('in setItemDrag ', saveData); + const dragItem = new DragItem(this.ctx); + dragItem.init(); + dragItem.item = item; + item['drag'] = dragItem; + + dragItem.visible = false; + + dragItem.x = item.x; + dragItem.y = item.y; + this.renderArr.push(dragItem); + + if (saveData) { + if (saveData.dragDot) { + dragItem.x = saveData.dragDot.x / saveData.mapScale * this.mapScale; + dragItem.y = saveData.dragDot.y / saveData.mapScale * this.mapScale; + } + } + + + // console.log('item.itemType: ', item.itemType); + // let w = item.width; + // let h = item.height; + // if (saveData) { + // switch (saveData.itemType) { + // case 'rect': + // w = saveData.rect.width; + // h = saveData.rect.height; + // break; + // case 'pic': + // w = saveData.imgSizeW * saveData.imgScale; + // h = saveData.imgSizeH * saveData.imgScale;; + // break; + // case 'text': + // w = saveData.rect.width; + // h = saveData.rect.height; + // break; + // } + // } + + // dragItem.setSize(w, h); + + + + } + + setItemAnima(item, saveData) { + console.log('in setItemAnima ', saveData); + // const pic = new EditorItem(this.ctx); + // pic.visible = false; + // item['pic'] = pic; + // if (saveData) { + + // let picUrl = saveData.pic_url; + // const actionData = saveData['actionData_' + item.gIdx]; + // if (actionData && actionData.type == 'pic') { + // picUrl = actionData.pic_url; + // } + + // console.log('saveData: ', saveData); + // console.log('picUrl: ', picUrl); + + // if (picUrl) { + // this.loadHotZonePic(pic, picUrl, saveData.imgScale); + // } + // } + + // pic.x = item.x; + // pic.y = item.y; + // this.renderArr.push(pic); + } + + + setItemLabel(item, saveData) { const textLabel = new HotZoneLabel(this.ctx); - textLabel.fontSize = this.hotZoneFontObj.size; - textLabel.fontName = this.hotZoneFontObj.name; - textLabel.fontColor = this.hotZoneFontObj.color; + if (this.hotZoneFontObj) { + 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; + if (saveData) { + + if (saveData.text && this.hotZoneFontObj) { + textLabel.text = saveData.text + } + + this.setActionFont(textLabel, saveData['actionData_' + item.gIdx]); textLabel.refreshSize(); + } textLabel.x = item.x; textLabel.y = item.y; this.renderArr.push(textLabel); + } - return item; + setActionFont(textLabel, actionData) { + if (actionData && actionData.type == 'text') { + + textLabel.text = actionData.text; + + for (let i=0; i<actionData.changeOption.length; i++) { + const op = actionData.changeOption[i]; + textLabel[op[0]] = op[1]; + } + } } + getDefaultItemType() { + if (this.customTypeGroupArr) { + const group = this.customTypeGroupArr[0]; + if (group.rect) { + return 'rect'; + } + if (group.pic) { + return 'pic'; + } + if (group.text) { + return 'text'; + } + } else { + return this.defaultItemType; + } + } getPicItem(img, saveData = null) { @@ -327,9 +578,11 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { item.y = saveRect.y + saveRect.height / 2; } else { - item.showLineDash(); + // item.showLineDash(); } + item.showLineDash(); + console.log('aaa'); }); return item; } @@ -337,6 +590,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { onAudioUploadSuccessByImg(e, img) { img.audio_url = e.url; + this.refresh(); } deleteItem(e, i) { @@ -345,15 +599,111 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { this.hotZoneArr.splice(i, 1); this.refreshHotZoneId(); + this.refresh(); } + + + // radioChange(e, item) { + // item.itemType = e; - radioChange(e, item) { - item.itemType = e; + // this.refreshItem(item); + // this.refresh(); + // // console.log(' in radioChange e: ', e); + // } - this.refreshItem(item); + customRadioChange(e, item) { + + console.log('in customRadioChange', e); + item.gIdx = -1; + setTimeout(() => { + item.gIdx = e; + this.refreshCustomItem(item); + this.refresh(); + }, 1); + + // const curGroup = this.customTypeGroupArr[e]; - // console.log(' in radioChange e: ', e); + } + + refreshCustomItem(item) { + this.hideHotZoneItem(item); + const group = this.customTypeGroupArr[item.gIdx]; + if (!group) { + return; + } + + if (group.text) { + this.showItemLabel(item); + } + + if (group.rect) { + this.showItemRect(item, !group.isFixed); + } + + if (group.pic && !group.anima) { + this.showItemPic(item); + } + + if (group.action) { + if (group.action.type == 'pic') { + this.showItemPic(item); + } + if (group.action.type == 'text') { + this.showItemLabel(item); + } + if (group.action.type == 'anima') { + this.showItemRect(item); + } + } + + item.drag.visible = group.drag; + + item.setAnimaStyle(group.animaSmall) + + + } + + showItemDrag(item) { + item.drag.visible = true; + // item.dragBody.visible = true; + // item.itemType = 'pic'; + // this.showArrowTop(item) + } + + + showItemPic(item) { + item.pic.visible = true; + item.itemType = 'pic'; + this.showArrowTop(item, true) + } + + showItemLabel(item) { + item.textLabel.visible = true; + item.itemType = 'text'; + this.showArrowTop(item) + } + + showItemRect(item, isShowArrowTop = true) { + item.visible = true; + item.itemType = 'rect'; + this.showArrowTop(item, isShowArrowTop) + } + + showArrowTop(item, isShowArrowTop = false) { + if (isShowArrowTop) { + item.arrowTop.visible = true; + item.arrowRight.visible = true; + } else { + item.arrowTop.visible = false; + item.arrowRight.visible = false; + } + } + + hideHotZoneItem(item) { + item.visible = false; + item.pic.visible = false; + item.textLabel.visible = false; } refreshItem(item) { @@ -368,33 +718,30 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { this.setTextState(item); break; default: - + this.setNoneState(item); } } init() { + console.log('init'); this.initData(); this.initCtx(); - this.initItem(); } initItem() { + + this.changeDetectorRef.markForCheck(); + this.changeDetectorRef.detectChanges(); + if (!this.bgItem) { this.bgItem = {}; } else { this.refreshBackground(() => { - - // if (!this.imgItemArr) { - // this.imgItemArr = []; - // } else { - // this.initImgArr(); - // } - - // console.log('aaaaa'); - + + if (!this.hotZoneItemArr) { this.hotZoneItemArr = []; } else { @@ -404,6 +751,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { }); } + this.refresh(); } initHotZoneArr() { @@ -427,6 +775,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { this.hotZoneArr = []; const arr = this.hotZoneItemArr.concat(); + console.log('this.hotZoneItemArr: ', this.hotZoneItemArr); for (let i = 0; i < arr.length; i++) { const data = JSON.parse(JSON.stringify(arr[i])); @@ -449,9 +798,15 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { item.pic_url = data.pic_url; item.text = data.text; item.itemType = data.itemType; - this.refreshItem(item); - console.log('item: ', item); + if (this.customTypeGroupArr) { + this.refreshCustomItem(item); + } else { + this.refreshItem(item); + } + + + console.log('1 item: ', item); this.hotZoneArr.push(item); } @@ -463,48 +818,6 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { } - 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}; - } - - let oldBgRect = this.bgItem.rect; - if (!oldBgRect) { - oldBgRect = curBgRect; - } - - 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}; - - 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); - } - this.refreshImageId(); - } - - initData() { this.canvasWidth = this.wrap.nativeElement.clientWidth; @@ -528,9 +841,28 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { this.oldPos = {x: this.mx, y: this.my}; - for (let i = 0; i < this.hotZoneArr.length; i++) { + + // 先检测拖拽点 + for (let i = this.hotZoneArr.length - 1; i >= 0; i--) { + + const item = this.hotZoneArr[i]; + + if (item && item.drag && item.drag.visible) { + + if (this.checkClickTarget(item.drag)) { + + this.clickedDragPoint(item.drag); + return; + } + } + } + + for (let i = this.hotZoneArr.length - 1; i >= 0; i--) { + const item = this.hotZoneArr[i]; + + console.log('mapDown item: ', item); let callback; let target; switch (item.itemType) { @@ -548,7 +880,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { break; } - if (this.checkClickTarget(target)) { + if (target && this.checkClickTarget(target)) { callback(target); return; } @@ -578,15 +910,18 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { const addY = this.my - this.oldPos.y; this.curItem.x += addX; this.curItem.y += addY; + + this.curItem.posX = this.curItem.x; + this.curItem.posY = this.curItem.y; } this.oldPos = {x: this.mx, y: this.my}; - this.saveDisabled = true; + // this.saveDisabled = false; } - mapUp(event) { + mapUp(event=null) { this.curItem = null; this.changeSizeFlag = false; this.changeTopSizeFlag = false; @@ -685,10 +1020,13 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { changeCurItem(item) { + console.log(' in changeCurItem', item) + this.hideAllLineDash(); this.curItem = item; this.curItem.showLineDash(); + } hideAllLineDash() { @@ -711,9 +1049,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { // 清除画布内容 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; @@ -722,8 +1058,16 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { // } // } + for (let i = 0; i < this.renderArr.length; i++) { + this.renderArr[i].update(this); + } + this.updateArr(this.hotZoneArr); - this.updatePos() + + + + this.updatePos(); + TWEEN.update(); @@ -833,7 +1177,9 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { checkClickTarget(target) { - + if (!target || !target.visible) { + return; + } const rect = target.getBoundingBox(); if (this.checkPointInRect(this.mx, this.my, rect)) { return true; @@ -852,9 +1198,21 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { saveClick() { + + const sendData = this.getSendData(); + this.save.emit(sendData); + } + + getSendData() { + const bgItem = this.bgItem; if (this.bg) { - bgItem['rect'] = this.bg.getBoundingBox(); + const rect = this.bg.getBoundingBox(); + bgItem['rect'] = rect; + rect.x = Math.round(rect.x * 100) / 100; + rect.y = Math.round(rect.y * 100) / 100; + rect.width = Math.round(rect.width * 100) / 100; + rect.height = Math.round(rect.height * 100) / 100; } else { bgItem['rect'] = { x: 0, @@ -870,19 +1228,52 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { for (let i = 0; i < hotZoneArr.length; i++) { const hotZoneItem = { + id: hotZoneArr[i].id, 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 + imgSizeW: hotZoneArr[i].pic ? hotZoneArr[i].pic.width : 0, + imgSizeH: hotZoneArr[i].pic ? hotZoneArr[i].pic.height : 0, + mapScale: this.mapScale, + skeJsonData: hotZoneArr[i].skeJsonData, + texJsonData: hotZoneArr[i].texJsonData, + texPngData: hotZoneArr[i].texPngData, + dragDot: hotZoneArr[i].drag.getPosition(), + gIdx: hotZoneArr[i].gIdx, }; - hotZoneItem['rect'] = hotZoneArr[i].getBoundingBox(); + + this.savePropertyArr.forEach((key) => { + if (hotZoneArr[i][key]) { + hotZoneItem[key] = hotZoneArr[i][key]; + } + }) + + hotZoneItem['actionData_' + hotZoneItem.gIdx] = hotZoneArr[i]['actionData_' + hotZoneArr[i].gIdx] + + + if (this.hotZoneFontObj) { + hotZoneItem['fontSize'] = this.hotZoneFontObj.size; + hotZoneItem['fontName'] = this.hotZoneFontObj.name; + hotZoneItem['ontColor'] = this.hotZoneFontObj.color; + } + + + if (hotZoneArr[i].itemType == 'pic') { + hotZoneItem['rect'] = hotZoneArr[i].pic.getBoundingBox(); + } else if (hotZoneArr[i].itemType == 'text') { + hotZoneArr[i].textLabel.refreshSize(); + hotZoneItem['rect'] = hotZoneArr[i].textLabel.getLabelRect(); + // hotZoneItem['rect'].width = hotZoneItem['rect'].width / hotZoneArr[i].textLabel.scaleX; + // hotZoneItem['rect'].height = hotZoneArr[i].textLabel.height * hotZoneArr[i].textLabel.scaleY; + + } else { + hotZoneItem['rect'] = hotZoneArr[i].getBoundingBox(); + } + // hotZoneItem['rect'] = hotZoneArr[i].getBoundingBox(); hotZoneItem['rect'].x = Math.round((hotZoneItem['rect'].x - bgItem['rect'].x) * 100) / 100; hotZoneItem['rect'].y = Math.round((hotZoneItem['rect'].y - bgItem['rect'].y) * 100) / 100; hotZoneItem['rect'].width = Math.round((hotZoneItem['rect'].width) * 100) / 100; @@ -894,7 +1285,360 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { console.log('hotZoneItemArr: ', hotZoneItemArr); - this.save.emit({bgItem, hotZoneItemArr}); + return {bgItem, hotZoneItemArr}; + } + + saveText(item) { + if (item.itemType == 'text') { + item.textLabel.text = item.text; + } + } + + saveItemPos(item) { + + console.log('item.posX: ', item.posX) + console.log('item.posY: ', item.posY) + + item.x = Number(item.posX || 0) + item.y = Number(item.posY || 0) + + + + // this.changeCurItem(item); + + + + // this.curItem.x = item.posX || 0; + // this.curItem.y = item.posY || 0; + + // this.mapUp(); + + + } + + onSaveCustomAction(e, item) { + + const data = e; + item['actionData_' + item.gIdx] = data; + + if (data.type == 'pic') { + let picUrl = data.pic_url; + if (picUrl) { + this.loadHotZonePic(item.pic, picUrl); + } + } + + if (data.type == 'text') { + this.setActionFont(item.textLabel, data); + item.textLabel.refreshSize(); + } + + // if (data.type == 'anima') { + // this.setActionAnima(item.anima, data); + // } + + // this.loadHotZonePic(item.pic, e.url); + this.refresh() + } + + setActionAnima() { + + } + + + setAnimaBtnClick(index) { + + console.log('aaaa') + this.isAnimaSmall = false; + + this.setCurDragonBone(index); + + // this.curDragonBoneIndex = index; + // this.curDragonBoneGIdx = Number(this.hotZoneArr[index].gIdx); + + // const {skeJsonData, texJsonData, texPngData} = this.hotZoneArr[index]; + + // this.skeJsonData = skeJsonData || {}; + // this.texJsonData = texJsonData || {}; + // this.texPngData = texPngData || {}; + + // this.animaPanelVisible = true; + + // this.refresh(); + } + + + setAnimaSmallBtnClick(index) { + + + console.log('bbb') + this.isAnimaSmall = true; + + this.setCurDragonBone(index); + + } + + setCurDragonBone(index) { + this.curDragonBoneIndex = index; + this.curDragonBoneGIdx = Number(this.hotZoneArr[index].gIdx); + + const {skeJsonData, texJsonData, texPngData} = this.hotZoneArr[index]; + + this.skeJsonData = skeJsonData || {}; + this.texJsonData = texJsonData || {}; + this.texPngData = texPngData || {}; + + this.animaPanelVisible = true; + + this.refresh(); + } + + setItemSizeByAnima(jsonData, item) { + console.log('json: ', jsonData); + + const request = new XMLHttpRequest(); + //通过urlèŽ·å–æ–‡ä»¶ï¼Œç¬¬äºŒä¸ªé€‰é¡¹æ˜¯æ–‡ä»¶æ‰€åœ¨çš„å…·ä½“åœ°å€ + request.open('GET', jsonData.url, true); + request.send(null); + request.onreadystatechange = ()=> { + if (request.readyState === 4 && request.status === 200) { + var type = request.getResponseHeader('Content-Type'); + if (type.indexOf("text") !== 1) { + //返回一个文件内容的对象 + + const data = JSON.parse(request.responseText); + console.log('request.responseText;', data) + const animaSize = data.armature[0].canvas; + item.width = animaSize.width; + item.height = animaSize.height; + // return request.responseText; + } + } + } + } + + animaPanelCancel() { + this.animaPanelVisible = false; + this.refresh(); + } + + animaPanelOk() { + + this.setItemDragonBoneData(this.hotZoneArr[this.curDragonBoneIndex]); + console.log('this.hotZoneArr: ', this.hotZoneArr); + this.animaPanelVisible = false; + + if (this.isAnimaSmall) { + this.setItemSizeByAnima(this.skeJsonData, this.hotZoneArr[this.curDragonBoneIndex]); + } + + this.refresh(); + } + + setItemDragonBoneData(item) { + item['skeJsonData'] = this.skeJsonData; + item['texJsonData'] = this.texJsonData; + item['texPngData'] = this.texPngData; + } + + skeJsonHandleChange(e) { + console.log('e: ', e); + switch (e.type) { + case 'start': + this.isSkeJsonLoading = true; + break; + + case 'success': + this.skeJsonData['url'] = e.file.response.url; + this.skeJsonData['name'] = e.file.name; + this.nzMessageService.success('ä¸Šä¼ æˆåŠŸ'); + this.isSkeJsonLoading = false; + break; + + case 'progress': + break; + } + } + + texJsonHandleChange(e) { + console.log('e: ', e); + switch (e.type) { + case 'start': + this.isTexJsonLoading = true; + break; + + case 'success': + this.texJsonData['url'] = e.file.response.url; + this.texJsonData['name'] = e.file.name; + this.nzMessageService.success('ä¸Šä¼ æˆåŠŸ'); + this.isTexJsonLoading = false; + break; + + case 'progress': + break; + } + } + + texPngHandleChange(e) { + console.log('e: ', e); + switch (e.type) { + case 'start': + this.isTexPngLoading = true; + break; + + case 'success': + this.texPngData['url'] = e.file.response.url; + this.texPngData['name'] = e.file.name; + this.nzMessageService.success('ä¸Šä¼ æˆåŠŸ'); + this.isTexPngLoading = false; + break; + + case 'progress': + break; + } + } + + copyItem(it) { + + const {hotZoneItemArr} = this.getSendData(); + let itemData; + hotZoneItemArr.forEach((data) => { + if (data.id == it.id) { + itemData = data; + } + }) + + + let curBgRect; + if (this.bg) { + curBgRect = this.bg.getBoundingBox(); + } else { + 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); + + + const data = itemData + + 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; + + + 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.hotZoneArr.push(item); + + if (this.customTypeGroupArr) { + this.refreshCustomItem(item); + } else { + this.refreshItem(item); + } + + this.refreshHotZoneId(); + + item['id'] = this.createItemId(); + + } + + createItemId() { + return new Date().getTime().toString(); + } + + copyHotZoneData() { + + const {bgItem, hotZoneItemArr} = this.getSendData(); + + // const hotZoneItemArrNew = []; + // const tmpArr = JSON.parse(JSON.stringify(hotZoneItemArr)); + // tmpArr.forEach((item) => { + // if (item.gIdx === '0') { + // hotZoneItemArr.push(item); + // } + // }) + + const jsonData = { + bgItem, + hotZoneItemArr, + isHasRect: this.isHasRect, + isHasPic: this.isHasPic, + isHasText: this.isHasText, + isHasAudio: this.isHasAudio, + isHasAnima: this.isHasAnima, + hotZoneFontObj: this.hotZoneFontObj, + defaultItemType: this.defaultItemType, + hotZoneImgSize: this.hotZoneImgSize, + }; + + + const oInput = document.createElement('input'); + oInput.value = JSON.stringify(jsonData); + document.body.appendChild(oInput); + oInput.select(); // 选择对象 + document.execCommand('Copy'); // 执行æµè§ˆå™¨å¤åˆ¶å‘½ä»¤ + + document.body.removeChild(oInput); + this.nzMessageService.success('å¤åˆ¶æˆåŠŸ'); + // alert('å¤åˆ¶æˆåŠŸ'); + + + } + + importData() { + if (!this.pasteData) { + return; + } + + + try { + const data = JSON.parse(this.pasteData); + console.log('data:', data); + const { + bgItem, + hotZoneItemArr, + isHasRect, + isHasPic, + isHasText, + isHasAudio, + isHasAnima, + hotZoneFontObj, + defaultItemType, + hotZoneImgSize, + } = data; + + this.hotZoneItemArr = hotZoneItemArr; + this.isHasRect = isHasRect; + this.isHasPic = isHasPic; + this.isHasText = isHasText; + this.isHasAudio = isHasAudio; + this.isHasAnima = isHasAnima; + this.hotZoneFontObj = hotZoneFontObj; + this.defaultItemType = defaultItemType; + this.hotZoneImgSize = hotZoneImgSize; + + this.bgItem = bgItem; + + this.pasteData = ''; + } catch (e) { + console.log('err: ', e); + this.nzMessageService.error('导入失败'); + } } private updatePos() { @@ -917,12 +1661,15 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { break; } - item.x = x; - item.y = y; - item.pic.x = x; - item.pic.y = y; - item.textLabel.x = x; - item.textLabel.y = y; + if (x != undefined && y != undefined) { + item.x = x; + item.y = y; + item.pic.x = x; + item.pic.y = y; + item.textLabel.x = x; + item.textLabel.y = y; + } + }); } @@ -944,6 +1691,12 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { item.textLabel.visible = true; } + private setNoneState(item: any) { + item.visible = false; + item.pic.visible = false; + item.textLabel.visible = false; + } + private clickedHotZoneRect(item: any) { if (this.checkClickTarget(item)) { @@ -962,6 +1715,17 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { private clickedHotZonePic(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); + } + this.curItem = item; } } @@ -972,15 +1736,42 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { } } - saveText(item) { - item.textLabel.text = item.text; + clickedDragPoint(item) { + this.curItem = item; } - private loadHotZonePic(pic: HotZoneImg, url) { - const baseLen = this.hotZoneImgSize * this.mapScale; + private loadHotZonePic(pic: HotZoneImg, url, scale = null) { + + let baseLen; + if (this.hotZoneImgSize) { + baseLen = this.hotZoneImgSize * this.mapScale; + } + pic.load(url).then(() => { - const s = getMinScale(pic, baseLen); - pic.setScaleXY(s); + if (!scale) { + if (baseLen) { + scale = getMinScale(pic, baseLen); + } else { + scale = this.bg.scaleX; + } + } + + pic.setScaleXY(scale); }); } + + + closeAfterPanel() { + this.refresh(); + } + /** + * 刷新 æ¸²æŸ“é¡µé¢ + */ + refresh() { + setTimeout(() => { + this.appRef.tick(); + }, 1); + } + + } diff --git a/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.html b/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.html index 935479752d531c52e99fa7bfb39b36d49dcc06fc..d4eb2974f68e12d5423308984d0fbf8b4f3a488e 100644 --- a/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.html +++ b/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.html @@ -1,7 +1,7 @@ -<div class="position-relative"> +<div class="position-relative" (drop)="handle_drop($event)" (dragover)="handle_dragover($event)"> - <button nz-button (click)="setAnimaBtnClick()" style=" border-radius: 0.5rem; border: 1px solid #ddd;"> + <button nz-button (click)="setAnimaBtnClick()" style=" border-radius: 0.5rem; border: 1px solid #ddd;" (dragover)="handle_dragover($event)"> <i nz-icon nzType="tool" nzTheme="outline"></i> {{btnName}} </button> diff --git a/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.ts b/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.ts index a99c3e4cf7ff4618296ff2f64c0f081e4aaef1e7..a5945671e147747b9d26d319405e58d1a4869bee 100644 --- a/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.ts +++ b/form_angular/src/app/common/upload-dragon-bone/upload-dragon-bone.component.ts @@ -178,4 +178,43 @@ export class UploadDragonBoneComponent implements OnDestroy, OnChanges { ngOnDestroy() { } + linkInputed (ske, tex, png) { + this.skeJsonData["url"] = ske.url; + this.skeJsonData["name"] = ske.name; + this.texJsonData["url"] = tex.url; + this.texJsonData["name"] = tex.name; + this.texPngData["url"] = png.url; + this.texPngData["name"] = png.name; + + this.animaPanelOk(); + } + + handle_dragover(e) { + e.preventDefault(); + } + + handle_drop(e) { + e.preventDefault(); + const dt = e.dataTransfer.getData("text/plain"); + console.log("handle_drop===", dt); + if (!dt) { + return; + } + try { + const {ske, tex, png} = JSON.parse(dt); + if (!ske || !tex || !png || + ske.url.indexOf("teach")<0 || ske.url.indexOf("cdn")<0 || ske.url.indexOf(".json")<0 || + tex.url.indexOf("teach")<0 || tex.url.indexOf("cdn")<0 || tex.url.indexOf(".json")<0 || + png.url.indexOf("teach")<0 || png.url.indexOf("cdn")<0 || png.url.indexOf(".png")<0 || + !ske.name || !tex.name || !png.name + ) { + console.warn("handle_dropæ‹–æ‹½åœ¨çº¿éª¨éª¼åŠ¨ç”»ä¼ é€’å‚æ•°ä¸åˆæ³•,应该是{ske:{url:'', name:''},tex:{url:'', name:''},png:{url:'', name:''}}"); + return; + } + this.linkInputed(ske, tex, png); + } catch (error) { + console.warn("handle_dropæ‹–æ‹½åœ¨çº¿éª¨éª¼åŠ¨ç”»ä¼ é€’å‚æ•°ä¸åˆæ³•,应该是{ske:{url:'', name:''},tex:{url:'', name:''},png:{url:'', name:''}}"); + } + } + } diff --git a/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html b/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html index b5c26bb34504cb78bc873f9e811802831b5f348e..8c3dc152c2ffd8a9b35c25d350505edc156f1af7 100644 --- a/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html +++ b/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html @@ -1,10 +1,12 @@ -<div class="position-relative"> +<div class="position-relative" (drop)="handle_drop($event)" (dragover)="handle_dragover($event)"> <nz-upload class="p-image-uploader" [nzDisabled]="disableUpload" [nzShowUploadList]="false" nzAccept = "image/*" [nzAction]="uploadUrl" [nzData]="uploadData" - (nzChange)="handleChange($event)"> + (nzChange)="handleChange($event)" + + > <!--[nzBeforeUpload]="customUpload">--> <div class="p-box d-flex align-items-center"> <div class="p-upload-icon" *ngIf="!picUrl && !uploading"> diff --git a/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts b/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts index f4694a1f1ae4b582b3c121e601c6322437888820..6068dcef79aec6e6e0d06faca774c08d1ecd2fee 100644 --- a/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts +++ b/form_angular/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts @@ -155,4 +155,39 @@ export class UploadImageWithPreviewComponent implements OnDestroy, OnChanges { ngOnDestroy() { } + linkInputed (url) { + const file = { + response: {url} + }; + const img = new Image(); + img.addEventListener('load', () => { + const height = img.naturalHeight; + const width = img.naturalWidth; + file['height'] = height; + file['width'] = width; + img.remove(); + this.imageUploaded.emit(file.response); + }); + img.src = url; + this.picUrl = url; + } + + handle_dragover(e) { + e.preventDefault(); + } + + handle_drop(e) { + const dt = e.dataTransfer.getData("text/plain"); + console.log("handle_drop===", dt); + if (!dt || dt.indexOf("teach")<0 || dt.indexOf("cdn")<0) { + return; + } + const white = [".jpg", ".jpeg", ".png", ".bmp", ".JPG", ".JPEG", ".PNG", ".BMP"]; + if (!white.includes(dt.substr(dt.lastIndexOf(".")))) { + return; + } + + this.linkInputed(dt); + } + } diff --git a/form_angular/src/app/common/upload-video/upload-video.component.html b/form_angular/src/app/common/upload-video/upload-video.component.html index 8f1533993f2bdcf3d5f3e0cd4337f3fa96a1ebd7..95303c4abf82c5f1dd72e0cf8d19550fa53867f0 100644 --- a/form_angular/src/app/common/upload-video/upload-video.component.html +++ b/form_angular/src/app/common/upload-video/upload-video.component.html @@ -1,21 +1,16 @@ -<div class="p-video-box"> -<div class="up-video" style="display: flex;"> - <!--<nz-upload class="" [nzDisabled]="!showUploadBtn"--> - <!--[nzShowUploadList]="false"--> - <!--[nzBeforeUpload]="beforeUpload"--> - <!--nzAccept = ".mp4"--> - <!--style="margin-right: 1rem">--> +<div class="p-video-box" (drop)="handle_drop($event)" (dragover)="handle_dragover($event)"> + <div class="up-video" style="display: flex;"> + <!--<nz-upload class="" [nzDisabled]="!showUploadBtn"--> + <!--[nzShowUploadList]="false"--> + <!--[nzBeforeUpload]="beforeUpload"--> + <!--nzAccept = ".mp4"--> + <!--style="margin-right: 1rem">--> - <nz-upload class="p-image-uploader" [nzDisabled]="uploading" - [nzShowUploadList]="false" - nzAccept = ".mp4" - [nzAction]="uploadUrl" - [nzData]="uploadData" - (nzChange)="handleChange($event)" - style="margin-right: 1rem"> + <nz-upload class="p-image-uploader" [nzDisabled]="uploading" [nzShowUploadList]="false" nzAccept=".mp4" + [nzAction]="uploadUrl" [nzData]="uploadData" (nzChange)="handleChange($event)" style="margin-right: 1rem"> <button type="button" nz-button nzType="default" *ngIf="showUploadBtn" [disabled]="uploading" - [nzLoading]="uploading" > + [nzLoading]="uploading"> <i nz-icon nzType="plus" nzTheme="outline"></i> <span>{{ uploading ? 'Uploading' : 'Select Video' }}</span> <!--<span>Select Video</span>--> @@ -25,14 +20,14 @@ </nz-upload> - <!--<button nz-button nzType="primary" *ngIf="showUploadBtn"--> - <!--style="margin-right: 1rem"--> - <!--type="button"--> - <!--[nzLoading]="uploading"--> - <!--(click)="handleUpload()"--> - <!--[disabled]="!videoFile || uploading">--> - <!--<i nz-icon type="upload" theme="outline"></i>--> - <!--<span>{{ uploading ? 'Uploading' : 'Start Upload' }}</span>--> + <!--<button nz-button nzType="primary" *ngIf="showUploadBtn"--> + <!--style="margin-right: 1rem"--> + <!--type="button"--> + <!--[nzLoading]="uploading"--> + <!--(click)="handleUpload()"--> + <!--[disabled]="!videoFile || uploading">--> + <!--<i nz-icon type="upload" theme="outline"></i>--> + <!--<span>{{ uploading ? 'Uploading' : 'Start Upload' }}</span>--> <!--</button>--> <!-- @@ -54,41 +49,37 @@ --> -</div> -<div class="p-box d-flex align-items-center p-video-uploader"> - <div class="p-upload-icon" *ngIf="!showUploadBtn && !videoUrl && !uploading"> - <i nz-icon nzType="upload" nzTheme="outline"></i> - <div class="m-3"></div> - <span>Click here to upload video</span> - <div class="mt-5 p-progress-bar" *ngIf="uploading"> - <div class="p-progress-bg" [style.width]="progress*0.2+'rem'"></div> - <div class="p-progress-value">{{progress}}%</div> - </div> </div> - <div class="p-upload-progress-bg dddd " *ngIf="uploading" - [ngClass]="{'smart-bar': showUploadBtn}" > - <div class="i-bg" [style.width]="progress+'%'"></div> - <div class="i-text"> - <fa-icon icon="cloud-upload-alt"></fa-icon> - Uploading... + <div class="p-box d-flex align-items-center p-video-uploader"> + <div class="p-upload-icon" *ngIf="!showUploadBtn && !videoUrl && !uploading"> + <i nz-icon nzType="upload" nzTheme="outline"></i> + <div class="m-3"></div> + <span>Click here to upload video</span> + <div class="mt-5 p-progress-bar" *ngIf="uploading"> + <div class="p-progress-bg" [style.width]="progress*0.2+'rem'"></div> + <div class="p-progress-value">{{progress}}%</div> + </div> </div> - </div> - <div class="p-upload-check-bg" *ngIf="checking"> - <div class="i-bg" [style.width]="progress+'%'"></div> - <div class="i-text"> - <fa-icon icon="cloud-upload-alt"></fa-icon> - <i nz-icon nzType="loading" nzTheme="outline"></i>Checking... + <div class="p-upload-progress-bg dddd " *ngIf="uploading" [ngClass]="{'smart-bar': showUploadBtn}"> + <div class="i-bg" [style.width]="progress+'%'"></div> + <div class="i-text"> + <fa-icon icon="cloud-upload-alt"></fa-icon> + Uploading... + </div> + </div> + <div class="p-upload-check-bg" *ngIf="checking"> + <div class="i-bg" [style.width]="progress+'%'"></div> + <div class="i-text"> + <fa-icon icon="cloud-upload-alt"></fa-icon> + <i nz-icon nzType="loading" nzTheme="outline"></i>Checking... + </div> + </div> + <div class="p-preview" *ngIf="!uploading && videoUrl "> + <!--<video crossorigin="anonymous" [src]="videoUrl" controls #videoNode></video>--> + <video [src]="safeVideoUrl(videoUrl)" controls #videoNode></video> </div> </div> - <div class="p-preview" *ngIf="!uploading && videoUrl " > - <!--<video crossorigin="anonymous" [src]="videoUrl" controls #videoNode></video>--> - <video [src]="safeVideoUrl(videoUrl)" controls #videoNode></video> + <div [style.display]="!checkVideoExists?'none':''"> + <span><i nz-icon nzType="loading" nzTheme="outline"></i> checking file to upload</span> </div> -</div> -<div [style.display]="!checkVideoExists?'none':''"> - <span><i nz-icon nzType="loading" nzTheme="outline"></i> checking file to upload</span> -</div> -</div> - - - +</div> \ No newline at end of file diff --git a/form_angular/src/app/common/upload-video/upload-video.component.ts b/form_angular/src/app/common/upload-video/upload-video.component.ts index 60c5764847a71bac523ca732a28fe7ea3ec43aa8..3915ad3a257d052c5c19b69803f51f5b9496de9a 100644 --- a/form_angular/src/app/common/upload-video/upload-video.component.ts +++ b/form_angular/src/app/common/upload-video/upload-video.component.ts @@ -225,5 +225,55 @@ export class UploadVideoComponent implements OnChanges, OnDestroy { // console.log(Math.floor(p * 100)); this.progress = Math.floor(p * 100); } + + linkInputed (url, name) { + const file = { + response: {url} + }; + const vid = document.createElement('video'); + vid.addEventListener('loadedmetadata', () => { + const height = vid.videoHeight; + const width = vid.videoWidth; + let duration = vid.duration; + if (duration) { + duration = duration * 1000; + } + file["height"] = height; + file["width"] = width; + file["duration"] = duration; + vid.preload = 'none'; + vid.src = ''; + vid.remove(); + this.videoUploaded.emit(file.response); + }); + vid.src = file.response.url; + this.videoUrl = url; + } + + handle_dragover(e) { + e.preventDefault(); + } + + handle_drop(e) { + const dt = e.dataTransfer.getData("text/plain"); + console.log("handle_drop===", dt); + if (!dt) { + return; + } + try { + const {url, name} = JSON.parse(dt); + if (url.indexOf("teach")<0 || url.indexOf("cdn")<0) { + return; + } + const white = [".mp4"]; + if (!white.includes(url.substr(url.lastIndexOf(".")))) { + return; + } + + this.linkInputed(url, name); + } catch (error) { + console.warn("handle_dropæ‹–æ‹½åœ¨çº¿è§†é¢‘ä¼ é€’å‚æ•°ä¸åˆæ³•,应该是{url:'', name:''}"); + } + } } diff --git a/form_angular/src/app/form/form.component.html b/form_angular/src/app/form/form.component.html index 255849f29702753ccedfe6e1d21a44026269263f..b0ed97e606e19c8bb80dc45a6f288cc034d59496 100644 --- a/form_angular/src/app/form/form.component.html +++ b/form_angular/src/app/form/form.component.html @@ -1,9 +1,5 @@ <div class="model-content"> <div style="padding: 10px;"> - <div class="border" style="width: 1000px;"> - <textarea style="width: 955px; height: 300px;" (blur)="load()" #itemTextarea>{{itemStr}}</textarea> - <button (click)="copyData();">Copy</button> - </div> <div class="border" style="width: 1000px;"> <span style="font-size: 20px;">æ ‡é¢˜: </span> @@ -19,6 +15,8 @@ ></app-audio-recorder> </div> + + <div class="border" style="width: 1000px;"> <div *ngFor="let question of item.questions; let i = index"> <div class="border" style="width: 950px;"> diff --git a/form_angular/src/app/form/form.component.ts b/form_angular/src/app/form/form.component.ts index 69a4f98dd7e1484c12c429be1b5dd75536cf4b9b..b29f7320f02bde41aab2be09df516a34428b1b3a 100644 --- a/form_angular/src/app/form/form.component.ts +++ b/form_angular/src/app/form/form.component.ts @@ -40,4 +40,19 @@ export class FormComponent extends ComponentBase implements OnInit, OnChanges, O this.item.audioFileName=name; this.save(); } + + handle_dragover(e) { + e.preventDefault(); + } + + handle_drop(e) { + e.preventDefault(); + const dt = e.dataTransfer.getData("text/plain"); + console.log("handle_drop===", dt); + // 网络文件 dt 的数æ®éµå¾ªå¦‚ä¸‹æ ¼å¼ + // 图片 "http://staging-teach.cdn.ireadabc.com/f38f9928-c3bd-47f8-9ed1-43c0e03d2f30.png"; + // 音频(JSONå—符串) {url: "http://staging-teach.cdn.ireadabc.com/1c8694612563f4e2da707f1f6a37d066_l.mp3", name: "test.mp3"}; + // 视频(JSONå—符串) {url: "http://staging-teach.cdn.ireadabc.com/c37a3945121274a1f7d95717327539ec_l.mp4", name: "视频.mp4"}; + // 骨骼动画(JSONå—符串) {"ske":{"url":"http://staging-teach.cdn.ireadabc.com/3d4a36b83aada60709771fbe15e2b6db.json","name":"飞鸟_ske.json"},"tex":{"url":"http://staging-teach.cdn.ireadabc.com/08a676a5f456634f9c6c90e9efd3c2ea.json","name":"飞鸟_tex.json"},"png":{"url":"http://staging-teach.cdn.ireadabc.com/874393ecf5e0cd42a09f5b34d48854d2.png","name":"飞鸟_tex.png"}}; + } } \ No newline at end of file diff --git a/form_angular/src/drag-test.html b/form_angular/src/drag-test.html new file mode 100644 index 0000000000000000000000000000000000000000..dab42104ba039317bec5ebf2d77891329e4a31a2 --- /dev/null +++ b/form_angular/src/drag-test.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Document</title> +</head> +<body> + <img id="drag" style="width: 100px; height: 100px; background-color: gold;" draggable="true" ele-data="http://staging-teach.cdn.ireadabc.com/c37a3945121274a1f7d95717327539ec_l.mp4" src="http://staging-teach.cdn.ireadabc.com/f38f9928-c3bd-47f8-9ed1-43c0e03d2f30.png"></img> + + <div id="target" ondrop="handle_drop(event)" ondragover="handle_dragover(event)" style="position: absolute; top: 10px; right: 10px; width: 80px; height: 80px; background: #00ffff;"> + + </div> + <script> + var dragEl = document.getElementById("drag"); + dragEl.ondragstart = function(e) { + + // 图片 + // const dt = "http://staging-teach.cdn.ireadabc.com/f38f9928-c3bd-47f8-9ed1-43c0e03d2f30.png"; + // e.dataTransfer.setData("text/plain", dt); + // 音频 + const dt = {url: "http://staging-teach.cdn.ireadabc.com/1c8694612563f4e2da707f1f6a37d066_l.mp3", name: "test.mp3"}; + e.dataTransfer.setData("text/plain", JSON.stringify(dt)); + // 视频 + // const dt = {url: "http://staging-teach.cdn.ireadabc.com/c37a3945121274a1f7d95717327539ec_l.mp4", name: "视频.mp4"}; + // e.dataTransfer.setData("text/plain", JSON.stringify(dt)); + // 骨骼动画 + // const dt = {"ske":{"url":"http://staging-teach.cdn.ireadabc.com/3d4a36b83aada60709771fbe15e2b6db.json","name":"飞鸟_ske.json"},"tex":{"url":"http://staging-teach.cdn.ireadabc.com/08a676a5f456634f9c6c90e9efd3c2ea.json","name":"飞鸟_tex.json"},"png":{"url":"http://staging-teach.cdn.ireadabc.com/874393ecf5e0cd42a09f5b34d48854d2.png","name":"飞鸟_tex.png"}}; + // e.dataTransfer.setData("text/plain", JSON.stringify(dt)) + } + dragEl.drop = function(e) { + e.dataTransfer.getData("text/plain"); + } + + var target = document.getElementById('target') + // target.ondragover = handle_dragover + + function handle_dragover(e) { + e.preventDefault() + } + + function handle_drop(e) { + } + </script> +</body> +</html> \ No newline at end of file