1. 程式人生 > >mui開發app之多圖壓縮與上傳(仿qq空間說說發表)

mui開發app之多圖壓縮與上傳(仿qq空間說說發表)

應廣大讀者建議,已經將該專案原始碼提交到地址:
https://download.csdn.net/download/u014466109/10465677
與本部落格相關的多圖壓縮上傳程式碼在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: "拍照" }]; //actionsheet plus.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);

相關推薦

mui開發app壓縮仿qq空間說說發表

應廣大讀者建議,已經將該專案原始碼提交到地址: https://download.csdn.net/download/u014466109/10465677 與本部落格相關的多圖壓縮上傳程式碼在dashen/service/ask.html,請解壓專案並移動

mui開發appplusready和init區別

除了function定義函式之外,全都寫在plusReady之中,function呼叫也放在其中,畢竟做app開發呼叫html5+api十分的頻繁,就像jq的$(document).ready()一樣的道理,尤其是出現plus物件的一定放在plusReady裡面!

laravel 圖片壓縮原生程式碼,

/** * 上傳騰訊雲伺服器圖片 * @return array */ function compression_upload_cos(Illuminate\Http\Request $request,$type) { $appid = config('file.teng

Spring Cloud Config svn配置倉庫動態重新整理客戶端自動重新整理

終於進入正文了,上篇完成了手動重新整理,貌似這種手動重新整理不是太好,因為你怎麼知道什麼時候去更新配置?我們的初衷是隻要配置檔案目錄下的檔案改變了,就要重新載入配置,也就是在svn倉庫的config目錄下的配置檔案改動自動重新整理 目前來看就兩個問題: 1:我怎麼確定是哪個

HTML5 file API加canvas實現圖片前端JS壓縮 轉載

www. 手機 回調 pre lan 瀏覽器中 rdp 效果 二進制 一、圖片上傳前端壓縮的現實意義 對於大尺寸圖片的上傳,在前端進行壓縮除了省流量外,最大的意義是極大的提高了用戶體驗。 這種體驗包括兩方面: 由於上傳圖片尺寸比較小,因此上傳速度會比較快,交互會更

angularJs 文件動態刪除其中一個文件的時候,要麽file沒被刪除,要麽刪除了之後,點擊事件失效

頁面 this 識別 更新 百度 一次 files fileinput type <div cacModule.controller(‘CacScriptEditCtrl‘, CacScriptEditCtrl); CacScriptEditCtrl.$i

選本地相簿中的圖片並展示仿QQ空間動態傳送頁面至伺服器

最近公司專案需要從本地上傳圖片到伺服器,直接去找才發現安卓居然還有這麼坑的時候,呼叫原生的只能選擇一張圖片,而且還沒有任何的細節優化,觸控圖片就直接返回了。這肯定不行啊!於是就在網上找啊找。。。找啊找。。。有很多都寫得花裡胡哨的看不懂,而且介面的UI也是low的不行。。終於

Android呼叫系統相機、相簿、裁剪圖片並壓縮適配7.0

作者:八怪不姓醜 連結:http://www.jianshu.com/p/e11a34e2ea4f 著作權歸作者所有,本文經作者授權推送。 一、前言 最近在開發中遇到了一個比較棘手的問題 由於在之前使用的版本-targetSdkVersion小於24也就是小於7.

h5mui開發app標題的滑動實現和樣式追蹤

mui.init({ gestureConfig: { longtap: true //預設為false }, swipe:true, //啟用右滑關閉功能 pullRefresh : { container:".mui-scroll-wrappe

mui開發APP教程建立專案

mui是一個基於H5+的前端框架,最近做畢業設計基於HTML5的APP,用的就是該框架,其中遇到不少坑,接下來貨闡述遇到的坑以及解決方法。至於mui是幹嘛的,有什麼優點就不說了,官網(http://de

mui開發APP教程mui.ajax請求後出現“載入中”

利用mui.ajax向伺服器請求資料會出現請求超時的情況,一般若是10S之後還沒有響應,就會定義為超時,那麼出錯了的時候,這10秒鐘不可能給使用者白屏,即便是請求成功之後開啟一個新頁面,那麼這個間隔時間也給使用者響應。 但是mui 的ajax並沒有實現類似jq

mui開發APP教程省市區級聯

demo預覽省市區級聯 在前一章我們寫了年月日級聯,這次我們來寫省市級聯,同樣,實現級聯的功能是基於mui的picker選擇器, 所以到匯入檔案,這次要匯入mui.picker.css、mui.

ArcGIS API For Javascript層顯示隱藏,層要素選框查詢

5、多圖層的載入與隱藏 利用Html+Javascript前端程式設計實現上傳到服務端的地圖服務中的多圖層的載入與隱藏。本實驗中除了底圖之外,添加了共10個圖層,分別為 賓館酒店_point (0) 餐飲_point (1) 超市商城_point (2) 地級市_font

Huffman的應用文件壓縮壓縮

讀取文件 size 父節點 .get 位移 etc RM 初始 amp 文件壓縮與解壓縮> ???? 近期這段時間一直在學習樹的這樣的數據結構,也接觸到了Hu

SpringBoot開發案例任務並行+線程池處理

Java SpringBoot 前言前幾篇文章著重介紹了後端服務數據庫和多線程並行處理優化,並示例了改造前後的偽代碼邏輯。當然了,優化是無止境的,前人栽樹後人乘涼。作為我們開發者來說,既然站在了巨人的肩膀上,就要寫出更加優化的程序。SpringBoot開發案例之JdbcTemplate批量操作Spri

Linux tar打包壓縮解壓使用

tartar打包壓縮與解壓使用 1.tar 壓縮打包/root/Desktop整個目錄,並把打包的文件放到/root/backup目錄下 [root@localhost ~]# tar -czvf /root/backup/desktop.tar.gz Desktop/ Desktop/ Desktop/ab

【轉】編程思想線程進程(1)——以操作系統的角度述說線程進程

意圖 發生 多個 責任 提升 get 好的 9.png 順序 什麽是線程 什麽是線程?線程與進程與有什麽關系?這是一個非常抽象的問題,也是一個特別廣的話題,涉及到非常多的知識。我不能確保能把它講的話,也不能確保講的內容全部都正確。即使這樣,我也希望盡可能地把他講通俗一點,

HBuilder Mui 開發App 實現ajax呼叫Java後臺的測試程式碼--仿照山西太原專案現實

1 HBuilder   url:'http://192.168.8.199:8089/data',====對應伺服器地址                 dataType:"

iOS開發技巧:圖片壓縮成指定的大小

iOS中,我們為了節省記憶體,需要對圖片來進行處理,來優化程式,提高程式的效率,下面是一個根據自己的要求來重新設定圖片的大小: 一、壓縮圖片有兩種方式,第一種是壓縮圖片的大小,重新生成圖片的尺寸:如下 [html] view plai

iOS開發知識:pod installpod update的區別

引言 許多使用cocoapod的人認為pod install只在第一次使用CocoaPod設定專案的時候使用,pod update是在設定完專案之後使用的,但事實並非如此。 這篇指南將會說明什麼時候應該使用pod install,什麼時候應該使用pod update。 如果你覺得這篇指南太過於