特性:
- 支持缩放瓦片图,定义瓦片图初始缩放比例,以鼠标所在位置为中心缩放
- 支持局部拖拽加载
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