diff --git a/form/src/app/app.module.ts b/form/src/app/app.module.ts
index fe6ed4a84703d0979fdffc285adeb919f43286e3..ae461d7dd5e8dee57e8115619aa8333acfeb2481 100644
--- a/form/src/app/app.module.ts
+++ b/form/src/app/app.module.ts
@@ -17,6 +17,7 @@ import {BackgroundImagePipe} from './pipes/background-image.pipe';
 import {UploadImageWithPreviewComponent} from './common/upload-image-with-preview/upload-image-with-preview.component';
 import {PlayerContentWrapperComponent} from './common/player-content-wrapper/player-content-wrapper.component';
 import {CustomHotZoneComponent} from './common/custom-hot-zone/custom-hot-zone.component';
+import {CustomHotZoneComponent1} from './common/custom-hot-zone-mini/custom-hot-zone-mini.component';
 import {UploadVideoComponent} from './common/upload-video/upload-video.component';
 import {TimePipe} from './pipes/time.pipe';
 import {ResourcePipe} from './pipes/resource.pipe';
@@ -25,6 +26,7 @@ import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontaweso
 import { fas } from '@fortawesome/free-solid-svg-icons';
 import { far } from '@fortawesome/free-regular-svg-icons';
 import { UploadDragonBoneComponent } from './common/upload-dragon-bone/upload-dragon-bone.component';
+import { CustomActionComponent } from './common/custom-action/custom-action.component';
 
 registerLocaleData(zh);
 
@@ -41,8 +43,10 @@ registerLocaleData(zh);
     TimePipe,
     UploadVideoComponent,
     CustomHotZoneComponent,
+    CustomHotZoneComponent1,
     UploadDragonBoneComponent,
-    PlayerContentWrapperComponent
+    PlayerContentWrapperComponent,
+    CustomActionComponent,
 
   ],
   imports: [
diff --git a/form/src/app/common/audio-recorder/audio-recorder.component.html b/form/src/app/common/audio-recorder/audio-recorder.component.html
index e174c34da6591aeefc1a0d1f9fb3576e6499d645..3c8d2d215843514f4ebc6a139ffde3b3307be3d0 100644
--- a/form/src/app/common/audio-recorder/audio-recorder.component.html
+++ b/form/src/app/common/audio-recorder/audio-recorder.component.html
@@ -35,7 +35,8 @@
     <ng-template #truthyTemplate >
 
       <div class="btn-delete" (click)="onBtnDeleteAudio()">
-        <fa-icon icon="close"></fa-icon>
+        <!-- <fa-icon icon="close"></fa-icon> -->
+        <i nz-icon nzType="close" nzTheme="outline"></i>
       </div>
 
     </ng-template>
diff --git a/form/src/app/common/audio-recorder/audio-recorder.component.ts b/form/src/app/common/audio-recorder/audio-recorder.component.ts
index 605db0ab773819d944f4b9932a82f5cfb6111f94..609ed49f10a526596589ea163bb6cb0696abe73f 100644
--- a/form/src/app/common/audio-recorder/audio-recorder.component.ts
+++ b/form/src/app/common/audio-recorder/audio-recorder.component.ts
@@ -26,7 +26,7 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
   uploadData;
 
   @Input()
-  needRemove = false;
+  needRemove = true;
 
   @Input()
   audioItem: any = null;
@@ -62,8 +62,25 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
       this.uploadUrl = url;
       this.uploadData = data;
     };
+
+    this.setUploadUrl();
   }
 
+
+  setUploadUrl() {
+
+    if (!this.uploadUrl) {
+
+      this.uploadUrl = (<any> window).courseware.uploadUrl();
+      this.uploadData = (<any> window).courseware.uploadData();
+
+      setTimeout(() => {
+        this.setUploadUrl();
+      }, 500);
+    }
+  }
+
+
   init() {
     this.playIcon = 'play';
     this.isPlaying = false;
@@ -157,6 +174,7 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
 
   onBtnDeleteAudio() {
     this.audioUrl = null;
+    this.audioUploaded.emit({});
     this.audioRemoved.emit();
   }
 
diff --git a/form/src/app/common/custom-action/custom-action.component.html b/form/src/app/common/custom-action/custom-action.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..d03a4521c95146446ba77e248b42f8b94a542f75
--- /dev/null
+++ b/form/src/app/common/custom-action/custom-action.component.html
@@ -0,0 +1,153 @@
+<div class="position-relative">
+
+
+  <button nz-button (click)="setAnimaBtnClick()" style=" border-radius: 0.5rem; border: 1px solid #ddd;">
+    <i nz-icon nzType="tool" nzTheme="outline"></i>
+    {{btnName}}
+  </button>
+
+
+  <!--配置龙骨面板-->
+  <nz-modal [(nzVisible)]="panelVisible" (nzAfterClose)="closePanel()" [nzTitle]="btnName" (nzOnCancel)="panelCancel()"
+    (nzOnOk)="panelOk()" nzOkText="保存">
+    <div>
+      <h4>基础内容:</h4>
+
+      <div style="margin-bottom: 10px; width: 80%; margin: auto;">
+
+        <!-- <nz-radio-group [ngModel]="item.type" (ngModelChange)="radioChange($event)">
+          <label nz-radio nzValue="pic">图片</label>
+          <label nz-radio nzValue="text">文本</label>
+        </nz-radio-group> -->
+
+        <div *ngIf="item.type == 'pic'">
+          <app-upload-image-with-preview [picUrl]="item?.pic_url"
+            (imageUploaded)="onItemImgUploadSuccess($event, item)">
+          </app-upload-image-with-preview>
+        </div>
+
+        <div *ngIf="item.type == 'text'">
+          <input type="text" nz-input [(ngModel)]="item.text" (blur)="saveText(item)">
+        </div>
+
+        <div *ngIf="item.type == 'anima'" style="margin-left: 100px;">
+          <app-upload-dragon-bone [skeJsonData]=item.skeJsonData [texJsonData]=item.texJsonData
+            [texPngData]=item.texPngData (save)="saveAnima($event)">
+          </app-upload-dragon-bone>
+        </div>
+      </div>
+
+
+      <nz-divider style="margin-top: 10px;"></nz-divider>
+
+      <h4>状态设置:</h4>
+      <div style="display: flex; justify-content: space-around;">
+
+        <!-- <div style="width: 30%; display: flex; align-items: center; flex-direction: column;">
+          <h5> 开始状态 </h5>
+          <div *ngFor="let op of item.changeOption; let i = index" style="margin-bottom: 5px; ">
+            <div style="display: flex; align-items: center; justify-content: center;">
+              <span>{{op[0]}}: </span> <input type="text" nz-input [(ngModel)]="op[1]" (blur)="saveText(op)" style="margin-left: 5px;">
+            </div>
+          </div>
+        </div>
+
+
+        <div style="width: 30%; display: flex; align-items: center; flex-direction: column; ">
+          <h5> 切换时间 </h5>
+          <div style="display: flex; width: 100%; align-items: center; justify-content: center;">
+            <span>time: </span> <input type="text" nz-input [(ngModel)]="item.changeTime" (blur)="saveText(item.changeTime)" style="width: 80px; margin-left: 5px;">
+          </div>
+        </div>
+
+
+        <div style="width: 30%; display: flex; align-items: center; flex-direction: column;">
+          <h5> 结束状态 </h5>
+          <div *ngFor="let op of item.changeOption; let i = index" style="margin-bottom: 5px; ">
+            <div style="display: flex; align-items: center; justify-content: center;">
+              <span>{{op[0]}}: </span> <input [disabled]="op[2] == null" type="text" nz-input [(ngModel)]="op[2]" (blur)="saveText(op)" style="margin-left: 5px;">
+            </div>
+          </div>
+        </div> -->
+        <div style="width: 30%; display: flex; align-items: center; flex-direction: column;">
+          <div *ngFor="let op of item.changeOption; let i = index" style="margin-bottom: 5px; ">
+            <div style="display: flex; align-items: center; justify-content: center;">
+              <span style="white-space: nowrap">{{op[0]}}: </span> <input type="text" nz-input [(ngModel)]="op[1]"
+                (blur)="saveText(op)" style="margin-left: 5px;">
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div style="display: flex; align-items: center; justify-content: center; margin-top: 10px;">
+        <button style="margin-left: 20px; margin-top: -5px" nz-button (click)="copyChangeData()"> 复制数据 </button>
+        <div style="margin-left: 20px; margin-top: -5px">
+
+          <span>粘贴数据: </span>
+          <input style="width: 100px;" type="text" nz-input [(ngModel)]="pasteData">
+          <button style="margin-left: 5px;" nz-button [disabled]="pasteData==''" nzType="primary"
+            (click)="importData()">导入</button>
+
+        </div>
+      </div>
+
+      <div *ngIf='audio'>
+        
+      <nz-divider style="margin-top: 10px;"></nz-divider>
+        <h4> 音频设置 </h4>
+
+        <app-audio-recorder style="margin: auto" [audioUrl]="item?.audio_url"
+          (audioUploaded)="onItemAudioUploadSuccess($event, item)"></app-audio-recorder>
+      </div>
+
+    </div>
+
+
+
+    <!-- 
+    <div class="anima-upload-btn">
+      <span style="margin-right: 10px">上传 ske_json 文件: </span>
+      <nz-upload [nzShowUploadList]="false" 
+                nzAccept="application/json"
+                [nzAction]="uploadUrl"
+                [nzData]="uploadData"
+                (nzChange)="skeJsonHandleChange($event)">
+        <button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
+      </nz-upload>
+      <i *ngIf="isSkeJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
+      <span *ngIf="skeJsonData && skeJsonData['name']" style="margin-left: 10px"><u> {{skeJsonData['name']}} </u></span>
+    </div>
+
+    <div class="anima-upload-btn">
+      <span style="margin-right: 10px">上传 tex_json 文件: </span>
+      <nz-upload [nzShowUploadList]="false"
+                nzAccept="application/json"
+                [nzAction]="uploadUrl"
+                [nzData]="uploadData"
+                (nzChange)="texJsonHandleChange($event)">
+        <button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
+      </nz-upload>
+      <i *ngIf="isTexJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
+      <span *ngIf="texJsonData && texJsonData['name']" style="margin-left: 10px"><u> {{texJsonData['name']}} </u></span>
+    </div>
+
+    <div class="anima-upload-btn">
+      <span style="margin-right: 10px">上传 tex_png 文件: </span>
+      <nz-upload [nzShowUploadList]="false"
+                nzAccept = "image/*"
+                [nzAction]="uploadUrl"
+                [nzData]="uploadData"
+                (nzChange)="texPngHandleChange($event)">
+        <button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
+      </nz-upload>
+      <i *ngIf="isTexPngLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
+      <span *ngIf="texPngData && texPngData['name']" style="margin-left: 10px"><u> {{texPngData['name']}} </u></span>
+    </div>
+
+    <div class="anima-upload-btn" *ngIf="animaNames && animaNames.length > 0">
+      提示:需包含动画: {{animaNames.toString()}}.
+    </div> -->
+
+  </nz-modal>
+
+</div>
\ No newline at end of file
diff --git a/form/src/app/common/custom-action/custom-action.component.scss b/form/src/app/common/custom-action/custom-action.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e9c56bfc8de8aec772d05405514870f9bb6c30f6
--- /dev/null
+++ b/form/src/app/common/custom-action/custom-action.component.scss
@@ -0,0 +1,110 @@
+@import '../../style/common_mixin.css';
+
+.p-image-uploader {
+  position: relative;
+  display: block;
+  width: 100%;
+  height: 0;
+  padding-bottom: 56.25%;
+  .p-box {
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    border: 2px dashed #ddd;
+    border-radius: 0.5rem;
+    background-color: #fafafa;
+    text-align: center;
+    color: #aaa;
+    .p-upload-icon {
+      text-align: center;
+      margin: auto;
+      .anticon-upload {
+        color: #888;
+        font-size: 5rem;
+      }
+      .p-progress-bar {
+        position: relative;
+        width: 20rem;
+        height: 1.5rem;
+        border: 1px solid #ccc;
+        border-radius: 1rem;
+        .p-progress-bg {
+          background-color: #1890ff;
+          border-radius: 1rem;
+          height: 100%;
+        }
+        .p-progress-value {
+          position: absolute;
+          top: 0;
+          left: 0;
+          width: 100%;
+          height: 100%;
+          text-shadow: 0 0 4px #000;
+          color: white;
+          text-align: center;
+          font-size: 0.9rem;
+          line-height: 1.5rem;
+        }
+      }
+    }
+    .p-preview {
+      width: 100%;
+      height: 100%;
+      background-size: contain;
+      background-repeat: no-repeat;
+      background-position: 50% 50%;
+      //background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png");
+    }
+  }
+  .d-flex{
+    display: flex;
+  }
+}
+
+.p-btn-delete {
+  position: absolute;
+  right: -0.5rem;
+  top: -0.5rem;
+  width: 2rem;
+  height: 2rem;
+  border: 0.2rem solid white;
+  border-radius: 50%;
+  font-size: 1.2rem;
+  background-color: #fb781a;
+  color: white;
+  text-align: center;
+}
+
+.p-upload-progress-bg {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  & .i-text {
+    position: absolute;
+    text-align: center;
+    color: white;
+    text-shadow: 0 0 2px rgba(0, 0, 0, .85);
+  }
+  & .i-bg {
+    position: absolute;
+    left: 0;
+    top: 0;
+    height: 100%;
+    background-color: #27b43f;
+    border-radius: 0.5rem;
+  }
+}
+
+.anima-upload-btn {
+  padding: 10px;
+}
+
+
+:host ::ng-deep .ant-upload {
+  display: block;
+}
diff --git a/form/src/app/common/custom-action/custom-action.component.ts b/form/src/app/common/custom-action/custom-action.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..65d5e4fbd5391b899da841c47e506017e91ae986
--- /dev/null
+++ b/form/src/app/common/custom-action/custom-action.component.ts
@@ -0,0 +1,218 @@
+import {ApplicationRef, Component, EventEmitter, Input, OnChanges, OnDestroy, Output} from '@angular/core';
+import { NzMessageService, UploadXHRArgs, UploadFile } from 'ng-zorro-antd';
+
+
+@Component({
+  selector: 'app-custom-action',
+  templateUrl: './custom-action.component.html',
+  styleUrls: ['./custom-action.component.scss']
+})
+export class CustomActionComponent implements OnDestroy, OnChanges {
+  uploading = false;
+  progress = 0;
+  @Input()
+  btnName = '配置变化状态';
+
+  @Input()
+  option = []
+
+  @Input()
+  item;
+
+  @Input()
+  type = 'text'
+
+  @Input()
+  audio =true
+
+  @Output()
+  save = new EventEmitter();
+
+  @Output()
+  refreshEmitter = new EventEmitter();
+
+  uploadUrl;
+  uploadData;
+
+  panelVisible = false;
+  pasteData = '';
+
+
+
+  constructor(private appRef: ApplicationRef, private nzMessageService: NzMessageService) {
+
+    window['air'].getUploadCallback = (url, data) => {
+      this.uploadUrl = url;
+      this.uploadData = data;
+    };
+
+    const tmpId = setInterval(() => {
+      console.log(' in setInterval')
+      this.uploadUrl = (<any> window).courseware.uploadUrl();
+      this.uploadData = (<any> window).courseware.uploadData();
+      if (this.uploadUrl) {
+        clearInterval(tmpId);
+      }
+    }, 500)
+
+  }
+
+  ngOnInit() {
+    this.initItem();
+  }
+
+  ngOnChanges() {
+ 
+  }
+
+  initItem() {
+
+    console.log('```this.item: ', this.item);
+    
+    if (!this.item) {
+      this.item = {
+        type: this.type,
+        // skeJsonData: {},
+        // texJsonData: {},
+        // texPngData: {},
+
+
+        // changeStart: [
+        
+        // ],
+        // changeEnd: [
+        
+        // ],
+        // changeTime: 0.3
+      };
+
+      if (this.option) {
+        this.item.changeOption = JSON.parse(JSON.stringify(this.option));
+      }
+    }
+
+    console.log('initItem', this.item);
+
+  }
+
+  setAnimaBtnClick() {
+    this.panelVisible = true;
+    this.refresh();
+  }
+
+  panelCancel() {
+    this.panelVisible = false;
+    this.refresh();
+  }
+
+  panelOk() {
+    // this.sendItemDragonBoneData();
+    this.panelVisible = false;
+    this.refresh();
+    this.save.emit(this.item);
+  }
+
+  saveText(t) {
+
+  }
+
+  radioChange(e) {
+    this.item.type = e;
+    console.log('e: ', e);
+  }
+
+
+  onItemImgUploadSuccess(e, item) {
+    item.pic_url = e.url;
+    this.refresh();
+  }
+
+
+  onItemAudioUploadSuccess(e, item) {
+    item.audio_url = e.url;
+    this.refresh();
+  }
+
+  saveAnima(e) {
+    console.log("~ e: ", e);
+  }
+
+  copyChangeData() {
+
+    console.log('this.item: ', this.item);
+
+    const jsonData = {
+      changeOption: this.item.changeOption,
+      changeTime : this.item.changeTime
+      // bgItem,
+      // hotZoneItemArr,
+      // isHasRect: this.isHasRect,
+      // isHasPic: this.isHasPic,
+      // isHasText: this.isHasText,
+      // isHasAudio: this.isHasAudio,
+      // isHasAnima: this.isHasAnima,
+      // hotZoneFontObj: this.hotZoneFontObj,
+      // defaultItemType: this.defaultItemType,
+      // hotZoneImgSize: this.hotZoneImgSize,
+    };
+
+
+    const oInput = document.createElement('input');
+    oInput.value = JSON.stringify(jsonData);
+    document.body.appendChild(oInput);
+    oInput.select(); // 选择对象
+    document.execCommand('Copy'); // 执行浏览器复制命令
+
+    document.body.removeChild(oInput);
+    this.nzMessageService.success('复制成功');
+    
+  }
+
+  importData() {
+    if (!this.pasteData) {
+      return;
+    }
+
+
+    try {
+      const data = JSON.parse(this.pasteData);
+      console.log('data:', data);
+      const {
+        changeOption,
+        changeTime
+      } = data;
+
+      this.item.changeOption = changeOption;
+      this.item.changeTime = changeTime;
+
+      this.pasteData = '';
+    } catch (e) {
+      console.log('err: ', e);
+      this.nzMessageService.error('导入失败');
+    }
+  }
+
+
+  /**
+   * 刷新 渲染页面
+   */
+  refresh() {
+
+    // this.refreshEmitter.emit();
+    setTimeout(() => {
+      this.appRef.tick();
+    }, 1);
+  }
+
+
+  closePanel() {
+    console.log(' in closePanel ');
+    this.refresh();
+  }
+
+
+
+  ngOnDestroy() {
+  }
+
+}
diff --git a/form/src/app/common/custom-hot-zone-mini/BRLNSDB.TTF b/form/src/app/common/custom-hot-zone-mini/BRLNSDB.TTF
new file mode 100644
index 0000000000000000000000000000000000000000..e5f34b2f342ffcd820a8a0956af3ab36bb1f9e1f
Binary files /dev/null and b/form/src/app/common/custom-hot-zone-mini/BRLNSDB.TTF differ
diff --git a/form/src/app/common/custom-hot-zone-mini/Unit.ts b/form/src/app/common/custom-hot-zone-mini/Unit.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5bed33b54a2a85a97065e113be34dd0fb60f722d
--- /dev/null
+++ b/form/src/app/common/custom-hot-zone-mini/Unit.ts
@@ -0,0 +1,2374 @@
+
+import TWEEN from '@tweenjs/tween.js';
+
+interface AirWindow  extends Window {
+  air: any;
+  curCtx: any;
+}
+declare let window: AirWindow;
+
+class Sprite {
+  x = 0;
+  y = 0;
+  color = '';
+  radius = 0;
+  alive = false;
+  margin = 0;
+  angle = 0;
+  ctx;
+
+  constructor(ctx = null) {
+    if (!ctx) {
+      this.ctx = window.curCtx;
+    } else {
+      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;
+  skewX = 0;
+  skewY = 0;
+
+  _shadowFlag = false;
+  _shadowColor;
+  _shadowOffsetX = 0;
+  _shadowOffsetY = 0;
+  _shadowBlur = 5;
+
+  _radius = 0;
+
+  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) {
+
+    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;
+    }
+
+    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();
+    // }
+
+  }
+
+  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) {
+
+      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) {
+          this.drawSelf();
+        }
+      } else {
+        child.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;
+    });
+
+
+    if (this.childDepandAlpha) {
+      child.alpha = this.alpha;
+    }
+
+  }
+  removeChild(child) {
+    const index = this.children.indexOf(child);
+    if (index !== -1) {
+      this.children.splice(index, 1);
+    }
+  }
+
+  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();
+  }
+  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 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};
+  }
+
+}
+
+
+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;
+
+
+    }
+
+    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;
+
+  }
+
+
+
+  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();
+    }
+
+
+    if (this.img) {
+
+      this._offCtx.drawImage(this.img, 0, 0);
+      this.ctx.drawImage(this._offCanvas,this._offX, this._offX);
+    }
+
+  }
+}
+
+
+
+
+
+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 );
+        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;
+      }
+    }
+
+    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 );
+        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('');
+    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;
+    this.height = h;
+
+    let offX = -totalW / 2;
+    for (const label of  labelArr) {
+      label.x = offX;
+      offX += label.width;
+    }
+
+    this.labelArr = labelArr;
+  }
+
+}
+
+
+
+
+export class Label extends MySprite {
+  private _text: string;
+
+  // fontSize:String = '40px';
+  fontName = 'font';
+  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();
+  }
+
+  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;
+    }
+
+    this.width = curX;
+    this.height = this.fontSize;
+    this.refreshAnchorOff();
+
+    this.ctx.restore();
+
+  }
+
+
+  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();
+        }
+      })
+      .start(); // Start the tween immediately.
+
+  }
+
+
+
+  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';
+      } 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;
+  }
+
+
+
+  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;
+    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;
+      } 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
+    // }
+
+
+    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.ctx.fillStyle = '#ff7600';
+    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';
+
+  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();
+      }
+    }, 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 {
+
+
+  lineDashFlag = false;
+  arrow: MySprite;
+  label: Label;
+  title;
+
+  arrowTop;
+  arrowRight;
+
+  audio_url;
+  pic_url;
+  text;
+  gIdx;
+
+  isAnimaStyle = false;
+
+  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 = 40;
+      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();
+  }
+
+  setAnimaStyle(isAnimaStyle) {
+    this.isAnimaStyle = isAnimaStyle;
+    console.log('in  setAnimaStyle ')
+  }
+
+  drawArrow() {
+    if (!this.arrow) { return; }
+
+    const rect = this.getBoundingBox();
+    this.arrow.x = rect.x + rect.width;
+    this.arrow.y = rect.y;
+
+    this.arrow.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() {
+
+
+    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 HotZoneImg extends MySprite {
+
+  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( 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();
+
+    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 EditorItem extends MySprite {
+
+  lineDashFlag = false;
+  arrow: MySprite;
+  label: Label;
+  text;
+  arrowTop;
+  arrowRight;
+
+  showLabel(text = null) {
+
+
+    if (!this.label) {
+      this.label = new Label(this.ctx);
+      this.label.anchorY = 0;
+      this.label.fontSize = 50;
+      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.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();
+  }
+
+  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() {
+
+
+    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();
+    }
+  }
+}
+
+
diff --git a/form/src/app/common/custom-hot-zone-mini/custom-hot-zone-mini.component.html b/form/src/app/common/custom-hot-zone-mini/custom-hot-zone-mini.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..d2bb85db677444a348cf2a024aeb48dfa2ae3954
--- /dev/null
+++ b/form/src/app/common/custom-hot-zone-mini/custom-hot-zone-mini.component.html
@@ -0,0 +1,232 @@
+<div class="p-image-children-editor " style="font-family: font;">
+  <div class="preview-box" #wrap>
+    <canvas id="canvas" #canvas></canvas>
+  </div>
+
+  <div nz-row nzType="flex" nzAlign="middle">
+    <div nz-col nzSpan="5" nzOffset="1" style="display:flex; flex-wrap:wrap;flex-direction: row;width: 100%;">
+
+      <!-- <h5> 添加背景: </h5>
+
+      <div class="bg-box">
+        <app-upload-image-with-preview [picUrl]="bgItem?.url" (imageUploaded)="onBackgroundUploadSuccess($event)">
+        </app-upload-image-with-preview>
+      </div>
+    </div> -->
+      <div>
+        <h5>题干音频</h5>
+        <div style="display: flex;align-items: center; margin-top: 5px">
+          <app-audio-recorder style="margin: auto" [audioUrl]="bgItem?.bgAudioUrl"
+            (audioUploaded)="onBgAudioUploadSuucess($event)"></app-audio-recorder>
+        </div>
+      </div>
+      <div nz-col nzSpan="5" nzOffset="1" class="img-box" style="width: auto;"
+        *ngFor="let it of hotZoneArr; let i = index">
+
+        <div
+          style="width: auto; margin: auto; padding: 5px;min-width: 220px;  margin-top: 30px; width:90%; border: 2px dashed #ddd; border-radius: 10px">
+          <span style="margin-left: 40%;"> 区域{{i + 1}}
+          </span>
+          <button style="float: right;" nz-button nzType="danger" nzSize="small" (click)="deleteBtnClick(i)">
+            X
+          </button>
+
+          <nz-divider style="margin-top: 10px;"></nz-divider>
+
+          <div style="margin-top: -20px; margin-bottom: 5px; width: 100%;">
+
+            <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>
+
+            <!-- <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>
+
+          <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_'] : {}"
+                [type]="customTypeGroupArr[it.gIdx].action.type" [option]="customTypeGroupArr[it.gIdx].action.option"
+                (save)="onSaveCustomAction($event, it)" [audio]='customTypeGroupArr[it.gIdx].action.audio'>
+                ></app-custom-action>
+            </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>
+
+
+      <div nz-col nzSpan="5" nzOffset="1" style="width: 230px;height: auto;align-self: center;">
+
+        <div class="bg-box" style="width: auto;height: auto;">
+          <button nz-button nzType="dashed" (click)="addBtnClick()" class="add-btn">
+            <i nz-icon nzType="plus-circle" nzTheme="outline"></i>
+            <!--Add Image-->
+            添加点击区域
+          </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>
+        保存
+      </button>
+      <button class="save-btn" nz-button nzType="danger" [nzSize]="'large'" nzShape="round" (click)="deleteClick()">
+        <i nz-icon nzType="save"></i>
+        删除
+      </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>
+
+
+  </div>
+
+  <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>
\ No newline at end of file
diff --git a/form/src/app/common/custom-hot-zone-mini/custom-hot-zone-mini.component.scss b/form/src/app/common/custom-hot-zone-mini/custom-hot-zone-mini.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..1a02d91f0608fdb8a4d941af6c0e5bee010ab822
--- /dev/null
+++ b/form/src/app/common/custom-hot-zone-mini/custom-hot-zone-mini.component.scss
@@ -0,0 +1,118 @@
+
+@font-face {
+  font-family: 'font';
+  src: url('BRLNSDB.TTF');
+}
+.p-image-children-editor {
+
+  width: 100%;
+  height: 100%;
+  border-radius: 0.5rem;
+
+  border: 2px solid #ddd;
+
+
+
+  .preview-box {
+
+    margin: auto;
+    width: 95%;
+    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%;
+    margin-bottom: 1rem;
+
+  }
+
+  .img-box {
+    margin-bottom: 1rem;
+
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+  }
+  .img-box-upload{
+    width: 80%;
+  }
+
+  .add-btn {
+    margin-top: 1rem;
+    width: 200px;
+    height: 90px;
+
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+}
+
+
+.save-box {
+  width: 100%;
+
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  justify-items: center;
+
+  .save-btn {
+    width: 160px;
+    height: 40px;
+
+    //margin-top: 20px;
+    margin-bottom: 20px;
+
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-left: 50px;
+    margin-right: 50px;
+  }
+}
+
+.anima-upload-btn {
+  padding: 10px;
+}
+
+h5 {
+  margin-top: 1rem;
+}
+
+
+//
+//@font-face
+//{
+//  font-family: 'BRLNSR_1';
+//  src: url("/assets/font/BRLNSR_1.TTF") ;
+//}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/form/src/app/common/custom-hot-zone-mini/custom-hot-zone-mini.component.ts b/form/src/app/common/custom-hot-zone-mini/custom-hot-zone-mini.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..68ae113aefbd4fffc80e30b26223695d3aa87bf0
--- /dev/null
+++ b/form/src/app/common/custom-hot-zone-mini/custom-hot-zone-mini.component.ts
@@ -0,0 +1,1573 @@
+import {
+  ApplicationRef,
+  ChangeDetectorRef,
+  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, ShapeRect, ShapeRectNew } from './Unit';
+import TWEEN from '@tweenjs/tween.js';
+import { getMinScale } from '../../play/Unit';
+import { tar } from 'compressing';
+import { NzMessageService } from 'ng-zorro-antd';
+import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
+
+
+@Component({
+  selector: 'app-custom-hot-zone-mini',
+  templateUrl: './custom-hot-zone-mini.component.html',
+  styleUrls: ['./custom-hot-zone-mini.component.scss']
+})
+export class CustomHotZoneComponent1 implements OnInit, OnDestroy, OnChanges {
+
+  @ViewChild('canvas', { static: true }) canvas: ElementRef;
+  @ViewChild('wrap', { static: true }) wrap: ElementRef;
+
+
+  @Input()
+  hotZoneItemArr = null;
+  @Input()
+  hotZoneArr = null;
+  @Input()
+  isHasRect = true;
+  @Input()
+  isHasPic = true;
+  @Input()
+  isHasText = true;
+  @Input()
+  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 = {
+  //   size: 50,
+  //   name: 'BRLNSR_1',
+  //   color: '#8f3758'
+  // }
+  @Input()
+  defaultItemType = 'text';
+  @Input()
+  hotZoneImgSize = 0;
+
+
+  @Output()
+  save = new EventEmitter();
+  @Output()
+  del = new EventEmitter();
+
+
+  saveDisabled = true;
+
+  canvasWidth = 1280;
+  canvasHeight = 720;
+  canvasBaseW = 1280;
+  // @HostListener('window:resize', ['$event'])
+  canvasBaseH = 720;
+  mapScale = 1;
+  ctx;
+  mx;
+  my; // 点击坐标
+  // 声音
+  bgAudio = new Audio();
+  images = new Map();
+  animationId: any;
+
+
+  // 资源
+  // rawImages = new Map(res);
+  winResizeEventStream = new Subject();
+  canvasLeft;
+  canvasTop;
+  renderArr;
+  imgArr = [];
+  oldPos;
+  radioValue;
+  curItem;
+  bg: MySprite;
+  changeSizeFlag = false;
+  changeTopSizeFlag = false;
+  changeRightSizeFlag = false;
+  animaPanelVisible = false;
+
+  uploadUrl;
+  uploadData;
+  skeJsonData = {};
+  texJsonData = {};
+  texPngData = {};
+  animaName = '';
+  curDragonBoneIndex;
+  curDragonBoneGIdx;
+  pasteData = '';
+
+  isSkeJsonLoading = false;
+  isTexJsonLoading = false;
+  isTexPngLoading = false;
+
+  isAnimaSmall = false;
+
+
+  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;
+
+  get bgItem() {
+    return this._bgItem;
+  }
+
+  @Input()
+  set bgItem(v) {
+    this._bgItem = v;
+
+    this.init();
+  }
+
+  onResize(event) {
+    this.winResizeEventStream.next();
+  }
+
+
+  ngOnInit() {
+
+
+    this.initListener();
+
+    // this.init();
+    this.update();
+
+    this.refresh();
+
+  }
+
+  ngOnDestroy() {
+    window.cancelAnimationFrame(this.animationId);
+  }
+
+
+  ngOnChanges() {
+
+  }
+
+  onBgAudioUploadSuucess(e) {
+    console.log(e)
+    this.bgItem.bgAudioUrl = e.url
+  }
+
+  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);
+    this.refresh();
+  }
+
+  onItemAudioUploadSuccess(e, item) {
+    item.audio_url = e.url;
+    this.refresh();
+  }
+
+
+  refreshBackground(callBack = null) {
+
+    if (!this.bg) {
+      this.bg = new MySprite(this.ctx);
+      this.renderArr.push(this.bg);
+    }
+
+    if (!this.bgItem.url) {
+      this.bgItem.url = 'http://staging-teach.cdn.ireadabc.com/b90a006ba41723ec11970051e92f43e0.png';
+    }
+
+    const bg = this.bg;
+    // if (this.bgItem.url) {
+
+    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);
+
+
+      bg.x = this.canvasWidth / 2;
+      bg.y = this.canvasHeight / 2;
+
+      if (callBack) {
+        callBack();
+      }
+
+      this.refresh();
+
+    });
+    // }
+
+  }
+
+
+  deleteBtnClick(index) {
+
+    const item = this.hotZoneArr.splice(index, 1)[0];
+    removeItemFromArr(this.renderArr, item.pic);
+    removeItemFromArr(this.renderArr, item.textLabel);
+
+    this.refreshHotZoneId();
+
+  }
+
+  onImgUploadSuccessByImg(e, img) {
+    img.pic_url = e.url;
+    this.refreshImage(img);
+    this.refresh();
+  }
+
+  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 = '区域' + (i + 1);
+
+      }
+    }
+    this.refresh();
+  }
+
+
+  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) {
+
+
+    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.getDefaultItemType();
+    item.gIdx = '0'
+
+    item['id'] = new Date().getTime().toString();
+    item['data'] = saveData;
+    console.log('item.x: ', item.x);
+
+    if (saveData) {
+
+      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.gIdx = saveData.gIdx;
+
+      item['id'] = saveData.id;
+      item['pic'] = saveData.pic_url
+      // item['skeJsonData'] = saveData.skeJsonData;
+      // item['texJsonData'] = saveData.texJsonData;
+      // item['texPngData'] = saveData.texPngData;
+      item['actionData_'] = saveData['actionData_'];
+    }
+
+    console.log('item.x:~~ ', item.x);
+
+    item.showLineDash();
+
+    // const pic = new HotZoneImg(this.ctx);
+
+
+    this.setItemPic(item, saveData);
+
+    this.setItemLabel(item, saveData);
+
+    this.setItemAnima(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) {
+
+      let picUrl = saveData.pic_url;
+      const actionData = saveData['actionData_'];
+      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);
+  }
+
+  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);
+    if (this.hotZoneFontObj) {
+      textLabel.fontSize = this.hotZoneFontObj.size;
+      textLabel.fontName = this.hotZoneFontObj.name;
+      textLabel.fontColor = this.hotZoneFontObj.color;
+    }
+
+    textLabel.textAlign = 'center';
+    // textLabel.setOutline();
+    item['textLabel'] = textLabel;
+    textLabel.setScaleXY(this.mapScale);
+    if (saveData) {
+
+      if (saveData.text && this.hotZoneFontObj) {
+        textLabel.text = saveData.text
+      }
+
+      this.setActionFont(textLabel, saveData['actionData_']);
+      textLabel.refreshSize();
+    }
+    textLabel.x = item.x;
+    textLabel.y = item.y;
+    this.renderArr.push(textLabel);
+  }
+
+  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) {
+
+
+    const item = new EditorItem(this.ctx);
+    item.load(img.pic_url).then(img => {
+
+      let maxW, maxH;
+      if (this.bg) {
+        maxW = this.bg.width * this.bg.scaleX;
+        maxH = this.bg.height * this.bg.scaleY;
+      } else {
+        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 {
+        item.setScaleXY(scaleY);
+      }
+      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();
+      }
+
+      item.showLineDash();
+      console.log('aaa');
+    });
+    return item;
+  }
+
+
+  onAudioUploadSuccessByImg(e, img) {
+    img.audio_url = e.url;
+    this.refresh();
+  }
+
+  addBtnClick() {
+    // this.imgArr.push({});
+    // this.hotZoneArr.push({});
+
+    const item = this.getHotZoneItem();
+    this.hotZoneArr.push(item);
+
+    this.refreshCustomItem(item)
+
+    this.refreshHotZoneId();
+
+  }
+
+  deleteItem(e, i) {
+    // this.imgArr.splice(i , 1);
+    // this.refreshImageId();
+
+    this.hotZoneArr.splice(i, 1);
+    this.refreshHotZoneId();
+    this.refresh();
+  }
+
+  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, true);
+    }
+
+    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.setAnimaStyle(group.animaSmall)
+
+
+  }
+
+  // radioChange(e, item) {
+  //   item.itemType = e;
+
+  //   this.refreshItem(item);
+  //   this.refresh();
+  //   // console.log(' in radioChange e: ', e);
+  // }
+
+  customRadioChange(e, item) {
+
+    console.log('in customRadioChange', e);
+    item.gIdx = -1;
+    item.textLabel.text = ' '
+    item.textLabel.width = 100
+
+    setTimeout(() => {
+      item.gIdx = e;
+      this.refreshCustomItem(item);
+      this.refresh();
+    }, 1);
+
+    // const curGroup = this.customTypeGroupArr[e];
+
+  }
+
+
+
+  setItemIsAnimaStyle(item, isAnimal) {
+
+  }
+
+  showItemPic(item) {
+    item.pic.visible = true;
+    item.itemType = 'pic';
+    this.showArrowTop(item)
+  }
+
+  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) {
+    switch (item.itemType) {
+      case 'rect':
+        this.setRectState(item);
+        break;
+      case 'pic':
+        this.setPicState(item);
+        break;
+      case 'text':
+        this.setTextState(item);
+        break;
+      default:
+        this.setNoneState(item);
+    }
+  }
+
+
+  init() {
+
+    console.log('init');
+    this.initData();
+    this.initCtx();
+
+    //要加载字体
+    setTimeout(() => {
+      this.initItem();
+    }, 100);
+  }
+
+  initItem() {
+
+    this.changeDetectorRef.markForCheck();
+    this.changeDetectorRef.detectChanges();
+
+    if (!this.bgItem) {
+      this.bgItem = {};
+    } else {
+      this.refreshBackground(() => {
+
+
+        if (!this.hotZoneItemArr) {
+          this.hotZoneItemArr = [];
+        } else {
+          this.initHotZoneArr();
+        }
+
+      });
+    }
+
+    this.refresh();
+  }
+
+  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 };
+    }
+
+    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();
+    console.log('this.hotZoneItemArr: ', this.hotZoneItemArr);
+    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;
+
+      if (this.customTypeGroupArr) {
+        this.refreshCustomItem(item);
+      } else {
+        this.refreshItem(item);
+      }
+
+
+      console.log('1 item: ', item);
+      this.hotZoneArr.push(item);
+
+    }
+
+    this.refreshHotZoneId();
+
+    // this.refreshImageId();
+
+  }
+
+
+  initData() {
+
+    this.canvasWidth = this.wrap.nativeElement.clientWidth;
+    this.canvasHeight = this.wrap.nativeElement.clientHeight;
+    this.mapScale = this.canvasWidth / this.canvasBaseW;
+    this.renderArr = [];
+    this.bg = null;
+
+    this.imgArr = [];
+    this.hotZoneArr = [];
+  }
+
+  initCtx() {
+    this.ctx = this.canvas.nativeElement.getContext('2d');
+    this.canvas.nativeElement.width = this.canvasWidth;
+    this.canvas.nativeElement.height = this.canvasHeight;
+  }
+
+
+  mapDown(event) {
+
+    this.oldPos = { x: this.mx, y: this.my };
+
+    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) {
+        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 (target && this.checkClickTarget(target)) {
+        callback(target);
+        return;
+      }
+    }
+
+
+  }
+
+
+  mapMove(event) {
+    if (!this.curItem) {
+      return;
+    }
+
+    if (this.changeSizeFlag) {
+      this.changeSize();
+
+    } else if (this.changeTopSizeFlag) {
+      this.changeTopSize();
+
+    } else if (this.changeRightSizeFlag) {
+      this.changeRightSize();
+
+    } else {
+
+      const addX = this.mx - this.oldPos.x;
+      const addY = this.my - this.oldPos.y;
+      this.curItem.x += addX;
+      this.curItem.y += addY;
+    }
+
+    this.oldPos = { x: this.mx, y: this.my };
+
+    // this.saveDisabled = false;
+
+  }
+
+  mapUp(event) {
+    this.curItem = null;
+    this.changeSizeFlag = false;
+    this.changeTopSizeFlag = false;
+    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 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.setScaleXY(s);
+    this.curItem.refreshLabelScale();
+  }
+
+
+  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 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();
+  }
+
+  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 minLen = 20;
+    let s;
+    if (lenW < minLen) {
+      lenW = minLen;
+    }
+    s = lenW / this.curItem.width;
+
+    this.curItem.scaleX = s;
+    this.curItem.refreshLabelScale();
+  }
+
+  changeItemSize(item) {
+    this.curItem = item;
+    this.changeSizeFlag = true;
+  }
+
+  changeItemTopSize(item) {
+    this.curItem = item;
+    this.changeTopSizeFlag = true;
+  }
+
+  changeItemRightSize(item) {
+    this.curItem = item;
+    this.changeRightSizeFlag = true;
+  }
+
+  changeCurItem(item) {
+
+    this.hideAllLineDash();
+
+    this.curItem = item;
+    this.curItem.showLineDash();
+  }
+
+  hideAllLineDash() {
+
+    for (let i = 0; i < this.imgArr.length; i++) {
+      if (this.imgArr[i].picItem) {
+        this.imgArr[i].picItem.hideLineDash();
+      }
+    }
+  }
+
+
+  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();
+  }
+
+  updateArr(arr) {
+    if (arr) {
+      for (let i = 0; i < arr.length; i++) {
+        arr[i].update();
+      }
+    }
+  }
+
+
+  renderAfterResize() {
+    this.canvasWidth = this.wrap.nativeElement.clientWidth;
+    this.canvasHeight = this.wrap.nativeElement.clientHeight;
+    this.init();
+  }
+
+  initListener() {
+
+    this.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;
+      };
+
+    } 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);
+      });
+
+      this.canvas.nativeElement.addEventListener('touchcancel', (event) => {
+        setMxMyByTouch(event);
+        this.mapUp(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;
+      };
+    }
+  }
+
+  IsPC() {
+    if (window['ELECTRON']) {
+      return false; // 封装客户端标记
+    }
+    if (document.body.ontouchstart !== undefined) {
+      return false;
+    } else {
+      return true;
+    }
+  }
+
+
+  checkClickTarget(target) {
+    if (!target || !target.visible) {
+      return;
+    }
+    const rect = target.getBoundingBox();
+    if (this.checkPointInRect(this.mx, this.my, rect)) {
+      return true;
+    }
+    return false;
+  }
+
+  checkPointInRect(x, y, rect) {
+    if (x >= rect.x && x <= rect.x + rect.width) {
+      if (y >= rect.y && y <= rect.y + rect.height) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  saveClick() {
+    const sendData = this.getSendData();
+    this.save.emit(sendData);
+  }
+
+  deleteClick() {
+    this.del.emit()
+  }
+
+  /** 改变内容 */
+  onChangeSwitch(data, name: string) {
+    data[name] = !data[name]
+  }
+
+  getSendData() {
+
+    const bgItem = this.bgItem;
+    if (this.bg) {
+      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,
+        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 = {
+        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,
+        fontScale: hotZoneArr[i].textLabel ? hotZoneArr[i].textLabel.scaleX : 1,
+        imgScale: hotZoneArr[i].pic ? hotZoneArr[i].pic.scaleX : 1,
+        mapScale: this.mapScale,
+        // skeJsonData: hotZoneArr[i].skeJsonData,
+        // texJsonData: hotZoneArr[i].texJsonData,
+        // texPngData: hotZoneArr[i].texPngData,
+        gIdx: hotZoneArr[i].gIdx
+      };
+
+      hotZoneItem['actionData_'] = hotZoneArr[i]['actionData_']
+
+
+      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;
+      hotZoneItem['rect'].height = Math.round((hotZoneItem['rect'].height) * 100) / 100;
+
+
+      hotZoneItemArr.push(hotZoneItem);
+    }
+
+    console.log('hotZoneItemArr: ', hotZoneItemArr);
+
+    return { bgItem, hotZoneItemArr };
+  }
+
+  saveText(item) {
+    if (item.itemType == 'text') {
+      item.textLabel.text = item.text;
+    }
+  }
+
+  onSaveCustomAction(e, item) {
+
+    const data = e;
+    item['actionData_'] = 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;
+    }
+  }
+
+  copyHotZoneData() {
+    const { hotZoneItemArr } = this.getSendData();
+    // 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 = {
+      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() {
+    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;
+      }
+
+      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;
+      }
+
+    });
+  }
+
+  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;
+  }
+
+  private setNoneState(item: any) {
+    item.visible = false;
+    item.pic.visible = false;
+    item.textLabel.visible = 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)) {
+
+      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;
+    }
+  }
+
+  private clickedHotZoneText(item: any) {
+    if (this.checkClickTarget(item)) {
+      this.curItem = item;
+    }
+  }
+
+  private loadHotZonePic(pic: HotZoneImg, url, scale = null) {
+
+    let baseLen;
+    if (this.hotZoneImgSize) {
+      baseLen = this.hotZoneImgSize * this.mapScale;
+    }
+
+    pic.load(url).then(() => {
+      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/src/app/common/custom-hot-zone/Unit.ts b/form/src/app/common/custom-hot-zone/Unit.ts
index 7b99189ae1e79f71bf621d6c98beff55cb7df827..5d11d29e42c8d68048eb708cc778d6e922cc682e 100644
--- a/form/src/app/common/custom-hot-zone/Unit.ts
+++ b/form/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,8 +2208,26 @@ 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 {
+
+  
+}
 
 
 
@@ -2208,6 +2237,8 @@ export class EditorItem extends MySprite {
   arrow: MySprite;
   label: Label;
   text;
+  arrowTop;
+  arrowRight;
 
   showLabel(text = null) {
 
@@ -2246,6 +2277,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 +2300,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 +2372,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/src/app/common/custom-hot-zone/custom-hot-zone.component.html b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.html
index 9028527061890eefb1557c53f49394c7ea827b11..5b4c960d0b2879108296f2446042b11bef192136 100644
--- a/form/src/app/common/custom-hot-zone/custom-hot-zone.component.html
+++ b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.html
@@ -32,33 +32,111 @@
 
         <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>
 
+        <!-- <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 +161,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 +193,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/src/app/common/custom-hot-zone/custom-hot-zone.component.scss b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.scss
index 9e2c2bf053571db2d78708132b23fe87e0acc9b2..e9c64dc393214577bbff75a4e57ec2969a3600e4 100644
--- a/form/src/app/common/custom-hot-zone/custom-hot-zone.component.scss
+++ b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.scss
@@ -81,19 +81,21 @@
   }
 }
 
-h5 {
-  margin-top: 1rem;
+.anima-upload-btn {
+  padding: 10px;
 }
 
-
-
-@font-face
-{
-  font-family: 'BRLNSR_1';
-  src: url("/assets/font/BRLNSR_1.TTF") ;
+h5 {
+  margin-top: 1rem;
 }
 
 
+//
+//@font-face
+//{
+//  font-family: 'BRLNSR_1';
+//  src: url("/assets/font/BRLNSR_1.TTF") ;
+//}
 
 
 
@@ -107,104 +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/src/app/common/custom-hot-zone/custom-hot-zone.component.ts b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.ts
index dc2a4cf04d4592cc6a399cf5708c713dbb3439fd..bbfc3d0f2466d2ba206f32fd6b8badaa4ce779ae 100644
--- a/form/src/app/common/custom-hot-zone/custom-hot-zone.component.ts
+++ b/form/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 {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,30 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
   @Input()
   isHasText = true;
   @Input()
-  hotZoneFontObj = {
-    size: 50,
-    name: 'BRLNSR_1',
-    color: '#8f3758'
-  }
+  isHasAudio = true;
   @Input()
-  defaultItemType = 'text';
+  isHasAnima = false;
+  @Input()
+  customTypeGroupArr; // [{name:string, rect:boolean, pic:boolean, text:boolean, audio:boolean, anima:boolean, animaNames:['name1', ..]}, ...]
+  @Input()
+  hotZoneFontObj;
+  @Input()
+  isCopyData = false;
 
+  // hotZoneFontObj = {
+  //   size: 50,
+  //   name: 'BRLNSR_1',
+  //   color: '#8f3758'
+  // }
+  @Input()
+  defaultItemType = 'text';
   @Input()
-  hotZoneImgSize = 190;
+  hotZoneImgSize = 0;
+
+
+  @Output()
+  save = new EventEmitter();
+
 
   saveDisabled = true;
 
@@ -86,8 +99,33 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
   changeSizeFlag = false;
   changeTopSizeFlag = false;
   changeRightSizeFlag = false;
+  animaPanelVisible = false;
+
+  uploadUrl;
+  uploadData;
+  skeJsonData = {};
+  texJsonData = {};
+  texPngData = {};
+  animaName = '';
+  curDragonBoneIndex;
+  curDragonBoneGIdx;
+  pasteData = '';
+
+  isSkeJsonLoading = false;
+  isTexJsonLoading = false;
+  isTexPngLoading = false;
+
+  isAnimaSmall = false;
+
 
-  constructor() {
+  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 +148,14 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
 
   ngOnInit() {
 
+
     this.initListener();
 
     // this.init();
     this.update();
 
+    this.refresh();
+
   }
 
   ngOnDestroy() {
@@ -136,10 +177,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,25 +193,32 @@ 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.x = this.canvasWidth / 2;
+      bg.y = this.canvasHeight / 2;
 
-        if (callBack) {
-          callBack();
-        }
-      });
-    }
+      if (callBack) {
+        callBack();
+      }
+
+      this.refresh();
+
+    });
+    // }
 
   }
 
@@ -199,6 +249,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 +272,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
 
       }
     }
+    this.refresh();
   }
 
 
@@ -245,10 +297,17 @@ 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'] = new Date().getTime().toString();
+    item['data'] = saveData;
+
+    console.log('item.x: ', item.x);
 
     if (saveData) {
 
@@ -257,41 +316,143 @@ 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];
     }
 
+    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);
+
+
+
+    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);
+  }
+
+  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 +488,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 +500,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
 
   onAudioUploadSuccessByImg(e, img) {
     img.audio_url = e.url;
+    this.refresh();
   }
 
   deleteItem(e, i) {
@@ -345,15 +509,106 @@ 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.refreshItem(item);
+  //   this.refresh();
+  //   // console.log(' in radioChange e: ', e);
+  // }
+
+  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, true);
+    }
+
+    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.setAnimaStyle(group.animaSmall)
+    
+
+  }
+
+  setItemIsAnimaStyle(item, isAnimal) {
+
+  }
+
+  showItemPic(item) {
+    item.pic.visible = true;
+    item.itemType = 'pic';
+    this.showArrowTop(item)
+  }
+
+  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,13 +623,14 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
         this.setTextState(item);
         break;
       default:
-
+        this.setNoneState(item);
     }
   }
 
 
   init() {
 
+    console.log('init');
     this.initData();
     this.initCtx();
 
@@ -382,18 +638,15 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
   }
 
   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 = [];
@@ -404,6 +657,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
       });
     }
 
+    this.refresh();
   }
 
   initHotZoneArr() {
@@ -427,6 +681,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 +704,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 +724,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 +747,10 @@ 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];
+      console.log('mapDown item: ', item);
       let callback;
       let target;
       switch (item.itemType) {
@@ -548,7 +768,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
           break;
       }
 
-      if (this.checkClickTarget(target)) {
+      if (target && this.checkClickTarget(target)) {
         callback(target);
         return;
       }
@@ -582,7 +802,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
 
     this.oldPos = {x: this.mx, y: this.my};
 
-    this.saveDisabled = true;
+    // this.saveDisabled = false;
 
   }
 
@@ -723,7 +943,7 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
     // }
 
     this.updateArr(this.hotZoneArr);
-    this.updatePos()
+    this.updatePos();
 
 
     TWEEN.update();
@@ -833,7 +1053,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 +1074,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 +1104,43 @@ 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
+        mapScale: this.mapScale,
+        skeJsonData: hotZoneArr[i].skeJsonData,
+        texJsonData: hotZoneArr[i].texJsonData,
+        texPngData: hotZoneArr[i].texPngData,
+        gIdx: hotZoneArr[i].gIdx
       };
-      hotZoneItem['rect'] = hotZoneArr[i].getBoundingBox();
+
+      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 +1152,275 @@ 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;
+    }
+  }
+
+  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;
+    }
+  }
+
+  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 +1443,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 +1473,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 +1497,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 +1518,38 @@ export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges {
     }
   }
 
-  saveText(item) {
-    item.textLabel.text = item.text;
-  }
+  private loadHotZonePic(pic: HotZoneImg, url, scale = null) {
+
+    let baseLen;
+    if (this.hotZoneImgSize) {
+      baseLen = this.hotZoneImgSize * this.mapScale;
+    }
 
-  private loadHotZonePic(pic: HotZoneImg, url) {
-    const 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/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts b/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts
index f4694a1f1ae4b582b3c121e601c6322437888820..78fd0de68f50fc42cd6c771bcc29f736b837113f 100644
--- a/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts
+++ b/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts
@@ -42,7 +42,24 @@ export class UploadImageWithPreviewComponent implements OnDestroy, OnChanges {
       this.uploadData = data;
     };
 
+    this.setUploadUrl();
   }
+
+
+  setUploadUrl() {
+
+    if (!this.uploadUrl) {
+
+      this.uploadUrl = (<any> window).courseware.uploadUrl();
+      this.uploadData = (<any> window).courseware.uploadData();
+
+      setTimeout(() => {
+        this.setUploadUrl();
+      }, 500);
+    }
+  }
+
+
   ngOnChanges() {
     if (!this.picItem) {
       return;
diff --git a/form/src/app/form/form.component.html b/form/src/app/form/form.component.html
index c07239d45cf36658f22d7be4473cd52667687489..501cbe890eaaa9409624e9396907c942f8ac9d1c 100644
--- a/form/src/app/form/form.component.html
+++ b/form/src/app/form/form.component.html
@@ -1,8 +1,36 @@
 <div class="model-content">
- 
   <div style="padding: 10px;">
-    
-    <div style="width: 300px;" align='center'>
+
+    <!--
+ 
+
+    <div style="width: 100%; margin-top: 15px; margin-bottom: 50px;" align="center">
+      <h2>标题设置</h2>
+      <div style="width: 50%; display: flex; justify-content: center; align-items: center;">
+        <input type="text" nz-input [(ngModel)]="item.title" (blur)="save()" style="width: 200px;margin-top: 5px">
+        <app-audio-recorder
+            style="margin-top: 5px; margin-left: 5px;"
+            [audioUrl]="item.title_audio_url"
+            (audioUploaded)="onAudioUploadSuccess($event, 'title_audio_url')"
+          ></app-audio-recorder>
+      </div>
+  
+    </div>
+  -->
+    <div *ngFor='let data of item ;index as i'>
+      <span> 卡片{{i+1}}</span>
+      <app-custom-hot-zone-mini [bgItem]="data.bgItem" [hotZoneItemArr]="data.hotZoneItemArr"
+        [customTypeGroupArr]="customTypeGroupArr" (save)="saveHotZone(data, $event)" (del)="delHotZone(i)">
+      </app-custom-hot-zone-mini>
+    </div>
+    <div style="margin-top: 20px; width: 100%; display: inline-flex; align-items: center;justify-content: center;">
+      <button class="save-btn" nz-button nzType="primary" [nzSize]="'large'" nzShape="round" (click)="addClick()">
+        <i nz-icon nzType="save"></i>
+        添加新卡片
+      </button>
+    </div>
+
+    <!-- <div style="width: 300px;" align='center'>
       <span>图1: </span>
       <app-upload-image-with-preview
         [picUrl]="item.pic_url"
@@ -29,8 +57,8 @@
         [audioUrl]="item.audio_url"
         (audioUploaded)="onAudioUploadSuccess($event, 'audio_url')"
       ></app-audio-recorder>
-    </div>
+    </div> -->
 
   </div>
 
-</div>
+</div>
\ No newline at end of file
diff --git a/form/src/app/form/form.component.ts b/form/src/app/form/form.component.ts
index 82a6e9121ba195cd3bf69b7c9744570ff9f97458..b4dccdc3456a2f1152718e568407a1c115ce4f42 100644
--- a/form/src/app/form/form.component.ts
+++ b/form/src/app/form/form.component.ts
@@ -10,10 +10,39 @@ import { JsonPipe } from '@angular/common';
 export class FormComponent implements OnInit, OnChanges, OnDestroy {
 
   // 储存数据用
-  saveKey = "test_001";
+  saveKey = "PU22";
   // 储存对象
   item;
 
+  customTypeGroupArr = [
+    {
+      name: '句子音频',
+      action: {
+        type: 'text',
+        audio:true,
+        option: [
+          ['fontColor', '#000000'],
+          ['fontSize', '100']
+        ]
+      }
+    },
+    {
+      name: '点击区域',
+      action: {
+        type: 'text',
+        aduio:false,
+        option: [
+          ['fontColor', '#000000'],
+          ['fontSize', '100']
+        ]
+      },
+    },
+    {
+      name: '图片',
+      pic: true
+    }
+  ]
+
   constructor(private appRef: ApplicationRef, private changeDetectorRef: ChangeDetectorRef) {
 
   }
@@ -35,12 +64,12 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
 
   ngOnInit() {
 
-    this.item = {};
+    this.item = [];
 
     // 获取存储的数据
     (<any>window).courseware.getData((data) => {
 
-      if (data) {
+      if (data && data.length) {
         this.item = data;
       }
 
@@ -63,33 +92,25 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
   }
 
 
-  /**
-   * 储存图片数据
-   * @param e
-   */
-  onImageUploadSuccess(e, key) {
+  /** 保存按钮 */
+  saveHotZone(group, e) {
+    console.log('e: ', e);
+    const { hotZoneItemArr, bgItem } = e;
 
-    this.item[key] = e.url;
-    this.save();
-  }
+    group.bgItem = bgItem;
+    group.hotZoneItemArr = hotZoneItemArr;
 
-  /**
-   * 储存音频数据
-   * @param e
-   */
-  onAudioUploadSuccess(e, key) {
-    this.item[key] = e.url;
     this.save();
   }
 
-  onWordAudioUploadSuccess(e, idx) {
-    this.item.wordList[idx].audio = e.url;
-    this.save();
+  /** 删除按钮 */
+  delHotZone(index: number) {
+    this.item.splice(index, 1)
   }
 
-  onBackWordAudioUploadSuccess(e, idx) {
-    this.item.wordList[idx].backWordAudio = e.url;
-    this.save();
+  /** 添加按钮 */
+  addClick() {
+    this.item.push({})
   }
 
   /**
diff --git a/play/assets/scene/anim.meta b/play/assets/scene/anim.meta
new file mode 100644
index 0000000000000000000000000000000000000000..acd7917acbeef9d969749844e6d7bf3bcfebdc4c
--- /dev/null
+++ b/play/assets/scene/anim.meta
@@ -0,0 +1,12 @@
+{
+  "ver": "1.1.2",
+  "uuid": "f10d537b-d9e1-4903-ae19-44fda7c00000",
+  "isBundle": false,
+  "bundleName": "",
+  "priority": 1,
+  "compressionType": {},
+  "optimizeHotUpdate": {},
+  "inlineSpriteFrames": {},
+  "isRemoteBundle": {},
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/anim/hand.anim b/play/assets/scene/anim/hand.anim
new file mode 100644
index 0000000000000000000000000000000000000000..dea2fc98a788fb63c0b63d6805647d72f1c5395e
--- /dev/null
+++ b/play/assets/scene/anim/hand.anim
@@ -0,0 +1,120 @@
+{
+  "__type__": "cc.AnimationClip",
+  "_name": "hand",
+  "_objFlags": 0,
+  "_native": "",
+  "_duration": 0.7,
+  "sample": 30,
+  "speed": 1,
+  "wrapMode": 2,
+  "curveData": {
+    "paths": {
+      "icon_hand": {
+        "comps": {
+          "cc.Sprite": {
+            "spriteFrame": [
+              {
+                "frame": 0,
+                "value": {
+                  "__uuid__": "562deefd-c9fd-42f0-97d7-d6f5893ef3f3"
+                }
+              },
+              {
+                "frame": 0.3333333333333333,
+                "value": {
+                  "__uuid__": "61e47c68-658d-416b-a46e-399ebfddd2c8"
+                }
+              },
+              {
+                "frame": 0.6666666666666666,
+                "value": {
+                  "__uuid__": "562deefd-c9fd-42f0-97d7-d6f5893ef3f3"
+                }
+              }
+            ]
+          }
+        },
+        "props": {
+          "color": [
+            {
+              "frame": 0,
+              "value": {
+                "__type__": "cc.Color",
+                "r": 255,
+                "g": 255,
+                "b": 255,
+                "a": 255
+              },
+              "curve": "constant"
+            },
+            {
+              "frame": 0.3333333333333333,
+              "value": {
+                "__type__": "cc.Color",
+                "r": 176,
+                "g": 176,
+                "b": 176,
+                "a": 255
+              },
+              "curve": "constant"
+            },
+            {
+              "frame": 0.6666666666666666,
+              "value": {
+                "__type__": "cc.Color",
+                "r": 255,
+                "g": 255,
+                "b": 255,
+                "a": 255
+              }
+            }
+          ]
+        }
+      },
+      "icon_dian": {
+        "props": {
+          "scale": [
+            {
+              "frame": 0,
+              "value": {
+                "__type__": "cc.Vec2",
+                "x": 1,
+                "y": 1
+              },
+              "curve": "constant"
+            },
+            {
+              "frame": 0.3333333333333333,
+              "value": {
+                "__type__": "cc.Vec2",
+                "x": 1.3,
+                "y": 1.3
+              },
+              "curve": "constant"
+            },
+            {
+              "frame": 0.6666666666666666,
+              "value": {
+                "__type__": "cc.Vec2",
+                "x": 1,
+                "y": 1
+              }
+            }
+          ],
+          "position": [
+            {
+              "frame": 0,
+              "value": [
+                -22.199,
+                34.822,
+                0
+              ],
+              "curve": "constant"
+            }
+          ]
+        }
+      }
+    }
+  },
+  "events": []
+}
\ No newline at end of file
diff --git a/play/assets/scene/anim/hand.anim.meta b/play/assets/scene/anim/hand.anim.meta
new file mode 100644
index 0000000000000000000000000000000000000000..6a535743024bb459b92e2d22a7a162544ad859ab
--- /dev/null
+++ b/play/assets/scene/anim/hand.anim.meta
@@ -0,0 +1,5 @@
+{
+  "ver": "2.1.0",
+  "uuid": "110d5a6d-4d4e-4a04-bed2-4bb56c56d03d",
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/anim/play.anim b/play/assets/scene/anim/play.anim
new file mode 100644
index 0000000000000000000000000000000000000000..2bc8125236b8a5bf281502a0ad9e02be42be6392
--- /dev/null
+++ b/play/assets/scene/anim/play.anim
@@ -0,0 +1,49 @@
+{
+  "__type__": "cc.AnimationClip",
+  "_name": "play",
+  "_objFlags": 0,
+  "_native": "",
+  "_duration": 0.6721311475409836,
+  "sample": 61,
+  "speed": 1,
+  "wrapMode": 2,
+  "curveData": {
+    "comps": {
+      "cc.Sprite": {
+        "spriteFrame": [
+          {
+            "frame": 0,
+            "value": {
+              "__uuid__": "e1f16c77-4cd2-497e-997a-b449b3d76d99"
+            }
+          },
+          {
+            "frame": 0.16393442622950818,
+            "value": {
+              "__uuid__": "52418a35-ae97-4789-9c2c-43a512ede990"
+            }
+          },
+          {
+            "frame": 0.32786885245901637,
+            "value": {
+              "__uuid__": "d40e39de-f46a-4f57-86ad-dc74e14f693b"
+            }
+          },
+          {
+            "frame": 0.4918032786885246,
+            "value": {
+              "__uuid__": "d7e29cfd-3377-4ecc-a909-3740e092b0f0"
+            }
+          },
+          {
+            "frame": 0.6557377049180327,
+            "value": {
+              "__uuid__": "e1f16c77-4cd2-497e-997a-b449b3d76d99"
+            }
+          }
+        ]
+      }
+    }
+  },
+  "events": []
+}
\ No newline at end of file
diff --git a/play/assets/scene/anim/play.anim.meta b/play/assets/scene/anim/play.anim.meta
new file mode 100644
index 0000000000000000000000000000000000000000..00dcfe8d17da44d8f6ab36d1548b13e1fdfe71be
--- /dev/null
+++ b/play/assets/scene/anim/play.anim.meta
@@ -0,0 +1,5 @@
+{
+  "ver": "2.1.0",
+  "uuid": "29f7a8c5-7319-4476-9ba0-04570a2c1aae",
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/anim/stop.anim b/play/assets/scene/anim/stop.anim
new file mode 100644
index 0000000000000000000000000000000000000000..8b3cdbb21c8c152614816e650978e3b364a14a6a
--- /dev/null
+++ b/play/assets/scene/anim/stop.anim
@@ -0,0 +1,25 @@
+{
+  "__type__": "cc.AnimationClip",
+  "_name": "stop",
+  "_objFlags": 0,
+  "_native": "",
+  "_duration": 0.016666666666666666,
+  "sample": 60,
+  "speed": 1,
+  "wrapMode": 1,
+  "curveData": {
+    "comps": {
+      "cc.Sprite": {
+        "spriteFrame": [
+          {
+            "frame": 0,
+            "value": {
+              "__uuid__": "e1f16c77-4cd2-497e-997a-b449b3d76d99"
+            }
+          }
+        ]
+      }
+    }
+  },
+  "events": []
+}
\ No newline at end of file
diff --git a/play/assets/scene/anim/stop.anim.meta b/play/assets/scene/anim/stop.anim.meta
new file mode 100644
index 0000000000000000000000000000000000000000..0eae5d699227e33a7fa6cbc09ff2552d4f73a864
--- /dev/null
+++ b/play/assets/scene/anim/stop.anim.meta
@@ -0,0 +1,5 @@
+{
+  "ver": "2.1.0",
+  "uuid": "b76a0905-ec65-4ce9-bd62-ea2a6fad9330",
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/anim/tips.anim b/play/assets/scene/anim/tips.anim
new file mode 100644
index 0000000000000000000000000000000000000000..fbe252434fdb1ee9ea35ea3045058ab3d911ce57
--- /dev/null
+++ b/play/assets/scene/anim/tips.anim
@@ -0,0 +1,31 @@
+{
+  "__type__": "cc.AnimationClip",
+  "_name": "tips",
+  "_objFlags": 0,
+  "_native": "",
+  "_duration": 0.5,
+  "sample": 40,
+  "speed": 1,
+  "wrapMode": 2,
+  "curveData": {
+    "props": {
+      "opacity": [
+        {
+          "frame": 0,
+          "value": 255,
+          "curve": "cubicIn"
+        },
+        {
+          "frame": 0.25,
+          "value": 0,
+          "curve": "cubicIn"
+        },
+        {
+          "frame": 0.5,
+          "value": 255
+        }
+      ]
+    }
+  },
+  "events": []
+}
\ No newline at end of file
diff --git a/play/assets/scene/anim/tips.anim.meta b/play/assets/scene/anim/tips.anim.meta
new file mode 100644
index 0000000000000000000000000000000000000000..cc71ec06289f1b7f9ed8b35000706d5ee5e5773f
--- /dev/null
+++ b/play/assets/scene/anim/tips.anim.meta
@@ -0,0 +1,5 @@
+{
+  "ver": "2.1.0",
+  "uuid": "a13d6552-0ece-42e3-813a-2029ad0cab0c",
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/audios/btn.mp3 "b/play/assets/scene/audios/\346\214\211\351\222\256.mp3"
similarity index 100%
rename from play/assets/scene/audios/btn.mp3
rename to "play/assets/scene/audios/\346\214\211\351\222\256.mp3"
diff --git a/play/assets/scene/audios/btn.mp3.meta "b/play/assets/scene/audios/\346\214\211\351\222\256.mp3.meta"
similarity index 61%
rename from play/assets/scene/audios/btn.mp3.meta
rename to "play/assets/scene/audios/\346\214\211\351\222\256.mp3.meta"
index 4255f217d13c5f8788bff619f2345a38b5365a4e..7611244735105d7f4e9133e14feaaa19566f99ad 100644
--- a/play/assets/scene/audios/btn.mp3.meta
+++ "b/play/assets/scene/audios/\346\214\211\351\222\256.mp3.meta"
@@ -1,6 +1,6 @@
 {
   "ver": "2.0.1",
-  "uuid": "f0680ae0-c079-45ef-abd7-9e63d90b982b",
+  "uuid": "39ef1939-3bf9-4d21-a67a-bc1dede521a9",
   "downloadMode": 0,
   "duration": 0.130612,
   "subMetas": {}
diff --git "a/play/assets/scene/audios/\346\217\220\347\244\272.mp3" "b/play/assets/scene/audios/\346\217\220\347\244\272.mp3"
new file mode 100644
index 0000000000000000000000000000000000000000..809b4d67a64908fc3f00307db1e0980b57d4e072
Binary files /dev/null and "b/play/assets/scene/audios/\346\217\220\347\244\272.mp3" differ
diff --git "a/play/assets/scene/audios/\346\217\220\347\244\272.mp3.meta" "b/play/assets/scene/audios/\346\217\220\347\244\272.mp3.meta"
new file mode 100644
index 0000000000000000000000000000000000000000..5a1e1c5286e49d56041910ed18a9590370d6276c
--- /dev/null
+++ "b/play/assets/scene/audios/\346\217\220\347\244\272.mp3.meta"
@@ -0,0 +1,7 @@
+{
+  "ver": "2.0.1",
+  "uuid": "e0bcf4cc-35a7-4d61-b202-8dd49299c2c0",
+  "downloadMode": 0,
+  "duration": 1.7487,
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/prefab.meta b/play/assets/scene/prefab.meta
new file mode 100644
index 0000000000000000000000000000000000000000..76d5051141ab4d2162b7bb6ba79f6f1bd7f25506
--- /dev/null
+++ b/play/assets/scene/prefab.meta
@@ -0,0 +1,12 @@
+{
+  "ver": "1.1.2",
+  "uuid": "be0db2d0-24f0-4d3d-b613-ad695edaac17",
+  "isBundle": false,
+  "bundleName": "",
+  "priority": 1,
+  "compressionType": {},
+  "optimizeHotUpdate": {},
+  "inlineSpriteFrames": {},
+  "isRemoteBundle": {},
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/prefab/hitItem.prefab b/play/assets/scene/prefab/hitItem.prefab
new file mode 100644
index 0000000000000000000000000000000000000000..96cbac35b351e1574c0ee9d0bb3d787da13e88c8
--- /dev/null
+++ b/play/assets/scene/prefab/hitItem.prefab
@@ -0,0 +1,217 @@
+[
+  {
+    "__type__": "cc.Prefab",
+    "_name": "",
+    "_objFlags": 0,
+    "_native": "",
+    "data": {
+      "__id__": 1
+    },
+    "optimizationPolicy": 0,
+    "asyncLoadAssets": false,
+    "readonly": false
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "hitItem",
+    "_objFlags": 0,
+    "_parent": null,
+    "_children": [
+      {
+        "__id__": 2
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 5
+      }
+    ],
+    "_prefab": {
+      "__id__": 6
+    },
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 64.47,
+      "height": 55
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "words",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 1
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 3
+      }
+    ],
+    "_prefab": {
+      "__id__": 4
+    },
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 103.13,
+      "height": 50.4
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Label",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_string": "test111",
+    "_N$string": "test111",
+    "_fontSize": 40,
+    "_lineHeight": 40,
+    "_enableWrapText": true,
+    "_N$file": {
+      "__uuid__": "c551970e-b095-45f3-9f1d-25cde8b8deb1"
+    },
+    "_isSystemFontUsed": false,
+    "_spacingX": 0,
+    "_batchAsBitmap": false,
+    "_styleFlags": 0,
+    "_underlineHeight": 0,
+    "_N$horizontalAlign": 1,
+    "_N$verticalAlign": 1,
+    "_N$fontFamily": "Arial",
+    "_N$overflow": 0,
+    "_N$cacheMode": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__uuid__": "2ce7d58d-b6fe-4ef7-a128-de76f672a803"
+    },
+    "fileId": "c1fOVqHUFI3qPBAVhvKrZa",
+    "sync": false
+  },
+  {
+    "__type__": "57f79KAb0tNU7HjHMpUOk2e",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 1
+    },
+    "_enabled": true,
+    "label": {
+      "__id__": 3
+    },
+    "tipClip": {
+      "__uuid__": "e0bcf4cc-35a7-4d61-b202-8dd49299c2c0"
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__uuid__": "2ce7d58d-b6fe-4ef7-a128-de76f672a803"
+    },
+    "fileId": "",
+    "sync": false
+  }
+]
\ No newline at end of file
diff --git a/play/assets/scene/prefab/hitItem.prefab.meta b/play/assets/scene/prefab/hitItem.prefab.meta
new file mode 100644
index 0000000000000000000000000000000000000000..937337b47ad69691df6916c7d6af8895edcd6828
--- /dev/null
+++ b/play/assets/scene/prefab/hitItem.prefab.meta
@@ -0,0 +1,8 @@
+{
+  "ver": "1.2.9",
+  "uuid": "2ce7d58d-b6fe-4ef7-a128-de76f672a803",
+  "optimizationPolicy": "AUTO",
+  "asyncLoadAssets": false,
+  "readonly": false,
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/prefab/picItem.prefab b/play/assets/scene/prefab/picItem.prefab
new file mode 100644
index 0000000000000000000000000000000000000000..0cece62762fc367b95fb1b9f9ea8607b7881bf6e
--- /dev/null
+++ b/play/assets/scene/prefab/picItem.prefab
@@ -0,0 +1,486 @@
+[
+  {
+    "__type__": "cc.Prefab",
+    "_name": "",
+    "_objFlags": 0,
+    "_native": "",
+    "data": {
+      "__id__": 1
+    },
+    "optimizationPolicy": 0,
+    "asyncLoadAssets": false,
+    "readonly": false
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "node",
+    "_objFlags": 0,
+    "_parent": null,
+    "_children": [
+      {
+        "__id__": 2
+      },
+      {
+        "__id__": 6
+      },
+      {
+        "__id__": 10
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 13
+      }
+    ],
+    "_prefab": {
+      "__id__": 14
+    },
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 40,
+      "height": 36
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "New Sprite(Splash)",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 1
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 3
+      },
+      {
+        "__id__": 4
+      }
+    ],
+    "_prefab": {
+      "__id__": 5
+    },
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 107,
+      "g": 106,
+      "b": 151,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 48,
+      "height": 44
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "a23235d1-15db-4b95-8439-a2e005bfff91"
+    },
+    "_type": 0,
+    "_sizeMode": 0,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Widget",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "alignMode": 1,
+    "_target": null,
+    "_alignFlags": 45,
+    "_left": -4,
+    "_right": -4,
+    "_top": -4,
+    "_bottom": -4,
+    "_verticalCenter": 0,
+    "_horizontalCenter": 0,
+    "_isAbsLeft": true,
+    "_isAbsRight": true,
+    "_isAbsTop": true,
+    "_isAbsBottom": true,
+    "_isAbsHorizontalCenter": true,
+    "_isAbsVerticalCenter": true,
+    "_originalWidth": 100,
+    "_originalHeight": 100,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__uuid__": "85e73971-9396-4c2a-9fac-2b187fd99c48"
+    },
+    "fileId": "3fpP7V8bRL9I4tBqsQ4W/R",
+    "sync": false
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "New Sprite(Splash)",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 1
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 7
+      },
+      {
+        "__id__": 8
+      }
+    ],
+    "_prefab": {
+      "__id__": 9
+    },
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 185,
+      "g": 213,
+      "b": 245,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 40,
+      "height": 36
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 6
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "a23235d1-15db-4b95-8439-a2e005bfff91"
+    },
+    "_type": 0,
+    "_sizeMode": 0,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Widget",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 6
+    },
+    "_enabled": true,
+    "alignMode": 1,
+    "_target": null,
+    "_alignFlags": 45,
+    "_left": 0,
+    "_right": 0,
+    "_top": 0,
+    "_bottom": 0,
+    "_verticalCenter": 0,
+    "_horizontalCenter": 0,
+    "_isAbsLeft": true,
+    "_isAbsRight": true,
+    "_isAbsTop": true,
+    "_isAbsBottom": true,
+    "_isAbsHorizontalCenter": true,
+    "_isAbsVerticalCenter": true,
+    "_originalWidth": 100,
+    "_originalHeight": 100,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__uuid__": "85e73971-9396-4c2a-9fac-2b187fd99c48"
+    },
+    "fileId": "e0zPyfqplEKZlyC2lXi40G",
+    "sync": false
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "New Node",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 1
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 11
+      }
+    ],
+    "_prefab": {
+      "__id__": 12
+    },
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 0,
+      "height": 0
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 10
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": null,
+    "_type": 0,
+    "_sizeMode": 1,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__uuid__": "85e73971-9396-4c2a-9fac-2b187fd99c48"
+    },
+    "fileId": "25GAuqDahFz4vaRdWo8jdV",
+    "sync": false
+  },
+  {
+    "__type__": "577b3ZhuUNJtLzUNX3CEf1G",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 1
+    },
+    "_enabled": true,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__uuid__": "85e73971-9396-4c2a-9fac-2b187fd99c48"
+    },
+    "fileId": "",
+    "sync": false
+  }
+]
\ No newline at end of file
diff --git a/play/assets/scene/prefab/picItem.prefab.meta b/play/assets/scene/prefab/picItem.prefab.meta
new file mode 100644
index 0000000000000000000000000000000000000000..99bf87943b331e0101597fc94e5a7626179281b3
--- /dev/null
+++ b/play/assets/scene/prefab/picItem.prefab.meta
@@ -0,0 +1,8 @@
+{
+  "ver": "1.2.9",
+  "uuid": "85e73971-9396-4c2a-9fac-2b187fd99c48",
+  "optimizationPolicy": "AUTO",
+  "asyncLoadAssets": false,
+  "readonly": false,
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/prefab/wordsItem.prefab b/play/assets/scene/prefab/wordsItem.prefab
new file mode 100644
index 0000000000000000000000000000000000000000..d72d6f1b4579107f8a01f798cd6d7a1b5c71fb7c
--- /dev/null
+++ b/play/assets/scene/prefab/wordsItem.prefab
@@ -0,0 +1,437 @@
+[
+  {
+    "__type__": "cc.Prefab",
+    "_name": "",
+    "_objFlags": 0,
+    "_native": "",
+    "data": {
+      "__id__": 1
+    },
+    "optimizationPolicy": 0,
+    "asyncLoadAssets": false,
+    "readonly": false
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "wordsItem",
+    "_objFlags": 0,
+    "_parent": null,
+    "_children": [
+      {
+        "__id__": 2
+      },
+      {
+        "__id__": 5
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 11
+      }
+    ],
+    "_prefab": {
+      "__id__": 12
+    },
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 64.51,
+      "height": 55
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "words",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 1
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 3
+      }
+    ],
+    "_prefab": {
+      "__id__": 4
+    },
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 64.51,
+      "height": 50.4
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Label",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_string": "test",
+    "_N$string": "test",
+    "_fontSize": 40,
+    "_lineHeight": 40,
+    "_enableWrapText": true,
+    "_N$file": {
+      "__uuid__": "c551970e-b095-45f3-9f1d-25cde8b8deb1"
+    },
+    "_isSystemFontUsed": false,
+    "_spacingX": 0,
+    "_batchAsBitmap": false,
+    "_styleFlags": 0,
+    "_underlineHeight": 0,
+    "_N$horizontalAlign": 1,
+    "_N$verticalAlign": 1,
+    "_N$fontFamily": "Arial",
+    "_N$overflow": 0,
+    "_N$cacheMode": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__uuid__": "a33b90a4-90af-4a31-91ad-110894bbe407"
+    },
+    "fileId": "c1fOVqHUFI3qPBAVhvKrZa",
+    "sync": false
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "btn_laba",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 1
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 6
+      },
+      {
+        "__id__": 7
+      },
+      {
+        "__id__": 8
+      }
+    ],
+    "_prefab": {
+      "__id__": 10
+    },
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 55,
+      "height": 59
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        78.809,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        0
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 5
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "e1f16c77-4cd2-497e-997a-b449b3d76d99"
+    },
+    "_type": 0,
+    "_sizeMode": 1,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Animation",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 5
+    },
+    "_enabled": true,
+    "_defaultClip": {
+      "__uuid__": "29f7a8c5-7319-4476-9ba0-04570a2c1aae"
+    },
+    "_clips": [
+      {
+        "__uuid__": "29f7a8c5-7319-4476-9ba0-04570a2c1aae"
+      },
+      {
+        "__uuid__": "b76a0905-ec65-4ce9-bd62-ea2a6fad9330"
+      }
+    ],
+    "playOnLoad": false,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Button",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 5
+    },
+    "_enabled": true,
+    "_normalMaterial": null,
+    "_grayMaterial": null,
+    "duration": 0.1,
+    "zoomScale": 1.1,
+    "clickEvents": [
+      {
+        "__id__": 9
+      }
+    ],
+    "_N$interactable": true,
+    "_N$enableAutoGrayEffect": false,
+    "_N$transition": 3,
+    "transition": 3,
+    "_N$normalColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_N$pressedColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "pressedColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "_N$hoverColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "hoverColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_N$disabledColor": {
+      "__type__": "cc.Color",
+      "r": 124,
+      "g": 124,
+      "b": 124,
+      "a": 255
+    },
+    "_N$normalSprite": null,
+    "_N$pressedSprite": null,
+    "pressedSprite": null,
+    "_N$hoverSprite": null,
+    "hoverSprite": null,
+    "_N$disabledSprite": null,
+    "_N$target": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.ClickEvent",
+    "target": {
+      "__id__": 1
+    },
+    "component": "",
+    "_componentId": "95b1cfOTcFNvrVj8RwK3uQo",
+    "handler": "onTouchStart",
+    "customEventData": ""
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__uuid__": "a33b90a4-90af-4a31-91ad-110894bbe407"
+    },
+    "fileId": "cdhgEaqJBJ7795mvHoWguU",
+    "sync": false
+  },
+  {
+    "__type__": "95b1cfOTcFNvrVj8RwK3uQo",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 1
+    },
+    "_enabled": true,
+    "label": {
+      "__id__": 3
+    },
+    "playAnim": {
+      "__id__": 7
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__uuid__": "a33b90a4-90af-4a31-91ad-110894bbe407"
+    },
+    "fileId": "",
+    "sync": false
+  }
+]
\ No newline at end of file
diff --git a/play/assets/scene/prefab/wordsItem.prefab.meta b/play/assets/scene/prefab/wordsItem.prefab.meta
new file mode 100644
index 0000000000000000000000000000000000000000..6a11647053b448eab9998d4860de0070bccc5918
--- /dev/null
+++ b/play/assets/scene/prefab/wordsItem.prefab.meta
@@ -0,0 +1,8 @@
+{
+  "ver": "1.2.9",
+  "uuid": "a33b90a4-90af-4a31-91ad-110894bbe407",
+  "optimizationPolicy": "AUTO",
+  "asyncLoadAssets": false,
+  "readonly": false,
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/scene/audioItem.js b/play/assets/scene/scene/audioItem.js
new file mode 100644
index 0000000000000000000000000000000000000000..2e00d0ed06d21b69edfa1f29f389f3de77d73ca4
--- /dev/null
+++ b/play/assets/scene/scene/audioItem.js
@@ -0,0 +1,103 @@
+cc.Class({
+    extends: cc.Component,
+
+    properties: {
+        playBtn: cc.Node,
+        label: cc.Label,
+        tiao: cc.Node
+    },
+    onload() {
+        this._clip = null
+        this._play = false
+        this._audioId = null
+        this._totoalTime = null
+        this._nowTime = null
+    },
+    onEnable() {
+        cc.systemEvent.on('stopBgMusic', this.onEvent, this)
+    },
+
+    onDisable() {
+        cc.systemEvent.off('stopBgMusic', this.onEvent, this)
+    },
+    init(url) {
+        this.stopAudio()
+        this.playBtn.children[0].active = false
+        this.playBtn.children[1].active = true
+        cc.assetManager.loadRemote(url, (err, audioClip) => {
+            if (err) return
+            this.clip = audioClip
+            this._totoalTime = audioClip.duration
+            this.label.string = '0:00/' + this.transTime(this._totoalTime)
+            this.tiao.children[0].getComponent(cc.Sprite).fillRange = 0
+            this.tiao.children[1].x =12
+        })
+    },
+
+    onPlay() {
+        this._play = !this._play
+        this.playBtn.children[0].active = this._play
+        this.playBtn.children[1].active = !this._play
+        if (this._play) {
+            if (this._audioId != null) {
+                cc.audioEngine.resume(this._audioId)
+            } else {
+                this._audioId = cc.audioEngine.play(this.clip, false, 0.8);
+                cc.audioEngine.setFinishCallback(this._audioId, this.stopAudio.bind(this));
+                this._nowTime = 0
+            }
+            cc.systemEvent.emit('stopWordsMusic')
+            this.schedule(this.onTimeLoop)
+        } else {
+            this.stopAudio()
+        }
+    },
+
+    /** 定时回调 */
+    onTimeLoop(dt) {
+        this._nowTime += dt
+        this.label.string = this.transTime(this._nowTime) + '/' + this.transTime(this._totoalTime)
+        if (this._nowTime > this._totoalTime) this._nowTime = this._totoalTime
+        let scale = this._nowTime / this._totoalTime
+        this.tiao.children[0].getComponent(cc.Sprite).fillRange = scale
+        this.tiao.children[1].x = 12 + 364 * scale
+    },
+
+    onEvent() {
+        if (!this._play) return
+        this.onStopAudio()
+    },
+
+    onStopAudio() {
+        if (this._nowTime < this._totoalTime) {
+            cc.audioEngine.pause(this._audioId)
+            this._play = false
+            this.playBtn.children[0].active = false
+            this.playBtn.children[1].active = true
+            this.unscheduleAllCallbacks()
+        } else {
+            this.stopAudio()
+        }
+    },
+
+    stopAudio() {
+        if (this._audioId != null) {
+            cc.audioEngine.stop(this._audioId)
+            this._audioId = null
+            this.unscheduleAllCallbacks()
+            this._play = false
+            this.playBtn.children[0].active = false
+            this.playBtn.children[1].active = true
+            this.tiao.children[0].getComponent(cc.Sprite).fillRange = 1
+            this.tiao.children[1].x = 12 + 364 * 1
+        }
+    },
+
+    /** 秒转分钟 */
+    transTime(time) {
+        let temp = Math.floor(time / 60)
+        time = (time - 60 * temp).toFixed(0)
+        if (time < 10) time = '0' + time
+        return temp + ':' + time
+    }
+});
diff --git a/play/assets/scene/script/util.js.meta b/play/assets/scene/scene/audioItem.js.meta
similarity index 74%
rename from play/assets/scene/script/util.js.meta
rename to play/assets/scene/scene/audioItem.js.meta
index e1def927553d2b09ca8503e2d4f8142de7384102..2372d3abc74dc6a1f1d328648b9b5305ef4f1512 100644
--- a/play/assets/scene/script/util.js.meta
+++ b/play/assets/scene/scene/audioItem.js.meta
@@ -1,6 +1,6 @@
 {
   "ver": "1.0.8",
-  "uuid": "ade7af40-d56d-4087-bbc6-2888fef55353",
+  "uuid": "a5d5c97d-70df-4203-9b44-2c83877fab88",
   "isPlugin": false,
   "loadPluginInWeb": true,
   "loadPluginInNative": true,
diff --git a/play/assets/scene/scene/hitItem.js b/play/assets/scene/scene/hitItem.js
new file mode 100644
index 0000000000000000000000000000000000000000..ba760ffa5335678f1b8686db0fb4992cacaf3fca
--- /dev/null
+++ b/play/assets/scene/scene/hitItem.js
@@ -0,0 +1,63 @@
+const tools = require("../script/tools");
+
+
+cc.Class({
+    extends: cc.Component,
+
+    properties: {
+        label: cc.Label,
+        tipClip: cc.AudioClip
+    },
+
+    data: null,
+    onLoad() {
+        this._show = false
+    },
+
+    onEnable() {
+        this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this)
+        cc.systemEvent.on('changeAnswerState', this.onChangeState, this)
+    },
+
+    onDisable() {
+        this.node.off(cc.Node.EventType.TOUCH_START, this.onTouchStart, this)
+        cc.systemEvent.off('changeAnswerState', this.onChangeState, this)
+    },
+
+    initWithData(data, scale) {
+        let action = data['actionData_']
+        if (!action) {
+            this.node.active = false
+            return
+        } else {
+            this.node.action = true
+        }
+        this.data = data
+        let rect = this.data.rect
+        this.node.x = (rect.x + rect.width / 2) * scale
+        this.node.y = (-rect.y - rect.height / 2) * scale
+
+        this.label.node.active = false
+        let option = action.changeOption
+        this.label.node.color = option[0][1] ? cc.color(option[0][1]) : cc.color(0, 0, 0)
+        let num = Number(option[1][1]) * scale * data.fontScale
+        this.label.fontSize = num
+        this.label.lineHeight = num
+        this.label.string = action.text ? action.text : ''
+        this.node.width = rect.width * scale
+        this.node.height = rect.height * scale
+    },
+
+    onTouchStart() {
+        if (this._show) return
+        this._show = true
+        this.label.node.active = true
+        cc.audioEngine.play(this.tipClip)
+    },
+
+    /** 改变答案显示状态 */
+    onChangeState(show) {
+        this.label.node.active = show
+        this._show =show
+    }
+});
diff --git a/play/assets/scene/scene/hitItem.js.meta b/play/assets/scene/scene/hitItem.js.meta
new file mode 100644
index 0000000000000000000000000000000000000000..ef69270e0d5565ace147c40185d196bc6eda5178
--- /dev/null
+++ b/play/assets/scene/scene/hitItem.js.meta
@@ -0,0 +1,9 @@
+{
+  "ver": "1.0.8",
+  "uuid": "57f79280-6f4b-4d53-b1e3-1cca543a4d9e",
+  "isPlugin": false,
+  "loadPluginInWeb": true,
+  "loadPluginInNative": true,
+  "loadPluginInEditor": false,
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/scene/picItem.js b/play/assets/scene/scene/picItem.js
new file mode 100644
index 0000000000000000000000000000000000000000..009df87111c3b3f838a6a9d5b068d5f859639858
--- /dev/null
+++ b/play/assets/scene/scene/picItem.js
@@ -0,0 +1,29 @@
+const tools = require("../script/tools");
+
+cc.Class({
+    extends: cc.Component,
+
+    properties: {
+    },
+
+    initWithData(data, scale) {
+        let sprite = this.node.children[2].getComponent(cc.Sprite)
+        tools.getSpriteFrimeByUrl(data.pic_url, (sp) => {
+            sprite.spriteFrame = sp
+            let rect = data.rect
+            this.node.setPosition((rect.x + rect.width / 2) * scale, (-rect.y - rect.height / 2) * scale)
+            let height = rect.height * scale
+            let width = rect.width * scale
+            sprite.node.width = width
+            sprite.node.height = height
+            this.node.height = height
+            this.node.width = width
+            let node = this.node.children[0]
+            node.height = height + 8
+            node.width = width + 8
+            node = this.node.children[1]
+            node.height = height
+            node.width = width
+        })
+    }
+});
diff --git a/play/assets/scene/scene/picItem.js.meta b/play/assets/scene/scene/picItem.js.meta
new file mode 100644
index 0000000000000000000000000000000000000000..d7713748a99ceb5e6aef7a9d78ec3376d694cf47
--- /dev/null
+++ b/play/assets/scene/scene/picItem.js.meta
@@ -0,0 +1,9 @@
+{
+  "ver": "1.0.8",
+  "uuid": "577b3661-b943-49b4-bcd4-357dc211fd46",
+  "isPlugin": false,
+  "loadPluginInWeb": true,
+  "loadPluginInNative": true,
+  "loadPluginInEditor": false,
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/scene/picNode.js b/play/assets/scene/scene/picNode.js
new file mode 100644
index 0000000000000000000000000000000000000000..7c018f60135ada03444a564997636774bc462aba
--- /dev/null
+++ b/play/assets/scene/scene/picNode.js
@@ -0,0 +1,83 @@
+const tools = require("../script/tools");
+
+cc.Class({
+    extends: cc.Component,
+
+    properties: {
+        hitPre: cc.Prefab,
+        wordsPre: cc.Prefab,
+        picPre: cc.Prefab
+    },
+
+    onLoad() {
+        this._hitItem = []
+        this._items = this.node.getChildByName('items')
+        this._sprite = this.getComponentInChildren(cc.Sprite)
+    },
+
+    initWithData(data) {
+        this.clearItems()
+        // tools.getSpriteFrimeByUrl(data.bgItem.url, (sp) => {
+        //     let rect = sp.getRect()
+        //     let scale = rect.width / rect.height
+        //     let originRect = cc.size(1280, 720)
+        //     let originScale = originRect.width / originRect.height
+        //     if (scale < originScale) {
+        //         scale = rect.height / originRect.height
+        //         let width = rect.width / scale
+        //         this.node.width = width
+        //         this.node.height = originRect.height
+
+        //     } else if (scale > originScale) {
+        //         scale = rect.width / originRect.width
+        //         this.node.height = rect.height / scale
+        //         this.node.width = originRect.width
+        //     } else {
+        //         scale = rect.width / originRect.width
+        //         this.node.width = originRect.width
+        //         this.node.height = originRect.height
+        //     }
+        //     this._sprite.spriteFrame = sp
+        //     this._sprite.node.width = this.node.width
+        //     this._sprite.node.height = this.node.height
+        //     this._items.width = this.node.width
+        //     this._items.height = this.node.height
+        //     this._items.x = -this.node.width / 2
+        //     this._items.y = this.node.height / 2
+        //     scale = data.bgItem.rect.width / this.node.width
+        //     //初始化点击区域
+        //     let node, comp
+        //     for (let data of data.hotZoneItemArr) {
+        //         node = cc.instantiate(this.hitPre)
+        //         this._items.addChild(node)
+        //         comp = node.getComponent('hitItem')
+        //         comp.initWithData(data, scale)
+        //         this._hitItem.push(node)
+        //     }
+        // })
+        let rect = data.bgItem.rect
+        let scale =  1280/rect.width 
+        let node
+        for (let one of data.hotZoneItemArr) {
+            if (one.gIdx == '0') { // 发音句子
+                node = cc.instantiate(this.wordsPre)
+                comp = node.getComponent('wordsItem')
+            } else if (one.gIdx == '1') {
+                node = cc.instantiate(this.hitPre)
+                comp = node.getComponent('hitItem')
+            } else {
+                node = cc.instantiate(this.picPre)
+                comp = node.getComponent('picItem')
+            }
+            this._items.addChild(node)
+            comp.initWithData(one, scale)
+            this._hitItem.push(node)
+        }
+    },
+
+    /** 清除item */
+    clearItems() {
+        this._items.removeAllChildren(true)
+        this._hitItem.length = 0
+    }
+});
diff --git a/play/assets/scene/scene/picNode.js.meta b/play/assets/scene/scene/picNode.js.meta
new file mode 100644
index 0000000000000000000000000000000000000000..e644c29df796589dfaba06b67edccf2f50249a89
--- /dev/null
+++ b/play/assets/scene/scene/picNode.js.meta
@@ -0,0 +1,9 @@
+{
+  "ver": "1.0.8",
+  "uuid": "fccd4db5-30ec-4b66-aea2-c29fd0c0301f",
+  "isPlugin": false,
+  "loadPluginInWeb": true,
+  "loadPluginInNative": true,
+  "loadPluginInEditor": false,
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/scene/scene.fire b/play/assets/scene/scene/scene.fire
index 3e7c9dc3d80d5a7f2861f81f99ab3c66cfa30439..1685917a5f52254e4802c24c1503c4403bc78691 100644
--- a/play/assets/scene/scene/scene.fire
+++ b/play/assets/scene/scene/scene.fire
@@ -75,22 +75,28 @@
         "__id__": 5
       },
       {
-        "__id__": 7
+        "__id__": 8
       },
       {
-        "__id__": 14
+        "__id__": 15
+      },
+      {
+        "__id__": 21
+      },
+      {
+        "__id__": 40
       }
     ],
     "_active": true,
     "_components": [
       {
-        "__id__": 24
+        "__id__": 58
       },
       {
-        "__id__": 25
+        "__id__": 59
       },
       {
-        "__id__": 26
+        "__id__": 60
       }
     ],
     "_prefab": null,
@@ -251,15 +257,18 @@
     "_components": [
       {
         "__id__": 6
+      },
+      {
+        "__id__": 7
       }
     ],
     "_prefab": null,
     "_opacity": 255,
     "_color": {
       "__type__": "cc.Color",
-      "r": 255,
-      "g": 255,
-      "b": 255,
+      "r": 197,
+      "g": 244,
+      "b": 187,
       "a": 255
     },
     "_contentSize": {
@@ -299,7 +308,34 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "32MJMZ2HRGF4BOf533Avyi"
+    "_id": "aeaOM8xiFHsZWw7c1ruylq"
+  },
+  {
+    "__type__": "cc.Widget",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 5
+    },
+    "_enabled": true,
+    "alignMode": 1,
+    "_target": null,
+    "_alignFlags": 45,
+    "_left": 0,
+    "_right": 0,
+    "_top": 0,
+    "_bottom": 0,
+    "_verticalCenter": 0,
+    "_horizontalCenter": 0,
+    "_isAbsLeft": true,
+    "_isAbsRight": true,
+    "_isAbsTop": true,
+    "_isAbsBottom": true,
+    "_isAbsHorizontalCenter": true,
+    "_isAbsVerticalCenter": true,
+    "_originalWidth": 1280,
+    "_originalHeight": 720,
+    "_id": "69cJgCzitLTLa9fFvOTBzD"
   },
   {
     "__type__": "cc.Sprite",
@@ -317,10 +353,10 @@
     "_srcBlendFactor": 770,
     "_dstBlendFactor": 771,
     "_spriteFrame": {
-      "__uuid__": "8288e3d4-4c75-4b27-8f01-f7014417f4dd"
+      "__uuid__": "a23235d1-15db-4b95-8439-a2e005bfff91"
     },
     "_type": 0,
-    "_sizeMode": 1,
+    "_sizeMode": 0,
     "_fillType": 0,
     "_fillCenter": {
       "__type__": "cc.Vec2",
@@ -331,25 +367,29 @@
     "_fillRange": 0,
     "_isTrimmedMode": true,
     "_atlas": null,
-    "_id": "97/S6HDq9MeqgmV1Zwnhbb"
+    "_id": "77W6Kcz1hJfo+eK7Hmtcqs"
   },
   {
     "__type__": "cc.Node",
-    "_name": "bottomPart",
+    "_name": "pic",
     "_objFlags": 0,
     "_parent": {
       "__id__": 2
     },
     "_children": [
       {
-        "__id__": 8
+        "__id__": 9
       },
       {
-        "__id__": 11
+        "__id__": 12
       }
     ],
     "_active": true,
-    "_components": [],
+    "_components": [
+      {
+        "__id__": 14
+      }
+    ],
     "_prefab": null,
     "_opacity": 255,
     "_color": {
@@ -361,8 +401,8 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 0,
-      "height": 0
+      "width": 1280,
+      "height": 720
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -373,8 +413,8 @@
       "__type__": "TypedArray",
       "ctor": "Float64Array",
       "array": [
-        635.132,
-        -356.326,
+        0,
+        0,
         0,
         0,
         0,
@@ -382,7 +422,7 @@
         1,
         1,
         1,
-        1
+        0
       ]
     },
     "_eulerAngles": {
@@ -396,23 +436,23 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "8c7k8ep/ZFNpO263+1QHz9"
+    "_id": "acFf5706VEr43k/0GoDH2k"
   },
   {
     "__type__": "cc.Node",
-    "_name": "btn_left",
+    "_name": "icon",
     "_objFlags": 0,
     "_parent": {
-      "__id__": 7
+      "__id__": 8
     },
     "_children": [],
     "_active": true,
     "_components": [
       {
-        "__id__": 9
+        "__id__": 10
       },
       {
-        "__id__": 10
+        "__id__": 11
       }
     ],
     "_prefab": null,
@@ -426,8 +466,8 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 61,
-      "height": 67
+      "width": 1280,
+      "height": 720
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -438,8 +478,8 @@
       "__type__": "TypedArray",
       "ctor": "Float64Array",
       "array": [
-        -148.464,
-        34,
+        0,
+        0,
         0,
         0,
         0,
@@ -461,14 +501,14 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "5ad2wLQLxIN5Eg7OHecSH6"
+    "_id": "e5gAWSYXpPDJKuNiEvXpPT"
   },
   {
     "__type__": "cc.Sprite",
     "_name": "",
     "_objFlags": 0,
     "node": {
-      "__id__": 8
+      "__id__": 9
     },
     "_enabled": true,
     "_materials": [
@@ -476,13 +516,11 @@
         "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
       }
     ],
-    "_srcBlendFactor": 770,
+    "_srcBlendFactor": 1,
     "_dstBlendFactor": 771,
-    "_spriteFrame": {
-      "__uuid__": "ce19457d-e8f3-4c38-ae3e-d4b99208ddb5"
-    },
+    "_spriteFrame": null,
     "_type": 0,
-    "_sizeMode": 1,
+    "_sizeMode": 0,
     "_fillType": 0,
     "_fillCenter": {
       "__type__": "cc.Vec2",
@@ -493,89 +531,45 @@
     "_fillRange": 0,
     "_isTrimmedMode": true,
     "_atlas": null,
-    "_id": "84mqOgJ3JNqZrYVTEU8CjE"
+    "_id": "0eTbXG/oZHmaY6kD6zm9pf"
   },
   {
-    "__type__": "cc.Button",
+    "__type__": "cc.Widget",
     "_name": "",
     "_objFlags": 0,
     "node": {
-      "__id__": 8
+      "__id__": 9
     },
     "_enabled": true,
-    "_normalMaterial": null,
-    "_grayMaterial": null,
-    "duration": 0.1,
-    "zoomScale": 1.2,
-    "clickEvents": [],
-    "_N$interactable": true,
-    "_N$enableAutoGrayEffect": false,
-    "_N$transition": 0,
-    "transition": 0,
-    "_N$normalColor": {
-      "__type__": "cc.Color",
-      "r": 255,
-      "g": 255,
-      "b": 255,
-      "a": 255
-    },
-    "_N$pressedColor": {
-      "__type__": "cc.Color",
-      "r": 211,
-      "g": 211,
-      "b": 211,
-      "a": 255
-    },
-    "pressedColor": {
-      "__type__": "cc.Color",
-      "r": 211,
-      "g": 211,
-      "b": 211,
-      "a": 255
-    },
-    "_N$hoverColor": {
-      "__type__": "cc.Color",
-      "r": 255,
-      "g": 255,
-      "b": 255,
-      "a": 255
-    },
-    "hoverColor": {
-      "__type__": "cc.Color",
-      "r": 255,
-      "g": 255,
-      "b": 255,
-      "a": 255
-    },
-    "_N$disabledColor": {
-      "__type__": "cc.Color",
-      "r": 124,
-      "g": 124,
-      "b": 124,
-      "a": 255
-    },
-    "_N$normalSprite": null,
-    "_N$pressedSprite": null,
-    "pressedSprite": null,
-    "_N$hoverSprite": null,
-    "hoverSprite": null,
-    "_N$disabledSprite": null,
-    "_N$target": null,
-    "_id": "bcYN/4EKBJhbIAfovo9Ah1"
+    "alignMode": 1,
+    "_target": null,
+    "_alignFlags": 45,
+    "_left": 0,
+    "_right": 0,
+    "_top": 0,
+    "_bottom": 0,
+    "_verticalCenter": 0,
+    "_horizontalCenter": 0,
+    "_isAbsLeft": true,
+    "_isAbsRight": true,
+    "_isAbsTop": true,
+    "_isAbsBottom": true,
+    "_isAbsHorizontalCenter": true,
+    "_isAbsVerticalCenter": true,
+    "_originalWidth": 636,
+    "_originalHeight": 396,
+    "_id": "4dr1MJnPlIVJruDphUKxu4"
   },
   {
     "__type__": "cc.Node",
-    "_name": "btn_right",
+    "_name": "items",
     "_objFlags": 0,
     "_parent": {
-      "__id__": 7
+      "__id__": 8
     },
     "_children": [],
     "_active": true,
     "_components": [
-      {
-        "__id__": 12
-      },
       {
         "__id__": 13
       }
@@ -591,20 +585,20 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 60,
-      "height": 66
+      "width": 1280,
+      "height": 720
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
-      "x": 0.5,
-      "y": 0.5
+      "x": 0,
+      "y": 1
     },
     "_trs": {
       "__type__": "TypedArray",
       "ctor": "Float64Array",
       "array": [
-        -47.164,
-        34,
+        -640,
+        360,
         0,
         0,
         0,
@@ -626,141 +620,88 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "46i3stdzpHX6zQHTGnRsNE"
+    "_id": "3a4oi+4+9Ka6PX0pprclAn"
   },
   {
-    "__type__": "cc.Sprite",
+    "__type__": "cc.Widget",
     "_name": "",
     "_objFlags": 0,
     "node": {
-      "__id__": 11
+      "__id__": 12
     },
     "_enabled": true,
-    "_materials": [
-      {
-        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
-      }
-    ],
-    "_srcBlendFactor": 770,
-    "_dstBlendFactor": 771,
-    "_spriteFrame": {
-      "__uuid__": "e5a2dbaa-a677-4a32-90d7-a1b057d7fb59"
-    },
-    "_type": 0,
-    "_sizeMode": 1,
-    "_fillType": 0,
-    "_fillCenter": {
-      "__type__": "cc.Vec2",
-      "x": 0,
-      "y": 0
-    },
-    "_fillStart": 0,
-    "_fillRange": 0,
-    "_isTrimmedMode": true,
-    "_atlas": null,
-    "_id": "42Sh8QS/BHn4WiGyPQPKPt"
+    "alignMode": 1,
+    "_target": null,
+    "_alignFlags": 45,
+    "_left": 0,
+    "_right": 0,
+    "_top": 0,
+    "_bottom": 0,
+    "_verticalCenter": 0,
+    "_horizontalCenter": 0,
+    "_isAbsLeft": true,
+    "_isAbsRight": true,
+    "_isAbsTop": true,
+    "_isAbsBottom": true,
+    "_isAbsHorizontalCenter": true,
+    "_isAbsVerticalCenter": true,
+    "_originalWidth": 720,
+    "_originalHeight": 720,
+    "_id": "b7NRXHDjZD05w1ysTiZHhR"
   },
   {
-    "__type__": "cc.Button",
+    "__type__": "fccd421MOxLZq6iwp/QwDAf",
     "_name": "",
     "_objFlags": 0,
     "node": {
-      "__id__": 11
+      "__id__": 8
     },
     "_enabled": true,
-    "_normalMaterial": null,
-    "_grayMaterial": null,
-    "duration": 0.1,
-    "zoomScale": 1.2,
-    "clickEvents": [],
-    "_N$interactable": true,
-    "_N$enableAutoGrayEffect": false,
-    "_N$transition": 0,
-    "transition": 0,
-    "_N$normalColor": {
+    "hitPre": {
+      "__uuid__": "2ce7d58d-b6fe-4ef7-a128-de76f672a803"
+    },
+    "wordsPre": {
+      "__uuid__": "a33b90a4-90af-4a31-91ad-110894bbe407"
+    },
+    "picPre": {
+      "__uuid__": "85e73971-9396-4c2a-9fac-2b187fd99c48"
+    },
+    "_id": "25htXxEOZC+47ROkvoLV/U"
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "pic_temp",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 2
+    },
+    "_children": [
+      {
+        "__id__": 16
+      },
+      {
+        "__id__": 18
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 20
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
       "__type__": "cc.Color",
       "r": 255,
       "g": 255,
       "b": 255,
       "a": 255
     },
-    "_N$pressedColor": {
-      "__type__": "cc.Color",
-      "r": 211,
-      "g": 211,
-      "b": 211,
-      "a": 255
-    },
-    "pressedColor": {
-      "__type__": "cc.Color",
-      "r": 211,
-      "g": 211,
-      "b": 211,
-      "a": 255
-    },
-    "_N$hoverColor": {
-      "__type__": "cc.Color",
-      "r": 255,
-      "g": 255,
-      "b": 255,
-      "a": 255
-    },
-    "hoverColor": {
-      "__type__": "cc.Color",
-      "r": 255,
-      "g": 255,
-      "b": 255,
-      "a": 255
-    },
-    "_N$disabledColor": {
-      "__type__": "cc.Color",
-      "r": 124,
-      "g": 124,
-      "b": 124,
-      "a": 255
-    },
-    "_N$normalSprite": null,
-    "_N$pressedSprite": null,
-    "pressedSprite": null,
-    "_N$hoverSprite": null,
-    "hoverSprite": null,
-    "_N$disabledSprite": null,
-    "_N$target": null,
-    "_id": "1aj32fYY1IxLesa77E70Qu"
-  },
-  {
-    "__type__": "cc.Node",
-    "_name": "res",
-    "_objFlags": 0,
-    "_parent": {
-      "__id__": 2
-    },
-    "_children": [
-      {
-        "__id__": 15
-      },
-      {
-        "__id__": 18
-      },
-      {
-        "__id__": 21
-      }
-    ],
-    "_active": false,
-    "_components": [],
-    "_prefab": null,
-    "_opacity": 255,
-    "_color": {
-      "__type__": "cc.Color",
-      "r": 255,
-      "g": 255,
-      "b": 255,
-      "a": 255
-    },
-    "_contentSize": {
-      "__type__": "cc.Size",
-      "width": 0,
-      "height": 0
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 1280,
+      "height": 720
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -771,7 +712,7 @@
       "__type__": "TypedArray",
       "ctor": "Float64Array",
       "array": [
-        0,
+        -1280,
         0,
         0,
         0,
@@ -780,7 +721,7 @@
         1,
         1,
         1,
-        1
+        0
       ]
     },
     "_eulerAngles": {
@@ -794,22 +735,22 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "0aAzbH6R1E+6AmGRrkKa5O"
+    "_id": "f5uVe6L1lNmYEspgnFI0dX"
   },
   {
     "__type__": "cc.Node",
-    "_name": "font",
+    "_name": "icon",
     "_objFlags": 0,
     "_parent": {
-      "__id__": 14
+      "__id__": 15
     },
-    "_children": [
+    "_children": [],
+    "_active": true,
+    "_components": [
       {
-        "__id__": 16
+        "__id__": 17
       }
     ],
-    "_active": true,
-    "_components": [],
     "_prefab": null,
     "_opacity": 255,
     "_color": {
@@ -821,8 +762,8 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 0,
-      "height": 0
+      "width": 1266,
+      "height": 706
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -842,7 +783,7 @@
         1,
         1,
         1,
-        1
+        0
       ]
     },
     "_eulerAngles": {
@@ -856,11 +797,41 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "9bLfcYeeNKrr524vzWchiM"
+    "_id": "e759xQxcRBDZCN5l4fsqO0"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 16
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 1,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": null,
+    "_type": 0,
+    "_sizeMode": 0,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": "0eSa63fVNKKLV/1Jn+eg8n"
   },
   {
     "__type__": "cc.Node",
-    "_name": "BRLNSDB",
+    "_name": "items",
     "_objFlags": 0,
     "_parent": {
       "__id__": 15
@@ -869,7 +840,7 @@
     "_active": true,
     "_components": [
       {
-        "__id__": 17
+        "__id__": 19
       }
     ],
     "_prefab": null,
@@ -883,20 +854,20 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 0,
-      "height": 0
+      "width": 1280,
+      "height": 720
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
-      "x": 0.5,
-      "y": 0.5
+      "x": 0,
+      "y": 1
     },
     "_trs": {
       "__type__": "TypedArray",
       "ctor": "Float64Array",
       "array": [
-        0,
-        0,
+        -640,
+        360,
         0,
         0,
         0,
@@ -918,54 +889,81 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "cfMLGsq0BMhJARv+ySMAxS"
+    "_id": "60JG0g75NIdb8hWvDUsLMj"
   },
   {
-    "__type__": "cc.Label",
+    "__type__": "cc.Widget",
     "_name": "",
     "_objFlags": 0,
     "node": {
-      "__id__": 16
+      "__id__": 18
     },
     "_enabled": true,
-    "_materials": [],
-    "_srcBlendFactor": 770,
-    "_dstBlendFactor": 771,
-    "_useOriginalSize": true,
-    "_string": "",
-    "_N$string": "",
-    "_fontSize": 40,
-    "_lineHeight": 40,
-    "_enableWrapText": true,
-    "_N$file": {
-      "__uuid__": "c551970e-b095-45f3-9f1d-25cde8b8deb1"
+    "alignMode": 1,
+    "_target": null,
+    "_alignFlags": 45,
+    "_left": 0,
+    "_right": 0,
+    "_top": 0,
+    "_bottom": 0,
+    "_verticalCenter": 0,
+    "_horizontalCenter": 0,
+    "_isAbsLeft": true,
+    "_isAbsRight": true,
+    "_isAbsTop": true,
+    "_isAbsBottom": true,
+    "_isAbsHorizontalCenter": true,
+    "_isAbsVerticalCenter": true,
+    "_originalWidth": 0,
+    "_originalHeight": 0,
+    "_id": "4eE1g6Ls9Nf5cKwDfBu7o1"
+  },
+  {
+    "__type__": "fccd421MOxLZq6iwp/QwDAf",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 15
     },
-    "_isSystemFontUsed": false,
-    "_spacingX": 0,
-    "_batchAsBitmap": false,
-    "_styleFlags": 0,
-    "_underlineHeight": 0,
-    "_N$horizontalAlign": 0,
-    "_N$verticalAlign": 0,
-    "_N$fontFamily": "Arial",
-    "_N$overflow": 0,
-    "_N$cacheMode": 0,
-    "_id": "9bNHNPu5lC7rQYyr8ai/sY"
+    "_enabled": true,
+    "hitPre": {
+      "__uuid__": "2ce7d58d-b6fe-4ef7-a128-de76f672a803"
+    },
+    "wordsPre": {
+      "__uuid__": "a33b90a4-90af-4a31-91ad-110894bbe407"
+    },
+    "picPre": {
+      "__uuid__": "85e73971-9396-4c2a-9fac-2b187fd99c48"
+    },
+    "_id": "89aCQ7yHtOn4s8onn5MbAu"
   },
   {
     "__type__": "cc.Node",
-    "_name": "img",
+    "_name": "bottomPart",
     "_objFlags": 0,
     "_parent": {
-      "__id__": 14
+      "__id__": 2
     },
     "_children": [
       {
-        "__id__": 19
+        "__id__": 22
+      },
+      {
+        "__id__": 24
+      },
+      {
+        "__id__": 31
+      },
+      {
+        "__id__": 35
       }
     ],
     "_active": true,
-    "_components": [],
+    "_components": [
+      {
+        "__id__": 39
+      }
+    ],
     "_prefab": null,
     "_opacity": 255,
     "_color": {
@@ -977,8 +975,8 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 0,
-      "height": 0
+      "width": 300,
+      "height": 103
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -989,8 +987,8 @@
       "__type__": "TypedArray",
       "ctor": "Float64Array",
       "array": [
-        0,
-        0,
+        490,
+        -308.5,
         0,
         0,
         0,
@@ -1012,20 +1010,20 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "53LUHHG2pEr79fyrvazXJs"
+    "_id": "8c7k8ep/ZFNpO263+1QHz9"
   },
   {
     "__type__": "cc.Node",
-    "_name": "icon",
+    "_name": "bg_bottom",
     "_objFlags": 0,
     "_parent": {
-      "__id__": 18
+      "__id__": 21
     },
     "_children": [],
     "_active": true,
     "_components": [
       {
-        "__id__": 20
+        "__id__": 23
       }
     ],
     "_prefab": null,
@@ -1039,8 +1037,8 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 138,
-      "height": 141
+      "width": 300,
+      "height": 103
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -1074,24 +1072,28 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "1blU2OArJIfoC9XfupGxJG"
+    "_id": "70X2WruCtItoUrT7FmCz3I"
   },
   {
     "__type__": "cc.Sprite",
     "_name": "",
     "_objFlags": 0,
     "node": {
-      "__id__": 19
+      "__id__": 22
     },
     "_enabled": true,
-    "_materials": [],
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
     "_srcBlendFactor": 770,
     "_dstBlendFactor": 771,
     "_spriteFrame": {
-      "__uuid__": "6fbc30a8-3c49-44ae-8ba4-7f56f385b78a"
+      "__uuid__": "ebbed2c5-6d87-463b-b957-47396e91f490"
     },
     "_type": 0,
-    "_sizeMode": 1,
+    "_sizeMode": 2,
     "_fillType": 0,
     "_fillCenter": {
       "__type__": "cc.Vec2",
@@ -1100,24 +1102,31 @@
     },
     "_fillStart": 0,
     "_fillRange": 0,
-    "_isTrimmedMode": true,
+    "_isTrimmedMode": false,
     "_atlas": null,
-    "_id": "03GEWUEZJGyKormWgIWCtM"
+    "_id": "c7OVcCQjtDmrknFQVhXiA3"
   },
   {
     "__type__": "cc.Node",
-    "_name": "audio",
+    "_name": "btn_checkall",
     "_objFlags": 0,
     "_parent": {
-      "__id__": 14
+      "__id__": 21
     },
     "_children": [
       {
-        "__id__": 22
+        "__id__": 25
+      },
+      {
+        "__id__": 27
       }
     ],
     "_active": true,
-    "_components": [],
+    "_components": [
+      {
+        "__id__": 29
+      }
+    ],
     "_prefab": null,
     "_opacity": 255,
     "_color": {
@@ -1129,8 +1138,8 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 0,
-      "height": 0
+      "width": 64,
+      "height": 68
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -1141,8 +1150,8 @@
       "__type__": "TypedArray",
       "ctor": "Float64Array",
       "array": [
-        0,
-        0,
+        -66,
+        -14.159,
         0,
         0,
         0,
@@ -1150,7 +1159,7 @@
         1,
         1,
         1,
-        1
+        0
       ]
     },
     "_eulerAngles": {
@@ -1164,20 +1173,20 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "b823DIVC9L+Ihc3T9Bt7m3"
+    "_id": "d0K0yjGA1FTbMcepb4WHvy"
   },
   {
     "__type__": "cc.Node",
-    "_name": "btn",
+    "_name": "show",
     "_objFlags": 0,
     "_parent": {
-      "__id__": 21
+      "__id__": 24
     },
     "_children": [],
-    "_active": true,
+    "_active": false,
     "_components": [
       {
-        "__id__": 23
+        "__id__": 26
       }
     ],
     "_prefab": null,
@@ -1191,8 +1200,8 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 0,
-      "height": 0
+      "width": 64,
+      "height": 69
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -1226,46 +1235,1465 @@
     "_is3DNode": false,
     "_groupIndex": 0,
     "groupIndex": 0,
-    "_id": "3d0p0/uJZJIoRva5Br2iqv"
+    "_id": "89JwlwBvNDsLk4syAzxxbN"
   },
   {
-    "__type__": "cc.AudioSource",
+    "__type__": "cc.Sprite",
     "_name": "",
     "_objFlags": 0,
     "node": {
-      "__id__": 22
+      "__id__": 25
     },
     "_enabled": true,
-    "_clip": {
-      "__uuid__": "f0680ae0-c079-45ef-abd7-9e63d90b982b"
-    },
-    "_volume": 1,
-    "_mute": false,
-    "_loop": false,
-    "playOnLoad": false,
-    "preload": false,
-    "_id": "0adN50f61DlbmppsPkOnjX"
-  },
-  {
-    "__type__": "cc.Canvas",
-    "_name": "",
-    "_objFlags": 0,
-    "node": {
-      "__id__": 2
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "a918ec7e-293c-43f1-aec1-c75a66e4af14"
     },
-    "_enabled": true,
-    "_designResolution": {
-      "__type__": "cc.Size",
-      "width": 1280,
-      "height": 720
+    "_type": 0,
+    "_sizeMode": 1,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
     },
-    "_fitWidth": false,
-    "_fitHeight": false,
-    "_id": "59Cd0ovbdF4byw5sbjJDx7"
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": "200LqappFKCLUsTniwvise"
   },
   {
-    "__type__": "cc.Widget",
-    "_name": "",
+    "__type__": "cc.Node",
+    "_name": "btn_replay",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 24
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 28
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 64,
+      "height": 69
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "246gastDRKu7/xuNtl/imt"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 27
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "9266d645-d228-407a-8bf1-5bff25c516c3"
+    },
+    "_type": 0,
+    "_sizeMode": 1,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": "f6oF0y1r1EELhPtNQWrpv2"
+  },
+  {
+    "__type__": "cc.Button",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 24
+    },
+    "_enabled": true,
+    "_normalMaterial": null,
+    "_grayMaterial": null,
+    "duration": 0.1,
+    "zoomScale": 1.1,
+    "clickEvents": [
+      {
+        "__id__": 30
+      }
+    ],
+    "_N$interactable": true,
+    "_N$enableAutoGrayEffect": false,
+    "_N$transition": 3,
+    "transition": 3,
+    "_N$normalColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_N$pressedColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "pressedColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "_N$hoverColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "hoverColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_N$disabledColor": {
+      "__type__": "cc.Color",
+      "r": 124,
+      "g": 124,
+      "b": 124,
+      "a": 255
+    },
+    "_N$normalSprite": null,
+    "_N$pressedSprite": null,
+    "pressedSprite": null,
+    "_N$hoverSprite": null,
+    "hoverSprite": null,
+    "_N$disabledSprite": null,
+    "_N$target": null,
+    "_id": "35It6TDn9KobgK3pQ3c96H"
+  },
+  {
+    "__type__": "cc.ClickEvent",
+    "target": {
+      "__id__": 2
+    },
+    "component": "",
+    "_componentId": "c238bwNxXtAHqIXQECY4nQz",
+    "handler": "onCheckall",
+    "customEventData": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "btn_left",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 21
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 32
+      },
+      {
+        "__id__": 34
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 64,
+      "height": 68
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        18,
+        -14.159,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        0
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "5ad2wLQLxIN5Eg7OHecSH6"
+  },
+  {
+    "__type__": "cc.Button",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 31
+    },
+    "_enabled": true,
+    "_normalMaterial": null,
+    "_grayMaterial": null,
+    "duration": 0.1,
+    "zoomScale": 1.1,
+    "clickEvents": [
+      {
+        "__id__": 33
+      }
+    ],
+    "_N$interactable": true,
+    "_N$enableAutoGrayEffect": false,
+    "_N$transition": 3,
+    "transition": 3,
+    "_N$normalColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_N$pressedColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "pressedColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "_N$hoverColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "hoverColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_N$disabledColor": {
+      "__type__": "cc.Color",
+      "r": 124,
+      "g": 124,
+      "b": 124,
+      "a": 255
+    },
+    "_N$normalSprite": null,
+    "_N$pressedSprite": null,
+    "pressedSprite": null,
+    "_N$hoverSprite": null,
+    "hoverSprite": null,
+    "_N$disabledSprite": null,
+    "_N$target": null,
+    "_id": "bcYN/4EKBJhbIAfovo9Ah1"
+  },
+  {
+    "__type__": "cc.ClickEvent",
+    "target": {
+      "__id__": 2
+    },
+    "component": "",
+    "_componentId": "c238bwNxXtAHqIXQECY4nQz",
+    "handler": "onClickLeft",
+    "customEventData": ""
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 31
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "ad0a3c91-cad1-449e-9ccc-00b77784be63"
+    },
+    "_type": 0,
+    "_sizeMode": 1,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": "93zcHsRZhA7783yB/mBlqo"
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "btn_right",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 21
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 36
+      },
+      {
+        "__id__": 38
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 64,
+      "height": 68
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        112,
+        -14.159,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        0
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "46i3stdzpHX6zQHTGnRsNE"
+  },
+  {
+    "__type__": "cc.Button",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 35
+    },
+    "_enabled": true,
+    "_normalMaterial": null,
+    "_grayMaterial": null,
+    "duration": 0.1,
+    "zoomScale": 1.1,
+    "clickEvents": [
+      {
+        "__id__": 37
+      }
+    ],
+    "_N$interactable": true,
+    "_N$enableAutoGrayEffect": false,
+    "_N$transition": 3,
+    "transition": 3,
+    "_N$normalColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_N$pressedColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "pressedColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "_N$hoverColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "hoverColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_N$disabledColor": {
+      "__type__": "cc.Color",
+      "r": 124,
+      "g": 124,
+      "b": 124,
+      "a": 255
+    },
+    "_N$normalSprite": null,
+    "_N$pressedSprite": null,
+    "pressedSprite": null,
+    "_N$hoverSprite": null,
+    "hoverSprite": null,
+    "_N$disabledSprite": null,
+    "_N$target": null,
+    "_id": "1aj32fYY1IxLesa77E70Qu"
+  },
+  {
+    "__type__": "cc.ClickEvent",
+    "target": {
+      "__id__": 2
+    },
+    "component": "",
+    "_componentId": "c238bwNxXtAHqIXQECY4nQz",
+    "handler": "onClickRight",
+    "customEventData": ""
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 35
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "68899d36-0959-405b-b0a4-ba99d96f471c"
+    },
+    "_type": 0,
+    "_sizeMode": 1,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": "d4dDRX1SZIy517c6gzyxSO"
+  },
+  {
+    "__type__": "cc.Widget",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 21
+    },
+    "_enabled": true,
+    "alignMode": 1,
+    "_target": null,
+    "_alignFlags": 36,
+    "_left": 0,
+    "_right": 0,
+    "_top": 0,
+    "_bottom": 0,
+    "_verticalCenter": 0,
+    "_horizontalCenter": 0,
+    "_isAbsLeft": true,
+    "_isAbsRight": true,
+    "_isAbsTop": true,
+    "_isAbsBottom": true,
+    "_isAbsHorizontalCenter": true,
+    "_isAbsVerticalCenter": true,
+    "_originalWidth": 0,
+    "_originalHeight": 0,
+    "_id": "14yYhIw95BeZx56bjhZzfB"
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "audio",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 2
+    },
+    "_children": [
+      {
+        "__id__": 41
+      },
+      {
+        "__id__": 48
+      },
+      {
+        "__id__": 54
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 56
+      },
+      {
+        "__id__": 57
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 500,
+      "height": 90
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        -315,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "73LZP/ZUhPjb95BiJ/JUtb"
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "btnPlay",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 40
+    },
+    "_children": [
+      {
+        "__id__": 42
+      },
+      {
+        "__id__": 44
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 46
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 73,
+      "height": 73
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        -204.199,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "6aSd82eBdJ3KE8dWlnKkyV"
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "btn_stop",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 41
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 43
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 69,
+      "height": 73
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "caur2ABY5CPrxVap+/dG1s"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 42
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "7b07d2a9-946a-46e7-ae60-71d45eb0d5c3"
+    },
+    "_type": 0,
+    "_sizeMode": 1,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": "9bUdEmv89LM7Ch2zikGZxE"
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "btn_next",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 41
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 45
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 64,
+      "height": 68
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "a26RWDR1dKgbvH/mmPKa4I"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 44
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "68899d36-0959-405b-b0a4-ba99d96f471c"
+    },
+    "_type": 0,
+    "_sizeMode": 1,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": "67n/3zVDlChbBxVBsMSZCn"
+  },
+  {
+    "__type__": "cc.Button",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 41
+    },
+    "_enabled": true,
+    "_normalMaterial": null,
+    "_grayMaterial": null,
+    "duration": 0.1,
+    "zoomScale": 1.2,
+    "clickEvents": [
+      {
+        "__id__": 47
+      }
+    ],
+    "_N$interactable": true,
+    "_N$enableAutoGrayEffect": false,
+    "_N$transition": 0,
+    "transition": 0,
+    "_N$normalColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_N$pressedColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "pressedColor": {
+      "__type__": "cc.Color",
+      "r": 211,
+      "g": 211,
+      "b": 211,
+      "a": 255
+    },
+    "_N$hoverColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "hoverColor": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_N$disabledColor": {
+      "__type__": "cc.Color",
+      "r": 124,
+      "g": 124,
+      "b": 124,
+      "a": 255
+    },
+    "_N$normalSprite": null,
+    "_N$pressedSprite": null,
+    "pressedSprite": null,
+    "_N$hoverSprite": null,
+    "hoverSprite": null,
+    "_N$disabledSprite": null,
+    "_N$target": null,
+    "_id": "76GOqNaq9B0oiRUsO6Ux3u"
+  },
+  {
+    "__type__": "cc.ClickEvent",
+    "target": {
+      "__id__": 40
+    },
+    "component": "",
+    "_componentId": "a5d5cl9cN9CA5tELIOHf6uI",
+    "handler": "onPlay",
+    "customEventData": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "bg_tiaodi",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 40
+    },
+    "_children": [
+      {
+        "__id__": 49
+      },
+      {
+        "__id__": 51
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 53
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 388,
+      "height": 30
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        -145.506,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "08zW2AlLdJdZ5SERtwWIqs"
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "bg_tiao",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 48
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 50
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 382,
+      "height": 24
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        3.449,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "693gzQ/ilBboz++pwIjRZW"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 49
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "802a73b5-336d-465e-a5aa-2c559975bd84"
+    },
+    "_type": 3,
+    "_sizeMode": 0,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 1,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": "22ejznEcFGuYZA5G0//V6z"
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "icon_move",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 48
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 52
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 255,
+      "g": 255,
+      "b": 255,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 26,
+      "height": 51
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        17,
+        0,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "0eGoPI+7hJDra6UYZOzegS"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 51
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "fff435c8-ec81-49f6-8793-3a8ae25d77e2"
+    },
+    "_type": 0,
+    "_sizeMode": 1,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": "7dLEK9QGpHx4ykezUqcHlh"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 48
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_spriteFrame": {
+      "__uuid__": "80fb10f3-51a4-4982-b965-590c813dd748"
+    },
+    "_type": 0,
+    "_sizeMode": 1,
+    "_fillType": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_atlas": null,
+    "_id": "d2iUs5jcxJcoSJAgf9ngMa"
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "time",
+    "_objFlags": 0,
+    "_parent": {
+      "__id__": 40
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 55
+      }
+    ],
+    "_prefab": null,
+    "_opacity": 255,
+    "_color": {
+      "__type__": "cc.Color",
+      "r": 108,
+      "g": 105,
+      "b": 155,
+      "a": 255
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 104.26,
+      "height": 31.5
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_trs": {
+      "__type__": "TypedArray",
+      "ctor": "Float64Array",
+      "array": [
+        183.568,
+        35.456,
+        0,
+        0,
+        0,
+        0,
+        1,
+        1,
+        1,
+        1
+      ]
+    },
+    "_eulerAngles": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_skewX": 0,
+    "_skewY": 0,
+    "_is3DNode": false,
+    "_groupIndex": 0,
+    "groupIndex": 0,
+    "_id": "9dlq477AlIkqZdPBNW6e1s"
+  },
+  {
+    "__type__": "cc.Label",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 54
+    },
+    "_enabled": true,
+    "_materials": [
+      {
+        "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
+      }
+    ],
+    "_srcBlendFactor": 770,
+    "_dstBlendFactor": 771,
+    "_string": "1:00/1:45",
+    "_N$string": "1:00/1:45",
+    "_fontSize": 25,
+    "_lineHeight": 25,
+    "_enableWrapText": true,
+    "_N$file": null,
+    "_isSystemFontUsed": true,
+    "_spacingX": 0,
+    "_batchAsBitmap": false,
+    "_styleFlags": 0,
+    "_underlineHeight": 0,
+    "_N$horizontalAlign": 1,
+    "_N$verticalAlign": 1,
+    "_N$fontFamily": "Arial",
+    "_N$overflow": 0,
+    "_N$cacheMode": 0,
+    "_id": "ef4UTltpZDP51GI6bexavI"
+  },
+  {
+    "__type__": "cc.Widget",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 40
+    },
+    "_enabled": true,
+    "alignMode": 1,
+    "_target": null,
+    "_alignFlags": 20,
+    "_left": 0,
+    "_right": 0,
+    "_top": 0,
+    "_bottom": 0,
+    "_verticalCenter": 0,
+    "_horizontalCenter": 0,
+    "_isAbsLeft": true,
+    "_isAbsRight": true,
+    "_isAbsTop": true,
+    "_isAbsBottom": true,
+    "_isAbsHorizontalCenter": true,
+    "_isAbsVerticalCenter": true,
+    "_originalWidth": 0,
+    "_originalHeight": 0,
+    "_id": "50C3HEd7VCHoMtvxKUTJaF"
+  },
+  {
+    "__type__": "a5d5cl9cN9CA5tELIOHf6uI",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 40
+    },
+    "_enabled": true,
+    "playBtn": {
+      "__id__": 41
+    },
+    "label": {
+      "__id__": 55
+    },
+    "tiao": {
+      "__id__": 48
+    },
+    "_id": "bc9MPqChFDCJsvpOdf++gN"
+  },
+  {
+    "__type__": "cc.Canvas",
+    "_name": "",
+    "_objFlags": 0,
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "_designResolution": {
+      "__type__": "cc.Size",
+      "width": 1280,
+      "height": 720
+    },
+    "_fitWidth": false,
+    "_fitHeight": false,
+    "_id": "59Cd0ovbdF4byw5sbjJDx7"
+  },
+  {
+    "__type__": "cc.Widget",
+    "_name": "",
     "_objFlags": 0,
     "node": {
       "__id__": 2
@@ -1291,13 +2719,37 @@
     "_id": "29zXboiXFBKoIV4PQ2liTe"
   },
   {
-    "__type__": "f4edeRi+NdAabqAkVYRwFjK",
+    "__type__": "c238bwNxXtAHqIXQECY4nQz",
     "_name": "",
     "_objFlags": 0,
     "node": {
       "__id__": 2
     },
     "_enabled": true,
-    "_id": "e687yyoRBIzZAOVRL8Sseh"
+    "picNode": {
+      "__id__": 8
+    },
+    "picTempNode": {
+      "__id__": 15
+    },
+    "leftNode": {
+      "__id__": 31
+    },
+    "rightNode": {
+      "__id__": 35
+    },
+    "checkNode": {
+      "__id__": 24
+    },
+    "bgAudioNode": {
+      "__id__": 40
+    },
+    "btnClip": {
+      "__uuid__": "39ef1939-3bf9-4d21-a67a-bc1dede521a9"
+    },
+    "tipClip": {
+      "__uuid__": "e0bcf4cc-35a7-4d61-b202-8dd49299c2c0"
+    },
+    "_id": "a1ibU1vO9Nwbfwjsm/NgGR"
   }
 ]
\ No newline at end of file
diff --git a/play/assets/scene/scene/scene.js b/play/assets/scene/scene/scene.js
index 0172591cd38c4ce7803d18bfd28efca5dd984c54..507d5888bde56e257007cde233013458188c589a 100644
--- a/play/assets/scene/scene/scene.js
+++ b/play/assets/scene/scene/scene.js
@@ -1,11 +1,32 @@
-import { onHomeworkFinish } from "../script/util";
-import { defaultData } from "../script/defaultData";
+const tools = require("./tools");
 
 cc.Class({
-
 	extends: cc.Component,
 
 	properties: {
+		picNode: {
+			type: cc.Node,
+			default: null
+		},
+		picTempNode: {
+			type: cc.Node,
+			default: null
+		},
+		leftNode: {
+			type: cc.Node,
+			default: null
+		},
+		rightNode: {
+			type: cc.Node,
+			default: null
+		},
+		checkNode: {
+			type: cc.Node,
+			default: null
+		},
+		bgAudioNode: cc.Node,
+		btnClip: cc.AudioClip,
+		tipClip: cc.AudioClip
 	},
 
 	// 生命周期 onLoad
@@ -61,53 +82,48 @@ cc.Class({
 
 		getData((data) => {
 			console.log('data:', data);
-			this.data = data || this.getDefaultData();
+			this.data = (data && data.length) ? data : this.getDefaultData();
 			this.data = JSON.parse(JSON.stringify(this.data))
 			this.preloadItem()
 		})
+		//init show
+		this.picNode.opacity = 0
+		this.leftNode.active = false
+		this.rightNode.active = false
+		this.answerState = false
 	},
 
-	getData(func) {
-		if (window && window.courseware) {
-			window.courseware.getData(func, 'scene');
-			return;
-		}
-
-		const middleLayer = cc.find('middleLayer');
-		if (middleLayer) {
-			const middleLayerComponent = middleLayer.getComponent('middleLayer');
-			middleLayerComponent.getData(func);
-			return;
-		}
+	onEnable() {
 
-		func(this.getDefaultData());
 	},
 
-	getDefaultData() {
-		return defaultData;
-	},
+	onDisable() {
 
-	preloadItem() {
-		this.addPreloadImage();
-		this.addPreloadAudio();
-		this.addPreloadAnima();
-		this.preload();
 	},
 
 
-	addPreloadImage() {
-
-		this._imageResList.push({ url: this.data.pic_url });
-		this._imageResList.push({ url: this.data.pic_url_2 });
+	getData(cb) {
+		cb(this.getDefaultData());
 	},
 
-	addPreloadAudio() {
-
-		this._audioResList.push({ url: this.data.audio_url });
+	getDefaultData() {
+		const dataJson = ' [{"bgItem":{"url":"http://staging-teach.cdn.ireadabc.com/b90a006ba41723ec11970051e92f43e0.png","rect":{"x":125.28,"y":0,"width":508.44,"height":286},"bgAudioUrl":"http://staging-teach.cdn.ireadabc.com/c8a7dd49a778b0b6dd509aac0ef437ff.mp3"},"hotZoneItemArr":[{"id":"1620909579034","index":0,"itemType":"text","fontScale":0.59296875,"imgScale":1,"mapScale":0.59296875,"gIdx":"0","actionData_":{"type":"text","changeOption":[["fontColor","#000000"],["fontSize","60"]],"text":"aaaaaaaaaaaaaa","audio_url":"http://staging-teach.cdn.ireadabc.com/c8a7dd49a778b0b6dd509aac0ef437ff.mp3"},"rect":{"width":292.76,"height":35.58,"x":12.63,"y":26.79}},{"id":"1620915585437","index":1,"pic_url":"http://staging-teach.cdn.ireadabc.com/31bde9b15582618fa5db4ac7cbc275b4.gif","itemType":"pic","fontScale":0.59296875,"imgScale":0.14977973568281938,"mapScale":0.59296875,"gIdx":"2","actionData_":{"type":"text","changeOption":[["fontColor","#000000"],["fontSize","100"]],"text":"bbbbbbbbbbb"},"rect":{"x":328.41,"y":11,"width":161.61,"height":68}},{"id":"1620920750092","index":2,"itemType":"text","fontScale":0.59296875,"imgScale":1,"mapScale":0.59296875,"gIdx":"0","actionData_":{"type":"text","changeOption":[["fontColor","#000000"],["fontSize","100"]],"text":"嗯?","audio_url":"http://staging-teach.cdn.ireadabc.com/7df4cc83a6c76dc6f0a526d07e6f1987.mp3"},"rect":{"width":118.58,"height":59.3,"x":203.93,"y":129.35}}]},{"bgItem":{"url":"http://staging-teach.cdn.ireadabc.com/b90a006ba41723ec11970051e92f43e0.png","bgAudioUrl":"http://staging-teach.cdn.ireadabc.com/8f73a6b73a217d25ca4f4a2e234c1513.mp3","rect":{"x":222.44,"y":0,"width":903.11,"height":508}},"hotZoneItemArr":[{"id":"1620920863432","index":0,"pic_url":"http://staging-teach.cdn.ireadabc.com/335dea1b83498b0c7c05be637dc13dad.jpeg","itemType":"text","fontScale":1.053125,"imgScale":0.22391857506361323,"mapScale":1.053125,"gIdx":"0","actionData_":{"type":"text","changeOption":[["fontColor","#FF0000"],["fontSize","100"]],"text":"This is a test"},"rect":{"width":558.89,"height":105.31,"x":13.12,"y":6.34}},{"id":"1620920877342","index":1,"itemType":"text","fontScale":1.053125,"imgScale":1,"mapScale":1.053125,"gIdx":"1","actionData_":{"type":"text","changeOption":[["fontColor","#0000FF"],["fontSize","100"]],"text":"you are so good"},"rect":{"width":734.29,"height":105.31,"x":106.43,"y":151.34}},{"id":"1620922839187","index":2,"itemType":"text","fontScale":1.053125,"imgScale":1,"mapScale":1.053125,"gIdx":"0","actionData_":{"type":"text","changeOption":[["fontColor","#000000"],["fontSize","100"]],"text":"_______________"},"rect":{"width":728.12,"height":105.31,"x":109.5,"y":170.34}}]}]'
+		const data = JSON.parse(dataJson);
+		return data;
 	},
 
-	addPreloadAnima() {
+	preloadItem() {
+		this.addPreload()
+		this.preload();
+	},
 
+	addPreload() {
+		for (let item of this.data) {
+			item.bgAudioUrl && this._audioResList.push({ url: item.bgAudioUrl })
+			for (let item of item.hotZoneItemArr) {
+				item.audio_url && this._audioResList.push({ url: item.audio_url })
+			}
+		}
 	},
 
 	preload() {
@@ -127,7 +143,6 @@ cc.Class({
 
 	loadEnd() {
 		this.initData();
-		this.initAudio();
 		this.initView();
 		// this.initListener();
 	},
@@ -138,229 +153,154 @@ cc.Class({
 		this._cantouch = true;
 	},
 
-	audioBtn: null,
-	initAudio() {
-		const audioNode = cc.find('Canvas/res/audio');
-
-		const getAudioByResName = (resName) => {
-			return audioNode.getChildByName(resName).getComponent(cc.AudioSource);
-		}
-
-		this.audioBtn = getAudioByResName('btn');
-
-	},
-
-
 	initView() {
-
 		this.initBg();
 		this.initPic();
-		this.initBtn();
-		this.initIcon();
 	},
 
 	initBg() {
-		const bgNode = cc.find('Canvas/bg');
-		bgNode.scale = this._mapScaleMax;
+		// const bgNode = cc.find('Canvas/bg');
+		// bgNode.scale = this._mapScaleMax;
+		// cc.find('Canvas/bottomPart').scale = this._mapScaleMin
 	},
 
-	pic1: null,
-	pic2: null,
 	initPic() {
-		const canvas = cc.find('Canvas');
-		const maxW = canvas.width * 0.7;
-
-		this.getSprNodeByUrl(this.data.pic_url, (sprNode) => {
-			const picNode1 = sprNode;
-			picNode1.scale = maxW / picNode1.width;
-			picNode1.baseX = picNode1.x;
-			canvas.addChild(picNode1);
-			this.pic1 = picNode1;
-
-			const labelNode = new cc.Node();
-			labelNode.color = cc.Color.YELLOW;
-			const label = labelNode.addComponent(cc.Label);
-			label.string = this.data.text;
-			label.fontSize = 60;
-			label.lineHeight = 60;
-			label.font = cc.find('Canvas/res/font/BRLNSDB').getComponent('cc.Label').font;
-			picNode1.addChild(labelNode);
-		});
-
-		this.getSprNodeByUrl(this.data.pic_url_2, (sprNode) => {
-			const picNode2 = sprNode;
-			picNode2.scale = maxW / picNode2.width;
-			canvas.addChild(picNode2);
-			picNode2.x = canvas.width;
-			picNode2.baseX = picNode2.x;
-			this.pic2 = picNode2;
-
-			const labelNode = new cc.Node();
-			const label = labelNode.addComponent(cc.RichText);
-			const size = 60
-			label.font = cc.find('Canvas/res/font/BRLNSDB').getComponent(cc.Label).font;
-			label.string = `<outline color=#751e00 width=4><size=${size}><color=#ffffff>${this.data.text}</color></size></outline>`
-			label.lineHeight = size;
-			picNode2.addChild(labelNode);
-		});
-
-	},
-
-	initIcon() {
-		const iconNode = this.getSprNode('icon');
-		iconNode.zIndex = 5;
-		iconNode.anchorX = 1;
-		iconNode.anchorY = 1;
-		iconNode.parent = cc.find('Canvas');
-		iconNode.x = iconNode.parent.width / 2 - 10;
-		iconNode.y = iconNode.parent.height / 2 - 10;
-
-		iconNode.on(cc.Node.EventType.TOUCH_START, () => {
-			this.playAudioByUrl(this.data.audio_url);
-		})
+		this.picNode.opacity = 0
+		cc.Tween.stopAllByTarget(this.picNode)
+		cc.tween(this.picNode).to(1, { opacity: 255 }, { easing: 'cubicInOut' }).start()
+		this.curPage = 0
+		if (this.data.length == 1) {
+			this.leftNode.active = false
+			this.rightNode.active = false
+		} else {
+			this.leftNode.active = false
+			this.rightNode.active = true
+		}
+		this.setContent(this.picNode, this.data[0])
 	},
-
 	curPage: null,
-	initBtn() {
 
-		this.curPage = 0;
-		const bottomPart = cc.find('Canvas/bottomPart');
-		bottomPart.zIndex = 5; // 提高层级
+	onClickRight() {
+		if (!this._cantouch) {
+			return;
+		}
 
-		bottomPart.x = bottomPart.parent.width / 2;
-		bottomPart.y = -bottomPart.parent.height / 2;
+		this.curPage += 1
 
-		const leftBtnNode = bottomPart.getChildByName('btn_left');
-		//节点中添加了button组件 则可以添加click事件监听
-		leftBtnNode.on('click', () => {
-			if (!this._cantouch) {
-				return;
-			}
-			if (this.curPage == 0) {
-				return;
-			}
-			this.curPage = 0
-			this.leftMove();
+		if (this.curPage == 1) {
+			this.leftNode.active = true
+			this.leftNode.scale = 1
+		}
 
-			// 游戏结束时需要调用这个方法通知系统作业完成
-			onHomeworkFinish();
+		if (this.curPage == this.data.length - 1) {
+			this.rightNode.active = false
+		}
 
-			cc.audioEngine.play(this.audioBtn.clip, false, 0.8)
-		})
+		this.leftMove()
 
-		const rightBtnNode = bottomPart.getChildByName('btn_right');
-		//节点中添加了button组件 则可以添加click事件监听
-		rightBtnNode.on('click', () => {
-			if (!this._cantouch) {
-				return;
-			}
-			if (this.curPage == 1) {
-				return;
-			}
+		cc.audioEngine.play(this.btnClip, false, 0.5)
+	},
 
-			this.curPage = 1
-			this.rightMove();
+	onClickLeft() {
+		if (!this._cantouch) {
+			return;
+		}
+		this.curPage -= 1
+		if (this.curPage == 0) {
+			this.leftNode.active = false
+		}
 
-			cc.audioEngine.play(this.audioBtn.clip, false, 0.5)
-		})
+		if (this.curPage == this.data.length - 2) {
+			this.rightNode.active = true
+			this.rightNode.scale = 1
+		}
+		this.rightMove()
+
+		cc.audioEngine.play(this.btnClip, false, 0.8)
 	},
 
+
+
+	/** 左移动 */
 	leftMove() {
+		this.stopAudio()
 		this._cantouch = false;
-		const len = this.pic1.parent.width;
-		cc.tween(this.pic1)
-			.to(1, { x: this.pic1.baseX }, { easing: 'cubicInOut' })
+		let width = cc.winSize.width
+		this.picNode.x = 0
+		this.picTempNode.x = width
+		this.setContent(this.picTempNode, this.data[this.curPage])
+		cc.tween(this.picNode)
+			.to(1, { x: -width }, { easing: 'cubicInOut' })
 			.start();
 
-		cc.tween(this.pic2)
-			.to(1, { x: this.pic2.baseX }, { easing: 'cubicInOut' })
+		cc.tween(this.picTempNode)
+			.to(1, { x: 0 }, { easing: 'cubicInOut' })
 			.call(() => {
+				let temp = this.picNode
+				this.picNode = this.picTempNode
+				this.picTempNode = temp
 				this._cantouch = true;
 			})
 			.start();
 	},
 
+	/** 右移动 */
 	rightMove() {
+		this.stopAudio()
 		this._cantouch = false;
-		const len = this.pic1.parent.width;
-		cc.tween(this.pic1)
-			.to(1, { x: this.pic1.baseX - len }, { easing: 'cubicInOut' })
+		let width = cc.winSize.width
+		this.picNode.x = 0
+		this.picTempNode.x = -width
+		this.setContent(this.picTempNode, this.data[this.curPage])
+		cc.tween(this.picNode)
+			.to(1, { x: width }, { easing: 'cubicInOut' })
 			.start();
 
-		cc.tween(this.pic2)
-			.to(1, { x: this.pic2.baseX - len }, { easing: 'cubicInOut' })
+		cc.tween(this.picTempNode)
+			.to(1, { x: 0 }, { easing: 'cubicInOut' })
 			.call(() => {
-				this._cantouch = true;
+				let temp = this.picNode
+				this.picNode = this.picTempNode
+				this.picTempNode = temp
+				this._cantouch = true
 			})
 			.start();
 	},
-	// update (dt) {},
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	// ------------------------------------------------
-	getSprNode(resName) {
-		const sf = cc.find('Canvas/res/img/' + resName).getComponent(cc.Sprite).spriteFrame;
-		const node = new cc.Node();
-		node.addComponent(cc.Sprite).spriteFrame = sf;
-		return node;
-	},
-
-
-	getSpriteFrimeByUrl(url, cb) {
-		cc.loader.load({ url }, (err, img) => {
-			const spriteFrame = new cc.SpriteFrame(img)
-			if (cb) {
-				cb(spriteFrame);
-			}
-		})
+	stopAudio() {
+		cc.systemEvent.emit('stopBgMusic')
+		cc.systemEvent.emit('stopWordsMusic')
+		this.answerState = false
+		this.checkNode.children[0].active = false
+		this.checkNode.children[1].active = true
 	},
 
-	getSprNodeByUrl(url, cb) {
-		const node = new cc.Node();
-		const spr = node.addComponent(cc.Sprite);
-		this.getSpriteFrimeByUrl(url, (sf) => {
-			spr.spriteFrame = sf;
-			if (cb) {
-				cb(node);
-			}
-		})
-	},
-
-	playAudioByUrl(audio_url, cb = null) {
-		if (audio_url) {
-			cc.assetManager.loadRemote(audio_url, (err, audioClip) => {
-				const audioId = cc.audioEngine.play(audioClip, false, 0.8);
-				if (cb) {
-					cc.audioEngine.setFinishCallback(audioId, () => {
-						cb();
-					});
-				}
-			});
+	// ------------------------------------------------
+	/**设置显示区域内容 */
+	setContent(picNode, data) {
+		if (!data) {
+			console.log('数据错误')
+			return
+		}
+		picNode.getComponent('picNode').initWithData(data)
+		let url = data.bgItem.bgAudioUrl
+		if (url && url != '') {
+			this.bgAudioNode.active = true
+			this.bgAudioNode.getComponent('audioItem').init(url)
+		} else {
+			this.bgAudioNode.active = false
 		}
 	},
 
+	answerState: null,
+
+	/** 点击切换答案显示 */
+	onCheckall() {
+		cc.audioEngine.playEffect(this.btnClip)
+		cc.audioEngine.playEffect(this.tipClip)
+		this.answerState = !this.answerState
+		this.checkNode.children[0].active = this.answerState
+		this.checkNode.children[1].active = !this.answerState
+		cc.systemEvent.emit('changeAnswerState', this.answerState)
+	}
 	// ------------------------------------------
-
 });
diff --git a/play/assets/scene/scene/scene.js.meta b/play/assets/scene/scene/scene.js.meta
index 76586520228a6b3e46f8441353b67382ce980986..41c911ba7be8b9b41ba346747ba4420f07947f02 100644
--- a/play/assets/scene/scene/scene.js.meta
+++ b/play/assets/scene/scene/scene.js.meta
@@ -1,6 +1,6 @@
 {
   "ver": "1.0.8",
-  "uuid": "f4ede462-f8d7-4069-ba80-915611c058ca",
+  "uuid": "c238bc0d-c57b-401e-a217-404098e27433",
   "isPlugin": false,
   "loadPluginInWeb": true,
   "loadPluginInNative": true,
diff --git a/play/assets/scene/scene/wordsItem.js b/play/assets/scene/scene/wordsItem.js
new file mode 100644
index 0000000000000000000000000000000000000000..36b19351c06572da791fd03c0dc029aca6522b42
--- /dev/null
+++ b/play/assets/scene/scene/wordsItem.js
@@ -0,0 +1,85 @@
+var playingItem = null
+
+cc.Class({
+    extends: cc.Component,
+
+    properties: {
+        label: cc.Label,
+        playAnim: cc.Animation
+    },
+
+    data: null,
+
+    audio_url: null,
+
+    onEnable() {
+        cc.systemEvent.on('stopWordsMusic', this.stopAudio, this)
+    },
+
+    onDisable() {
+        cc.systemEvent.off('stopWordsMusic', this.stopAudio, this)
+    },
+
+    initWithData(data, scale) {
+        let action = data['actionData_']
+        if (!action) {
+            this.node.active = false
+            return
+        } else {
+            this.node.action = true
+        }
+        this.data = data
+        let rect = this.data.rect
+        this.node.x = (rect.x + rect.width / 2) * scale
+        this.node.y = (-rect.y - rect.height / 2) * scale
+        this.node.width = rect.width * scale
+        this.node.height = rect.height * scale
+
+        let node = this.label.node
+        let option = action.changeOption
+        node.color = option[0][1] ? cc.color(option[0][1]) : cc.color(0, 0, 0)
+        let num = Number(option[1][1]) * scale * data.fontScale
+        this.label.fontSize = num
+        this.label.lineHeight = num
+        this.label.string = action.text ? action.text : ''
+        this.audioId = null
+        this.audio_url = action.audio_url
+        if (this.audio_url) {
+            let node = this.playAnim.node
+            node.setPosition(this.node.width / 2 + node.width / 2 + 15, (-this.node.height + node.height) / 2)
+            node.active = true
+        } else {
+            this.playAnim.node.active = false
+        }
+    },
+
+    onTouchStart() {
+        if (this.audioId != null) return
+        if (this.audio_url && this.audio_url != '') {
+            this.playAudio(this.audio_url)
+            this.playAnim.play('play')
+            cc.systemEvent.emit('stopBgMusic')
+        }
+    },
+
+    /** 播放音乐 */
+    playAudio(url) {
+        cc.assetManager.loadRemote(url, (err, audioClip) => {
+            if (err) return
+            if(playingItem) playingItem.stopAudio()
+            this.audioId = cc.audioEngine.play(audioClip, false, 0.8);
+            cc.audioEngine.setFinishCallback(this.audioId, this.stopAudio.bind(this));
+            playingItem = this
+        });
+    },
+
+    stopAudio() {
+        if (this.audioId != null) {
+            cc.audioEngine.stop(this.audioId)
+            this.audioId = null
+            this.playAnim.play('stop')
+        }
+    },
+    /** 音频id */
+    audioId: null,
+});
diff --git a/play/assets/scene/scene/wordsItem.js.meta b/play/assets/scene/scene/wordsItem.js.meta
new file mode 100644
index 0000000000000000000000000000000000000000..c6fcda956e5a5f4f12cdbbe290e242ac226e0d43
--- /dev/null
+++ b/play/assets/scene/scene/wordsItem.js.meta
@@ -0,0 +1,9 @@
+{
+  "ver": "1.0.8",
+  "uuid": "95b1c7ce-4dc1-4dbe-b563-f11c0adee428",
+  "isPlugin": false,
+  "loadPluginInWeb": true,
+  "loadPluginInNative": true,
+  "loadPluginInEditor": false,
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/script/NewScript.ts b/play/assets/scene/script/NewScript.ts
new file mode 100644
index 0000000000000000000000000000000000000000..69a9a626130ea0105f61e2839a2e59fbae7c4627
--- /dev/null
+++ b/play/assets/scene/script/NewScript.ts
@@ -0,0 +1,41 @@
+// Learn TypeScript:
+//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
+// Learn Attribute:
+//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
+// Learn life-cycle callbacks:
+//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
+
+const { ccclass, property } = cc._decorator;
+
+@ccclass
+export default class NewClass extends cc.Component {
+
+    @property(cc.Label)
+    label: cc.Label = null;
+
+    @property
+    text: string = 'hello';
+
+    // LIFE-CYCLE CALLBACKS:
+
+    // onLoad () {}
+
+    start() {
+        cc.color()
+        this.node.off(cc.Node.EventType.MOUSE_DOWN)
+        cc.systemEvent.emit('stopMusic')
+    }
+
+    // update (dt) {}
+
+    onEnable() {
+        this.node.removeAllChildren()
+        // let one = new cc.Node()
+        // one.removeFromParent()
+        let one = new cc.Label()
+        one
+        // cc.audioEngine.setFinishCallback()
+    }
+
+
+}
diff --git a/play/assets/scene/script/NewScript.ts.meta b/play/assets/scene/script/NewScript.ts.meta
new file mode 100644
index 0000000000000000000000000000000000000000..ebea4308159c94d1633affbebfbed3d2e1053784
--- /dev/null
+++ b/play/assets/scene/script/NewScript.ts.meta
@@ -0,0 +1,9 @@
+{
+  "ver": "1.0.8",
+  "uuid": "81db3e2c-d815-4891-a77d-5651d54dc92d",
+  "isPlugin": false,
+  "loadPluginInWeb": true,
+  "loadPluginInNative": true,
+  "loadPluginInEditor": false,
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/script/tools.js b/play/assets/scene/script/tools.js
new file mode 100644
index 0000000000000000000000000000000000000000..da77811d83fec84ed8c217f434cb213412ec94fe
--- /dev/null
+++ b/play/assets/scene/script/tools.js
@@ -0,0 +1,12 @@
+const tools = {
+    getSpriteFrimeByUrl(url, cb) {
+        cc.loader.load({ url }, (err, img) => {
+            const spriteFrame = new cc.SpriteFrame(img)
+            if (cb) {
+                cb(spriteFrame);
+            }
+        })
+    }
+}
+
+module.exports = tools
\ No newline at end of file
diff --git a/play/assets/scene/script/tools.js.meta b/play/assets/scene/script/tools.js.meta
new file mode 100644
index 0000000000000000000000000000000000000000..2203e16be7b647de032bf79f486554599b816261
--- /dev/null
+++ b/play/assets/scene/script/tools.js.meta
@@ -0,0 +1,9 @@
+{
+  "ver": "1.0.8",
+  "uuid": "68947d90-e044-48ff-8bce-670db8633681",
+  "isPlugin": false,
+  "loadPluginInWeb": true,
+  "loadPluginInNative": true,
+  "loadPluginInEditor": false,
+  "subMetas": {}
+}
\ No newline at end of file
diff --git a/play/assets/scene/script/util.js b/play/assets/scene/script/util.js
deleted file mode 100644
index 7af7189e0876a8c81ce489ad12ba830b9f98d9d2..0000000000000000000000000000000000000000
--- a/play/assets/scene/script/util.js
+++ /dev/null
@@ -1,354 +0,0 @@
-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 exchangeNodePos(baseNode, targetNode) {
-  return baseNode.convertToNodeSpaceAR(targetNode._parent.convertToWorldSpaceAR(cc.v2(targetNode.x, targetNode.y)));
-}
-
-export function RandomInt(a, b = 0) {
-  let max = Math.max(a, b);
-  let min = Math.min(a, b);
-  return Math.floor(Math.random() * (max - min) + min);
-}
-
-export function randomSortByArr(arr) {
-  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 setSprNodeMaxLen(sprNode, maxW, maxH) {
-  const sx = maxW / sprNode.width;
-  const sy = maxH / sprNode.height;
-  const s = Math.min(sx, sy);
-  sprNode.scale = Math.round(s * 1000) / 1000;
-}
-
-export function localPosTolocalPos(baseNode, targetNode) {
-	const worldPos = targetNode.parent.convertToWorldSpaceAR(cc.v2(targetNode.x, targetNode.y));
-	const localPos = baseNode.parent.convertToNodeSpaceAR(cc.v2(worldPos.x, worldPos.y));
-	return localPos;
-}
-
-export function worldPosToLocalPos(worldPos, baseNode) {
-	const localPos = baseNode.parent.convertToNodeSpaceAR(cc.v2(worldPos.x, worldPos.y));
-	return localPos;
-}
-
-export function getScaleRateBy2Node(baseNode, targetNode, maxFlag = true) {
-	const worldRect1 = targetNode.getBoundingBoxToWorld();
-	const worldRect2 = baseNode.getBoundingBoxToWorld();
-
-	const sx = worldRect1.width / worldRect2.width;
-	const sy = worldRect1.height / worldRect2.height;
-	if (maxFlag) {
-		return Math.max(sx, sy);
-	} else {
-		return Math.min(sx, sy);
-	}
-}
-
-export function getDistance (start, end){
-    var pos = cc.v2(start.x - end.x, start.y - end.y);
-    var dis = Math.sqrt(pos.x*pos.x + pos.y*pos.y);
-    return dis;
-}
-
-export function playAudioByUrl(audio_url, cb=null) {
-	if (audio_url) {
-		cc.assetManager.loadRemote(audio_url, (err, audioClip) => {
-      const audioId = cc.audioEngine.play(audioClip, false, 0.8);
-      if (cb) {
-        cc.audioEngine.setFinishCallback(audioId, () => {
-          cb();
-        });
-      }
-		});
-	}
-}
-
-
-export function btnClickAnima(btn, time=0.15, rate=1.05) {
-  btn.tmpScale = btn.scale;
-  btn.on(cc.Node.EventType.TOUCH_START, () => {
-    cc.tween(btn)
-      .to(time / 2, {scale: btn.scale * rate})
-      .start()
-  })
-  btn.on(cc.Node.EventType.TOUCH_CANCEL, () => {
-    cc.tween(btn)
-      .to(time / 2, {scale: btn.tmpScale})
-      .start()
-  })
-  btn.on(cc.Node.EventType.TOUCH_END, () => {
-    cc.tween(btn)
-      .to(time / 2, {scale: btn.tmpScale})
-      .start()
-  })
-}
-
-
-export function getSpriteFrimeByUrl(url, cb) {
-  cc.loader.load({ url }, (err, img) => {
-    const spriteFrame = new cc.SpriteFrame(img)
-    if (cb) {
-      cb(spriteFrame);
-    }
-  })
-}
-
-export function getSprNode(resName) {
-  const sf = cc.find('Canvas/res/img/' + resName).getComponent(cc.Sprite).spriteFrame;
-  const node = new cc.Node();
-  node.addComponent(cc.Sprite).spriteFrame = sf;
-  return node;
-}
-
-export function getSprNodeByUrl(url, cb) {
-  const node = new cc.Node();
-  const spr = node.addComponent(cc.Sprite);
-  getSpriteFrimeByUrl(url, (sf) => {
-    spr.spriteFrame = sf;
-    if (cb) {
-      cb(spr);
-    }
-  })
-}
-
-
-
-export function playAudio(audioClip, cb = null) {
-  if (audioClip) {
-    const audioId = cc.audioEngine.playEffect(audioClip, false, 0.8);
-    if (cb) {
-      cc.audioEngine.setFinishCallback(audioId, () => {
-        cb();
-      });
-    }
-  }
-}
-
-export async function asyncDelay(time) {
-  return new Promise((resolve, reject) => {
-    try {
-      setTimeout(() => {
-        resolve();
-      }, time * 1000);
-    } catch (e) {
-      reject(e);
-    }
-  })
-}
-
-export class FireworkSettings {
-  baseNode; // 父节点
-  nodeList; // 火花节点的array
-  pos; // 发射点
-  side; // 发射方向
-  range; // 扩散范围
-  number; // 发射数量
-  scalseRange; // 缩放范围
-  constructor(baseNode, nodeList,
-    pos = cc.v2(0, 0),
-    side = cc.v2(0, 100),
-    range = 50,
-    number = 100,
-    scalseRange = 0
-  ) {
-    this.baseNode = baseNode;
-    this.nodeList = nodeList;
-    this.pos = pos;
-    this.side = side;
-    this.range = range;
-    this.number = number;
-    this.scalseRange = scalseRange;
-  }
-
-  static copy(firework) {
-    return new FireworkSettings(
-      firework.baseNode,
-      firework.nodeList,
-      firework.pos,
-      firework.side,
-      firework.range,
-      firework.number,
-    );
-  }
-}
-
-export async function showFireworks(fireworkSettings) {
-  const { baseNode, nodeList, pos, side, range, number, scalseRange } = fireworkSettings;
-  new Array(number).fill(' ').forEach(async (_, i) => {
-
-    let rabbonNode = new cc.Node();
-    rabbonNode.parent = baseNode;
-    rabbonNode.x = pos.x;
-    rabbonNode.y = pos.y;
-    rabbonNode.angle = 60 * Math.random() - 30;
-
-    let node = cc.instantiate(nodeList[RandomInt(nodeList.length)]);
-    node.parent = rabbonNode;
-    node.active = true;
-    node.x = 0;
-    node.y = 0;
-    node.angle = 0;
-    node.scale = (Math.random() - 0.5) * scalseRange + 1;
-
-    const rate = Math.random();
-    const angle = Math.PI * (Math.random() * 2 - 1);
-
-    await asyncTweenBy(rabbonNode, 0.3, {
-      x: side.x * rate + Math.cos(angle) * range * rate,
-      y: side.y * rate + Math.sin(angle) * range * rate
-    }, {
-      easing: 'quadIn'
-    });
-
-    cc.tween(rabbonNode)
-      .by(8, { y: -2000 })
-      .start();
-
-    cc.tween(rabbonNode)
-      .to(5, { scale: (Math.random() - 0.5) * scalseRange + 1 })
-      .start();
-
-    rabbonFall(rabbonNode);
-
-    await asyncDelay(Math.random());
-    cc.tween(node)
-      .by(0.15, { x: -10, angle: -10 })
-      .by(0.3, { x: 20, angle: 20 })
-      .by(0.15, { x: -10, angle: -10 })
-      .union()
-      .repeatForever()
-      .start();
-
-    cc.tween(rabbonNode)
-      .delay(5)
-      .to(0.3, { opacity: 0 })
-      .call(() => {
-        node.stopAllActions();
-        node.active = false;
-        node.parent = null;
-        node = null;
-      })
-      .start();
-  });
-}
-
-async function rabbonFall(node) {
-  const time = 1 + Math.random();
-  const offsetX = RandomInt(-200, 200) * time;
-  await asyncTweenBy(node, time, { x: offsetX, angle: offsetX * 60 / 200 });
-  rabbonFall(node);
-}
-
-
-export async function asyncTweenTo(node, duration, obj, ease = undefined) {
-  return new Promise((resolve, reject) => {
-    try {
-      cc.tween(node)
-        .to(duration, obj, ease)
-        .call(() => {
-          resolve();
-        })
-        .start();
-    } catch (e) {
-      reject(e);
-    }
-  });
-}
-
-export async function asyncTweenBy(node, duration, obj, ease = undefined) {
-  return new Promise((resolve, reject) => {
-    try {
-      cc.tween(node)
-        .by(duration, obj, ease)
-        .call(() => {
-          resolve();
-        })
-        .start();
-    } catch (e) {
-      reject(e);
-    }
-  });
-}
-
-export function showTrebleFirework(baseNode, rabbonList) {
-  const middle = new FireworkSettings(baseNode, rabbonList);
-  middle.pos = cc.v2(0, -400);
-  middle.side = cc.v2(0, 1000);
-  middle.range = 200;
-  middle.number = 100;
-  middle.scalseRange = 0.4;
-
-  const left = FireworkSettings.copy(middle);
-  left.pos = cc.v2(-600, -400);
-  left.side = cc.v2(200, 1000);
-
-  const right = FireworkSettings.copy(middle);
-  right.pos = cc.v2(600, -400);
-  right.side = cc.v2(-200, 1000);
-
-  showFireworks(middle);
-  showFireworks(left);
-  showFireworks(right);
-}
-
-export function onHomeworkFinish() {
-  const middleLayer = cc.find('middleLayer');
-  if (middleLayer) {
-    const middleLayerComponent = middleLayer.getComponent('middleLayer');
-    if (middleLayerComponent.role == 'student') {
-      middleLayerComponent.onHomeworkFinish(() => { });
-    }
-  } else {
-    console.log('onHomeworkFinish');
-  }
-}
\ No newline at end of file
diff --git a/play/assets/scene/textures/.keep b/play/assets/scene/textures/.keep
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/play/assets/scene/textures/1orange.png b/play/assets/scene/textures/1orange.png
deleted file mode 100644
index fe9a37149865449e4f1ad38938476486aa62260a..0000000000000000000000000000000000000000
Binary files a/play/assets/scene/textures/1orange.png and /dev/null differ
diff --git a/play/assets/scene/textures/bg.jpg b/play/assets/scene/textures/bg.jpg
deleted file mode 100644
index 701c49c4c716d9e48412993f87f47d0fdcfbbe44..0000000000000000000000000000000000000000
Binary files a/play/assets/scene/textures/bg.jpg and /dev/null differ
diff --git a/play/assets/scene/textures/bg_bg.png b/play/assets/scene/textures/bg_bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..f97b3be60d41f29034210353c9b4ca125e3b80d3
Binary files /dev/null and b/play/assets/scene/textures/bg_bg.png differ
diff --git a/play/assets/scene/textures/bg.jpg.meta b/play/assets/scene/textures/bg_bg.png.meta
similarity index 77%
rename from play/assets/scene/textures/bg.jpg.meta
rename to play/assets/scene/textures/bg_bg.png.meta
index 14c84e9b1cecc7d63b0d11d7be9c7627f4a1d901..e893624c80d2c85219557a2449ed5c42360c3928 100644
--- a/play/assets/scene/textures/bg.jpg.meta
+++ b/play/assets/scene/textures/bg_bg.png.meta
@@ -1,6 +1,6 @@
 {
   "ver": "2.3.5",
-  "uuid": "e1b4d971-9876-4832-803a-5a321964a78b",
+  "uuid": "f63732e7-8e36-4aec-ba67-bed81381046d",
   "type": "sprite",
   "wrapMode": "clamp",
   "filterMode": "bilinear",
@@ -11,10 +11,10 @@
   "height": 720,
   "platformSettings": {},
   "subMetas": {
-    "bg": {
+    "bg_bg": {
       "ver": "1.0.4",
-      "uuid": "8288e3d4-4c75-4b27-8f01-f7014417f4dd",
-      "rawTextureUuid": "e1b4d971-9876-4832-803a-5a321964a78b",
+      "uuid": "ee7569bd-8d46-467d-a753-3753438bf3fe",
+      "rawTextureUuid": "f63732e7-8e36-4aec-ba67-bed81381046d",
       "trimType": "auto",
       "trimThreshold": 1,
       "rotated": false,
diff --git a/play/assets/scene/textures/bg_buttondi.png b/play/assets/scene/textures/bg_buttondi.png
new file mode 100644
index 0000000000000000000000000000000000000000..26575ae620d7b28b0f15f2e884dd893edb67062e
Binary files /dev/null and b/play/assets/scene/textures/bg_buttondi.png differ
diff --git a/play/assets/scene/textures/bg_buttondi.png.meta b/play/assets/scene/textures/bg_buttondi.png.meta
new file mode 100644
index 0000000000000000000000000000000000000000..a30ee3fd191d17b0415bd37edb98483bd6647e92
--- /dev/null
+++ b/play/assets/scene/textures/bg_buttondi.png.meta
@@ -0,0 +1,36 @@
+{
+  "ver": "2.3.5",
+  "uuid": "643a188a-2667-42d4-9dec-076bcd58cb46",
+  "type": "sprite",
+  "wrapMode": "clamp",
+  "filterMode": "bilinear",
+  "premultiplyAlpha": false,
+  "genMipmaps": false,
+  "packable": true,
+  "width": 300,
+  "height": 103,
+  "platformSettings": {},
+  "subMetas": {
+    "bg_buttondi": {
+      "ver": "1.0.4",
+      "uuid": "ebbed2c5-6d87-463b-b957-47396e91f490",
+      "rawTextureUuid": "643a188a-2667-42d4-9dec-076bcd58cb46",
+      "trimType": "auto",
+      "trimThreshold": 1,
+      "rotated": false,
+      "offsetX": 0,
+      "offsetY": 0,
+      "trimX": 0,
+      "trimY": 0,
+      "width": 300,
+      "height": 103,
+      "rawWidth": 300,
+      "rawHeight": 103,
+      "borderTop": 0,
+      "borderBottom": 0,
+      "borderLeft": 0,
+      "borderRight": 0,
+      "subMetas": {}
+    }
+  }
+}
\ No newline at end of file
diff --git a/play/assets/scene/textures/bg_tiao.png b/play/assets/scene/textures/bg_tiao.png
new file mode 100644
index 0000000000000000000000000000000000000000..317412c8439b1c33d12716b1843a1bf2385f5ad1
Binary files /dev/null and b/play/assets/scene/textures/bg_tiao.png differ
diff --git a/play/assets/scene/textures/icon.png.meta b/play/assets/scene/textures/bg_tiao.png.meta
similarity index 51%
rename from play/assets/scene/textures/icon.png.meta
rename to play/assets/scene/textures/bg_tiao.png.meta
index 53dc69a10c6f823908f9361602c14f5c0be01346..944fb4d66849d8a88e83aaad4950d034e05ea260 100644
--- a/play/assets/scene/textures/icon.png.meta
+++ b/play/assets/scene/textures/bg_tiao.png.meta
@@ -1,35 +1,35 @@
 {
   "ver": "2.3.5",
-  "uuid": "18d07592-51a9-421e-8972-0f67b68d29e1",
+  "uuid": "a3794aeb-2188-40a5-9fdc-88cda61a83ee",
   "type": "sprite",
   "wrapMode": "clamp",
   "filterMode": "bilinear",
   "premultiplyAlpha": false,
   "genMipmaps": false,
   "packable": true,
-  "width": 144,
-  "height": 144,
+  "width": 388,
+  "height": 30,
   "platformSettings": {},
   "subMetas": {
-    "icon": {
+    "bg_tiao": {
       "ver": "1.0.4",
-      "uuid": "6fbc30a8-3c49-44ae-8ba4-7f56f385b78a",
-      "rawTextureUuid": "18d07592-51a9-421e-8972-0f67b68d29e1",
+      "uuid": "802a73b5-336d-465e-a5aa-2c559975bd84",
+      "rawTextureUuid": "a3794aeb-2188-40a5-9fdc-88cda61a83ee",
       "trimType": "auto",
       "trimThreshold": 1,
       "rotated": false,
       "offsetX": 0,
-      "offsetY": -0.5,
+      "offsetY": 0,
       "trimX": 3,
-      "trimY": 2,
-      "width": 138,
-      "height": 141,
-      "rawWidth": 144,
-      "rawHeight": 144,
+      "trimY": 3,
+      "width": 382,
+      "height": 24,
+      "rawWidth": 388,
+      "rawHeight": 30,
       "borderTop": 0,
       "borderBottom": 0,
-      "borderLeft": 0,
-      "borderRight": 0,
+      "borderLeft": 35,
+      "borderRight": 35,
       "subMetas": {}
     }
   }
diff --git a/play/assets/scene/textures/bg_tiaodi.png b/play/assets/scene/textures/bg_tiaodi.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b818b5c80a90ae6d8d4bab84ee0133c7ec66e3a
Binary files /dev/null and b/play/assets/scene/textures/bg_tiaodi.png differ
diff --git a/play/assets/scene/textures/1orange.png.meta b/play/assets/scene/textures/bg_tiaodi.png.meta
similarity index 57%
rename from play/assets/scene/textures/1orange.png.meta
rename to play/assets/scene/textures/bg_tiaodi.png.meta
index cbc7d03803bf7cb91d6eb2c6c3e3fefa7f656b9d..4684c92cf37a9fe4c3ae2b99fcac43d790c53f3f 100644
--- a/play/assets/scene/textures/1orange.png.meta
+++ b/play/assets/scene/textures/bg_tiaodi.png.meta
@@ -1,31 +1,31 @@
 {
   "ver": "2.3.5",
-  "uuid": "efa5fa09-a4dd-4bfc-ab7e-17c19f85408f",
+  "uuid": "48386723-6509-4917-bcee-6257dd7b1506",
   "type": "sprite",
   "wrapMode": "clamp",
   "filterMode": "bilinear",
   "premultiplyAlpha": false,
   "genMipmaps": false,
   "packable": true,
-  "width": 366,
-  "height": 336,
+  "width": 388,
+  "height": 30,
   "platformSettings": {},
   "subMetas": {
-    "1orange": {
+    "bg_tiaodi": {
       "ver": "1.0.4",
-      "uuid": "43d1e79d-6de8-4dcb-b8ce-d767df7913aa",
-      "rawTextureUuid": "efa5fa09-a4dd-4bfc-ab7e-17c19f85408f",
+      "uuid": "80fb10f3-51a4-4982-b965-590c813dd748",
+      "rawTextureUuid": "48386723-6509-4917-bcee-6257dd7b1506",
       "trimType": "auto",
       "trimThreshold": 1,
       "rotated": false,
       "offsetX": 0,
-      "offsetY": -0.5,
+      "offsetY": 0,
       "trimX": 0,
-      "trimY": 1,
-      "width": 366,
-      "height": 335,
-      "rawWidth": 366,
-      "rawHeight": 336,
+      "trimY": 0,
+      "width": 388,
+      "height": 30,
+      "rawWidth": 388,
+      "rawHeight": 30,
       "borderTop": 0,
       "borderBottom": 0,
       "borderLeft": 0,
diff --git a/play/assets/scene/textures/btn_checkall.png b/play/assets/scene/textures/btn_checkall.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a09962cffb58f74991e35f9960d7b71824af897
Binary files /dev/null and b/play/assets/scene/textures/btn_checkall.png differ
diff --git a/play/assets/scene/textures/btn_right.png.meta b/play/assets/scene/textures/btn_checkall.png.meta
similarity index 57%
rename from play/assets/scene/textures/btn_right.png.meta
rename to play/assets/scene/textures/btn_checkall.png.meta
index a0c8dc85f70bce2ef10d8efee4997c3bae467c4b..f76df38b053e0391ce3166e763bfefe2003926fd 100644
--- a/play/assets/scene/textures/btn_right.png.meta
+++ b/play/assets/scene/textures/btn_checkall.png.meta
@@ -1,31 +1,31 @@
 {
   "ver": "2.3.5",
-  "uuid": "d582359e-924e-4ee9-9964-1fc4bb417e71",
+  "uuid": "ac8d3349-20ae-40cc-8dd0-71eefbfb25ed",
   "type": "sprite",
   "wrapMode": "clamp",
   "filterMode": "bilinear",
   "premultiplyAlpha": false,
   "genMipmaps": false,
   "packable": true,
-  "width": 61,
-  "height": 67,
+  "width": 64,
+  "height": 69,
   "platformSettings": {},
   "subMetas": {
-    "btn_right": {
+    "btn_checkall": {
       "ver": "1.0.4",
-      "uuid": "e5a2dbaa-a677-4a32-90d7-a1b057d7fb59",
-      "rawTextureUuid": "d582359e-924e-4ee9-9964-1fc4bb417e71",
+      "uuid": "a918ec7e-293c-43f1-aec1-c75a66e4af14",
+      "rawTextureUuid": "ac8d3349-20ae-40cc-8dd0-71eefbfb25ed",
       "trimType": "auto",
       "trimThreshold": 1,
       "rotated": false,
-      "offsetX": -0.5,
-      "offsetY": 0.5,
+      "offsetX": 0,
+      "offsetY": 0,
       "trimX": 0,
       "trimY": 0,
-      "width": 60,
-      "height": 66,
-      "rawWidth": 61,
-      "rawHeight": 67,
+      "width": 64,
+      "height": 69,
+      "rawWidth": 64,
+      "rawHeight": 69,
       "borderTop": 0,
       "borderBottom": 0,
       "borderLeft": 0,
diff --git a/play/assets/scene/textures/btn_laba.png b/play/assets/scene/textures/btn_laba.png
new file mode 100644
index 0000000000000000000000000000000000000000..bf183e9db46dcf42fd5cfd510c6390bc6e945edb
Binary files /dev/null and b/play/assets/scene/textures/btn_laba.png differ
diff --git a/play/assets/scene/textures/btn_laba.png.meta b/play/assets/scene/textures/btn_laba.png.meta
new file mode 100644
index 0000000000000000000000000000000000000000..3fea37c51eb6538e7b1f6c287e9ed319f9f1e970
--- /dev/null
+++ b/play/assets/scene/textures/btn_laba.png.meta
@@ -0,0 +1,36 @@
+{
+  "ver": "2.3.5",
+  "uuid": "262f4c58-21a1-4020-aacc-e1a5eb3a4756",
+  "type": "sprite",
+  "wrapMode": "clamp",
+  "filterMode": "bilinear",
+  "premultiplyAlpha": false,
+  "genMipmaps": false,
+  "packable": true,
+  "width": 55,
+  "height": 59,
+  "platformSettings": {},
+  "subMetas": {
+    "btn_laba": {
+      "ver": "1.0.4",
+      "uuid": "e1f16c77-4cd2-497e-997a-b449b3d76d99",
+      "rawTextureUuid": "262f4c58-21a1-4020-aacc-e1a5eb3a4756",
+      "trimType": "auto",
+      "trimThreshold": 1,
+      "rotated": false,
+      "offsetX": 0,
+      "offsetY": 0,
+      "trimX": 0,
+      "trimY": 0,
+      "width": 55,
+      "height": 59,
+      "rawWidth": 55,
+      "rawHeight": 59,
+      "borderTop": 0,
+      "borderBottom": 2,
+      "borderLeft": 0,
+      "borderRight": 0,
+      "subMetas": {}
+    }
+  }
+}
\ No newline at end of file
diff --git a/play/assets/scene/textures/btn_laba1.png b/play/assets/scene/textures/btn_laba1.png
new file mode 100644
index 0000000000000000000000000000000000000000..305076ee57c23870634b3308101487cbaa325720
Binary files /dev/null and b/play/assets/scene/textures/btn_laba1.png differ
diff --git a/play/assets/scene/textures/btn_laba1.png.meta b/play/assets/scene/textures/btn_laba1.png.meta
new file mode 100644
index 0000000000000000000000000000000000000000..f92c699c70f475e61b9ab07d22e4f399b1099715
--- /dev/null
+++ b/play/assets/scene/textures/btn_laba1.png.meta
@@ -0,0 +1,36 @@
+{
+  "ver": "2.3.5",
+  "uuid": "599220e7-d544-4218-8459-7903245da287",
+  "type": "sprite",
+  "wrapMode": "clamp",
+  "filterMode": "bilinear",
+  "premultiplyAlpha": false,
+  "genMipmaps": false,
+  "packable": true,
+  "width": 55,
+  "height": 59,
+  "platformSettings": {},
+  "subMetas": {
+    "btn_laba1": {
+      "ver": "1.0.4",
+      "uuid": "d7e29cfd-3377-4ecc-a909-3740e092b0f0",
+      "rawTextureUuid": "599220e7-d544-4218-8459-7903245da287",
+      "trimType": "auto",
+      "trimThreshold": 1,
+      "rotated": false,
+      "offsetX": 0,
+      "offsetY": 0,
+      "trimX": 0,
+      "trimY": 0,
+      "width": 55,
+      "height": 59,
+      "rawWidth": 55,
+      "rawHeight": 59,
+      "borderTop": 0,
+      "borderBottom": 0,
+      "borderLeft": 0,
+      "borderRight": 0,
+      "subMetas": {}
+    }
+  }
+}
\ No newline at end of file
diff --git a/play/assets/scene/textures/btn_laba2.png b/play/assets/scene/textures/btn_laba2.png
new file mode 100644
index 0000000000000000000000000000000000000000..2a44f157bebcf964fc92fd93c66ecd5b1d76eb0f
Binary files /dev/null and b/play/assets/scene/textures/btn_laba2.png differ
diff --git a/play/assets/scene/textures/btn_laba2.png.meta b/play/assets/scene/textures/btn_laba2.png.meta
new file mode 100644
index 0000000000000000000000000000000000000000..0e9d068808fd9f4062d51c9ae4bd7136f7491c8c
--- /dev/null
+++ b/play/assets/scene/textures/btn_laba2.png.meta
@@ -0,0 +1,36 @@
+{
+  "ver": "2.3.5",
+  "uuid": "24d282c3-8a6f-4e2e-b241-37ec553fd4ac",
+  "type": "sprite",
+  "wrapMode": "clamp",
+  "filterMode": "bilinear",
+  "premultiplyAlpha": false,
+  "genMipmaps": false,
+  "packable": true,
+  "width": 55,
+  "height": 59,
+  "platformSettings": {},
+  "subMetas": {
+    "btn_laba2": {
+      "ver": "1.0.4",
+      "uuid": "d40e39de-f46a-4f57-86ad-dc74e14f693b",
+      "rawTextureUuid": "24d282c3-8a6f-4e2e-b241-37ec553fd4ac",
+      "trimType": "auto",
+      "trimThreshold": 1,
+      "rotated": false,
+      "offsetX": 0,
+      "offsetY": 0,
+      "trimX": 0,
+      "trimY": 0,
+      "width": 55,
+      "height": 59,
+      "rawWidth": 55,
+      "rawHeight": 59,
+      "borderTop": 0,
+      "borderBottom": 0,
+      "borderLeft": 0,
+      "borderRight": 0,
+      "subMetas": {}
+    }
+  }
+}
\ No newline at end of file
diff --git a/play/assets/scene/textures/btn_laba3.png b/play/assets/scene/textures/btn_laba3.png
new file mode 100644
index 0000000000000000000000000000000000000000..4aebcea2500ed0075c7ac403aae0fc306ca07fda
Binary files /dev/null and b/play/assets/scene/textures/btn_laba3.png differ
diff --git a/play/assets/scene/textures/btn_laba3.png.meta b/play/assets/scene/textures/btn_laba3.png.meta
new file mode 100644
index 0000000000000000000000000000000000000000..75dca07bde910182f8397393a7fabbdcdb54eadc
--- /dev/null
+++ b/play/assets/scene/textures/btn_laba3.png.meta
@@ -0,0 +1,36 @@
+{
+  "ver": "2.3.5",
+  "uuid": "ac87980c-a042-419f-a9e9-1d1b07c511c0",
+  "type": "sprite",
+  "wrapMode": "clamp",
+  "filterMode": "bilinear",
+  "premultiplyAlpha": false,
+  "genMipmaps": false,
+  "packable": true,
+  "width": 55,
+  "height": 59,
+  "platformSettings": {},
+  "subMetas": {
+    "btn_laba3": {
+      "ver": "1.0.4",
+      "uuid": "52418a35-ae97-4789-9c2c-43a512ede990",
+      "rawTextureUuid": "ac87980c-a042-419f-a9e9-1d1b07c511c0",
+      "trimType": "auto",
+      "trimThreshold": 1,
+      "rotated": false,
+      "offsetX": 0,
+      "offsetY": 0,
+      "trimX": 0,
+      "trimY": 0,
+      "width": 55,
+      "height": 59,
+      "rawWidth": 55,
+      "rawHeight": 59,
+      "borderTop": 0,
+      "borderBottom": 0,
+      "borderLeft": 0,
+      "borderRight": 0,
+      "subMetas": {}
+    }
+  }
+}
\ No newline at end of file
diff --git a/play/assets/scene/textures/btn_last.png b/play/assets/scene/textures/btn_last.png
new file mode 100644
index 0000000000000000000000000000000000000000..79dcf965be8eacfbe6055896d31ab3975e577590
Binary files /dev/null and b/play/assets/scene/textures/btn_last.png differ
diff --git a/play/assets/scene/textures/btn_left.png.meta b/play/assets/scene/textures/btn_last.png.meta
similarity index 62%
rename from play/assets/scene/textures/btn_left.png.meta
rename to play/assets/scene/textures/btn_last.png.meta
index 2812db2c1edaf060f69bfe9cef23bf25469265ae..776877514057340a1fa52c6945eee5c7639e3559 100644
--- a/play/assets/scene/textures/btn_left.png.meta
+++ b/play/assets/scene/textures/btn_last.png.meta
@@ -1,20 +1,20 @@
 {
   "ver": "2.3.5",
-  "uuid": "9a79969a-0506-48d4-bc98-3c05d109b027",
+  "uuid": "0a31905b-7b30-49c5-b25b-9996adcbc749",
   "type": "sprite",
   "wrapMode": "clamp",
   "filterMode": "bilinear",
   "premultiplyAlpha": false,
   "genMipmaps": false,
   "packable": true,
-  "width": 61,
-  "height": 67,
+  "width": 64,
+  "height": 68,
   "platformSettings": {},
   "subMetas": {
-    "btn_left": {
+    "btn_last": {
       "ver": "1.0.4",
-      "uuid": "ce19457d-e8f3-4c38-ae3e-d4b99208ddb5",
-      "rawTextureUuid": "9a79969a-0506-48d4-bc98-3c05d109b027",
+      "uuid": "ad0a3c91-cad1-449e-9ccc-00b77784be63",
+      "rawTextureUuid": "0a31905b-7b30-49c5-b25b-9996adcbc749",
       "trimType": "auto",
       "trimThreshold": 1,
       "rotated": false,
@@ -22,10 +22,10 @@
       "offsetY": 0,
       "trimX": 0,
       "trimY": 0,
-      "width": 61,
-      "height": 67,
-      "rawWidth": 61,
-      "rawHeight": 67,
+      "width": 64,
+      "height": 68,
+      "rawWidth": 64,
+      "rawHeight": 68,
       "borderTop": 0,
       "borderBottom": 0,
       "borderLeft": 0,
diff --git a/play/assets/scene/textures/btn_left.png b/play/assets/scene/textures/btn_left.png
deleted file mode 100644
index e3428fd5bcda4bad311e87c5aa5669fdb7e96a60..0000000000000000000000000000000000000000
Binary files a/play/assets/scene/textures/btn_left.png and /dev/null differ
diff --git a/play/assets/scene/textures/btn_next.png b/play/assets/scene/textures/btn_next.png
new file mode 100644
index 0000000000000000000000000000000000000000..8ced122de5e1847bac25a99046344f1eae55eb31
Binary files /dev/null and b/play/assets/scene/textures/btn_next.png differ
diff --git a/play/assets/scene/textures/btn_next.png.meta b/play/assets/scene/textures/btn_next.png.meta
new file mode 100644
index 0000000000000000000000000000000000000000..1c32d37029932d528a13908454cef214b10d923a
--- /dev/null
+++ b/play/assets/scene/textures/btn_next.png.meta
@@ -0,0 +1,36 @@
+{
+  "ver": "2.3.5",
+  "uuid": "933eab7f-2c09-439c-a700-ba2374594e48",
+  "type": "sprite",
+  "wrapMode": "clamp",
+  "filterMode": "bilinear",
+  "premultiplyAlpha": false,
+  "genMipmaps": false,
+  "packable": true,
+  "width": 64,
+  "height": 68,
+  "platformSettings": {},
+  "subMetas": {
+    "btn_next": {
+      "ver": "1.0.4",
+      "uuid": "68899d36-0959-405b-b0a4-ba99d96f471c",
+      "rawTextureUuid": "933eab7f-2c09-439c-a700-ba2374594e48",
+      "trimType": "auto",
+      "trimThreshold": 1,
+      "rotated": false,
+      "offsetX": 0,
+      "offsetY": 0,
+      "trimX": 0,
+      "trimY": 0,
+      "width": 64,
+      "height": 68,
+      "rawWidth": 64,
+      "rawHeight": 68,
+      "borderTop": 0,
+      "borderBottom": 0,
+      "borderLeft": 0,
+      "borderRight": 0,
+      "subMetas": {}
+    }
+  }
+}
\ No newline at end of file
diff --git a/play/assets/scene/textures/btn_play.png b/play/assets/scene/textures/btn_play.png
new file mode 100644
index 0000000000000000000000000000000000000000..ee299e0eaaef7efa0f0559b1771011b751425fff
Binary files /dev/null and b/play/assets/scene/textures/btn_play.png differ
diff --git a/play/assets/scene/textures/btn_play.png.meta b/play/assets/scene/textures/btn_play.png.meta
new file mode 100644
index 0000000000000000000000000000000000000000..6eae8332077047c210af7e5be298789b47da08cc
--- /dev/null
+++ b/play/assets/scene/textures/btn_play.png.meta
@@ -0,0 +1,36 @@
+{
+  "ver": "2.3.5",
+  "uuid": "ffead944-ef83-403c-9841-4af0e5d4f6dd",
+  "type": "sprite",
+  "wrapMode": "clamp",
+  "filterMode": "bilinear",
+  "premultiplyAlpha": false,
+  "genMipmaps": false,
+  "packable": true,
+  "width": 69,
+  "height": 73,
+  "platformSettings": {},
+  "subMetas": {
+    "btn_play": {
+      "ver": "1.0.4",
+      "uuid": "6c58ba73-4d8e-421a-b822-14f68c6bae45",
+      "rawTextureUuid": "ffead944-ef83-403c-9841-4af0e5d4f6dd",
+      "trimType": "auto",
+      "trimThreshold": 1,
+      "rotated": false,
+      "offsetX": 0,
+      "offsetY": 0,
+      "trimX": 0,
+      "trimY": 0,
+      "width": 69,
+      "height": 73,
+      "rawWidth": 69,
+      "rawHeight": 73,
+      "borderTop": 0,
+      "borderBottom": 0,
+      "borderLeft": 0,
+      "borderRight": 0,
+      "subMetas": {}
+    }
+  }
+}
\ No newline at end of file
diff --git a/play/assets/scene/textures/btn_replay.png b/play/assets/scene/textures/btn_replay.png
new file mode 100644
index 0000000000000000000000000000000000000000..c6a630cff109653a66c9905772d83895c228826b
Binary files /dev/null and b/play/assets/scene/textures/btn_replay.png differ
diff --git a/play/assets/scene/textures/btn_replay.png.meta b/play/assets/scene/textures/btn_replay.png.meta
new file mode 100644
index 0000000000000000000000000000000000000000..9f6edff18dc7b5de84aab184f04299c38d15f053
--- /dev/null
+++ b/play/assets/scene/textures/btn_replay.png.meta
@@ -0,0 +1,36 @@
+{
+  "ver": "2.3.5",
+  "uuid": "ed8e56de-6441-4bbe-9994-3ef5d18fc780",
+  "type": "sprite",
+  "wrapMode": "clamp",
+  "filterMode": "bilinear",
+  "premultiplyAlpha": false,
+  "genMipmaps": false,
+  "packable": true,
+  "width": 64,
+  "height": 69,
+  "platformSettings": {},
+  "subMetas": {
+    "btn_replay": {
+      "ver": "1.0.4",
+      "uuid": "9266d645-d228-407a-8bf1-5bff25c516c3",
+      "rawTextureUuid": "ed8e56de-6441-4bbe-9994-3ef5d18fc780",
+      "trimType": "auto",
+      "trimThreshold": 1,
+      "rotated": false,
+      "offsetX": 0,
+      "offsetY": 0,
+      "trimX": 0,
+      "trimY": 0,
+      "width": 64,
+      "height": 69,
+      "rawWidth": 64,
+      "rawHeight": 69,
+      "borderTop": 0,
+      "borderBottom": 0,
+      "borderLeft": 0,
+      "borderRight": 0,
+      "subMetas": {}
+    }
+  }
+}
\ No newline at end of file
diff --git a/play/assets/scene/textures/btn_right.png b/play/assets/scene/textures/btn_right.png
deleted file mode 100644
index db0f274024b4ad41d5219acf3936ec2b2f79459c..0000000000000000000000000000000000000000
Binary files a/play/assets/scene/textures/btn_right.png and /dev/null differ
diff --git a/play/assets/scene/textures/btn_stop.png b/play/assets/scene/textures/btn_stop.png
new file mode 100644
index 0000000000000000000000000000000000000000..e7eee33d71b1074c151b1f9d7baeb12f9b422d39
Binary files /dev/null and b/play/assets/scene/textures/btn_stop.png differ
diff --git a/play/assets/scene/textures/btn_stop.png.meta b/play/assets/scene/textures/btn_stop.png.meta
new file mode 100644
index 0000000000000000000000000000000000000000..0f506ea2c81c7ff4b2f55ed9fa216bcb7db22867
--- /dev/null
+++ b/play/assets/scene/textures/btn_stop.png.meta
@@ -0,0 +1,36 @@
+{
+  "ver": "2.3.5",
+  "uuid": "4658250e-a295-4297-87c7-6c12f62290f2",
+  "type": "sprite",
+  "wrapMode": "clamp",
+  "filterMode": "bilinear",
+  "premultiplyAlpha": false,
+  "genMipmaps": false,
+  "packable": true,
+  "width": 69,
+  "height": 73,
+  "platformSettings": {},
+  "subMetas": {
+    "btn_stop": {
+      "ver": "1.0.4",
+      "uuid": "7b07d2a9-946a-46e7-ae60-71d45eb0d5c3",
+      "rawTextureUuid": "4658250e-a295-4297-87c7-6c12f62290f2",
+      "trimType": "auto",
+      "trimThreshold": 1,
+      "rotated": false,
+      "offsetX": 0,
+      "offsetY": 0,
+      "trimX": 0,
+      "trimY": 0,
+      "width": 69,
+      "height": 73,
+      "rawWidth": 69,
+      "rawHeight": 73,
+      "borderTop": 0,
+      "borderBottom": 0,
+      "borderLeft": 0,
+      "borderRight": 0,
+      "subMetas": {}
+    }
+  }
+}
\ No newline at end of file
diff --git a/play/assets/scene/textures/icon.png b/play/assets/scene/textures/icon.png
deleted file mode 100644
index 63bf81e6ea88059e83d595ba2ae71fa1e0e746c8..0000000000000000000000000000000000000000
Binary files a/play/assets/scene/textures/icon.png and /dev/null differ
diff --git a/play/assets/scene/textures/icon_move.png b/play/assets/scene/textures/icon_move.png
new file mode 100644
index 0000000000000000000000000000000000000000..da22f70ca65785cd1a6008ce19ea3ebae6cd2b75
Binary files /dev/null and b/play/assets/scene/textures/icon_move.png differ
diff --git a/play/assets/scene/textures/icon_move.png.meta b/play/assets/scene/textures/icon_move.png.meta
new file mode 100644
index 0000000000000000000000000000000000000000..7f6304de752150842f26104941d32371c8c6d90c
--- /dev/null
+++ b/play/assets/scene/textures/icon_move.png.meta
@@ -0,0 +1,36 @@
+{
+  "ver": "2.3.5",
+  "uuid": "a5f1b0df-14e7-4b67-94f7-3e03221ce599",
+  "type": "sprite",
+  "wrapMode": "clamp",
+  "filterMode": "bilinear",
+  "premultiplyAlpha": false,
+  "genMipmaps": false,
+  "packable": true,
+  "width": 26,
+  "height": 51,
+  "platformSettings": {},
+  "subMetas": {
+    "icon_move": {
+      "ver": "1.0.4",
+      "uuid": "fff435c8-ec81-49f6-8793-3a8ae25d77e2",
+      "rawTextureUuid": "a5f1b0df-14e7-4b67-94f7-3e03221ce599",
+      "trimType": "auto",
+      "trimThreshold": 1,
+      "rotated": false,
+      "offsetX": 0,
+      "offsetY": 0,
+      "trimX": 0,
+      "trimY": 0,
+      "width": 26,
+      "height": 51,
+      "rawWidth": 26,
+      "rawHeight": 51,
+      "borderTop": 0,
+      "borderBottom": 0,
+      "borderLeft": 0,
+      "borderRight": 0,
+      "subMetas": {}
+    }
+  }
+}
\ No newline at end of file
diff --git a/play/settings/project.json b/play/settings/project.json
index 60318bd094eadb4e3b3a9c9464d8a61cc130d766..5729c6bbd7f1ad0daa0eaebe2fa7743132bddbcb 100644
--- a/play/settings/project.json
+++ b/play/settings/project.json
@@ -1,5 +1,5 @@
 {
-  "last-module-event-record-time": 1600677246969,
+  "last-module-event-record-time": 1620757263933,
   "migrate-history": [
     "cloud-function"
   ]