特性:
- 可以自定义拖拽过程鼠标样式
- 可以禁止拖拽
- 动态设置拖拽和滚动区域元素
sgDragMoveTile源码
<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>
用例
<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>
关联文章