广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >微信小程序图片上传组件实现图片拖拽排序
  • 726
分享到

微信小程序图片上传组件实现图片拖拽排序

2024-04-02 19:04:59 726人浏览 泡泡鱼
摘要

目录引言首先来看效果组件设计使用方式总结引言 图片上传组件是一个组件库目前来看必不可少的功能了。笔者近日给自己开源的toy工具库也添加了这一功能。相比原生和大部分组件库来说,它不仅支

引言

图片上传组件是一个组件库目前来看必不可少的功能了。笔者近日给自己开源的toy工具库也添加了这一功能。相比原生和大部分组件库来说,它不仅支持长按提示删除,还能够支持图片的拖拽排序,很是nice!

(也是为了毕设时身边同学能够更快上手小程序,更加将中心侧重于逻辑和设计?)

本文我将继续介绍组件的设计思路:

首先来看效果

对于组件内部来说。笔者提供了一个参数去让开发者决定是否应该在场景中支持拖动排序。这里略去这些无关代码。

拖拽排序功能使用了微信小程序提供的movable-area组件(标签,但小程序也是封装了html,所以以原生组件代称)。它相当于提供了一个可滑动区域,在此区域内的movable-view组件内容可以任意排列。其效果就相当于window中的“桌面图标非对齐”效果 —— 记住这个描述,它和下面的内容联系紧密!

其中主要的两个参数是:

  • x:定义x轴方向的偏移,如果x的值不在可移动范围内,会自动移动到可移动范围;改变x的值会触发动画;
  • y:定义y轴方向的偏移,如果y的值不在可移动范围内,会自动移动到可移动范围;改变y的值会触发动画;

嗯,可以知道,其内部是通过 js 触发的动画。而且可能是requestAnimeFrame api

组件设计

知道了所用标签,接下来就该正式开发了。但是你会发现,这里其实有两种使用方式:

对每个元素使用movable-view包裹,让他们可以随意拖拽位置:

<view class="container">
    <movable-area style="width: 100%;height: auto;">
        <view class="image-list">
            <!-- 显示图片 -->
            <block wx:if="{{yMovable}}">
                <movable-view x="{{x}}" y="{{y}}" direction="all" inertia damping="{{5000}}" friction="{{1}}" disabled="{{disabled}}" wx:for="{{images}}" wx:key="{{item.index}}">
                    <view class="image-wrap image-bg {{(images.length > 2) ? 'image-flex' : ''}}" id="{{item.index}}" data-index='{{index}}' bindlongpress='onShowMenu' bindtouchstart='touchs' bindtouchend='touchend' bindtouchmove='touchm'>
                        <image class="image" src="{{item.img}}" mode="aspectFill" bind:tap="onPreviewImage" data-imgsrc="{{item.img}}"></image>
                        <i class="iconfont icon-delete" wx:if="{{showMenuImg}}" bind:tap="onDelImage" data-index="{{index}}"></i>
                    </view>
                </movable-view>
            </block>
            
            <!-- 选择图片 -->
            <view class="image-wrap selectphoto" bind:tap="onChooseImage" hidden="{{!selectPhoto}}">
                <i class="iconfont icon-jiashang"></i>
            </view>
        </view>
    </movable-area>
</view>

图片只是展示;单独设置一个元素,在长按图片时显示,其值为当前选中的图片,拖拽的是这个元素,到达目标位置后消失,图片列表重新排序。

<view class="container">
    <movable-area style="width: 100%;height: auto;">
        <view class="image-list">
            <!-- 显示图片 -->
            <block wx:if="{{yMovable}}">
                <block wx:for="{{images}}" wx:key="{{item.index}}">
                    <view class="image-wrap image-bg {{(images.length > 2) ? 'image-flex' : ''}}" id="{{item.index}}" data-index='{{index}}' bindlongpress='onShowMenu' bindtouchstart='touchs' bindtouchend='touchend' bindtouchmove='touchm'>
                        <image class="image" src="{{item.img}}" mode="aspectFill" bind:tap="onPreviewImage" data-imgsrc="{{item.img}}"></image>
                        <i class="iconfont icon-delete" wx:if="{{showMenuImg}}" bind:tap="onDelImage" data-index="{{index}}"></i>
                    </view>
                </block>
                <movable-view x="{{x}}" y="{{y}}" direction="all" inertia damping="{{5000}}" friction="{{1}}" disabled="{{disabled}}">
                    <view class='image-wrap image-check' style="z-index: 3;" hidden='{{hidden}}'>
                        <image class="image" src="{{doubleImg}}" mode="aspectFill"></image>
                    </view>
                </movable-view>
            </block>
            
            <!-- 选择图片 -->
            <view class="image-wrap selectphoto" bind:tap="onChooseImage" hidden="{{!selectPhoto}}">
                <i class="iconfont icon-jiashang"></i>
            </view>
        </view>
    </movable-area>
</view>

第一种方式的优势在于:可以有更加“真实”的效果。这里的真实意为重新排列时也有滑动的动画效果。但是带来的性能损耗也是极大的,你只能尽力调控各种数据来让显示更加“跟手”一些。但是基于此,你可以通过js计算达到像QQ空间那样的实时排列效果!

第二种方式的优势在于:性能开销相对小一些。但展示效果更像WEB而非APP(这两个的区别你应该是知道的)。

当前版本中,笔者采用的是第二种方式。其关键 js 代码如下:

const MAX_IMG_NUM=9;
Component({
  
  properties: {
    yMovable:{
      type:Boolean,
      value:false
    },
  },


  
  data: {
    images:[],
    selectPhoto:true,
    showMenuImg: false,
    flag: false,
    hidden:true,
    x:0,
    y:0,
    disabled: true,
    elements:[],
    doubleImg: ""
  },

  
  methods: {
  	//长按事件
    onShowMenu(e){
        const detail = e.currentTarget;
        if(!this.data.showMenuImg) {
          // 使手机振动15ms
          wx.vibrateShort();
        }
        this.setData({
            showMenuImg: true
        })
        if(this.properties.yMovable) {
            this.setData({
                x: detail.offsetLeft+5,
                y: detail.offsetTop,
                hidden: false,
                flag:true,
                doubleImg: this.data.images[detail.dataset.index].img
            })
        }
    },
    //触摸开始
    touchs:function(e){
        this.setData({
          beginIndex:e.currentTarget.dataset.index
        })
    },
    //触摸结束
    touchend:function(e){
        if (!this.data.flag) {
          return;
        }
        const x = e.changedTouches[0].pageX
        const y = e.changedTouches[0].pageY
        const list = this.data.elements;
        let data = this.data.images
        for(var j = 0; j<list.length; j++){
          const item = list[j];
          if(x>item.left && x<item.right && y>item.top && y<item.bottom){
            const endIndex = item.dataset.index;
            const beginIndex = this.data.beginIndex;
            //向后移动
            if (beginIndex < endIndex) {
              let tem = data[beginIndex];
              for (let i = beginIndex; i < endIndex; i++) {
                data[i] = data[i + 1]
              }
              data[endIndex] = tem;
            }
            //向前移动
            if (beginIndex > endIndex) {
              let tem = data[beginIndex];
              for (let i = beginIndex; i > endIndex; i--) {
                data[i] = data[i - 1]
              }
              data[endIndex] = tem;
            }
    
            this.setData({
                images: data
            })
            this.initImg(this.triggerMsg(data, "sort-img"))
          }
        }
        this.setData({
          hidden: true,
          flag: false
        })
    },
    //滑动
    touchm:function(e){
        if(this.data.flag){
          const x = e.touches[0].pageX
          const y = e.touches[0].pageY
          this.setData({
            x: x - 75,
            y: y - 45
          })
        }
    },
    
    //选择图片
    onChooseImage(){
        let images = this.data.images;
        let imageLen = images.length;
        let max=MAX_IMG_NUM-imageLen;
        wx.chooseImage({
          count:max,
          sizeType:['original','compressed'],
          sourceType:['album','camera'],
          success: (res) => {
            max-=res.tempFilePaths.length;
            let _images = images.map(item => {
                return item.img
            })
            images = _images.concat(res.tempFilePaths)
            for(let i=0;i<images.length;i++) {
                images[i] = {
                    img: images[i],
                    index: i+1
                }
            }
            this.setData({
              selectPhoto:max<=0?false:true,
              images,
              showMenuImg: false
            })
            this.triggerMsg(images, "choose-img")
            if(this.properties.yMovable) {
                this.initImg()
            }
          },
          fail:(res)=>{
          }
        })
    },
	
	// 初始化位置信息
    initImg(fn=function(){}) {
        let query = wx.createSelectorQuery().in(this);
        let nodesRef = query.selectAll(".image-bg");
        nodesRef.fields({
            dataset: true,
            rect:true
        },(result)=>{
            this.setData({
                elements: result;
                fn();
            })
        }).exec()
    },
    
    //删除
    onDelImage(event){
        let images = this.data.images;
        images.splice(event.target.dataset.index,1)
        this.setData({
          images
        })
        this.initImg(this.triggerMsg(images, "delete-img"))
        if(images.length== MAX_IMG_NUM-1){
          this.setData({
            selectPhoto:true
          })
        }
    },

    triggerMsg(images, key) {
      this.triggerEvent('chooseImg', {
        images: images.map(item => {
            return item.img
        }),
        key: key
      })
    },
  }
})

上面代码中最重要的就是initImg函数的这段代码!它用来获取wxml节点的相关属性!fields API的参数及默认值有:

id:false,//是否返回节点id
rect:fasle,//是否返回节点布局位置
dataset: true,//返回数据集
size: true,//返回宽高
scrollOffset: true,//返回 scrollLeft,scrollTop
properties: ['scrollX', 'scrollY'],//监听属性名
computedStyle: ['margin', 'backgroundColor']//此处返回指定要返回的样式名

这个API的调用是后面定位的关键,它必须放在获取到图片数组之后执行(不管同步还是异步的)。也是第二种方法和第一种方法的区别之处 —— 第一种方法是纯 js 计算实时位置。所以它需要在结束后进行排序。

这时候问题就来了:像本文这种场景,同时有 x 和 y 两个方向的位置,sort将会极其复杂,而且sort本身的性能将会被内部繁杂的代码死死拖住。这就是上面说第一种方法性能问题的原因所在。

但是本文这种方法将sort简化为当前拖动元素和目标位置图片两个物体的四个方向判断,也就是经典“小球撞墙”临界问题。这也是其优势所在。

另一个需要注意的地方就是 touchm函数中的setData。这里面进行的是拖拽元素位置改变,也就是“跟手率”(我自己编的)。可以对此数值进行微调来让效果更加nice一些。

使用方式

首先在JSON文件中进行组件引入:

{
  "usinGComponents": {
    "y-img":"/components/yImg/index"
  }
}

然后再wxml中:

<view class="container">
	<y-img bind:chooseImg="chooseImg"></y-img>
	<!--或:-->
    <y-img yMovable bind:chooseImg="chooseImg"></y-img>
</view>
chooseImg(e) {
      console.log(e.detail)
},

GitHub地址:https://github.com/1314mxc/yunUI#img,欢迎使用、查看和star!

总结

到此这篇关于微信小程序图片上传组件实现图片拖拽排序的文章就介绍到这了,更多相关微信小程序图片拖拽排序内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 微信小程序图片上传组件实现图片拖拽排序

本文链接: https://www.lsjlt.com/news/143644.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 微信小程序图片上传组件实现图片拖拽排序
    目录引言首先来看效果组件设计使用方式总结引言 图片上传组件是一个组件库目前来看必不可少的功能了。笔者近日给自己开源的toy工具库也添加了这一功能。相比原生和大部分组件库来说,它不仅支...
    99+
    2022-11-13
  • 微信小程序怎么实现图片拖拽排序
    这篇文章主要介绍“微信小程序怎么实现图片拖拽排序”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“微信小程序怎么实现图片拖拽排序”文章能帮助大家解决问题。首先来看效果对于组件内部来说。笔者提供了一个参数...
    99+
    2023-06-29
  • 微信小程序实现上传图片
    本文实例为大家分享了微信小程序实现上传图片的具体代码,供大家参考,具体内容如下 //wxml <button class='button' bingtap="uploadSom...
    99+
    2022-11-13
  • 微信小程序实现图片上传
    微信小程序实现图片上传 最近做了个小程序,涉及到了图片上传的功能,今天给大家详细介绍下如何实现小程序图片上传,话不多说先上代码 首先是静态布局和样式部分 .wxml代码部分 ...
    99+
    2023-09-07
    微信小程序 小程序 微信
  • 使用element+vuedraggable实现图片上传拖拽排序
    本文实例为大家分享了用element+vuedraggable实现图片上传拖拽排序的具体代码,供大家参考,具体内容如下 <template>     <div cl...
    99+
    2022-11-13
  • 使用微信小程序实现图片拖拽功能
    使用微信小程序实现图片拖拽功能引言:随着微信小程序的流行,更多的开发者开始探索小程序的各种功能和特性。其中,实现图片拖拽功能是一项常见的需求。本文将介绍如何使用微信小程序的API和组件,实现图片拖拽的效果,并提供具体的代码示例。一、设计思路...
    99+
    2023-11-21
    图片 微信小程序 拖拽
  • 微信小程序实现上传图片小功能
    本文实例为大家分享了微信小程序实现上传图片的具体代码,供大家参考,具体内容如下 用到的apiwx.chooseMedia(); 用于拍摄或从手机相册中选择图片或视频 功能:点击上传图...
    99+
    2022-11-13
  • 微信小程序实现图片上传功能
    微信小程序实现图片上传功能随着移动互联网的发展,微信小程序已经成为了人们生活中不可或缺的一部分。微信小程序不仅提供了丰富的应用场景,还支持开发者自定义功能,其中包括图片上传功能。本文将介绍如何在微信小程序中实现图片上传功能,并提供具体的代码...
    99+
    2023-11-21
    微信小程序 图片上传 功能实现
  • 微信小程序如何实现上传图片
    这篇文章主要介绍微信小程序如何实现上传图片,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! 一 小程序端user.wxml<view class='u...
    99+
    2022-10-19
  • 怎么使用element+vuedraggable实现图片上传拖拽排序
    这篇文章主要介绍了怎么使用element+vuedraggable实现图片上传拖拽排序的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用element+vuedraggable实现图片上传拖拽排序文章都会有...
    99+
    2023-06-29
  • 微信小程序实现上传图片的功能
    本文实例为大家分享了微信小程序实现上传图片的具体代码,供大家参考,具体内容如下 效果图 WXML <view class="img-wrap"> <vie...
    99+
    2022-11-12
  • 微信小程序实现图片上传(清晰版)
    在wxml文件中添加一个按钮和一个image标签用于显示上传的图片 选择图片 ...
    99+
    2023-08-31
    微信小程序 小程序 前端
  • 微信小程序实现多文件或者图片上传
    本文实例为大家分享了微信小程序实现多文件或者图片上传的具体代码,供大家参考,具体内容如下 html <view class="list1">     <view c...
    99+
    2022-11-13
  • 微信小程序图片上传功能怎么实现
    这篇文章主要介绍“微信小程序图片上传功能怎么实现”,在日常操作中,相信很多人在微信小程序图片上传功能怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”微信小程序图片上传功能怎么实现”的疑惑有所帮助!接下来...
    99+
    2023-06-30
  • 微信小程序怎么实现多文件或图片上传
    本文小编为大家详细介绍“微信小程序怎么实现多文件或图片上传”,内容详细,步骤清晰,细节处理妥当,希望这篇“微信小程序怎么实现多文件或图片上传”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。html<view&...
    99+
    2023-07-02
  • 微信小程序实现图片裁剪并上传功能
    微信小程序实现图片裁剪并上传功能随着微信小程序的快速发展,越来越多的开发者开始关注微信小程序的开发技巧和功能实现。其中,图片裁剪并上传功能是一个常见的需求,本文将介绍如何在微信小程序中实现图片裁剪并上传的功能,并提供具体的代码示例。一、功能...
    99+
    2023-11-21
    微信 小程序 图片裁剪 上传
  • 微信小程序图片上传功能的实现方法
    目录前言首先是静态布局和样式部分下面是js的部分,我已详细备注~~~总结前言 最近做了个小程序,涉及到了图片上传的功能,今天给大家详细介绍下如何实现小程序图片上传,话不多说先上代码 ...
    99+
    2022-11-13
  • 微信小程序如何实现上传图片到服务器
    这篇文章主要介绍了微信小程序如何实现上传图片到服务器,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。上传图片到服务器:1.先在前端写一个选择图...
    99+
    2022-10-19
  • 使用微信小程序实现拖拽排序功能
    使用微信小程序实现拖拽排序功能 示例代码刚开始学习微信小程序时,我一直以为实现拖拽排序功能是很困难的事情。然而,通过深入研究官方文档和尝试不同的方法,我终于成功地实现了这一功能。在本篇文章中,我将分享实现拖拽排序功能的具体代码示例。首先,在...
    99+
    2023-11-21
    微信小程序 功能实现 拖拽排序
  • 微信小程序实现长按拖拽排序功能
    工作中遇到一个上传图片长按后拖动排序的一个功能,于是写下了一个小demo。希望能对你有遇到的问题有帮助。 演示效果: wxml <view class='outer' >...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作