
特性:
- 可以自定义拖拽过程鼠标样式
- 可以禁止拖拽
- 动态设置拖拽和滚动区域元素
- 支持监听滚动条@scroll事件
- <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);
- }
- if (this.scrollContainer) {
- this.scrollContainer.addEventListener("scroll", this.scroll);
- }
- },
- removeEvents(d) {
- if (this.dragContainer) {
- this.dragContainer.removeAttribute("sgDragMoveTile_grab");
- this.dragContainer.removeEventListener("mousedown", this.mousedown);
- }
- if (this.scrollContainer) {
- this.scrollContainer.removeEventListener("scroll", this.scroll);
- }
- removeEventListener("mouseup", this.mouseup);
- },
- scroll(e) {
- this.$emit(`scroll`, e);
- },
- 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, {
- scrollLeft: scrollContainer.scrollLeft,
- scrollTop: scrollContainer.scrollTop,
- });
- };
- 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>