【sgTileImage】自定义组件:瓦片图拖拽局部加载、实现以鼠标为中心缩放

 

特性:

  1. 支持缩放瓦片图,定义瓦片图初始缩放比例,以鼠标所在位置为中心缩放
  2. 支持局部拖拽加载

sgTileImage源码 

<template><div :class="$options.name"><div class="sg-ctrl"><label>缩放百分比</label><el-input-number style="width: 150px;" v-model.trim="scaleValue" :precision="0" :step="10" :min="10" :max="100":controls-position="`left`" @change="changeScaleValue" /></div><div class="sg-tile-img" ref="scrollContainer"><div ref="dragContainer" :style="{ width: `${tileSize * colCount}px` }"><img v-for="(a, i) in tiles" :key="i" :ref="`tile${i}`" :loaded="a.loaded" :width="tileSize":height="tileSize" draggable="false"></div></div><sgDragMoveTile :data="dragMoveTileData" @dragMove="dragMove" /></div>
</template>
<script>
import sgDragMoveTile from "@/vue/components/admin/sgDragMoveTile";
export default {name: 'sgTileImage',components: {sgDragMoveTile},data() {return {dragMoveTileData: {},scaleValue: 100,orginTileSize: 0,tileSize: 0,colCount: 0,rowCount: 0,tiles: [],//瓦片图数组mousePoint_bk: null,}},props: ["data",/* data格式:{orginTileSize:500,//瓦片图原始尺寸colCount: 20,//行数rowCount: 20,//列数scaleValue: 100,//缩放百分比tiles: [],//瓦片图数组} */],watch: {data: {handler(newValue, oldValue) {if (newValue && Object.keys(newValue).length) {newValue.orginTileSize && (this.orginTileSize = newValue.orginTileSize);newValue.colCount && (this.colCount = newValue.colCount);newValue.rowCount && (this.rowCount = newValue.rowCount);newValue.scaleValue && (this.scaleValue = newValue.scaleValue);newValue.tiles && (this.tiles = newValue.tiles);this.$nextTick(() => { this.loadScreenViewTiles(); });}},deep: true,//深度监听immediate: true,//立即执行},scaleValue: {handler(newValue, oldValue) {this.tileSize = this.orginTileSize * newValue / 100;this.$nextTick(() => { this.loadScreenViewTiles(); });},deep: true,//深度监听immediate: true,//立即执行},},destroyed() {removeEventListener('mousewheel', this.mousewheel);},mounted() {this.dragMoveTileData = {scrollContainer: this.$refs.scrollContainer,dragContainer: this.$refs.dragContainer,}let rect_scrollContainer = this.$refs.scrollContainer.getBoundingClientRect();this.mousePoint_bk = {x: rect_scrollContainer.width / 2,y: rect_scrollContainer.height / 2,};setTimeout(() => {this.loadScreenViewTiles();addEventListener('mousewheel', this.mousewheel, { passive: false });}, 1000);},methods: {// 校正放大缩小后,瓦片图的坐标(目的是为了让缩放看起来是以鼠标坐标为中心点)centerPosition(e, {rect_dragContainer_orign,scrollLeft_orgin,scrollTop_orgin,mousePoint }) {let scrollContainer = this.$refs.scrollContainer;let dragContainer = this.$refs.dragContainer;let rect_dragContainer = dragContainer.getBoundingClientRect();let scale = rect_dragContainer.width / rect_dragContainer_orign.width;//缩放比例let mouse_left_dis_orgin = scrollLeft_orgin + mousePoint.x;//缩放前鼠标距离瓦片图最左侧的距离let mouse_top_dis_orgin = scrollTop_orgin + mousePoint.y;//缩放前鼠标距离瓦片图最顶部的距离let mouse_left_dis = mouse_left_dis_orgin * scale;//缩放后鼠标距离瓦片图最左侧的距离let mouse_top_dis = mouse_top_dis_orgin * scale;//缩放后鼠标距离瓦片图最顶部的距离let scrollLeft = mouse_left_dis - mousePoint.x;let scrollTop = mouse_top_dis - mousePoint.y;scrollContainer.scrollLeft = scrollLeft;scrollContainer.scrollTop = scrollTop;this.mousePoint_bk = mousePoint;},mousewheel(e) {// 记录缩放前的数据let rect_dragContainer_orign = this.$refs.dragContainer.getBoundingClientRect();let scrollContainer = this.$refs.scrollContainer;let mousePoint = { x: e.x, y: e.y };let scrollLeft_orgin = scrollContainer.scrollLeft;let scrollTop_orgin = scrollContainer.scrollTop;// 开始缩放e.deltaY < 0 && (this.scaleValue += 10);e.deltaY > 0 && (this.scaleValue -= 10);// 开始计算坐标this.$nextTick(() => {this.centerPosition(e, {rect_dragContainer_orign,scrollLeft_orgin,scrollTop_orgin,mousePoint})});e.preventDefault && e.preventDefault();//阻止默认的滚轮事件return false;},// 获取浏览器可视范围的瓦片图,并加载图片loadScreenViewTiles(d) {let scrollContainer = this.$refs.scrollContainer;if (scrollContainer) {let rect_scrollContainer = scrollContainer.getBoundingClientRect();this.tiles.forEach((v, i) => {let tile = this.$refs[`tile${i}`];if (tile) {tile = tile[0];let rectTile = tile.getBoundingClientRect();if (rectTile.x + rectTile.width > rect_scrollContainer.x - rectTile.width &&rectTile.y + rectTile.height > rect_scrollContainer.y - rectTile.height &&rectTile.x < rect_scrollContainer.x + rect_scrollContainer.width &&rectTile.y < rect_scrollContainer.y + rect_scrollContainer.height) {tile.onload = d => { v.loaded = true; };tile.src = v.img;}}});}},dragMove(d) {this.loadScreenViewTiles();},changeScaleValue(d) {this.mousewheel(this.mousePoint_bk);},},
};
</script>
<style lang="scss" scoped> .sgTileImage {.sg-ctrl {position: absolute;left: 10px;top: 10px;z-index: 1;box-sizing: border-box;padding: 10px 20px;background-color: white;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);border-radius: 4px;display: flex;align-items: center;justify-content: flex-end;label {margin-right: 10px;}}.sg-tile-img {position: absolute;left: 0;top: 0;overflow: auto;width: 100%;height: 100%;div {display: flex;flex-wrap: wrap;img {border: none;opacity: 0;transition: opacity .382s;&[loaded] {opacity: 1;}}}}}
</style>

 用例

<template><div><sgTileImage :data="tileImageData" /></div>
</template>
<script>
import sgTileImage from "@/vue/components/admin/sgTileImage";
export default {components: { sgTileImage },data() {return {tileImageData: {orginTileSize: 500,//瓦片图原始尺寸colCount: 20,//行数rowCount: 20,//列数tiles: [],//瓦片图数组}}},created() {this.tileImageData.tiles = [...Array(this.tileImageData.colCount * this.tileImageData.rowCount)].map((v, i) => ({loaded: false,img: `http://shuzhiqiang.com/tiles/${i}.jpg`,}));//瓦片图数组},};
</script>

依赖组件【sgDragMoveTile】自定义组件:拖拽瓦片图、地图、大图,滚动条对应同步滚动_你挚爱的强哥的博客-CSDN博客【代码】【sgDragMoveTile】自定义组件:拖拽瓦片图、地图、大图,滚动条对应同步滚动。https://blog.csdn.net/qq_37860634/article/details/133292981

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/90895.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ElasticSearch映射与模板介绍

一、前言 前面有相关系列文章介绍了ES的基本概念和各种版本SDK的使用&#xff0c;ES现在已升级到8.5版本&#xff0c;有些概念和SDK用法都有很大变化&#xff0c;后续ES相关的文章会以8.3版本为基准介绍一些实际中应用需要掌握的概念以及一些比较实际的例子。 二、映射 ES环…

Flask配合Echarts写一个动态可视化大屏

ch 技术 后端&#xff1a;flask 可视化&#xff1a;echarts 前端&#xff1a;HTMLJavaScriptcss 大屏布局 大屏拆分 案例项目中大屏可按版块进行拆解&#xff0c;会发现这里大屏主要由标题、折线图、柱状图、地图、滚动图和词云等组成&#xff0c;整体可切分为8个版块&…

Unity 制作登录功能02-创建和链接数据库(SQlite)

国际惯例&#xff1a;先看效果 1.SQlite是一种嵌入型数据库 在Unity开发游戏时使用SQLite有多种原因&#xff0c;以下是其中一些主要原因&#xff1a; 嵌入式数据库&#xff1a;SQLite是一个嵌入式数据库引擎&#xff0c;这意味着它不需要单独的服务器进程。这使得使用SQLite非…

VUE2项目:尚品汇VUE-CLI脚手架初始化项目以及路由组件分析(一)

标题 环境VUE2目录publicassetscomponentsmain.jsbabel.config.jspackage.jsonvue.config.js 项目路由分析Header与Footer非路由组件完成Header示例 路由组件的搭建声明式导航编程式导航 Footer组件的显示与隐藏路由传递参数重写push和replace三级联动组件拆分附件 环境 前提要…

子序列问题集合

子序列问题 删除一次得到的最大和最大子数组和最长公共子序列&#xff1a;最长上升子序列&#xff08;要输出序列&#xff0c;和最大长度&#xff09;1.dp2.贪心二分 导弹拦截 &#xff08;最长上升/下降子序列长度&#xff09; 删除一次得到的最大和 class Solution { public:…

Elasticsearch基础篇(二):Elasticsearch在windows和liunx上的安装部署

Elasticsearch简介 前言1. Windows环境部署Elasticsearch1.1 下载并解压Elasticsearch压缩包1.2 命令行启动elasticsearch1.3 验证是否成功启动elasticsearch1.4 关闭Elasticsearch1.5 在Windows上安装Elasticsearch作为服务 2. Liunx环境部署Elasticsearch安装 Elasticsearch …

Android Studio 的android.jar文件在哪儿

一般在&#xff1a;C:\Users\admin\AppData\Local\Android\Sdk\platforms\android-33下&#xff08;不一定是33&#xff0c;这个得看你Android Studio->app->builde.gradle的targetSdk是多少&#xff09; 怎么找&#xff1a; 1.打开Android Studio 粘贴地址后&#xff0…

UE学习记录07----C++中使用事件委托

1.c定义多播委托&#xff0c;示例代码&#xff1a; #include "Delegates/Delegate.h"DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyDelegate, UObject*, SelectAgent);/****/ UCLASS(Blueprintable, DisplayName "VM_PlaceEntity") class PR_PLACEE…

在nodejs中如何防止ssrf攻击

在nodejs中如何防止ssrf攻击 什么是ssrf攻击 ssrf&#xff08;server-side request forgery&#xff09;是服务器端请求伪造&#xff0c;指攻击者能够从易受攻击的Web应用程序发送精心设计的请求的对其他网站进行攻击。(利用一个可发起网络请求的服务当作跳板来攻击其他服务)…

word 多级目录的问题

一、多级标题自动编号 --> 制表符 -> 空格 网址&#xff1a; 【Word技巧】2 标题自动编号——将多级列表链接到样式 - YouTube 二、多级列表 --> 正规形式编号 网址&#xff1a;Word 教学 - 定框架&#xff1a;文档格式与多级标题&#xff01; - YouTube 三、目…

【项目】基于C++11实现的数据库连接池

文章目录 前置知识关键技术点项目背景连接池功能点介绍MySQL Server参数介绍功能设计连接池功能点介绍开发平台选型 关于MySQL数据库编程MySQL接口介绍 测试表设计Connection设计数据库配置文件mysql.conf日志文件log.hppConnectionPool设计压力测试源码链接&#xff1a; 前置知…

南京大学【软件分析】13 Static Analysis for Security

文章目录 1. Information Flow Security2. Confidentiality and Integrity3. Explicit Flows and Covert/Hidden Channels4. Taint Analysis污点分析案例 1. Information Flow Security 引起安全问题最主要的两大原因是&#xff1a;injection errors&#xff08;2013-2019排名…

【深度学习实验】卷积神经网络(六):卷积神经网络模型(VGG)训练、评价

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 构建数据集&#xff08;CIFAR10Dataset&#xff09; a. read_csv_labels&#xff08;&#xff09; b. CIFAR10Dataset 2. 构建模型&#xff08;FeedForward&…

【网络协议】TCP

TCP协议全称为传输控制协议(Transmission Control Protocol).要理解TCP就要从他的特性开始说&#xff0c;这些特性各自之间或多或少各有联结&#xff0c;需要以宏观视角来看待。 目录&#xff1a; 1.TCP报文格式 因为报文解释过于繁琐&#xff0c;具体内容请看这篇文章TCP报文…

问题 - 谷歌浏览器 network 看不到接口请求解决方案

谷歌浏览器 -> 设置 -> 重置设置 -> 将设置还原为其默认值 查看接口情况&#xff0c;选择 All 或 Fetch/XHR&#xff0c;勾选 Has blocked cookies 即可 如果万一还不行&#xff0c;卸载浏览器重装。 参考&#xff1a;https://www.cnblogs.com/tully/p/16479528.html

微信小程序开发基础(二)基本组件

本帖开始介绍小程序中的一些基本组件~ 微信小程序是一种轻量、快速、跨平台的应用程序&#xff0c;是微信公众号的重要组成部分。随着微信小程序的普及&#xff0c;越来越多的开发者和企业开始使用微信小程序来搭建自己的应用&#xff0c;但是对于初次接触微信小程序的开发者…

CSS 基础 3

目录 &#x1f680; 导读 -- target 盒子模型 看透网页布局的本质 盒子模型组成 边框(border) border-style ​编辑border-color border-width 边框写法 简写 分开写 表格细线边框 边框会影响盒子实际大小 内边距 内容 内边距-padding padding属性简写 pad…

《PPT 自我介绍》:一本让你的职场表现更加出色的秘籍?

这里提供一个2000字左右的PPT自我介绍模板制作指南&#xff1a; 自我介绍是面试或工作中常见的情况&#xff0c;利用PPT可以给人留下更深刻的印象。但如何快速且专业地制作一个自我介绍PPT呢?这里给大家介绍几点技巧&#xff1a; 1. 选择一个简洁大方的PPT模板 首先要选择一…

STM32F4X UCOSIII任务信号量

STM32F4X UCOSIII任务信号量 任务信号量与内核信号量对比内核信号量任务信号量 UCOSIII任务信号量API任务信号量发送函数任务信号量接收函数 UCOSIII任务信号量例程 之前的章节中讲解过信号量这个机制&#xff0c;UCOSIII除了有内核信号量之外&#xff0c;还有任务信号量。在UC…

前端项目练习(练习-002-NodeJS项目初始化)

首先&#xff0c;创建一个web-002项目&#xff0c;内容和web-001一样。 下一步&#xff0c;规范一下项目结构&#xff0c;将html&#xff0c;js&#xff0c;css三个文件放到 src/view目录下面&#xff1a; 由于html引入css和js时&#xff0c;使用的是相对路径&#xff0c;所以…