1***@qq.com
1***@qq.com
  • 发布:2025-08-15 09:21
  • 更新:2025-08-15 09:53
  • 阅读:33

【报Bug】movable-view 进行可拖拽和可缩放大小功能,缩放到最大时候拖动x为0坐标,然后再重新动态x=0,会远距离不等于0

分类:uni-app

产品分类: uniapp/小程序/微信

PC开发环境操作系统: Mac

PC开发环境操作系统版本号: 10.15.1

HBuilderX类型: 正式

HBuilderX版本号: 4.75

第三方开发者工具版本号: 4.75

基础库版本号: 3.8.10

项目创建方式: HBuilderX

示例代码:
<template>  
    <view class="container">  
        <!-- 顶部标题 -->  
        <view class="header">  
            <text class="title">藏品布局工具</text>  
        </view>  

        <view class="main-content">  
            <!-- 中间:布局区域 -->  
            <view class="center-panel">  
                <text class="panel-title">布局区域</text>  
                <movable-area class="layout-area" ref="layoutArea">  
                    <!-- 选中的背景图 -->  
                    <image v-if="data.default" :src="data.default.bgImg" class="background-image"></image>  

                    <!-- 可拖拽的藏品 -->  
                    <movable-view direction="all" scale @change="(e:any) => handleDragChange(index,item, e)"  
                        v-for="(item,index) in addedCollections" :key="item.id" class="draggable-item" :x="item.x"  
                        :y="item.y" :width="item.width" :height="item.height" @scale="(e:any)=>onScale(item,e)"  

                        :scale-value="item.scale" scale-min='0.8' scale-max='2' :animation="false"  
                        :style="{ zIndex: item.zIndex, position: 'absolute' }" :data-id="item.id">  
                        {{item.scale}}  
                        <image :src="(item.thumbnail)" mode="widthFix" class="collection-img"  
                            :style="{width:'100px',height:'100px'}"></image>  
                    </movable-view>  
                </movable-area>  
            </view>  

            <!-- 右侧:藏品列表 -->  
            <view class="right-panel">  
                <text class="panel-title">我的藏品</text>  
                <view class="my-collections">  
                    <view class="collection-item" v-for="item in data.cpList" :key="item.id"  
                        @tap="addItemDirectly(item)">  
                        <image :src="(item.thumbnail)" mode="aspectFill" class="collection-img"  
                            :style="{width:'100px',height:'100px'}"></image>  
                    </view>  
                </view>  
            </view>  
        </view>  

        <!-- 底部操作按钮 -->  
        <view class="bottom-actions">  
            <button class="action-btn" @click="resetLayout">重置布局</button>  
            <button class="action-btn primary" @click="saveLayout">保存布局</button>  
        </view>  

    </view>  
</template>  

<script setup lang="ts">  
    import { ref, onMounted, nextTick, watch, reactive } from 'vue';  
    import { onLoad } from "@dcloudio/uni-app";  

    const data = reactive<any>({  
        default:{bgImg: 'https://oss.elianip.com/images/2025/August/64201b5f309c69a43dc8c0355da67aa5a01a21.jpg'},  
        cpList: [  
            { "id": 350315, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749023825, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1256, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": "0", "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },   
            { "id": 350314, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749023454, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1255, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": 0, "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },  
            { "id": 350313, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749022226, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1254, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": 1, "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },   
            { "id": 350312, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749022166, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1253, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": 1, "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },   
            { "id": 350311, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749022089, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1252, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": 1, "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },   
            { "id": 350310, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749019534, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1251, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": 1, "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },   
            { "id": 350287, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749017366, "nftIntro": "民以食为天,我们感恩土地的馈赠喜看稻菽千重浪,同时铭记“珍惜盘中餐的古训,珍惜每一粒粮食。在世界粮食日川渝数藏推出主题藏品《五谷丰登》以此向那些默默耕耘的农耕人致敬。", "nftName": "五谷丰登", "nftId": 534, "imagePath": "https://oss.elianip.com/images/2024/October/96ea720504a0d927850a764e1b21f7b341bfc1.jpg", "txId": "", "amount": 1, "nftSn": 1819, "totalQuantity": 2024, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 0, "transferCount": 1, "isNew": 1, "thumbnail": "/images/2024/October/eb2ee5e11906f4bd10a48c34b8b28a6f988120.jpg", "tag": "", "tagImage": "", "lockTime": 0 },   
            { "id": 350285, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749017366, "nftIntro": "民以食为天,我们感恩土地的馈赠喜看稻菽千重浪,同时铭记“珍惜盘中餐的古训,珍惜每一粒粮食。在世界粮食日川渝数藏推出主题藏品《五谷丰登》以此向那些默默耕耘的农耕人致敬。", "nftName": "五谷丰登", "nftId": 534, "imagePath": "https://oss.elianip.com/images/2024/October/96ea720504a0d927850a764e1b21f7b341bfc1.jpg", "txId": "", "amount": 1, "nftSn": 1818, "totalQuantity": 2024, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 0, "transferCount": 1, "isNew": 1, "thumbnail": "/images/2024/October/eb2ee5e11906f4bd10a48c34b8b28a6f988120.jpg", "tag": "", "tagImage": "", "lockTime": 0 }],  
        scale: 1,  
        addedCollections:[]  
    })  

    onLoad((option) => {  
        //data.default = JSON.parse(option?.item || '{}')  
        //getNftListfn()  
    })  

    const getNftListfn = async () => {  
        //let { list } = await getNftList(1, 100);  
        //data.cpList = list  
    }  

    // 响应式状态  
    const addedCollections = ref<any>([]);  
    const layoutArea = ref(null);  
    const layoutAreaRect = ref({ width: 0, height: 0 });  

    const maxZIndex = ref(0);  

    // 初始化  
    onMounted(() => {  
        // 修复1:Vue3 setup中没有this,移除第二个参数  

        // 修复2:确保DOM渲染完成后获取尺寸  
        nextTick(() => {  
            getLayoutAreaRect().then(() => {  
                console.log('布局区域尺寸初始化完成', layoutAreaRect.value);  
            });  
        });  
    });  

    // 获取布局区域尺寸(改为Promise确保异步执行完成)  
    const getLayoutAreaRect = () : Promise<void> => {  
        return new Promise((resolve) => {  
            uni.createSelectorQuery()  
                .select(".layout-area")  
                .boundingClientRect((rect : any) => {  
                    if (rect) {  
                        layoutAreaRect.value = {  
                            width: rect.width,  
                            height: rect.height  
                        };  

                    }  
                    resolve();  
                })  
                .exec();  
        });  
    };  

    // 直接添加藏品  
    const addItemDirectly = async (item : any) => {  
        // 确保尺寸已获取  
        if (!layoutAreaRect.value.width) {  
            await getLayoutAreaRect();  
        }  
        addItemToLayout(item);  
    };  

    // 更新zIndex  
    const updateMaxZIndex = () => {  
        maxZIndex.value = Math.max(...addedCollections.value.map((item : any) => item.zIndex || 0));  
    };  

    // 添加藏品到布局区域  
    const addItemToLayout = (item : any) => {  
            /*  if(addedCollections.value.length>0){  
                    addedCollections.value.map((item:any)=>{  
                        item.x=item.oldx  
                        item.y=item.oldy  
                        item.scale=item.scaleold  
                        console.log(item,'map')  
                        return item  
                    })  
                } */  

        for (const key in addedCollections.value) {  
          if (data.addedCollections && data.addedCollections.hasOwnProperty(key)) {  
            addedCollections.value[key] = data.addedCollections[key];  
          }  
        }  
        const randomX =20 //Math.ceil(Math.random() * (layoutAreaRect.value.width - 100)) + 20;  
        const randomY =20// Math.ceil(Math.random() * (layoutAreaRect.value.height - 100)) + 20;  

        const newItem = {  
            ...item,  
            x: randomX,  
            y: randomY,  
            //oldx:randomX,  
            //oldy:randomY,  
            scale: 1,  
            //scaleold: 1,  
            width: '100px',  
            height: '100px',  
            zIndex: maxZIndex.value + 1,  

        };  
console.log(addedCollections.value)  
        addedCollections.value.push(newItem)  
        data.addedCollections=JSON.parse(JSON.stringify(addedCollections.value))  

    console.log(addedCollections.value)  
        updateMaxZIndex();  
    };  

    // 处理拖拽位置变化  
    const handleDragChange = (index : number, item : any, e : any) => {  
        console.log(e)  
        updateMaxZIndex();  
    /*  item.zIndex = maxZIndex.value + 1;  
        item.oldx = e.detail.x;  
        item.oldy = e.detail.y; */  
        console.log(item)  
                const targetItem = data.addedCollections.find((el : any) => el.id === item.id);  
        targetItem.x=e.detail.x;  
        targetItem.y=e.detail.y;  
        targetItem.zIndex=maxZIndex.value + 1  
        /*   
        const targetItem = addedCollections.value.find((el : any) => el.id === item.id);  
        if (targetItem) {  

        }  
        if (addedCollections.value[index]) {  
                addedCollections.value[index].x = e.detail.x;  
                addedCollections.value[index].y = e.detail.y;  
            } */  
    }  
    const onScale = (item : any,e : any) => {  
        console.log(e)  

    /*      item.scaleold = e.detail.scale  
            item.oldx = e.detail.x;  
            item.oldy = e.detail.y; */  
            const targetItem = data.addedCollections.find((el : any) => el.id === item.id);  
        targetItem.y=e.detail.y;  
        targetItem.x=e.detail.x;  
        targetItem.scale=e.detail.scale;  

console.log('item,',item)  

    }  
    // 重置布局  
    const resetLayout = () => {  
        uni.showModal({  
            title: '提示',  
            content: '确定要清空当前布局吗?',  
            success: res => {  
                if (res.confirm) {  
                    addedCollections.value = [];  
                }  
            }  
        });  
    };  

    // 保存布局  
    const saveLayout = async () => {  
        if (addedCollections.value.length === 0) {  
            uni.showToast({ title: '请添加藏品到布局', icon: 'none' });  
            return;  
        }  

    };  
</script>  

<style scoped>  
    /* 保持原有样式不变 */  
    .container {  
        display: flex;  
        flex-direction: column;  
        min-height: 100vh;  
        background-color: #f5f5f5;  
    }  

    .header {  
        padding: 16px;  
        background-color: #333;  
        color: white;  
        text-align: center;  
    }  

    .title {  
        font-size: 18px;  
        font-weight: bold;  
    }  

    .main-content {  
        display: flex;  
        flex: 1;  
        padding: 16px;  
        gap: 16px;  
        box-sizing: border-box;  
    }  

    .right-panel {  
        width: 200px;  
        background-color: white;  
        border-radius: 8px;  
        padding: 12px;  
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);  
        display: flex;  
        flex-direction: column;  
        box-sizing: border-box;  
    }  

    .center-panel {  
        flex: 1;  
        background-color: white;  
        border-radius: 8px;  
        padding: 12px;  
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);  
        display: flex;  
        flex-direction: column;  
    }  

    .panel-title {  
        font-size: 16px;  
        font-weight: bold;  
        margin-bottom: 12px;  
        color: #333;  
        padding-bottom: 8px;  
        border-bottom: 1px solid #eee;  
    }  

    .my-collections {  
        display: flex;  
        flex-direction: column;  
        gap: 10px;  
        overflow-y: auto;  
        flex: 1;  
    }  

    .collection-item {  
        width: 100%;  
        height: 80px;  
        border-radius: 6px;  
        cursor: pointer;  
        transition: all 0.2s;  
        position: relative;  
    }  

    .collection-item:active {  
        opacity: 0.8;  
        transform: scale(0.98);  
    }  

    .bg-img,  
    .collection-img {  
        width: 100%;  
        height: 100%;  
        object-fit: cover;  
    }  

    .layout-area {  
        flex: 1;  
        background-color: #f9f9f9;  
        border-radius: 8px;  
        overflow: hidden;  
        position: relative;  
        min-height: 500px;  
        width: 100%;  
    }  

    .background-image {  
        width: 100%;  
        height: 100%;  
        object-fit: contain;  
        z-index: 0;  
    }  

    .draggable-item {  
        width: 100px;  
        height: 100px;  
    }  

    .bottom-actions {  
        padding: 16px;  
        display: flex;  
        gap: 12px;  
        justify-content: center;  
        background-color: white;  
        border-top: 1px solid #eee;  
    }  

    .action-btn {  
        padding: 10px 20px;  
        border-radius: 6px;  
        font-size: 14px;  
        border: 1px solid #ddd;  
        background-color: white;  
        color: #333;  
    }  

    .action-btn.primary {  
        background-color: #007aff;  
        color: white;  
        border-color: #007aff;  
    }  

    @media (max-width: 768px) {  
        .main-content {  
            flex-direction: column;  
        }  

        .right-panel {  
            width: 100%;  
            height: 200px;  
        }  

        .my-collections {  
            flex-direction: row;  
        }  

        .collection-item {  
            flex: 1;  
            height: 150px;  
        }  
    }  
</style>

操作步骤:

缩放到最大时候拖动x为0坐标,然后点击下面新增图片再重新动态上一个元素x=0,会远距离不等于0,只要不是最大就正常

预期结果:

没有bug

实际结果:

缩放到最大时候拖动x为0坐标,然后点击下面新增图片再重新动态上一个元素x=0,会远距离不等于0

bug描述:

movable-view 进行可拖拽和可缩放大小功能,缩放到最大时候拖动x为0坐标,然后再重新动态x=0,会远距离不等于0

2025-08-15 09:21 负责人:无 分享
已邀请:
1***@qq.com

1***@qq.com (作者) - 软件攻城师

小程序真机测试也有bug,拖拽会抖动,然后sacle默认写1.2直接也会抖动溜走

DCloud_UNI_JBB

DCloud_UNI_JBB

测试一下原生微信小程序是否也有同样的问题

  • 1***@qq.com (作者)

    现已修复这个bug,但是又出现了另外一个bug,sace放大到最大的状态,然后弄到x=0,然后新增图片,看元素上一个最大的坐标没变化,但是离开x不等于0

    2025-08-15 11:38

  • 1***@qq.com (作者)

    代码已更新,附件已更新

    2025-08-15 11:45

  • DCloud_UNI_JBB

    回复 1***@qq.com: 这个组件 uniapp 没有做啥特殊处理,有问题的话你可以先测试一下原生微信小程序是否有一样的问题

    2025-08-15 11:51

要回复问题请先登录注册