小程序之图片的上传、删除和预览和视频的上传和删除

最近在做一个小程序,帖子中用到了一个关于文字、图片和视频的一些操作。

最终的样式

未添加任何图片和视频

点击视频和图片的任意一个上传按钮就会开始上传

wx-1.png
添加图片

这部分可以对图片进行预览和删除

wx-2.png
添加视频

视频和删除和播放

wx-3.png

这个可以实现输入文字的统计和限制,图片的上传、预览和删除,视频的上传和删除功能。

如何实现上面的那些样式呢?

大家可以先阅读下面的文档,会发现其实很简单。

小程序关于图片操作的api文档:https://developers.weixin.qq.com/miniprogram/dev/api/wx.compressImage.html

小程序关于视频操作的api文档:https://developers.weixin.qq.com/miniprogram/dev/api/wx.saveVideoToPhotosAlbum.html

首先wxml文件

<view class="containor">
  <view class="publish_text_area">
    <!-- 标题 -->
    <view class="text_area_title">
      <input 
        class="title_input" 
        placeholder="请输入标题" 
        maxlength="25" 
        placeholder-style="color:#b3b3b3;font-size:16px;" 
        bindinput="handleTitleInput"
        value="{{title}}"
      ></input>
      <!-- 标题字数限制 -->  
      <view 
        class="{{ titleCount < 25 ? 'title_input_counter' : 'title_input_error_counter' }}"
      >{{titleCount}}/25</view>
    </view>
    <!-- 内容 -->
    <view class="text_area_content">
      <view class="area_content">
        <view class="area_content_out">
          <textarea 
            class="content-textarea" 
            placeholder="请输入正文内容..." 
            maxlength="255" 
            placeholder-style="color:#b3b3b3;font-size:12px;"
            style="height: 8rem" 
            bindinput="handleContentInput" 
            value="{{content}}"
          />
          <!-- 字数限制 -->  
          <view class="{{ contentCount < 255 ? 'content_textarea_counter' : 'content_textarea_error_counter'}}">{{contentCount}}/255</view>
        </view>
      </view>
    </view>
  </view>

  <view class="publish_imgs_area">
    <!-- 图片 -->
    <view class="imgs_area" wx:for="{{images}}" wx:key="*this">
      <view class="iamge_item">
        <image 
          class="iamge_content" 
          src="{{item}}" 
          data-id="{{index}}"
          mode="aspectFill" 
          bindtap="previewIamge"
        />
        <image 
          class="iamge_cancel" 
          src="./images/cancel.png" 
          mode="aspectFill" 
          data-id="{{index}}"
          bindtap="deleteImage"
        />
      </view>
    </view>
    <!-- 视频 -->
    <view class="video_area" wx:if="{{video != ''}}">
      <video
        class="video_item"
        src="{{video}}"
        controls
      ></video>
      <image 
        class="video_delete" 
        src="./images/video_del.png" 
        mode="aspectFill" 
        bindtap="videoDelete"
      />
    </view>
    <!-- 图片上传图片按钮 -->
    <view class="imgs_area" bindtap="chooseImage" wx:if="{{images.length < 9 && video == ''}}">
      <view class="iamge_item">
        <image class="iamge_content" src="./images/upload.png" mode="aspectFill" />
      </view>
    </view>
    <!-- 视频上传图片按钮 -->
    <view class="imgs_area" bindtap="chooseVideo" wx:if="{{video == '' &&  images.length == 0}}">
      <view class="iamge_item">
        <image class="iamge_content" src="./images/video.png" mode="aspectFill" />
      </view>
    </view>
  </view>
  <view class="btn_all_area">
    <button
      class="btn_area"
      type="primary"
      bindtap="submitClick"
    >提交</button>
    <button
      class="btn_area"
      type="warn"
      bindtap="resetClick"
    >重置</button>
  </view>
</view>

接下来wxss文件

page {
    background-color: #f1efef;
}

.containor {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.publish_text_area {
    background-color: #ffffff;
    display: flex;
    flex-direction: column;
    justify-content: center;
    margin:20rpx 20rpx 6rpx 20rpx;
    border-radius: 15rpx;
}

.text_area_title {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    margin: 10rpx;
}

.text_area_content {
    
}

.title_input {
    font-size: 30rpx;
    width:590rpx;
}

.title_input_counter {
    font-size:32rpx;
    color:#b3b3b3;
    margin-top:5rpx;
}

.title_input_error_counter {
    font-size:32rpx;
    color:#ce2f2f;
    margin-top:5rpx;
}

.area_content {
    border-top: 1rpx solid #f1efef;
    margin-left: 10rpx;
    margin-right: 10rpx;
}

.area_content_out {
    /* border-top: 1px solid #f1efef; */
    margin-top: 10rpx;
}

.content-textarea {
    width: 690rpx;
    font-size: 24rpx;
}

.content_textarea_counter {
    color:#d4d0d0;
    font-size:30rpx;
    text-align:right;
}

.content_textarea_error_counter {
    color:#ce2f2f;
    font-size:30rpx;
    text-align:right;
}
/* 图片部分 */
.publish_imgs_area{
    background-color: #ffffff;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    flex-wrap: wrap;
    border-radius: 15rpx;
    margin: 20rpx;
    padding-left: 8rpx;
    padding-top: 8rpx;
    padding-bottom: 8rpx;
    /* height: 450rpx; */
}

.iamge_item {
    width: 225rpx;
    height: 225rpx;
    padding: 4rpx;
}

.iamge_content{
    width: 223rpx;
    height: 223rpx;
    border-radius: 15rpx;
    border: 1px solid #f1efef;
}

.iamge_cancel{
    width:40rpx;
    height:40rpx;
    border-radius:50%;
    position:relative;
    top:-259rpx;
    right:-204rpx;
    z-index:800;
}

/* 视频部分样式 */
.video_area {
    width: 700rpx;
    position: relative;
}

.video_item {
    width: 700rpx;
}
.video_delete {
    width: 50rpx;
    height: 50rpx;
    position: absolute;
    top: 10rpx;
    right: 2rpx;    
}

.btn_all_area {
    background-color: #ffffff;
    display: flex;
    flex-direction: row;
    justify-content: center;
    margin:20rpx 20rpx 6rpx 20rpx;
    border-radius: 15rpx;
    /* position: absolute;
    bottom: 0; */
}

.btn_area {
    width: 350rpx;
}

最后是Js文件

对于图片的上传,可以存在两种情况:1、第一次就上传了九张图片;2、第一次不够九张,第二次接着上传。所有我们需要对这个条件就行判断。

Page({
  /**
   * 页面的初始数据
   */
  data: {
    // 标题数
    titleCount: 0,
    // 详情数
    contentCount: 0,
    // 标题内容
    title: '',
    // 标题内容
    content: '',
    // 图片列表
    images: [],
    // 视频
    video : '',
  },

  // 图片操作的具体函数
  ImageOperator() {
    wx.chooseImage({
      count: 9,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success: res =>  {
        // 上传的图片数据
        const imgList = res.tempFilePaths;
        // 原始的图片数据
        const imageList = this.data.images;

        // 原来的图片数量
        let imageLenght = imageList.length;
        // 当前的图片数量
        let nowLenght = imgList.length;
        console.log(imageLenght);

        if ( imageLenght == 9 ) {
          console.log("数量已经有9张,请删除在添加...");
        }
        if ( imageLenght < 9 ) {
          let images = [];
          // 获取缺少的图片张数
          let residue = 9 - imageLenght;
          // 如果缺少的张数大于当前的的张数  
          if ( residue >= nowLenght ) {
            // 直接将两个数组合并为一个  
            images = imageList.concat(imgList);
          }else {
            // 否则截取当前的数组一部分  
            images = imageList.concat(imgList.slice(0, residue));
          }  
          this.setData({
            images
          })
        }
      }
    })
    
  },

  // 标题操作
  handleTitleInput(event) {
    let inputValue = event.detail.value;
    // 确保标题不存在空格  
    if(inputValue.lastIndexOf(" ") != -1){
      inputValue = inputValue.substring(0, inputValue.lastIndexOf(" "));
    }
    let titleCount = inputValue.length;
    if(titleCount <= 25){
      this.setData({
        titleCount: titleCount ,
        title: inputValue
      })
    }
  },
  // 内容操作
  handleContentInput(event) {
    let textareaValue = event.detail.value;
    let contentCount = textareaValue.length;
    if(contentCount <= 255){
      this.setData({
        contentCount: contentCount,
        content: textareaValue
      })
    }
  },
  // 图片获取
  chooseImage() {
    if (this.data.images.length == 0) {
      wx.showToast({
        title: '视频和图片只能选择上传一种类型!',
        icon: 'none',
        duration: 2000,
        success: res => {
          this.ImageOperator()
        }
      })
    }else {
      this.ImageOperator()
    }
    
  },
  // 删除图片
  deleteImage(event) {
    //获取数据绑定的data-id的数据
    const nowIndex = event.currentTarget.dataset.id;
    let images = this.data.images;
    images.splice(nowIndex, 1);
    this.setData({
      images
    })
  },
  // 预览图片
  previewIamge(event) {
    const nowIndex = event.currentTarget.dataset.id;
    const images = this.data.images;
    wx.previewImage({
      current: images[nowIndex],  //当前预览的图片
      urls: images,  //所有要预览的图片
    })
  },
  // 上传视频
  chooseVideo() {
    // 弹层  
    wx.showToast({
      title: '视频和图片只能选择上传一种类型!',
      icon: 'none',
      duration: 2000,
      success: res => {
        wx.chooseVideo({
          sourceType: ['album', 'camera'],
          compressed: true,
          maxDuration: 10,
          camera: 'back',
          success: res => {
            console.log(res);
            const video = res.tempFilePath;
            this.setData({video})
          }
        })
      }
    })
  },
  // 删除视频
  videoDelete(){
    wx.showModal({
      title: '警告',
      content: '确定要删除该视频吗',
      success: res => {
        if (res.confirm) {
          this.setData({
            video: ''
          })
        }
      }
    })
  },
  // 表单提交事件
  submitClick() {

  },
  // 重置表单
  resetClick() {
    wx.showModal({
      title: '警告',
      content: '重置表单将需要重新上传数据',
      success: res => {
        if (res.confirm) {
          this.setData({
            titleCount: 0,
            contentCount: 0,
            title: '',
            content: '',
            images: [],
            video : ''
          })
        }
      }
    })
  }
})

这样就实现了,代码还有很多需要优化的地方,如果需要请自行斟酌使用!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容

  • 每天的学习记录,可能有的地方写的不对,因为刚学,以后发现错的话会回来改掉整体流程 https://develope...
    有点健忘阅读 4,646评论 0 7
  • 写在前面 微信小程序出来也蛮久了,经过了市场的考验,已经站稳脚跟,融入到了各行各业,市场需求激增打来的是开发人员的...
    月梦佳期阅读 1,685评论 1 1
  • 给提问的开发者的建议:提问之前先查询 文档、通过社区右上角搜索搜索已经存在的问题。 写一个简明扼要的标题,并且...
    极乐叔阅读 13,406评论 0 3
  • 亲爱的上帝: 我感觉非常累。也感觉自己确实像是站在悬崖边上,昨天晚上的梦魇有增无减,居然开始听到另外一些精神在唱些...
    轻轻阅读 161评论 0 1
  • 今天参加完厦门的培训,搭上动车到了漳州,那是我本科母校的所在。和两个大学同学见面,其中一位还带了自己的未婚妻过来,...
    大叔开始留胡子了阅读 262评论 0 0