当前位置: 首页 > 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.lqws.cn/news/594397.html

相关文章:

  • 前端第二节(Vue)
  • 【实战】 容器中Spring boot项目 Graphics2D 画图中文乱码解决方案
  • anchor 智能合约案例3 之 journal
  • Docker进阶命令与参数——AI教你学Docker
  • 想做跑腿配送生意,怎么第三方平台订单对接?
  • MCU、LIN收发器、LIN总线、节点,它们之间是如何协作的?
  • SVN 分支管理(本文以Unity项目为例)
  • 以下是 Kafka 不同认证方式的配置示例,结合前面的单表设计方案,展示如何为每种认证方式填充配置表
  • 【Go-选项模式】
  • Spring Boot 2 多模块项目中配置文件的加载顺序
  • 2025年主流大厂Java后端面试题主题深度解析
  • 【深度学习新浪潮】人工智能在文物考古领域有哪些最新研究进展?
  • 基于开源AI大模型AI智能名片S2B2C商城小程序的流量转化与价值沉淀研究
  • 借助飞算AI新手小白快速入门Java实操记录
  • AbMole| H₂DCFDA(M9096;活性氧(ROS)探针)
  • C#基础(DllImport)
  • CppCon 2018 学习:Better C++ using Machine Learning on Large Projects
  • [Python 基础课程]字符串
  • Tomcat9部署jsp产生错误FileCountLimitExceededException
  • 网络安全监测探针功能
  • Python 数据分析:DataFrame,生成,用字典创建 DataFrame ,键值对数量不一样怎么办?
  • python+uniapp基于微信小程序的PS社区系统
  • 基于3D卷积神经网络与多模态信息融合的医学影像肿瘤分类与可视化分析
  • JVM调优实战 Day 15:云原生环境下的JVM配置
  • Go 服务如何“主动”通知用户?SSE广播与断线重连实战
  • 【算法】动态规划:python实现 1
  • 前端开发git的使用(常用命令和规范)
  • Python ORM 完全指南:从基础到高级实践
  • UI前端大数据可视化实战技巧分享:如何选择合适的颜色与图表类型?
  • MATLAB构建capm和三因子模型