<!--
 * 【模块 export 内容】
 * JsvSceneTransition:场景过渡组件。
 *      props说明:
 *          imageUrl     {String}    (必填) 显示图片的加载地址
 *          displayWidth {Number}    (必填) 想要展示的宽度
 *          ArraySet     {Array}     (必填) 模板配置项，包括：每个模块的width,height,left,top,url
 *          style        {Object}    (必填) 模板配置总长度和总宽度。(width,height)
 *      defineExpose说明:
 *          sag          {Function}  控制组件变成碎片进行下垂运动的方法
 *          recover      {Function}  控制碎片还原的方法
-->

<template>
  <div
    :style="{
      width: props.style.width,
      height: props.style.height,
      transform: `scale3d(${props.displayWidth / props.style.width},${
        props.displayWidth / props.style.width
      },1)`,
      transformOrigin: 'left top',
    }"
  >
    <jsv-free-move-actor
      v-for="(item, index) in props.ArraySet"
      :ref="(el) => (refArray[index] = el)"
      :top="item.top"
      :left="item.left"
      :width="item.width"
      :height="item.height"
    >
      <jsv-mask-clip-div
        :style="{
          top: 0,
          left: 0,
          width: item.width,
          height: item.height,
        }"
        :viewSrc="props.imageUrl"
        :maskSrc="item.url"
        :maskLeft="item.left / props.style.width"
        :maskTop="item.top / props.style.height"
        :maskWidth="item.width / props.style.width"
        :maskHeight="item.height / props.style.height"
      />
    </jsv-free-move-actor>
  </div>
</template>

<script setup>
import { JsvMaskClipDiv, JsvFreeMoveActor, FreeMoveFunc } from "jsview";
import { onMounted } from "vue";

const props = defineProps({
  imageUrl: { type: String, require: true },
  displayWidth: { type: Number, require: true },
  ArraySet: { type: Array, require: true },
  style: { type: Object, require: true },
});

let interactNexus = FreeMoveFunc.newNexus();
//FreeMove引用
const refArray = [];
const controlArray = new Array(props.ArraySet.length).fill(null);

//算图的中心点
const center = {
  x: Math.floor(props.style.width / 2),
  y: Math.floor(props.style.height / 2),
};
//算所有遮罩层中心点
const centerItemArray = [];
props.ArraySet.forEach((item, index) => {
  const centerX = (item.left + item.width) / 2;
  const centerY = (item.top + item.height) / 2;
  centerItemArray.push({
    x: centerX,
    y: centerY,
  });
});
//召回点坐标队列
let recallArray = new Array(props.ArraySet.length);

//Y轴方向随机初速度
const randomYArray = [-60, -70, -80];
const randomSelect = () => {
  let randomNum = Math.random();
  if (randomNum < 0.33) {
    return randomYArray[0];
  } else if (randomNum < 0.66) {
    return randomYArray[1];
  } else {
    return randomYArray[2];
  }
};
//往下运动函数
const sag = () => {
  centerItemArray.forEach((item, index) => {
    if (center.x - item.x <= Math.abs(60)) {
      controlArray[index].run((cmds) => [
        cmds.action().setSpdAndAccel(16, randomSelect(), 0, 15, null, null),
        cmds
          .condition()
          .reachPosition(undefined, 1380)
          .then([cmds.action().stopMoving()]),
      ]);
    } else if (center.x - item.x <= 200) {
      controlArray[index].run((cmds) => [
        cmds.action().setSpdAndAccel(8, randomSelect(), 0, 15, null, null),
        cmds
          .condition()
          .reachPosition(undefined, 1380)
          .then([cmds.action().stopMoving()]),
      ]);
    } else if (center.x - item.x <= 500) {
      controlArray[index].run((cmds) => [
        cmds.action().setSpdAndAccel(-8, randomSelect(), 0, 15, null, null),
        cmds
          .condition()
          .reachPosition(undefined, 1380)
          .then([cmds.action().stopMoving()]),
      ]);
    } else if (center.x - item.x > 500) {
      controlArray[index].run((cmds) => [
        cmds.action().setSpdAndAccel(-16, randomSelect(), 0, 15, null, null),
        cmds
          .condition()
          .reachPosition(undefined, 1380)
          .then([cmds.action().stopMoving()]),
      ]);
    } else if (center.x - item.x < -60) {
      controlArray[index].run((cmds) => [
        cmds.action().setSpdAndAccel(20, randomSelect(), 0, 15, null, null),
        cmds
          .condition()
          .reachPosition(undefined, 1380)
          .then([cmds.action().stopMoving()]),
      ]);
    }
    //给所有运动物体创建onNexusEvent条件以便召回
    controlArray[index].run((cmds) => [
      cmds
        .condition()
        .onNexusEvent(interactNexus, 1001 + index)
        .then([
          (a) => {
            //给还原数组赋值
            recallArray[index] = {
              x: a.xPos,
              y: a.yPos,
            };
            recover(index);
          },
        ]),
    ]);
  });
};

const fireNeEvent = () => {
  controlArray.forEach((item, index) => {
    item.run((cmds) => [
      cmds.action().stopMoving(),
      cmds.state().fireNexusEvent(interactNexus, 1001 + index),
    ]);
  });
};
//往回恢复的函数
const recover = (index) => {
  controlArray[index].run((cmds) => [
    cmds
      .action()
      .moveTo(
        0,
        0,
        (Math.abs(recallArray[index].x) * (recallArray[index].y / 15)) /
          Math.abs(recallArray[index].y),
        recallArray[index].y / 15,
        () => {
          controlArray[index].run((cmds) => [
            cmds.action().teleportTo(0, 0),
            cmds.state().clearAllConditions(),
          ]);
        }
      ),
  ]);
};

onMounted(() => {
  for (let i = 0; i < refArray.length; i++) {
    controlArray[i] = refArray[i].control;
  }
});
defineExpose({ sag, fireNeEvent });
</script>

<style scoped></style>
