分屏架构自定义实现

119 阅读1分钟
<!--
 * @Date: 2021-04-12 11:36:51
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2021-04-15 17:36:45
 * @FilePath: \videojs-test\src\views\Grids.vue
-->
<template>
  <div
    class="main"
    ref="main"
    :style="{
      width: `${renderData.width}px`,
      height: `${renderData.height}px`,
    }"
  >
    <!-- 可滚动区域 -->
    <div class="btn" v-if="renderData.type === 2">
      <button @click="handleClick(0)">
        横向分屏
      </button>
      <button @click="handleClick(1)">
        纵向分屏
      </button>
    </div>

    <div
      :class="{ appwrapper: true, shu: renderData.type === 1 }"
      v-if="renderData.type !== 2"
    >
      <App
        v-for="(item, index) in renderData.children"
        :key="index"
        :renderData="item"
      />
    </div>

    <div
      class="item"
      v-if="renderData.type !== 2"
      :style="{
        width: `${renderData.type === 0 ? renderData.width : defaultWidth}px`,
        height: `${renderData.type === 0 ? defaultWidth : renderData.width}px`,
        top: `${
          renderData.type === 0
            ? renderData.children[0].height - defaultWidth / 2
            : 0
        }px`,
        left: `${
          renderData.type === 0
            ? 0
            : renderData.children[0].width - defaultWidth / 2
        }px`,
        cursor: renderData.type === 0 ? 'n-resize' : 'e-resize',
      }"
      @mousedown="handleMouseDown"
    ></div>
  </div>
</template>

<script>
export default {
  name: "App",
  props: {
    renderData: {
      type: Object,
      default: () => ({}),
    },
  },
  watch: {
    renderData: {
      deep: true,
      handler(value) {
        if (value.children) {
          if (value.type === 0) {
            value.children[0].width = value.children[1].width = value.width;
            value.children[0].height =
              (value.children[0].height /
                (value.children[0].height + value.children[1].height)) *
              value.height;
            value.children[1].height =
              (value.children[1].height /
                (value.children[0].height + value.children[1].height)) *
              value.height;
          } else {
            value.children[0].height = value.children[1].height = value.height;
            value.children[0].width =
              (value.children[0].width /
                (value.children[0].width + value.children[1].width)) *
              value.width;
            value.children[1].width =
              (value.children[1].width /
                (value.children[0].width + value.children[1].width)) *
              value.width;
          }
        }
      },
    },
  },
  data() {
    return {
      defaultWidth: 4,
    };
  },
  methods: {
    handleClick(num) {
      this.renderData.type = num;
      this.$set(this.renderData, "children", [
        {
          type: 2,
          width: num === 0 ? this.renderData.width : this.renderData.width / 2,
          height:
            num === 0 ? this.renderData.height / 2 : this.renderData.height,
        },
        {
          type: 2,
          width: num === 0 ? this.renderData.width : this.renderData.width / 2,
          height:
            num === 0 ? this.renderData.height / 2 : this.renderData.height,
        },
      ]);
    },
    handleMouseDown(e) {
      let start = e.clientX;
      let end = e.clientY;
      document.onmousemove = (e) => {
        const sestart = e.clientX;
        const seend = e.clientY;

        const disx = sestart - start;
        const disy = seend - end;

        start = sestart;
        end = seend;

        //console.log(disx, disy);

        if (this.renderData.type === 0) {
          //横屏
          this.renderData.children[0].height += disy;
          if (this.renderData.children[0].height <= 0) {
            this.renderData.children[0].height = 0;
          }
          if (this.renderData.children[0].height >= this.renderData.height) {
            this.renderData.children[0].height = this.renderData.height;
          }
          this.renderData.children[1].height =
            this.renderData.height - this.renderData.children[0].height;
        } else {
          this.renderData.children[0].width += disx;
          if (this.renderData.children[0].width <= 0) {
            this.renderData.children[0].width = 0;
          }
          if (this.renderData.children[0].width >= this.renderData.width) {
            this.renderData.children[0].width = this.renderData.width;
          }
          this.renderData.children[1].width =
            this.renderData.width - this.renderData.children[0].width;
        }
      };
      document.onmouseup = () => {
        document.onmousemove = null;
        document.onmouseleave = null;
      };
    },
  },
};
</script>

<style>
.main {
  position: relative;
  box-sizing: border-box;
  overflow: hidden;
  border: 2px solid red;
}
.item {
  background: chartreuse;
  position: absolute;
  cursor: e-resize;
}
.main .btn {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 80px;
  height: 60px;
  font-size: 12px;
  justify-content: space-between;
  display: flex;
  flex-direction: column;
  user-select: none;
  margin: auto;
}

/* 分割线 */
.shu {
  display: flex;
}
</style>