[sgDragMoveTile] Custom components: drag and drop tiles, maps, large pictures, scroll bars corresponding to synchronous scrolling

characteristic:

  1. You can customize the mouse style during the drag and drop process
  2. Can disable dragging
  3. Dynamically set drag and scroll area elements

sgDragMoveTile source code

<template>
    <div :class="$options.name"> </div>
</template>
<script>
export default {
    name: 'sgDragMoveTile',
    data() {
        return {
            scrollContainer: null,
            dragContainer: null,
        }
    },
    props: [
        "data",
        /*data格式:{
            scrollContainer:滚动条容器的element,
            dragContainer:拖拽的element,
        }*/
        "disabled",//是否禁用
        "cursor",//鼠标样式
        /*cursor格式说明:{
            grab:'default',//移入可拖拽区域的鼠标样式
            grabbing:'default',//拖拽过程中鼠标样式
        }*/
    ],
    watch: {
        data: {
            handler(newValue, oldValue) {
                if (newValue && Object.keys(newValue).length) {
                    newValue.scrollContainer && (this.scrollContainer = newValue.scrollContainer);
                    newValue.dragContainer && (this.dragContainer = newValue.dragContainer);
                    this.addEvents();
                } else {
                    this.removeEvents();
                }
            },
            deep: true,//深度监听
            immediate: true,//立即执行
        },
        disabled: {
            handler(newValue, oldValue) {
                newValue ? this.removeEvents() : this.addEvents();
            }, deep: true, immediate: true,
        },
    },
    mounted() {
        this.$parent.$el.style.setProperty("--sgDragMoveTile-grab", (this.cursor || {}).grab || 'grab'); //js往css传递局部参数
        this.$parent.$el.style.setProperty("--sgDragMoveTile-grabbing", (this.cursor || {}).grabbing || 'grabbing'); //js往css传递局部参数
    },
    methods: {
        addEvents(d) {
            this.removeEvents();
            if (this.dragContainer) {
                this.dragContainer.setAttribute('sgDragMoveTile_grab', 'ready');
                this.dragContainer.addEventListener('mousedown', this.mousedown);
            }
        },
        removeEvents(d) {
            if (this.dragContainer) {
                this.dragContainer.removeAttribute('sgDragMoveTile_grab');
                this.dragContainer.removeEventListener('mousedown', this.mousedown);
            }
            removeEventListener('mouseup', this.mouseup);
        },
        mousedown(e) {
            this.$emit(`dragStart`, e);
            if (!this.isNotAllowedDrag()) return;
            this.dragContainer.setAttribute('sgDragMoveTile_grab', 'down');
            let scrollContainer = this.scrollContainer;
            let dragContainer = this.dragContainer;
            //鼠标按下那一刻,滚动条的位置
            let mouseDownScrollPosition = {
                scrollLeft: scrollContainer.scrollLeft,
                scrollTop: scrollContainer.scrollTop
            };
            //鼠标按下的位置坐标
            let mouseDownPoint = {
                x: e.clientX,
                y: e.clientY
            };
            dragContainer.onmousemove = e => {
                //鼠标滑动的实时距离
                let dragMoveDiff = {
                    x: mouseDownPoint.x - e.clientX,
                    y: mouseDownPoint.y - e.clientY
                };
                scrollContainer.scrollLeft = mouseDownScrollPosition.scrollLeft + dragMoveDiff.x;
                scrollContainer.scrollTop = mouseDownScrollPosition.scrollTop + dragMoveDiff.y;
                this.$emit(`dragMove`, e);
            };
            addEventListener('mouseup', this.mouseup);
        },
        mouseup(e) {
            this.dragContainer.onmousemove = null;
            removeEventListener('mouseup', this.mouseup);
            this.isNotAllowedDrag();
            this.$emit(`dragEnd`, e);
        },
        isNotAllowedDrag(d) {
            let scrollContainer = this.scrollContainer, rect_scrollContainer = scrollContainer.getBoundingClientRect();
            let dragContainer = this.dragContainer, rect_dragContainer = dragContainer.getBoundingClientRect();

            // 滚动区域不小于拖拽区域
            if (rect_scrollContainer.width >= rect_dragContainer.width && rect_scrollContainer.height >= rect_dragContainer.height) {
                this.dragContainer.setAttribute('sgDragMoveTile_grab', 'not-allowed');
                return false;
            } else {
                this.dragContainer.setAttribute('sgDragMoveTile_grab', 'ready');
                return true;
            }
        },
    },
    destroyed() {
        this.removeEvents();
    },
};
</script>
<style lang="scss" >
[sgDragMoveTile_grab="ready"] {
    /*禁止选中文本*/
    user-select: none;
    cursor: var(--sgDragMoveTile-grab); //css获取js传递的参数

    * {
        cursor: var(--sgDragMoveTile-grab); //css获取js传递的参数
    }
}

[sgDragMoveTile_grab="down"] {
    /*禁止选中文本*/
    user-select: none;
    cursor: var(--sgDragMoveTile-grabbing); //css获取js传递的参数

    * {
        cursor: var(--sgDragMoveTile-grabbing); //css获取js传递的参数
    }
}

[sgDragMoveTile_grab="not-allowed"] {
    /*禁止选中文本*/
    user-select: none;
    cursor: not-allowed;

    * {
        cursor: not-allowed;
    }
}
</style>

Example

<template>
  <div :class="$options.name">
    <div class="sg-ctrl">
      <label>缩放百分比</label>
      <el-input-number style="width: 150px;" v-model.trim="scaleValue" :precision="0" :step="10" :min="10" :max="100"
        :controls-position="`left`" />
    </div>
    <div class="sg-tile-img" ref="scrollContainer">
      <div ref="dragContainer" :style="{ width: `${tileSize * colCount}px` }">
        <img v-for="(a, i) in tiles" :key="i" :loading="a.loading" :width="tileSize" :height="tileSize">
      </div>
    </div>
    <sgDragMoveTile :data="dragMoveTileData" />
  </div>
</template>
<script>
import sgDragMoveTile from "@/vue/components/admin/sgDragMoveTile";
export default {
  name: 'sgTileImage',
  components: {
    sgDragMoveTile
  },
  data() {
    return {
      dragMoveTileData: {},
      scaleValue: 100,
      orginTileSize: 0,
      tileSize: 0,
      colCount: 0,
      rowCount: 0,
      tiles: [],//瓦片图数组
    }
  },
  watch: {
    data: {
      handler(newValue, oldValue) {
        let len = 144;//瓦片图数量
        this.tiles = [...Array(len)].map(v => ({
          loading: false,
        }));
        this.orginTileSize = 500
        this.colCount = Math.sqrt(len)
        this.rowCount = Math.sqrt(len)
        console.log(this.tiles)

      },
      deep: true,//深度监听
      immediate: true,//立即执行
    },
    scaleValue: {
      handler(newValue, oldValue) {
        this.tileSize = this.orginTileSize * newValue / 100;
      },
      deep: true,//深度监听
      immediate: true,//立即执行
    },
  },
  mounted() {
    this.dragMoveTileData = {
      scrollContainer: this.$refs.scrollContainer,
      dragContainer: this.$refs.dragContainer,
    }
  },
};
</script>
<style lang="scss" scoped> 
.sgTileImage {  
   .sg-ctrl {
     position: absolute;
     right: 0;
     top: 0;
     z-index: 1;
     box-sizing: border-box;
     padding: 10px 20px;
     background-color: white;
     box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
     border-radius: 4px;
     display: flex;
     align-items: center;
     justify-content: flex-end;
     label {
       margin-right: 10px;
     }
   }
   .sg-tile-img {
     position: absolute;
     left: 0;
     top: 0;
     overflow: auto;
     width: 100%;
     height: 100%;
     div {
       display: flex;
       flex-wrap: wrap;

       img {
         border: none;
       }
     }
   }
 }
</style>

Related articles [Classic] Native JS implements "drag the content DIV with the mouse", and the scroll bar corresponds to synchronous scrolling_When js is dragged, the index bar follows the drag_Your beloved Brother Qiang's blog-CSDN Blog [Code] [ Classic] Native JS implements "drag the content DIV with the mouse", and the scroll bar corresponds to synchronous scrolling. _When dragging js, the index bar follows the dragging https://blog.csdn.net/qq_37860634/article/details/127253779

Guess you like

Origin blog.csdn.net/qq_37860634/article/details/133292981