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

VUE3+TS实现图片缩放移动弹窗

完整代码

使用VUE3、TS,实现将图片通过鼠标拖拽缩放以及选择缩放比例。

<template><div><el-dialogv-model="dialogVisible"title="查看图片":close-on-click-modal="false":close-on-press-escape="false"fullscreenstyle="overflow: hidden;"><div style="margin-bottom: 10px;"><el-selectv-model="magnification"placeholder="请选择图片放大尺寸"size="large"style="width: 240px"@change="changePicSize"><el-optionv-for="item in options":key="item.value":label="item.label":value="item.value"/></el-select></div><div class="img_area" ref="container" @wheel.prevent="handleWheel"@mousemove="handleDrag"@mouseup="endDrag"@mouseleave="endDrag"><img :style="imageStyle" class="auto-scale-image" :src="props.imgSrc" ref="image"@mousedown="startDrag"draggable="false"/></div><template #footer></template></el-dialog></div>
</template>
<script lang='ts' setup>// 显隐设置const props = defineProps<{modelValue: boolean,imgSrc:any}>()const emit = defineEmits<{(e: 'update:modelValue', value: boolean): void}>()const dialogVisible = computed({get: () => props.modelValue,set: (value) => emit('update:modelValue', value)})let magnification = $ref(null) as anylet options = [{value: 0.1,label: '0.1',},{value: 1,label: '1',},{value: 2,label: '2',},]const translate = ref({ x: 0, y: 0 });const scale = ref(1);const isDragging = ref(false);const container = ref<HTMLDivElement | null>(null);const step = ref(0.1)const minScale = ref(0.1) const maxScale = ref(3) const imageStyle = computed(() => ({transform: `scale(${scale.value}) translate(${translate.value.x}px, ${translate.value.y}px)`,transformOrigin: 'center center',cursor: isDragging.value ? 'grabbing' : 'grab'}));// 处理鼠标滚轮缩放const handleWheel = (e: WheelEvent) => {if (!container.value) return;const delta = e.deltaY > 0 ? -step.value : step.value;const newScale = Math.max(minScale.value, Math.min(maxScale.value, scale.value + delta));// 计算缩放中心点const rect = container.value.getBoundingClientRect();const mouseX = e.clientX - rect.left;const mouseY = e.clientY - rect.top;// 计算缩放后的偏移量,使鼠标位置保持相对不变const scaleRatio = newScale / scale.value;translate.value = {x: translate.value.x * scaleRatio + (1 - scaleRatio) * (mouseX - rect.width / 2 - translate.value.x),y: translate.value.y * scaleRatio + (1 - scaleRatio) * (mouseY - rect.height / 2 - translate.value.y)};scale.value = newScale;};// 响应式状态const image = ref<HTMLImageElement | null>(null);const startPos = ref({ x: 0, y: 0 });// 开始拖拽const startDrag = (e: MouseEvent) => {if (e.button !== 0) return; // 只响应左键isDragging.value = true;startPos.value = {x: e.clientX - translate.value.x,y: e.clientY - translate.value.y};e.preventDefault();};// 处理拖拽const handleDrag = (e: MouseEvent) => {if (!isDragging.value) return;let newX = e.clientX - startPos.value.x;let newY = e.clientY - startPos.value.y;translate.value = { x: newX, y: newY };};// 结束拖拽const endDrag = () => {isDragging.value = false;};// 通过选择器改变图片大小const changePicSize = () => {scale.value = magnification;centerImage();}// 居中图片const centerImage = () => {if (!container.value) return;const imageContainer = container.value;imageContainer.scrollLeft = (imageContainer.scrollWidth - imageContainer.clientWidth) / 2;imageContainer.scrollTop = (imageContainer.scrollHeight - imageContainer.clientHeight) / 2;};
</script>
<style scope lang="less">.img_area{width: 100%;height: calc(100vh - 130px);text-align: center;.auto-scale-image{max-width: 100%;max-height: 100%;object-fit: contain; /* 保持宽高比 */}}
</style>
http://www.xdnf.cn/news/564067.html

相关文章:

  • 10.18 LangChain ToolMessage实战:多轮交互与状态管理全解析
  • Java 项目管理工具:Maven 与 Gradle 的深度对比与选择
  • 定时器的两种实现方式
  • C语言---结构体 、联合体、枚举
  • JavaScript性能优化实战(14):跨端JavaScript性能优化
  • ​C++性能优化的7大核心策略与实战案例
  • qt浏览文件支持惯性
  • AI赋能R-Meta分析核心技术:从热点挖掘到高级模型
  • 【音频】wav文件如何解析编码格式(压缩格式)?
  • 前端开发遇到 Bug,怎么办?如何利用 AI 高效解决问题
  • 电脑中所有word文件图标变白怎么恢复
  • WebSocket 是什么?
  • SQL 数值计算全解析:ABS、CEIL、FLOOR与ROUND函数深度精讲
  • 深入了解redis的哈希槽的知识
  • 关于收集 Android Telephony 网络信息的设计思考
  • 网络基础的介绍
  • 如何提高独立服务器的安全性?
  • 从电商角度设计大模型的 Prompt
  • Java 参数值传递机制
  • 全平台开源电子书阅读器推荐,支持多端同步+AI朗读!支持epub/mobi/azw3/pdf常见电子书格式!
  • PostgreSQL基础操作
  • 29.第二阶段x64游戏实战-技能冷却
  • Node.js 24发布:性能与安全双提升
  • 【Vue篇】重剑无锋:面经PC项目工程化实战面经全解
  • 苹果企业签名为什么会出现授信异常
  • 《从虚拟 DOM 到 Diff 算法:深度解析前端高效更新的核心原理》-简版
  • logits是啥、傅里叶变换
  • day 32
  • 谷歌I/O 2025 完全指南:由Gemini开创的AI新时代及其对我们未来的影响
  • DevExpress Blazor中文教程 - 如何用AI聊天组件构建大型语言模型聊天APP?