vue 放大镜(简易)
目录
zoom组件
<template><div class="pic-img"><div class="img-container"><img ref="img" @load="imgLoaded" :src="url" :style="overlayStyle" @error="imgerrorfun"/><div class="overlay"@mousemove.stop="!moveEvent && mouseMove($event)"@mouseout.stop="!leaveEvent && mouseLeave($event)":style="overlayStyle"></div><divv-if="!hideZoom && imgLoadedFlag &&!hideSelector":class="['img-selector', {'circle': type === 'circle'}]":style="[imgSelectorStyle, imgSelectorSize, imgSelectorPosition, !outShow && imgBg, !outShow && imgBgSize, !outShow && imgBgPosition]"><slot></slot></div><divv-if="outShow"v-show="!hideOutShow":class="['img-out-show', {'base-line': baseline}]":style="[imgOutShowSize, imgOutShowPosition, imgBg, imgBgSize, imgBgPosition]"><div v-if="pointer" class="img-selector-point"></div></div></div></div></template><script>
export default {name: "vue-photo-zoom-pro",props: {url: { type: String, default: require('@/assets/images/default-zoom.jpg') }, // 图片地址highUrl: String, // 更清晰的图片,若不提供会采用 urlwidth: { type: Number, default: 168 }, // 内部放大区域宽度type: { type: String, default: "square", validator: function(value) { return ["circle", "square"].indexOf(value) !== -1 } },selectorStyle: { type: Object, default() { return {} } },outShowStyle: {},scale: { type: Number, default: 3 }, // 放大倍数moveEvent: { type: [Object, MouseEvent], default: null }, // 当需要在外部监听移动事件时,请通过该字段传入事件(必须包含 pageX,pageY,clientY),这将禁用内部移动监听leaveEvent: { type: [Object, MouseEvent], default: null }, // 当需要在外部监听离开事件时,请通过该字段传入事件hideZoom: { type: Boolean, default: false }, // 隐藏放大镜outShow: { type: Boolean, default: false }, // 是否外置放大镜pointer: { type: Boolean, default: false }, // 外部区域的中心点baseline: { type: Boolean, default: false }, // 外部区域的基线overlayStyle:{ type: String, default: 'width:100%;height:100%' },},computed: {addWidth() { return !this.outShow ? (this.width / 2) * (1 - this.scale) : 0 },imgSelectorPosition() {let { top, left } = this.selector;return { top: `${top}px`, left: `${left}px` };},imgSelectorSize() {let width = this.selector.width;return { width: `${width}px`, height: `${width}px` };},imgSelectorStyle() {return this.selectorStyle;},imgOutShowSize() {let { scale, selector: { width } } = this;return { width: `${width * scale}px`, height: `${width * scale}px` };},imgOutShowPosition() {return { top: `${this.outShowTop}px`, right: `${-8}px` };},imgBg() {return { backgroundImage: `url(${this.highUrl || this.url})` };},imgBgSize() {let { scale, imgInfo: { height, width } } = this;return { backgroundSize: `${width * scale}px ${height * scale}px` };},imgBgPosition() {let { bgLeft, bgTop } = this.selector;return { backgroundPosition: `${bgLeft}px ${bgTop}px` };},},data() {return {selector: {width: this.width,top: 0,left: 0,bgTop: 0,bgLeft: 0,rightBound: 0,bottomBound: 0,absoluteLeft: 0,absoluteTop: 0},imgInfo: {},$img: null,screenWidth: document.body.clientWidth,outShowInitTop: 0,outShowTop: 0,hideOutShow: true,imgLoadedFlag: false,hideSelector: false,timer: null};},methods: {imgLoaded() {let imgInfo = this.$img.getBoundingClientRect();if (JSON.stringify(this.imgInfo) != JSON.stringify(imgInfo)) {this.imgInfo = imgInfo;this.initSelectorProperty(this.width);this.resetOutShowInitPosition();}if (!this.imgLoadedFlag) {this.imgLoadedFlag = true;this.$emit("created", imgInfo);}},mouseMove(e) {if (!this.hideZoom && this.imgLoadedFlag) {this.imgLoaded();const { pageX, pageY, clientY } = e;const { scale, selector, outShow, addWidth, outShowAutoScroll } = this;let { outShowInitTop } = this;const scrollTop = pageY - clientY;const { absoluteLeft, absoluteTop, rightBound, bottomBound } = selector;const x = pageX - absoluteLeft; // 选择器的x坐标 相对于图片const y = pageY - absoluteTop; // 选择器的y坐标if (outShow) {if (!outShowInitTop) {outShowInitTop = this.outShowInitTop = scrollTop + this.imgInfo.top;}this.hideOutShow && (this.hideOutShow = false);this.outShowTop =scrollTop > outShowInitTop ? scrollTop - outShowInitTop : 0;}this.hideSelector && (this.hideSelector = false);selector.top = y > 0 ? (y < bottomBound ? y : bottomBound) : 0;selector.left = x > 0 ? (x < rightBound ? x : rightBound) : 0;selector.bgLeft = addWidth - x * scale; // 选择器图片的坐标位置selector.bgTop = addWidth - y * scale;}},initSelectorProperty(selectorWidth) {const selectorHalfWidth = selectorWidth / 2;const selector = this.selector;const { width, height, left, top } = this.imgInfo;const { scrollLeft, scrollTop } = document.documentElement;selector.width = selectorWidth;selector.rightBound = width - selectorWidth;selector.bottomBound = height - selectorWidth;selector.absoluteLeft = left + selectorHalfWidth + scrollLeft;selector.absoluteTop = top + selectorHalfWidth + scrollTop;},mouseLeave() {this.hideSelector = true;if (this.outShow) {this.hideOutShow = true;}},reset() {Object.assign(this.selector, {top: 0,left: 0,bgLeft: 0,bgTop: 0});this.resetOutShowInitPosition();},resetOutShowInitPosition() {this.outShowInitTop = 0;},imgerrorfun(e){// let img = require('@/assets/vehicle_img/blank_vehicle.jpg')// this.url = img// e.target.src = img// e.target.οnerrοr= null}},watch: {moveEvent(e) {this.mouseMove(e);},leaveEvent(e) {this.mouseLeave(e);},url(n) {this.imgLoadedFlag = false;// let img = require('@/assets/vehicle_img/blank_vehicle.jpg')// if(n == img){// this.outShow = false// }},width(n) {this.initSelectorProperty(n);},screenWidth(val) {if (!this.timer) {this.screenWidth = val;this.timer = setTimeout(() => {this.imgLoaded();clearTimeout(this.timer);this.timer = null;}, 400);}}},mounted() {this.$img = this.$refs["img"];},
};
</script><style scoped>.img-container {position: relative;}.overlay{cursor: crosshair;position: absolute;top: 0;left: 0;opacity: 0.5;z-index: 3;}.img-selector {position: absolute;cursor: crosshair;border: 1px solid rgba(0, 0, 0, 0.1);background-repeat: no-repeat;background-color: rgba(64, 64, 64, 0.6);}.img-selector.circle {border-radius: 50%;}.img-out-show {z-index: 5000;position: absolute;background-repeat: no-repeat;-webkit-background-size: cover;background-color: white;transform: translate(100%, 0);}.img-selector-point {position: absolute;width: 4px;height: 4px;top: 50%;left: 50%;transform: translate(-50%, -50%);background-color: black;}.img-out-show.base-line::after {position: absolute;box-sizing: border-box;content: "";width: 1px;border: 1px dashed rgba(0, 0, 0, 0.36);top: 0;bottom: 0;left: 50%;transform: translateX(-50%);}.img-out-show.base-line::before {position: absolute;box-sizing: border-box;content: "";height: 1px;border: 1px dashed rgba(0, 0, 0, 0.36);left: 0;right: 0;top: 50%;transform: translateY(-50%);}
</style>
<template><div class='wrapper'><div class='box'><!-- <pic-zoom:url="storageUrl":bigWidth="150":scale="3"overlayStyle="width: 100%;height: 400px;border-radius: 3px;"></pic-zoom> --><pic-zoom:width="150":url="url":scale="3"type="square":pointer="true":out-show="true"overlayStyle="width: 100%;height: 100%;"></pic-zoom></div></div>
</template><script>
import PicZoom from '@/components/PicZoom'
export default {components: { PicZoom },data() {return {url: 'https://bpic.588ku.com/illus_water_img/18/08/18/472f21d353b64c95b9994be6ed3b7274.jpg!/watermark/url/L3dhdGVyL3dhdGVyX2JhY2tfNDAwXzIwMC5wbmc=/repeat/true',}},
}
</script><style lang='scss' scoped>
.box {width: 400px;height: 400px;
}
</style>
相关文章:
vue 放大镜(简易)
目录 zoom组件 <template><div class"pic-img"><div class"img-container"><img ref"img" load"imgLoaded" :src"url" :style"overlayStyle" error"imgerrorfun"/><div cl…...
【计算机网络】第一章——概述
个人主页直达:小白不是程序媛 系列专栏:计算机网络基础 目录 前言 计算机网络概述 概念 功能 组成 分类 标准化工作 性能指标 速率 带宽 吞吐量 时延 时延带宽积 往返时延RTT 利用率 分层 为什么要分层? 分层的基本原则&am…...
vue实现在页面拖拽放大缩小div并显示鼠标在div的坐标
1、功能要求: 实现在一个指定区域拖拽div,并可以放大缩小,同时显示鼠标在该div里的坐标,如图可示 缩小并拖动 2、实现 <div class"div_content" ref"div_content"><div class"div_image" id"…...
LuatOS-SOC接口文档(air780E)-- io - io操作(扩展)
示例 -- io模块是lua原生模块,LuatOS增加了一些API -- 请配合os模块一起使用-- 只读模式, 打开文件 local fd io.open("/xxx.txt", "rb") -- 读写默认,打开文件 local fd io.open("/xxx.txt", "wb") -- 写入文件,且截断为0字节 loc…...
【数据结构】线性表(六)堆栈:顺序栈及其基本操作(初始化、判空、判满、入栈、出栈、存取栈顶元素、清空栈)
文章目录 一、堆栈1. 定义2. 基本操作 二、顺序栈0. 顺序表1. 头文件和常量2. 栈结构体3. 栈的初始化4. 判断栈是否为空5. 判断栈是否已满6. 入栈7. 出栈8. 查看栈顶元素9. 清空栈10. 主函数11. 代码整合 堆栈Stack 和 队列Queue是两种非常重要的数据结构,两者都是特…...
父组件可以监听到子组件的生命周期吗?
在 Vue 中,父组件是可以监听到子组件的生命周期的。Vue 提供了一些特殊的钩子函数,可以在父组件中监听子组件的生命周期事件。 以下是一些常用的方法来监听子组件的生命周期: 1:使用$emit: 在子组件的生命周期钩子函数中,使用 $emit 方法触发自定义事件,向父组件发送通…...
[开源]MIT开源协议,基于Vue3.x可视化拖拽编辑,页面生成工具
一、开源项目简介 AS-Editor 基于 Vue3.x 可视化拖拽编辑,页面生成工具。提升前端开发效率,可集成至移动端项目作为通过定义 JSON 直接生成 UI 界面。 二、开源协议 使用MIT开源协议 三、界面展示 四、功能概述 基于Vue可视化拖拽编辑,…...
【C++ Primer Plus学习记录】数组的替代品
目录 1.模板类vector 2.模板类array(C11) 3.比较数组、vector对象和array对象 模板类vector和array是数组的替代品。 1.模板类vector 模板类vector类似于string类,也是一种动态数组。您可以在运行阶段设置vector对象的长度,可…...
JSP免杀马
JSP免杀马 随着Java框架的进化和程序员的内卷,使用PHP编写的系统越来少,使用Java编写的系统越来越多。JSP马的使用越来越多,但是就目前来看,各大厂商对JSP马的查杀效果还是不尽人意。这里简单通过Java的反射机制和ClassLoader技术…...
2023-10-16 node.js-调用python-记录
NodeJS 作为后端,仅在需要时调用 Python 在某些特殊的场景下,比如复杂耗时的数据处理和运算时,我们可以用 Python 脚本编写,然后使用 Node 的子进程调用 Python 脚本即可,这样可以提升效率。如下代码,我们…...
Kotlin 设置和获取协程名称
1,设置写成名称 创建协程作用域是或者创建协程是有个上下文参数(context: CoroutineContext) 创建协程作用域 CoroutineScope(Dispatchers.IO CoroutineName("协程A"))//Dispatchers.IO根据实际情况设置可有可无 源码…...
awk命令的使用
1.概念: awk是Linux以及UNIX环境中现有的功能最强大的数据处理工具 awk是一种处理文本数据的编程语言。awk的设计使得它非常适合于处理由行和列组成的文本数据 awk程序可以读取文本文件,对数据进行排序,对其中的数值执行计算以及生成报表等…...
【面试系列】Vue
引言:下面是一些常见的 Vue 面试题和对应的答案 目录 1. Vue 是什么?它有哪些特点?2. Vue 的生命周期有哪些?请简要描述每个生命周期的作用。3. Vue 组件间通信的有哪些方式?4. Vue 的 computed 和 watch 的区别是什么…...
揭开MyBatis的神秘面纱:掌握动态代理在底层实现中的精髓
一日小区漫步,我问朋友:Mybatis中声明一个interface接口,没有编写任何实现类,Mybatis就能返回接口实例,并调用接口方法返回数据库数据,你知道为什么不? 朋友很是诧异:是啊ÿ…...
结合领域驱动设计,理解TOGAF之架构方法论
TOGAF(The Open Group Architecture Framework)是一个开放的架构方法论,旨在支持组织制定和实施企业架构。它提供了一种框架来创建和管理企业架构,并包含了一组最佳实践,帮助组织实现其业务目标。 TOGAF框架包括四个主…...
Vue-vue项目Element-UI 表单组件内容要求判断
整体添加判断 <el-formref"ruleFormRef":model"formModel"class"demo-ruleForm"label-position"top"status-icon:rules"rules"><el-form-item label"姓名" prop"applyUsers" class"form-…...
【试题027】C语言宏定义小例题
1.题目: #define MOD(a,b) a%b int main() { int x4,y16,z; zMOD(y,x); printf("%dn".z);} 则程序执行的结果是? 2.代码分析: #include <stdio.h> #define MOD(a,b) a%b int main() {int x 4, y 16, z;z MOD(y, …...
解决 sharp: Installation error: unable to verify the first certificate
使用 plasmo 时报错如下: E:\chromeplugins>pnpm create plasmo ../.pnpm-store/v3/tmp/dlx-46852 | 2 ../.pnpm-store/v3/tmp/dlx-46852 | Progress: resolved 2, reused 2, downloaded 0, added 2, done 🟣 Plasmo v0.83.0 &…...
【Java】Java实现100万+ 的高并发、高性能设计
Java实现100万 的高并发、高性能设计 1、简述 现百万级并发编是一项综合性的技术,同时,它与现实生活中 的场景有着紧密的联系。 搞懂并发编程有三大核心问题 分工问题 同步问题 互斥问题 本文就对这三大核心问题进行简单的介绍 2、分工问题 关于分工…...
linux系统下,在vscode的命令行中调试python文件
首先参考vscode官网文档Command line debugging 步骤 1(只需一次):安装debugpy 步骤 2:在命令行中运行 python -m debugpy --listen 5678 --wait-for-client -m dir1.dir2.your_script 以上命令使用了端口5678,也可…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
