<
>

利用vue组件实现图片的拖拽和缩放功能

2022-04-16 17:10:15 来源:易采站长站 作者:

目录
前言如图所示:方法如下:总结

前言

vue实现一个组件其实很简单但是要写出一个好的可复用的组件那就需要多学习和钻研一下,一个好的组件必须有其必不可少的有优点:一是能提高应用开发效率、测试性、复用性等;二是组件应该是高内聚、低耦合的;三是组件应遵循单向数据流的原则。

在实现我的图片的拖拽组件我们的搞清其原理,在这里我使用的是mousedown,mousemove和mouseup来实现拖拽。

如图所示:

Start用于记录拖拽元素初始位置。定义isMousedown变量来判断鼠标是否按下, 如果isMousedown === tr拖拽元素缩放值 } }, 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>

总结

暂时禁止评论

微信扫一扫

易采站长站微信账号