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. 【嵌入式AI】全志 XR806 OpenHarmony 鸿蒙系统固件烧录

      欢迎关注我的公众号 [极智视界],回复001获取Google编程规范   O_o   >_<   o_O   O_o   ~_~   o_O   大家好,我是极智视界,本教程详细记录了 ...

  3. npm ERR! Error: EPERM: operation not permitted

    转载于:https://blog.csdn.net/qq_36772866/article/details/86934950 win10 在npm install时报错 解决方案 删除node-mou ...

  4. Linux使用tar解压的时候去掉父级目录

    去除解压目录结构使用  --strip-components N 如: 压缩文件text.tar 中文件信息为 src/src1/src2/text.txt 运行 tar -zxvf text.tar ...

  5. C++ 获取函数耗时

    C++ 记录耗时 #include <sys/timeb.h> #include <stdio.h> long long getSystemTime() { struct ti ...

  6. 【九度OJ】题目1474:矩阵幂 解题报告

    [九度OJ]题目1474:矩阵幂 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1474 题目描述: 给定一个n*n的矩阵,求该矩阵的 ...

  7. 【剑指Offer】把二叉树打印成多行 解题报告(Python)

    [剑指Offer]把二叉树打印成多行 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews ...

  8. Nginx应用场景配置

    Nginx应用全入门 基础回顾 Nginx是什么? Nginx是一个高性能的HTTP和反向代理web服务器,特点是内存少,并发能力强 Nginx能做什么 Http服务器(Web服务器) 反向代理服务器 ...

  9. Codeforces 777E:Hanoi Factory(贪心)

    Of course you have heard the famous task about Hanoi Towers, but did you know that there is a specia ...

  10. 如何在 Go 中将 []byte 转换为 io.Reader?

    原文链接: 如何在 Go 中将 []byte 转换为 io.Reader? 在 stackoverflow 上看到一个问题,题主进行了一个网络请求,接口返回的是 []byte.如果想要将其转换成 io ...