Uniapp做一个查看图片可缩放可移动的组件

技术, 资源  ·  2025-01-10

在这里插入图片描述

源码下载:

下载地址:点击下载

示例演示:

演示地址:点击前往

因为是手机端,所以需要触摸可移动,双指放大缩小。

 首先在components里建个组件
 查看图片使用 uni-popup 弹窗,你也可以直接外面包裹一层 View
 要注意 transform的translate和scale属性在同一标签上不会一起生效
 移动就根据触摸效果进行偏移图片
 缩放就根据双指距离的变大变小进行缩放

环境:Uniapp v2/v3版本通胀、HbuilderX

<template>
    <view>
        <uni-popup style="z-index: 99998;" ref="showImage" type="center">
            <view :style="{'transform':'translate('+x+'px,'+y+'px)'}">
                <img
                    :style="{'transform':'scale(' + scale +')','height': height + 'px'}"
                    @touchstart="touchstart"
                    @touchmove="touchmove"
                    @touchend="touchend"
                    @touchcancel="touchcancel"
                    mode="aspectFit"
                    :src="src"></img>
            </view>
            <view class="closePopup" @click="close">
                <uni-icons type="closeempty" size="32" color="#fff"></uni-icons>
            </view>
        </uni-popup>
    </view>
</template>

<script>
    export default {
        name:"selectImage",
        data() {
            return {
                height: 0,
                src: '',
                x: 0,
                y:0,
                clientX: 0,
                clientY: 0,
                moveX: 0,
                moveY: 0,
                touchType: 0, // 0为单指触摸  1为双指
                // 初始双指距离
                distance: 0,
                // 初始缩放比例
                scale: 1
            };
        },
        created() {
            const me = this
            uni.getSystemInfo({
                success(res) {
                    // 默认图片高度占屏幕一半展示
                    me.height = res.windowHeight / 2
                }
            })
        },
        methods: {
            // 获取两点距离
            getDistance (point1, point2) {
                const x = point1.clientX - point2.clientX
                const y = point1.clientY - point2.clientY
                return Math.sqrt(x*x + y*y)
            },
            // 触摸开始
            touchstart (e) {
                // 当触摸事件为一个时
                if (e.touches.length === 1) {
                    // 记录开始触摸位置
                    this.clientX = e.changedTouches[0].clientX
                    this.clientY = e.changedTouches[0].clientY
                    this.touchType = 0
                } else if (e.touches.length === 2) {
                    // 双指进行放大缩小操作
                    this.touchType = 1
                    // 获取双指距离
                    this.distance = this.getDistance(e.touches[0], e.touches[1])
                }
            },
            // 触摸移动中
            touchmove (e) {
                // 当触摸事件为一个时
                if (this.touchType === 0) {
                    // 记录移动的距离 
                    const moveX = e.changedTouches[0].clientX - this.clientX
                    const moveY = e.changedTouches[0].clientY - this.clientY
                    // 最终偏移距离为初始偏移距离+当前偏移距离
                    this.x = this.moveX + moveX
                    this.y = this.moveY + moveY
                } else if (this.touchType === 1) {
                    // 双指进行放大缩小操作
                    if (e.touches.length === 2) {
                        // 获取移动后的双指距离
                        const le = this.getDistance(e.touches[0], e.touches[1])
                        // 最终放大 缩小效果为 初始放大缩小比例 * 当前放大缩小比例
                        const bl = le / this.distance
                        const scale = this.scale * bl
                        this.scale = scale > 0.1 ? scale : 0.1
                        // 随着移动将开始的位置重置 不然会一次性放很大 或者缩很小,不好控制
                        this.distance = le
                    }
                }
            },
            // 触摸结束
            touchend (e) {
                // 当触摸事件为一个时
                if (this.touchType === 0) {
                    // 记录最终移动距离
                    const moveX = e.changedTouches[0].clientX - this.clientX
                    const moveY = e.changedTouches[0].clientY - this.clientY
                    // 最终偏移距离为初始偏移距离+当前偏移距离
                    this.x = this.moveX + moveX
                    this.y = this.moveY + moveY
                    // 当前偏移距离设置为当前位置
                    this.moveX = this.x
                    this.moveY = this.y
                } else if (this.touchType === 1) {
                    // 当双指松开后
                    console.log(e)
                }
            },
            // 因电话等打断时触发
            touchcancel (e) {
                if (this.touchType === 0) {
                    this.x = 0
                    this.y = 0
                } else {
                    this.clientX = 0
                    this.clientY = 0
                    this.moveX = 0
                    this.moveY = 0
                    this.touchType = 0 // 0为单指触摸  1为双指
                    // 初始双指距离
                    this.distance = 0
                    // 初始缩放比例
                    this.scale = 1
                }
            },
            open () {
                this.$refs.showImage.open()
            },
            close () {
                this.x = 0
                this.src = ''
                this.y = 0
                this.clientX = 0
                this.clientY = 0
                this.moveX = 0
                this.moveY = 0
                this.touchType = 0 // 0为单指触摸  1为双指
                // 初始双指距离
                this.distance = 0
                // 初始缩放比例
                this.scale = 1
                this.$refs.showImage.close()
            }
        }
    }
</script>

<style>
    .closePopup {
        position: fixed;
        top: 40px;
        right: 40px;
        width: 50px;
        height: 50px;
        text-align: center;
        line-height: 50px;
        z-index: 99999;
    }
</style>

外面组件调用时引用或者全局注册后使用

外面图片上加个点击事件

@click="look(url)"

方法直接调用组件open方法就OK了。

look (url) {
    this.$refs.showImg.src = url
    this.$refs.showImg.open()
},

效果图:

---------------查看----------------在这里插入图片描述

---------------移动----------------

在这里插入图片描述

---------------放大----------------

在这里插入图片描述

源码下载:

下载地址:点击下载

示例演示:

演示地址:点击前往

评论