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>

vue组件实现图片的拖拽和缩放的更多相关文章

  1. Winform图片拖拽与缩放

    最近做项目的时候遇到上传施工平面布置图,查看,因为图片比较大,一般的显示器分辨率无法显示全,然后还需要放大看清楚图片里面的文字内容,所以需要用到图片的拖拽与缩放功能.这里整理下具体操作. 首先新建一个 ...

  2. 在 Element-UI 的 Table 组件上添加列拖拽效果

    Element-UI 的 Table组件很强大,但是我们的需求更强大... 简单粗暴的来一发效果图: 一.数据驱动 传统的拖动效果,都是基于通过 mousedown.mousemove.mouseup ...

  3. vue-drag-resize 可拖拽可缩放的标签,如何管理多个拖拽元素之间的zIndex?操作上需要保持当前激活的组件是最上层,但是在总体上,又要确保其图层管理的顺序。

    麻烦总是不断出现,还好办法总比困难多, 1.公司开发一款可视化编辑html网页的多媒体编辑平台,牵扯到标签元素的拖拽,缩放,我找了找方法发现原生技术实现起来代码太多,麻烦,还好找到了一个vue组件,可 ...

  4. Qt之股票组件-自选股--列表可以拖拽、右键常用菜单

    目录 一.开头嘴一嘴 二.效果展示 三.自选股列表 1.列表初始化 2.添加Item 3.右键菜单 4.拖拽Item 5.刷新数据 四.相关文章 原文链接:Qt之股票组件-自选股--列表可以拖拽.右键 ...

  5. Ant Design -- 图片可拖拽效果,图片跟随鼠标移动

    Ant Design 图片可拖拽效果,图片跟随鼠标移动,需计算鼠标在图片中与图片左上角的X轴的距离和鼠标在图片中与图片左上角的Y轴的距离. constructor(props) { super(pro ...

  6. H5拖拽 构造拖拽及缩放 pdf展示

    前言: 协助项目需要实现一个签名的功能. 功能说明:1.有文本签名和头像签名.2.头像签名需要实现可拖拽功能.3.需要展示的是pdf的文件并需要获取签名位于pdf文件的相对位置. 功能一:实现拖拽 思 ...

  7. H5拖拽 构造拖拽及缩放 pdf文件转换为html预览

    前言: 协助项目需要实现一个签名的功能. 功能说明:1.有文本签名和头像签名.2.头像签名需要实现可拖拽功能.3.需要展示的是pdf的文件并需要获取签名位于pdf文件的相对位置. 功能一:实现拖拽 思 ...

  8. svg拖拽和缩放

    需求:做机房平面图,用svg实现拖拽和缩放,刚开始一头雾水,不知所措,好在皇天不负有心人........ 本文重点介绍拖拽,单纯实现很简单,但是由于vue项目,机房图有很多事件,拖拽就成了难点 简单介 ...

  9. JS利用 Sea.js 实现模块化:拖拽、缩放及范围限制

    知识点总结: Sea.js的使用:define.export.seajs.use.require等方法:   参考:http://seajs.org/docs/ Sea.js与require.js的区 ...

随机推荐

  1. 甘特图中与任务有关的操作(Project)

    <Project2016 企业项目管理实践>张会斌 董方好 编著 任务建好了不是马上就没事了,后面还有各种事,比如像我这种粗心的,冷不丁就会冒出个"通假字"什么的,难道 ...

  2. IDEA 2021.2.1 破解版下载_激活安装图文教程(永久激活,亲测有效)

    1.IntelliJ IDEA 2021 链接:https://pan.baidu.com/s/1Pwz3GrrkJdDZzg-wg5UjMw 提取码:56o6 无限重置 30 天试用期补丁 链接:h ...

  3. java 图形化小工具Abstract Window Toolit 常用组件:对话框Dialog FileDialog

    对话框 Dialog是Window类的子类,是1个容器类,属于特殊组件,对话框是可以独立存在的顶级窗口,因此用法与普通窗口的用法几乎完全一样.但对话框有如下两点需要注意. (1),对话框通常依赖于其他 ...

  4. 阿里巴巴分布式服务框架HSF

    HSF称之为高速服务框架HSF(High-speed Service Framework),是在阿里巴巴广泛使用的分布式RPC服务框架. HSF连通不同的业务系统,解耦系统间的实现依赖.HSF从分布式 ...

  5. JAVA微信公众号网页开发——将文章群发到微信公众号中(文章使用富文本,包含图片)

    SendTextToAllUserAct.java package com.weixin.sendmessage; import org.apache.commons.lang.StringUtils ...

  6. 【九度OJ】题目1137:浮点数加法 解题报告

    [九度OJ]题目1137:浮点数加法 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1137 题目描述: 求2个浮点数相加的 ...

  7. 【LeetCode】6. ZigZag Conversion Z 字形变换

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:字形变换,ZigZag,题解,Leetcode, 力扣,P ...

  8. leetcode5225最大相等频率

    题目 正整数数组nums,找到满足条件的最长前缀,返回其长度.该前缀满足:删除一个元素后,剩下的每个数字出现的次数相同. ps:如果删除后没有元素存在,也可以认为每个数字有相同的次数. 数组长度:[2 ...

  9. The Monkey King(hdu5201)

    The Monkey King Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  10. python学习第三天:python基础(数据类型和变量)

    注释 以  # 开头的语句是注释,如,注释不会被编译运行: 格式 当语句以冒号:结尾时,缩进的语句视为代码块.按照约定俗成的管理,应该始终坚持使用4个空格的缩进(在文本编辑器中,需要设置把Tab自动转 ...