当前位置: 首页 > 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.dtcms.com/a/263870.html

相关文章:

  • JavaScript 安装使用教程
  • Web3区块链有哪些岗位?
  • 141.在 Vue 3 中使用 OpenLayers Link 交互:把地图中心点 / 缩放级别 / 旋转角度实时写进 URL,并同步解析显示
  • 【MyBatis保姆级教程下】万字XML进阶实战:配置指南与深度解析
  • python高级变量VIII
  • 转录组分析流程(四):Cox+Lasso筛选预后基因
  • JVM内存模型与垃圾回收机制分析
  • 【java链式调用流操作】
  • Python实现NuScenes数据集可视化:从3D边界框到2D图像的投影原理与实践
  • mac部署dify
  • 笔记/计算机网络
  • 【数据结构】 排序算法
  • beego打包发布到Centos系统及国产麒麟系统完整教程
  • 【文件读取】open | with | as
  • 实体类JavaBean
  • 到底什么是“数字化”?数字化的本质是什么?
  • 从输入到路径:AI赋能的地图语义解析与可视化探索之旅(2025技术全景)
  • 边截图边操作?试试 Snipaste 的浮动贴图功能
  • adc模数转换器
  • Gartner《Choosing Event Brokers to Support Event-DrivenArchitecture》心得
  • OSE3.【Linux】练习:编写进度条及pv命令项目中的进度条函数
  • Postman - API 调试与开发工具 - 标准使用流程
  • 搜索与回溯算法(基础算法)
  • 华为交换机堆叠与集群技术深度解析附带脚本
  • Golang的并发编程实践总结
  • 【pathlib 】Python pathlib 库教程
  • 成都芯谷金融中心文化科技园:打造区域科技活力
  • nginx配置websocket
  • 用java,把12.25.pdf从最后一个点分割,得到pdf
  • Elastic 构建 Elastic Cloud Serverless 的历程