基于element-puls的el-image-viewer组件实现移动端单指拖拽和双指缩放功能

 逻辑参考链接:移动端双指缩放图片JS事件的实践心得 « 张鑫旭-鑫空间-鑫生活

 参考链接:双指缩放

<template>

  <!-- 图片展示 -->

  <el-image-viewer v-if="imgViewerVisible" @close="closePreview" :url-list="propsVal.imgList" />

  <!-- 图片展示 -->

</template>

<script lang="ts" setup name="imageVIewer">

import { ref, nextTick } from '@vue/runtime-core';

import { IsMobileBrowser } from "../tools"

const propsVal = defineProps(

  {

    imgList: {

      type: Array<String>,

    }

  }

)

// 是否显示

const imgViewerVisible = ref(true)

// 显示

function openImage() {

  imgViewerVisible.value = true

  imageVisibleHandle()

}

// 隐藏

function closeImage() {

  imgViewerVisible.value = false

  imageVisibleHandle()

}

function closePreview() {

  closeImage()

  return '关闭了'

}

// 容器变量

let container = document.querySelector('.el-image-viewer__img') as HTMLElement

let image_viewer__wrapper = document.querySelector('.el-image-viewer__wrapper') as HTMLElement

// 单指变量

let initialX = 0; // 初始点击X点位

let initialY = 0; // 初始点击Y点位

let offsetX = 0; // 盒子内距离点位的X轴

let offsetY = 0; // 盒子内距离点位的Y轴

let isSingle: boolean = true;//判断是否是单指操作

// 双指变量

const store = {

  scale: 1

} as any;

// 双指触摸监听器功能实现

function wrapper_touchstartHandle(e: any) {

  var touches = e.touches;

  var events = touches[0];

  var events2 = touches[1];

  if (!e) {

    return;

  }

  // 第一个触摸点的坐标

  store.pageX = events.pageX;

  store.pageY = events.pageY;

  store.moveable = true;

  if (events2) {

    store.pageX2 = events2.pageX;

    store.pageY2 = events2.pageY;

  }

  store.originScale = store.scale || 1;

}

// 双指拖拽监听器功能实现

function wrapper_touchmoveHandle(e: any) {

  if (!store.moveable) {

    return;

  }

  var touches = e.touches;

  var events = touches[0];

  var events2 = touches[1];

  // 双指移动

  if (events2) {

    // 第2个指头坐标在touchmove时候获取

    if (!store.pageX2) {

      store.pageX2 = events2.pageX;

    }

    if (!store.pageY2) {

      store.pageY2 = events2.pageY;

    }

    // 获取坐标之间的举例

    var getDistance = function (start: any, stop: any) {

      return Math.hypot(stop.x - start.x, stop.y - start.y);

    };

    // 双指缩放比例计算

    var zoom = getDistance({

      x: events.pageX,

      y: events.pageY

    }, {

      x: events2.pageX,

      y: events2.pageY

    }) /

      getDistance({

        x: store.pageX,

        y: store.pageY

      }, {

        x: store.pageX2,

        y: store.pageY2

      });

    // 应用在元素上的缩放比例

    var newScale = store.originScale * zoom;

    // 最大缩放比例限制

    if (newScale > 3) {

      newScale = 3;

    }

    // 记住使用的缩放值

    store.scale = newScale;

    // 图像应用缩放效果

    container.style.transform = 'scale(' + newScale + ')';
    container.style.transition = "transform .3s";
  }

}

// 双指离开听器功能实现

function touchendClear(e: any) {

  isSingle = false

  store.moveable = false;

  delete store.pageX2;

  delete store.pageY2;

}

// 单指触摸监听器功能实现

function container_touchstartHandle(e: any) {

  // 当一只手指触摸时

  isSingle = true

  if (e.touches.length === 1 && isSingle) {

    // 拿到当前的位置

    initialX = e.touches[0].clientX;

    initialY = e.touches[0].clientY;

    // 拿到点位距离盒子的位置

    offsetX = initialX - container.offsetLeft;

    offsetY = initialY - container.offsetTop;

  }

}

// 单指拖拽监听器功能实现

function container_touchmoveHandle(e: any) {

  if (e.touches.length == 1 && isSingle) {



    // 获取当前触摸点的位置

    const currentX = e.touches[0].clientX;

    const currentY = e.touches[0].clientY;

    // 移动元素的位置

    if (container.style.position != 'fixed') container.style.position = 'fixed'

    container.style.left = (currentX - offsetX) + 'px';

    container.style.top = (currentY - offsetY) + 'px';

  }

}

// 图片显示隐藏处理

function imageVisibleHandle() {

  // 监听图片打开关闭动作,进行双指缩放以及图片拖拽功能

  nextTick(() => {

    // 渲染完成后拿到盒子本体

    container = document.querySelector('.el-image-viewer__img') as HTMLElement

    image_viewer__wrapper = document.querySelector('.el-image-viewer__wrapper') as HTMLElement

    if (imgViewerVisible.value) {

      //  移动端隐藏按钮

      if (IsMobileBrowser()) {

        const button: HTMLElement = document.querySelector('.el-image-viewer__actions') as HTMLElement

        button.style.display = 'none'

      }

      // 当 imgViewerVisible 变为 true 时,启用触摸屏幕缩放

      // 双指触摸监听器

      image_viewer__wrapper.addEventListener('touchstart', wrapper_touchstartHandle);

      // 双指拖拽监听器

      image_viewer__wrapper.addEventListener('touchmove', wrapper_touchmoveHandle);

      // 双指离开监听器

      image_viewer__wrapper.addEventListener('touchend', touchendClear);

      // 停止触摸

      image_viewer__wrapper.addEventListener('touchcancel', function () {

        store.moveable = false;

        delete store.pageX2;

        delete store.pageY2;

      });



      // 单指触摸监听器

      container.addEventListener('touchstart', container_touchstartHandle)

      // 单指拖拽监听器

      container.addEventListener('touchmove', container_touchmoveHandle)

    } else {

      // 如果是关闭就移除监听器并清除数据

      if (!!image_viewer__wrapper) {

        image_viewer__wrapper.removeEventListener('touchstart', wrapper_touchstartHandle)

        image_viewer__wrapper.removeEventListener('touchmove', wrapper_touchmoveHandle)

        image_viewer__wrapper.removeEventListener('touchend', touchendClear)

      }

      if (!!container) {

        container.removeEventListener('touchstart', container_touchstartHandle)

        container.removeEventListener('touchmove', container_touchmoveHandle)

      }

    }

  })

}

defineExpose({

  openImage,

  closeImage

})

</script>



<style type="text/css"></style>


PS:IsMobileBrowser是一个判断是否为移动端设备的方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现Vue3 Element-Plus的el-table汇总行单元格合并,你可以使用`span-method`属性来定义一个函数,该函数可以返回每个单元格需要合并的行数和列数。下面是一个示例代码: ```html <el-table :data="tableData" border style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> <el-table-column label="合计" :span-method="objectSpanMethod"> <template #default="{ rows, row, column, $index }"> <span v-if="$index === 0">{{ row.total }}</span> </template> </el-table-column> </el-table> ``` 在上面的代码中,我们定义了一个`objectSpanMethod`方法,并将其赋值给`span-method`属性。这个方法接收四个参数:`{ rows, row, column, $index }`。其中`rows`是当前列的所有行数据,`row`是当前行数据,`column`是当前列数据,`$index`是当前行的索引。 下面是`objectSpanMethod`方法的实现: ```js methods: { objectSpanMethod({ row, column, rowIndex, columnIndex }) { if (columnIndex === 3) { if (rowIndex === 0) { return { rowspan: this.tableData.length, colspan: 1 }; } else { return { rowspan: 0, colspan: 0 }; } } } } ``` 在上面的代码中,我们检查当前列是否为第四列(即“合计”列),如果是,我们检查当前行是否为第一行。如果是,我们返回一个对象`{ rowspan: this.tableData.length, colspan: 1 }`,其中`rowspan`表示当前单元格需要合并的行数,`colspan`表示当前单元格需要合并的列数。如果当前行不是第一行,则返回一个空对象`{ rowspan: 0, colspan: 0 }`,表示当前单元格不需要合并。 这样,我们就可以实现Vue3 Element-Plus的el-table汇总行单元格合并了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值