手标扫面区域选中

该代码段展示了一个使用Vue.js编写的自定义时间段选择组件。组件包括一个可拖动调整大小的遮罩层,以及一组可被选择的方块元素。通过监听鼠标事件来计算遮罩层的位置和大小,并更新数据模型,实现元素的选中效果。
摘要由CSDN通过智能技术生成

<template>

  <el-dialog

    title="时间段选择"

    :visible.sync="dialogVisible"

    :close-on-click-modal="false"

    custom-class="custom-dialog-style"

    width="1000px"

    :close="close"

  >

    <div class="container">

      <div class="wrap">

        <div class="right">

          <div class="bottom" @mousedown="handleMouseDown">

            <div

              :style="

                'width:' +

                  mask_width +

                  'left:' +

                  mask_left +

                  'height:' +

                  mask_height +

                  'top:' +

                  mask_top

              "

              v-show="positionList.is_show_mask"

              class="mask"

            ></div>

            <div v-for="i in 30" class="box">

              <div class="check_box">

                <i class="el-icon-check"></i>

              </div>

              <span>*</span>

              <div>出函机构</div>

            </div>

          </div>

        </div>

      </div>

    </div>

    <div slot="footer">

      <el-button @click="close">取 消</el-button>

      <el-button type="primary" @click="submit">确 定</el-button>

    </div>

  </el-dialog>

</template>

<script>

const positionList = {

  is_show_mask: false,

  box_screen_left: 0, // 盒子距离浏览器左侧的距离

  box_screen_top: 0, //盒子距离浏览器顶部的距离

  start_x: 0,

  start_y: 0,

  end_x: 0,

  end_y: 0

};

export default {

  data() {

    return {

      dialogVisible: true,

      totalNum: 336,

      dataItem: [],

      isClick: true,

      positionList: { ...positionList }

    };

  },

  computed: {

    mask_width() {

      return `${Math.abs(

        this.positionList.end_x - this.positionList.start_x

      )}px;`;

    },

    mask_height() {

      return `${Math.abs(

        this.positionList.end_y - this.positionList.start_y

      )}px;`;

    },

    mask_left() {

      return `${Math.min(this.positionList.start_x, this.positionList.end_x) -

        this.positionList.box_screen_left}px;`;

    },

    mask_top() {

      return `${Math.min(this.positionList.start_y, this.positionList.end_y) -

        this.positionList.box_screen_top}px;`;

    }

  },

  mounted() {

    this.init();

  },

  methods: {

    init() {

      // ref 调用init弹窗即可

      this.dialogVisible = true;

      this.initList();

    },

    initList() {

      for (let i = 1; i <= this.totalNum; i++) {

        let map = {

          selected: false,

          key: i

        };

        this.dataItem.push(map);

      }

    },

    setData(value) {

      this.initList();

      value.forEach(v => {

        this.dataItem[v - 1].selected = true;

      });

    },

    handleMouseDown(event) {

      this.positionList.is_show_mask = true;

      this.positionList.start_x = event.clientX;

      this.positionList.start_y = event.clientY;

      this.positionList.end_x = event.clientX;

      this.positionList.end_y = event.clientY;

      this.positionList.box_screen_left = document

        .querySelector(".bottom")

        .getBoundingClientRect().left;

      this.positionList.box_screen_top = document

        .querySelector(".bottom")

        .getBoundingClientRect().top;

      document.body.addEventListener("mousemove", this.handleMouseMove); //监听鼠标移动事件

      document.body.addEventListener("mouseup", this.handleMouseUp); //监听鼠标抬起事件

    },

    handleMouseMove(event) {

      this.positionList.end_x = event.clientX;

      this.positionList.end_y = event.clientY;

    },

    handleMouseUp(event) {

      document.body.removeEventListener("mousemove", this.handleMouseMove);

      document.body.removeEventListener("mouseup", this.handleMouseUp);

      // this.positionList = { ...positionList };

      // this.positionList.is_show_mask = false;

      // this.handleDomSelect();

      // this.resSetXY();

    },

    handleDomSelect() {

      const dom_mask = window.document.querySelector(".mask");

      // getClientRects()方法 每一个盒子的边界矩形的矩形集合

      const rect_select = dom_mask.getClientRects()[0];

      document.querySelectorAll(".select-item").forEach((node, index) => {

        const rects = node.getClientRects()[0];

        if (this.collide(rects, rect_select) === true) {

          this.dataItem[index].selected = !this.dataItem[index].selected;

        }

      });

    },

    collide(rect1, rect2) {

      const maxX = Math.max(rect1.x + rect1.width, rect2.x + rect2.width);

      const maxY = Math.max(rect1.y + rect1.height, rect2.y + rect2.height);

      const minX = Math.min(rect1.x, rect2.x);

      const minY = Math.min(rect1.y, rect2.y);

      return (

        maxX - minX <= rect1.width + rect2.width &&

        maxY - minY <= rect1.height + rect2.height

      );

    },

    resSetXY() {

      this.positionList.start_x = 0;

      this.positionList.start_y = 0;

      this.positionList.end_x = 0;

      this.positionList.end_y = 0;

    },

    close() {

      this.dialogVisible = false;

      this.dataItem = [];

    },

    submit() {}

  }

};

</script>

<style lang="scss" scoped>

.container {

  height: 600px;

  border: 1px solid #f1f1f1;

  .box {

    display: flex;

    -moz-user-select: none; /* Firefox私有属性 */

    -webkit-user-select: none; /* WebKit内核私有属性 */

    -ms-user-select: none; /* IE私有属性(IE10及以后) */

    -khtml-user-select: none; /* KHTML内核私有属性 */

    -o-user-select: none; /* Opera私有属性 */

    user-select: none; /* CSS3属性 */

    cursor: pointer;

    span {

      color: red;

      margin: 3px;

    }

    min-width: 120px;

    line-height: 20px;

    height: 20px;

    padding: 30px;

  }

  .check_box {

    width: 16px;

    height: 16px;

    border: 1px solid #f1f1f1;

    margin-top: 3px;

  }

  .wrap {

    display: flex;

    border: 1px solid #f1f1f1;

    border-bottom: 0;

    flex-wrap: wrap;

    .left {

      .merge-column {

        width: 4vw;

        height: 6vh;

        padding: 3px 5px;

        min-width: 76px;

        min-height: 55px;

        display: flex;

        align-items: center;

        border-right: 1px solid #f1f1f1;

        border-bottom: 1px solid #f1f1f1;

      }

      .td-title {

        width: 4vw;

        height: 3vh;

        min-height: 27px;

        min-width: 76px;

        padding: 3px 5px;

        text-align: center;

        border-right: 1px solid #f1f1f1;

        border-bottom: 1px solid #f1f1f1;

      }

      &:last-child {

        border-bottom: 0;

      }

    }

    .right {

      display: flex;

      flex-wrap: wrap;

      .top {

        width: 100%;

        display: flex;

        flex-wrap: wrap;

        align-content: flex-start;

        .merge-row {

          width: 50%;

          height: 3vh;

          padding: 3px 5px;

          min-width: 420px;

          min-height: 27px;

          text-align: center;

          border-right: 1px solid #f1f1f1;

          border-bottom: 1px solid #f1f1f1;

          &:nth-child(2) {

            border-right: 0;

          }

        }

        .unit {

          width: calc(100% / 24);

          height: 3vh;

          padding: 3px 5px;

          min-width: 35px;

          min-height: 27px;

          text-align: center;

          border-right: 1px solid #f1f1f1;

          border-bottom: 1px solid #f1f1f1;

          &:last-child {

            border-right: 0;

          }

        }

      }

      .bottom {

        width: 100%;

        position: relative;

        display: flex;

        flex-wrap: wrap;

        .mask {

          position: absolute;

          background: #409eff;

          opacity: 0.4;

          z-index: 100;

          left: 0;

          top: 0;

        }

        .select-item {

          width: calc(100% / 48);

          height: 3vh;

          min-width: 17px;

          min-height: 27px;

          cursor: pointer;

          padding: 3px 5px;

          border-right: 1px solid #f1f1f1;

          border-bottom: 1px solid #f1f1f1;

          &:hover {

            background: #f1f1f1;

          }

        }

        .selected {

          background: #7bc8ff;

          &:hover {

            background: #7bc8ff;

          }

        }

        *:nth-child(48n + 1) {

          border-right: 0;

        }

      }

    }

  }

}

</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值