应广大读者建议,已经将该项目源码提交到地址:

https://github.com/devilyouwei/dashen

与本博客相关的多图压缩上传代码在dashen/service/ask.html,请解压项目并移动到hbuilder中打开。

欲实现效果图

提出需求点:

  1. 用户可自由添加删除替换多张图片,并且显示相应缩略图,限制为8张
  2. 用户可选择压缩图或直接上传原图功能
  3. 返回提醒用户会丢失填写的信息

下面一个个实现上述需求,从简单到复杂:

需求3:

用户返回弹出提示框,使用mui.confirm如下:

var oldBack = mui.back;
mui.back=function(e){mui.confirm("尚未提交,返回后将会丢失填写内容物,是否返回?","返回确认",['返回','取消'],function(e){if(e.index==0)oldBack();})
}

(以上代码买应写在mui.plusReady()之中,因为里面需要用到html5+的方法,mui.back()就是5+方法)

第一步克隆了一个mui.back,因为下面他自己会被重写了,而真正返回的时候还是需要用到原来的mui.back()!

重写是为了再返回前执行一段逻辑,按照官方的说法,confirm弹出是异步执行(非阻塞)所以另外一种在mui.init({beforeBack:function})的方式是不合适,因为beforeBack选项要求的是阻塞的,可能会导致还没有按下confirm中的按钮,因为执行了return true而退出了,弹出窗口就显得没有意义了!只能使用重写back方法的办法了!

mui.confirm传入四个参数,提示主内容,标题,按钮数组,回调函数(对按钮数组的下表进行判断)

自由增删改图片

qq空间发表说说可以携带图片,通过缩略图的形式让用户修改自己要上传的图片,不过腾讯做的那个高级多了,还可以拖拽图片打开大图编辑等等,在此只实现最简单的功能。

专门写一个函数来实现这个功能:init_image_add()

//初始化图片添加器
function init_image_add() {//上传图片上限,超过不现实加号if(question.files.length >= IMG_MAX_NUM)return;var placeholder = document.createElement('div');placeholder.setAttribute('class', 'image-item space');//删除图片var closeButton = document.createElement('div');closeButton.setAttribute('class', 'image-close');closeButton.innerHTML = 'X';//小X的点击事件closeButton.addEventListener('tap', function(event) {removeFile(getChildrenIndex(placeholder)); //删除实际图片数组元素,先删除数组中的imageList.removeChild(placeholder); //删除ui,必须后删除,否则节点会找不到了if(question.files.length >= IMG_MAX_NUM - 1)init_image_add();event.stopPropagation();}, false);placeholder.addEventListener('tap', function(event) {var btnArray = [{title: "相册"}, {title: "拍照"}];//actionsheetplus.nativeUI.actionSheet({title: "选择图片",cancel: "取消",buttons: btnArray}, function(e) {var i = e.index;switch(i) {case 0:break;case 1:plus.gallery.pick(function(e) {plus.io.resolveLocalFileSystemURL(e, function(entry) {var url = entry.toLocalURL();var name = url.substr(e.lastIndexOf('/') + 1);//压缩取得缩略图plus.zip.compressImage({src: url,dst: '_doc/' + name,overwrite: true,quality: 50,height: '300px',clip: {top: "25%",left: "25%",width: "300px",height: "300px"}}, function(zip) {placeholder.style.backgroundImage = "url('" + zip.target + "')";if(!placeholder.classList.contains('space')) { //已有图片exFile(getChildrenIndex(placeholder), url);} else { //加号placeholder.classList.remove('space');addFile(url);init_image_add();}}, function(zip) {mui.toast('压缩失败!');});}, function(e) {console.log("读取相册文件错误:" + e.message);});}, function(e) {console.log(e.message);}, {});break;case 2:plus.camera.getCamera().captureImage(function(e) {plus.io.resolveLocalFileSystemURL(e, function(entry) {var url = entry.toLocalURL();var name = url.substr(e.lastIndexOf('/') + 1);//压缩plus.zip.compressImage({src: url,dst: '_doc/' + name,overwrite: true,quality: 50,height: '300px',clip: {top: "25%",left: "25%",width: "300px",height: "300px"}}, function(zip) {placeholder.style.backgroundImage = "url('" + zip.target + "')";if(!placeholder.classList.contains('space')) { //已有图片exFile(getChildrenIndex(placeholder), url);} else { //加号placeholder.classList.remove('space');addFile(url);init_image_add();}}, function(zip) {mui.toast('压缩失败!');});}, function(e) {console.log("读取拍照文件错误:" + e.message);});}, function(s) {console.log("error" + s);}, {});break;}});}, false);

代码有点长,只能作为参考,讲一下其中的算法:

首先这个函数应该在plusReady()内调用,并且在载入页面的时候就要调用了!

这个函数作用:生成一个图片添加按钮:

如图所示的“+”号,并且为这个新增的加号添加监听事件

  1. 点击“+”号弹出actionsheet选择相册或者相机添加图片
  2. 点击右上角“x”号可以删除一张图片

添加的方式是使用js生成dom并且插入到相应的节点

 var placeholder = document.createElement('div');placeholder.setAttribute('class', 'image-item space');//删除图片var closeButton = document.createElement('div');closeButton.setAttribute('class', 'image-close');closeButton.innerHTML = 'X';

以下是将会生成的对应的html代码

<div class="image-item space" id="img1"><div class="image-close">x</div>
</div>

可以想到这个函数应该要递归调用,这个递归是基于事件的,什么事件呢?

就是每一次添加完一张图片的事件,比如途中加号前面一张图被添加完成后立刻就会递归一次,调用init_image_add()自己

给个流程图:

压缩图片:

使用:plus.zip.compressImage

html5+官方文档:

例:


//压缩取得缩略图
plus.zip.compressImage({src: url,dst: '_doc/' + name,overwrite: true,quality: 50,height: '300px',clip: {top: "25%",left: "25%",width: "300px",height: "300px"}
}, function(zip) {placeholder.style.backgroundImage = "url('" + zip.target + "')";if(!placeholder.classList.contains('space')) { //已有图片exFile(getChildrenIndex(placeholder), url);} else { //加号placeholder.classList.remove('space');addFile(url);init_image_add();}
}, function(zip) {mui.toast('压缩失败!');
});

方法传入的参数:

  1. 压缩参数:


  1. 成功回调函数

  2. 失败回调函数

最终上传,多图压缩!

上传原图不在赘述,直接跳过此处,参考uploader上传即可_

这里是有一点小麻烦,个人折腾了一个小时才算弄完美了

千万注意,compressImage方法是异步执行的,也就是说,如果你打算将所有要上传的图片在for循环中遍历并且压缩是不妥当的,因为这些图片将会并行压缩,而由于是多图上传,你不知道所有图片压缩完成是什么时候,一张图的话可以直接在成功的回调函数中执行后面的逻辑

我采用了递归的方法解决了多图压缩并且压缩全部完成后再执行后面的逻辑,相当于强行把一个异步的函数写成了同步(阻塞)函数,需要结合“回调函数”+“递归调用”!

代码如下:

//用户未选取上传原图时上传前调用
function zip_upload_imgs(len = question.files.length - 1) {//第一次递归显示等待if(len == question.files.length - 1)plus.nativeUI.showWaiting("正在压缩图片...", {back: "none"});//当长度小于0时,结束递归if(len < 0) {//关闭等待plus.nativeUI.closeWaiting();return submitAsk();}//上传压缩图var url = question.files[len];plus.zip.compressImage({src: url,dst: '_doc/zip_' + url.substr(url.lastIndexOf('/') + 1),overwrite: true,quality: 50,height: "90%",}, function(zip) {//压缩成功,替换原图路径question.files[len] = zip.target;zip_upload_imgs(--len);}, function() {//压缩失败mui.toast('压缩失败!');});
}

这个函数就有意思了,递归出现在当前图片压缩成功后调用(在回调函数中递归),这样就解决了异步的问题,等待压缩而不执行之后的逻辑!

当然这里因为压缩时间可能会长一点,需要用到等待窗口提供用户友好,以免用户不知道这段时间是在压缩!

这个递归函数默认传入的是需要压缩的图片的数组长度值,这个图片数组(question.files)是个全局或者说相对于函数来说是更加全局的,他不会因为函数结束而回收!处于函数作用域之外!

数组是反向递归的,下标从大到小,最大的时候第一次执行函数所以显示等待提示,最后一次是当下标小于0时(数组下标越界)结束递归,中间每一次执行完,递归前将下标-1,传入下一次递归!

在return后面紧跟着的是一个一直在等待着的sumitAsk()函数,这个函数是最终上传图片+提交表单的!之所以说是“一直等待着的提交函数”,因为他本来会因为异步执行的“plus.zip.compressImage”而先执行掉,导致图片没有压缩就上传了,我之前折腾了很久就是因为这个问题,如果不按照上述的回调+递归模式,图片还在压缩,sumit就执行了,那么图片数组没有变,依然上传了原图!

JavaScript中有的是异步函数,有的是同步函数,需要严格注意,异步函数会重新打开一个“时间线”去执行自己,忽略掉同步的函数,所以应该要做到等待异步函数执行完成后继续执行同步函数!

上传图片

使用函数:plus.uploader.createUoload()

官方说明

我需要上传

  1. 图片文件(根据上述的图片数组,question.files,其中保存的都是要上传的图片的绝对路径)
  2. 表单数据

示例如下:

function submitAsk() {//建立连接var url = HTTP_DOMAIN + "Service/ask";var uploader = plus.uploader.createUpload(url, {method: 'POST'}, function(upload, status) {plus.nativeUI.closeWaiting();if(status == 200) {var res = JSON.parse(upload.responseText);//服务器方登陆失效if(res.login == 0) {plus.nativeUI.toast(res.info);app.clearToken();app.toLogin();return false;}console.log(upload.responseText);if(res.status == 1) {mui.alert("您的问题已提交,等待附近的人解答", "发表成功", "确定", function() {mui.back();});} else {mui.toast(res.info);}} else {mui.toast("网络服务器连接失败!稍后重试");}});//添加上传数据for(key in question) {if(key == "files")continue;uploader.addData(key, question[key]);}//如果有礼物图片就上传if(question.gift_img != "") {uploader.addFile(question.gift_img, {key: "gift_img"});}//添加上传文件for(var i = 0; i < question.files.length; i++) {uploader.addFile(question.files[i], {key: "img" + i});}//开始上传任务plus.nativeUI.showWaiting("正在提交...",{back:"none"});uploader.start();
}

注意addData和addFile的使用:

其中addData是上传数据的键值对,就像表单name和value一样一一对应,在这之前已经放入了question对象之中:

document.getElementById("submit").addEventListener("tap", function() {//获取表单数据question.title = document.getElementById("title").value;question.content = document.getElementById("content").value;question.gift_img = document.getElementById("gift_img").getAttribute("src");question.reward = document.getElementById("reward").value;question.message = document.getElementById("message").value;question.price = document.getElementById("price").value;console.log(JSON.stringify(question));/** 必填项目:标题,内容,难度*/if(plus.networkinfo.getCurrentType() == plus.networkinfo.CONNECTION_NONE)return mui.toast("连接网络失败,请稍后再试");if(trim(question.title) == "")return mui.toast("请给出问题标题!");if(trim(question.content) == "")//判断网络连接return mui.toast("无法提交,请详细填写以下问题内容!");if(question.star <= 0 || question.star > 5)return mui.toast("请给出问题难度!");//用户未选择上传原图时,压缩所有上传图片if(!document.getElementById("high_img").classList.contains("mui-active") && question.files.length > 0) {zip_upload_imgs();} else {submitAsk();}}, false);

关于异步上传plus.uploader,详细请参阅:
http://www.html5plus.org/doc/zh_cn/uploader.html#plus.uploader.createUpload

mui开发app之多图压缩与上传(仿qq空间说说发表)相关推荐

  1. Bmob+Luban(鲁班)压缩图片实现相册选择图片压缩后上传到Bmob后台Glide加载图片显示到本地

    源代码已上传CSDN:https://download.csdn.net/download/qq_16519957/11068345 因为本章需要跟前面的知识结合起来看所以就做了一个前面链接方便大家查 ...

  2. mui开发app教程-1

    上一篇:前言 目录 创建项目方式 功能1:引导页 引导页显示 引导页代码模板 引导页全屏显示设置 引导页跳转首页 功能2:首页选项卡设计 选项卡依赖文件 选项卡代码模板 选项卡更改图标 使用成果展示和 ...

  3. MUI开发APP文本框获得焦点并弹出软键盘

    在使用MUI开发APP时,经常需要让文本框获得焦点,并弹出软键盘,方便用户操作.在使用混合模式开发时,这需要调用Native.js方法. MUI官网展示了调用软键盘的示例:MUI官网示例. 调用软键盘 ...

  4. 【Android UI设计与开发】第09期:底部菜单栏(四)Fragment+PopupWindow仿QQ空间最新版底部菜单栏

    转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/9023451          在今天的这篇文章当中,我依然会以实战加理论结合 ...

  5. android 快速实现图片压缩与上传

    由于最近项目更新功能比较的忙,也没时间去整理自己的知识点和管理自己的博客.在android对手机相册中的图片的压缩和上传到服务器上,这样的功能在每个app开发中都会有这样的需求.所以今天就对andro ...

  6. 使用自开发的代理服务器解决 SAP UI5 FileUploader 上传文件时遇到的跨域访问错误试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 作者简介 Jerry Wang,2007 年从电子科技大学计算机专业硕士毕业后加入 SAP 成都研究院工作至今.Jerry 是 SAP 社区导师,S ...

  7. iOS传感器集锦、飞机大战、开发调试工具、强制更新、Swift仿QQ空间头部等源码

    iOS精选源码 飞机大作战 MUPhotoPreview -简单易用的图片浏览器 image LLDebugTool是一款针对开发者和测试者的调试工具,它可以帮... image 多个UIScroll ...

  8. Unity iOS 之 [iOS]App上架流程[利用Archive进行上传]

    [iOS]App上架流程[利用Archive进行上传] 准备: 1. 一个开发者账号(需要交过钱的,?好黑) 2. 一个做完的项目 检查: 1. 你的Xcode必须是正式版,不可以是beta版本(不能 ...

  9. iOS视频录制、压缩、上传(整理)

    iOS视频录制.压缩.上传(整理) 我们在项目中有时会碰到视频相关的需求,一般的可以分为几种情况: 1. 简单的视频开发,对界面无要求,可直接使用系统UIImagePickerController. ...

最新文章

  1. Jenkins实现SVN+Maven+Java项目的持续集成
  2. AR凭什么成为元宇宙和现实间的技术纽带?听听业内怎么说|量子位· 对撞派...
  3. 自学python的书籍逐级推荐-近300本Python书籍到底哪家强,用Python告诉你
  4. 密码学笔记——zip明文攻击
  5. 能源36号文解读_IDC报告预测:今年中国新能源汽车销量将达116万辆,未来五年复合增长率36%_详细解读_最新资讯_热点事件...
  6. 在线看大会!就来云栖号!
  7. 可以直接考甲级吗_函授本科可以考四级吗
  8. python读取txt文件每一行存为列表,从txt文件中读取一定数量的行,并以python方式转换为list...
  9. datax 不识别字段过滤_静电式空气过滤器有什么特点 静电式空气过滤器特点介绍【详解】...
  10. C++函数使用规范建议
  11. VMware项目虚拟机IP修改说明
  12. html egg mac os 10.7,10.7、10.8 MAC OS原版通用安装教程
  13. 免费公网动态IP方案
  14. 美丽世界的另一面!(请保护好你身边的亲朋好友)
  15. 1096 大美数 分数 15
  16. 紫薇~还记得大明湖畔的HTML5智力拼图吗?
  17. OSM数据下载及两种格式转换方法(shp等格式)
  18. 基于Python(Django)+MongoDB实现的(Web)新闻采集和订阅系统【100010319】
  19. 团队开发工具之一——Wiki
  20. qgraphicsview 绘图软件 github_重磅推荐!免费在线分析与绘图神器分享

热门文章

  1. 演出商业怎么实施RPA虚拟员工提高计费效率
  2. JavaScript判断数据类型的方式
  3. java的安装环境配置详细步骤
  4. 数据结构(Java)---链表
  5. Jmeter 参数化--4种方式
  6. “手把手”教你C语言八大排序
  7. 软件质量测试决策表和判定表,黑盒测试技术(Decision Tables 决策表法,又称判定表法)软件质量保证与测试...
  8. DAY28:Linux、Windows 系统提权
  9. 《研究生完全求生手册》笔记
  10. 人工智能的特点及人工智能应用