当前位置: 首页 > news >正文

uniapp+vue写小程序页面,实现一张图片默认放大后,可以在容器内上下左右拖动查看

1.组件chargingimageViewer

<template><view class="image-view" @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd"><image:src="imageUrl"mode="aspectFill":style="{width: imageWidth + 'rpx',height: imageHeight + 'rpx',transform: `translate(${currentX}rpx, ${currentY}rpx)`,}"></image></view>
</template><script setup>import { ref, onMounted, computed } from 'vue';const props = defineProps({imageUrl: {type: String,required: true,},});// 视图容器尺寸const VIEW_WIDTH = 750; // 微信小程序设计稿宽度const VIEW_HEIGHT = 1800;// 缩放限制const MAX_SCALE = 5;const MIN_SCALE = ref(1);// 图片信息const imageWidth = ref(0);const imageHeight = ref(0);const originalWidth = ref(0);const originalHeight = ref(0);const scale = ref(1);const initialScale = ref(1);// 拖动状态const isDragging = ref(false);const isPinching = ref(false);const startX = ref(0);const startY = ref(0);const startDistance = ref(0);const currentX = ref(0);const currentY = ref(0);const lastX = ref(0);const lastY = ref(0);const pivotX = ref(0);const pivotY = ref(0);// 计算图片按比例放大后的尺寸const calculateImageSize = (width, height, scaleVal = 1.1) => {// 计算宽高比const ratio = width / height;// 优先满足高度,因为容器高度更大let newHeight = VIEW_HEIGHT;let newWidth = newHeight * ratio;// 如果宽度超出容器,则以宽度为基准if (newWidth < VIEW_WIDTH) {newWidth = VIEW_WIDTH;newHeight = newWidth / ratio;}// 应用缩放newWidth *= scaleVal;newHeight *= scaleVal;return {width: newWidth,height: newHeight,};};// 获取图片原始尺寸const getImageInfo = () => {uni.getImageInfo({src: props.imageUrl,success: (res) => {originalWidth.value = res.width;originalHeight.value = res.height;// 计算按比例放大后的图片尺寸const size = calculateImageSize(res.width, res.height);imageWidth.value = size.width;imageHeight.value = size.height;initialScale.value = size.width / res.width;// 设置最小缩放比例MIN_SCALE.value = initialScale.value;scale.value = initialScale.value;// 初始居中显示currentX.value = (VIEW_WIDTH - size.width) / 2;currentY.value = (VIEW_HEIGHT - size.height) / 2;lastX.value = currentX.value;lastY.value = currentY.value;},fail: (err) => {console.error('获取图片信息失败', err);},});};// 限制图片拖动边界const limitBounds = () => {// 计算可拖动范围const maxX = Math.max(0, (VIEW_WIDTH - imageWidth.value) / 2);const minX = Math.min(0, VIEW_WIDTH - imageWidth.value - maxX);const maxY = Math.max(0, (VIEW_HEIGHT - imageHeight.value) / 2);const minY = Math.min(0, VIEW_HEIGHT - imageHeight.value - maxY);// 限制X方向if (currentX.value > maxX) {currentX.value = maxX;} else if (currentX.value < minX) {currentX.value = minX;}// 限制Y方向if (currentY.value > maxY) {currentY.value = maxY;} else if (currentY.value < minY) {currentY.value = minY;}};// 更新图片尺寸和位置const updateImage = () => {const size = calculateImageSize(originalWidth.value, originalHeight.value, scale.value);imageWidth.value = size.width;imageHeight.value = size.height;// 调整位置以保持缩放中心不变if (isPinching.value) {currentX.value = pivotX.value - (pivotX.value - lastX.value) * (scale.value / lastScale.value);currentY.value = pivotY.value - (pivotY.value - lastY.value) * (scale.value / lastScale.value);}// 限制边界limitBounds();};let lastScale = 1;// 触摸事件处理const onTouchStart = (e) => {if (e.touches.length === 1) {// 单点触摸 - 拖动isDragging.value = true;isPinching.value = false;startX.value = e.touches[0].clientX;startY.value = e.touches[0].clientY;} else if (e.touches.length === 2) {// console.log(e.touches);// // 双点触摸 - 缩放// isDragging.value = false;// isPinching.value = true;// const touch1 = e.touches[0];// const touch2 = e.touches[1];// // 计算两点距离// const dx = touch2.clientX - touch1.clientX;// const dy = touch2.clientY - touch1.clientY;// startDistance.value = Math.sqrt(dx * dx + dy * dy);// // 计算缩放中心点// pivotX.value = (touch1.clientX + touch2.clientX) / 2;// pivotY.value = (touch1.clientY + touch2.clientY) / 2;// // 记录当前状态// lastScale = scale.value;// lastX.value = currentX.value;// lastY.value = currentY.value;}};const onTouchMove = (e) => {// 阻止事件冒泡和默认行为,防止页面滚动// e.stopPropagation()// e.preventDefault()if (isDragging.value && e.touches.length === 1) {// 处理拖动const clientX = e.touches[0].clientX;const clientY = e.touches[0].clientY;// 计算移动距离const deltaX = clientX - startX.value;const deltaY = clientY - startY.value;// 更新图片位置currentX.value = lastX.value + deltaX;currentY.value = lastY.value + deltaY;// 限制边界limitBounds();} else if (isPinching.value && e.touches.length === 2) {// // 处理缩放// const touch1 = e.touches[0];// const touch2 = e.touches[1];// // 计算两点距离// const dx = touch2.clientX - touch1.clientX;// const dy = touch2.clientY - touch1.clientY;// const distance = Math.sqrt(dx * dx + dy * dy);// // 计算缩放比例// const newScale = lastScale * (distance / startDistance.value);// // 限制缩放范围// if (newScale >= MIN_SCALE.value && newScale <= MAX_SCALE) {//   scale.value = newScale;//   updateImage();// }}};const onTouchEnd = () => {// 阻止事件冒泡,防止页面滚动// e.stopPropagation()isDragging.value = false;isPinching.value = false;lastX.value = currentX.value;lastY.value = currentY.value;};onMounted(() => {getImageInfo();});
</script><style scoped>.image-view {width: 750rpx;height: 1800rpx;overflow: hidden;position: relative;}image {position: absolute;transition: transform 0s;}
</style>

2.引用

<view class="mapbox"><chargingimageViewer :imageUrl="imageUrl"></chargingimageViewer></view>import chargingimageViewer from '@/components/chargingimageViewer/chargingimageViewer.vue';const imageUrl = ref('../../static/images/dingwei.png');

http://www.lryc.cn/news/578497.html

相关文章:

  • android13 如何定时输出app的帧率FPS
  • 应急响应类题练习——玄机第五章 Windows 实战-evtx 文件分析
  • mac重复文件清理,摄影师同款清理方案
  • COCO、VOC 和 YOLO三种主流目标检测数据格式的详细对比与示例说明
  • Java Selenium反爬虫技术方案
  • 笔记本电脑怎样投屏到客厅的大电视?怎样避免将电脑全部画面都投出去?
  • 基于c#语言的股票模拟交易软件的开发与实现
  • Vue3 使用 i18n 实现国际化完整指南
  • AiPy实战(7):一键生成天气组件,解放UI设计的双手
  • 应用场景全解析:飞算 JavaAI 的实战舞台
  • 业界优秀的零信任安全管理系统产品介绍
  • 启用不安全的HTTP方法
  • 内部类与Lambda的衍生关系(了解学习内部类,Lambda一篇即可)
  • [6-02-01].第48节:场景整合 -搭建父项目
  • DIC技术在金属材料裂纹尖端张开位移(COD)分析中的创新应用
  • Badoo×亚矩云手机:社交约会革命的“云端心跳加速剂“
  • 企业上网行为管理:零信任安全产品的对比分析
  • 3D 商品展示与 AR 试戴能为珠宝行业带来一些便利?
  • 软件测试复习之单元测试
  • Sql注入中万能密码order by联合查询利用
  • linux系统编程——Makefile、GDB调试
  • Terraform Helm:微服务基础设施即代码
  • Linux容器讲解以及对应软件使用
  • 云原生的本质
  • Oracle 常用函数
  • WPF学习(三)
  • 3.1.1.9 安全基线检查项目九:检查是否设置限制su命令用户组
  • 企业级应用技术-ELK日志分析系统
  • Windows10/11 轻度优化 纯净版,12个版本!
  • 基于开源AI大模型AI智能名片S2B2C商城小程序的流量转化与价值沉淀研究