網站首頁 Vue 正文
前言
vue實現一個組件其實很簡單但是要寫出一個好的可復用的組件那就需要多學習和鉆研一下,一個好的組件必須有其必不可少的有優點:一是能提高應用開發效率、測試性、復用性等;二是組件應該是高內聚、低耦合的;三是組件應遵循單向數據流的原則。
在實現我的圖片的拖拽組件我們的搞清其原理,在這里我使用的是mousedown,mousemove和mouseup來實現拖拽。
如圖所示:
方法如下:
1.新建ElementDrag.vue文件內容如下:
<template> <div class="drag-outer" ref="dragWrap" @mousemove="dragMousemove"> <div class="drag-inner" ref="dragElement" @mousedown="dragMousedown" @mouseup.stop="isMousedown = false"> <slot></slot> </div> </div> </template>
2. 定義moveStart用于記錄拖拽元素初始位置。定義isMousedown變量來判斷鼠標是否按下, 如果isMousedown === true鼠標移動就改變darg-inner位置。
<script> export default { name: 'ElementDrag', data() { return { isMousedown: false, //鼠標是否按下 moveStart: {x: 0, y: 0}, //拖拽元素初始位置 translate: {x: 0, y: 0}, //計算拖拽元素在下下x,y方向各移動了多少 scale: 1, //拖拽元素縮放值 } }, methods: { dragMousedown() { this.moveStart.x = event.clientX this.moveStart.y = event.clientY this.isMousedown = true }, dragMousemove() { if(this.isMousedown) { this.translate.x += (event.clientX - this.moveStart.x) / this.scale this.translate.y += (event.clientY - this.moveStart.y) / this.scale this.$refs.dragElement.style.transform = `scale(${this.scale}) translate(${this.translate.x}px, ${this.translate.y}px)` this.moveStart.x = event.clientX this.moveStart.y = event.clientY } } } } </script>
3.樣式部分我們設置外層drag-outer用flex布局讓里面元素快速居中, user-drag: none;禁用圖片等元素的可拖拽屬性。
<style lang="scss" scoped> .drag-outer { width: 100%; height: 100%; overflow: hidden; display: flex; justify-content: center; align-items: center; .drag-inner { transform-origin: center center; display: flex; justify-content: center; align-items: center; cursor: move; user-select: none; >* { -webkit-user-drag: none; user-drag: none; } } } </style>
4.添加鼠標滾輪事件縮放drag-inner元素, e.wheelDelta為正表示放大,為負縮小,值越大表示滾動越快。通過scale控制拖拽元素縮放。同過對組件傳值scaleZoom來控制其縮放最大最小程度值。
... methods: { props: { type: Object, default(){ return { min: 0.5, max: 5 } } }, ... handleScroll(e) { let speed = e.wheelDelta/120 if(e.wheelDelta > 0 && this.scale < this.scaleZoom.max) { this.scale+=0.04*speed this.$refs.dragElement.style.transform = `scale(${this.scale}) translate(${this.translate.x}px, ${this.translate.y}px)` }else if(e.wheelDelta < 0 && this.scale > this.scaleZoom.min){ this.scale+=0.04*speed this.$refs.dragElement.style.transform = `scale(${this.scale}) translate(${this.translate.x}px, ${this.translate.y}px)` } } }, mounted() { window.addEventListener('mousewheel',this.handleScroll,false) }
5.以上代碼已經實現了功能我們預期的功能,但是為了更好的體驗,需要進一步優化組件。添加isHover來控制鼠標是否移動到了drag-outer以外,如果isHover為false這時鼠標滾輪滾動不會縮放元素,并且將isMousedown設置為false。再使用插槽slot預覽位置。
<template> <div class="drag-outer" ref="dragWrap" @mouseenter="isHover = true" @mouseleave="isHover = isMousedown = false" @mousemove="dragMousemove"> <div class="drag-inner" ref="dragElement" @mousedown="dragMousedown" @mouseup.stop="isMousedown = false"> <slot></slot> </div> </div> </template> .... data() { return { ..., isHover: false, } }, methods: { ... handleScroll(e) { if(this.isHover) { let speed = e.wheelDelta/120 if(e.wheelDelta > 0 && this.scale < this.scaleZoom.max) { this.scale+=0.04*speed this.$refs.dragElement.style.transform = `scale(${this.scale}) translate(${this.translate.x}px, ${this.translate.y}px)` }else if(e.wheelDelta < 0 && this.scale > this.scaleZoom.min){ this.scale+=0.04*speed this.$refs.dragElement.style.transform = `scale(${this.scale}) translate(${this.translate.x}px, ${this.translate.y}px)` } } } }
貼上組件的最終代碼:
<template> <div class="drag-outer" ref="dragWrap" :style="outerOptions" @mouseenter="isHover = true" @mouseleave="isHover = isMousedown = false" @mousemove="dragMousemove"> <div class="drag-inner" ref="dragElement" :style="innerOptions" @mousedown="dragMousedown" @mouseup.stop="isMousedown = false"> <slot></slot> </div> </div> </template> <script> export default { name: 'ElementDrag', props: { outerOptions: { type: Object, default () { return { background: 'rgba(0,0,0,0.9)' } } }, innerOptions: { type: Object, default () { return { background: 'rgba(0,0,0,0.1)', } } }, scaleZoom: { type: Object, default () { return { max: 5, min: 0.2 } } } }, data() { return { isMousedown: false, isHover: false, moveStart: {}, translate: {x: 0, y: 0}, scale: 1 } }, methods: { handleScroll(e) { if(this.isHover) { let speed = e.wheelDelta/120 if(e.wheelDelta > 0 && this.scale < this.scaleZoom.max) { this.scale+=0.04*speed this.$refs.dragElement.style.transform = `scale(${this.scale}) translate(${this.translate.x}px, ${this.translate.y}px)` }else if(e.wheelDelta < 0 && this.scale > this.scaleZoom.min){ this.scale+=0.04*speed this.$refs.dragElement.style.transform = `scale(${this.scale}) translate(${this.translate.x}px, ${this.translate.y}px)` } } }, dragMousedown() { this.moveStart.x = event.clientX this.moveStart.y = event.clientY this.isMousedown = true }, dragMousemove() { if(this.isMousedown) { this.translate.x += (event.clientX - this.moveStart.x) / this.scale this.translate.y += (event.clientY - this.moveStart.y) / this.scale this.$refs.dragElement.style.transform = `scale(${this.scale}) translate(${this.translate.x}px, ${this.translate.y}px)` this.moveStart.x = event.clientX this.moveStart.y = event.clientY } } }, mounted() { window.addEventListener('mousewheel',this.handleScroll,false) } } </script> <style lang="scss" scoped> .drag-outer { width: 100%; height: 100%; overflow: hidden; display: flex; justify-content: center; align-items: center; .drag-inner { transform-origin: center center; display: flex; justify-content: center; align-items: center; cursor: move; user-select: none; >* { -webkit-user-drag: none; user-drag: none; } } } </style>
在home.vue文件使用:點擊體驗
<template> <div class="home"> <ElementDrag> <img src="https://img0.baidu.com/it/u=937276518,3474029246&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=750"> </ElementDrag> </div> </template> <script> import ElementDrag from '@/components/ElementDrag' export default { name: 'Home', components: { ElementDrag } } </script> <style scoped> .home { width: 100vw; height: 100vh; } </style>
總結
原文鏈接:https://www.cnblogs.com/lmf-sky/p/15816763.html
相關推薦
- 2022-07-31 C++超詳細講解引用和指針_C 語言
- 2022-03-31 python猜單詞游戲的實現_python
- 2022-12-23 Android中Intent與Bundle的使用詳解_Android
- 2022-12-24 利用C語言實現頁面置換算法的詳細過程_C 語言
- 2022-03-05 Flutter基本組件Basics?Widget學習_Android
- 2022-11-12 sass在react中的基本使用(實例詳解)_React
- 2022-05-24 Python的列表推導式你了解嗎_python
- 2022-02-28 Error: A <Route> is only ever to be used as the ch
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支