
HBuilder+MUI开发APP实战-司机签收系统(二)Common.js封装
这部分直接上代码,都是自己一行一行码出来的,每个方法都非常有用:
- msg: function(msg, icon, timer) 弹出层
- alert: function(msg, icon, callback) 弹出框,带确认按钮,可事件回调
- confrim: function(msg, callback) 确认框,带事件回调
- open: function(url, params, aniShow) 打开新页面,or 页面跳转
- close: function() 关闭当前页面
- exit: function() Android下直接退出,ios不支持
- backExit: function() 点击2次返回退出app
- currPageId: function(callback) 获取当前窗体的ID
- getParam: function(key, callback) 获取上个页面船体过来的参数
- GetUrlParms: function() 获取get url地址里的所有参数,返回数组
- isBrowser:这是个属性,用来判定是否是在浏览器中打开,如果一套代码想兼容app和微信,这个很有用
- loading: function() 自定义的弹出loading,加载数据前显示
- loadingClose: function(timer) 关闭loading
- ajax: function(type, url, params, callback, callbackErr, el) 异步请求数据,支持post、get、put、delete等。
- update: function() 系统自动升级
- updateCheck: function() 自动升级的具体实现
- validaCom:验证规则封装
- jsonCom:操作JSON封装
- dataCom 数据存储封装
- netCom:网络监测封装
-
account:当前登录用户信息封装
define(['_', 'layer', 'config', 'common'], function(_, layer, config) { return { //系统提醒 msg: function(msg, icon, timer) { timer = (timer == undefined ? 1500 : timer*1000); layer.msg(msg, { icon: icon, anim: 0, time: timer }); }, //系统弹出提醒 alert: function(msg, icon, callback) { layer.msg(msg, { title: '', icon: icon, shade: 0.3, shadeClose: false, btnAlign: 'c', btn: ['我知道了'], time: 9999999, yes: function(idx) { if(callback) callback(); layer.close(idx); } }); }, confrim: function(msg, callback) { var my = this; layer.msg(msg, { time: 9999999, icon: 3, shade: 0.3, shadeClose: false, btn: ['确 定', '取 消'], yes: function(index) { if(callback) callback(); layer.close(index); } }); }, //打开新窗体 open: function(url, params, aniShow) { var my = this; if(!my.isBrowser) { //app跳转 if(!aniShow) { var anType = ['slide-in-right', 'slide-in-left', 'slide-in-top', 'slide-in-bottom', 'fade-in', 'zoom-out', 'zoom-fade-out', 'pop-in']; var anIdx = Math.floor((Math.random() * anType.length)); if(mui.os.ios) aniShow = anType[anType.length - 1]; else aniShow = anType[0]; } mui.openWindow({ id: url, url: url, extras: params, createNew: false, show: { autoShow: true, //页面loaded事件发生后自动显示,默认为true aniShow: aniShow, //anType[anIdx], //页面显示动画,默认为”slide-in-right“; duration: 200 //页面动画持续时间,Android平台默认100毫秒,iOS平台默认200毫秒; }, waiting: { autoShow: false, //自动显示等待框,默认为true title: config.dictionary.strings.LOADING, //等待对话框上显示的提示内容 options: { //back:'none', background: 'rgba(0,0,0,0.75)', round: 5, loading: { //icon: '/img/loading-png.png', height: '50px', display: 'inline' } } }, }) } else { //浏览器跳转 var newUrl = url; var newParams; if(params != null) { newParams = my.jsonCom.jsonToUrlParam(params); url += "?" + newParams; } //加随机参数清缓存 if(url.indexOf('?') == -1) url += '?_=' + (new Date().getTime()); else url += '&_=' + (new Date().getTime()); top.location.href = url; } }, //关闭窗体 close: function() { if(!this.isBrowser) { var ws = plus.webview.currentWebview(); plus.webview.close(ws); } else history.back(); }, exit: function() { plus.runtime.quit(); }, //双击返回退出APP backExit: function() { var my = this; if(!my.isBrowser) { var _clickNum = 0; mui.init({ beforeback: function() { _clickNum++; if(_clickNum > 1) { plus.runtime.quit(); } else { my.msg("再按一次退出应用"); } setTimeout(function() { _clickNum = 0; }, 1000); return false; } }); } }, //获取当前页面ID currPageId: function(callback) { if(sysCom.isBrowser) callback(location.href); else { mui.plusReady(function() { callback(plus.webview.getLaunchWebview().getURL()); }); } }, //获取页面参数 getParam: function(key, callback) { if(!sysCom.isBrowser) { mui.plusReady(function() { var wv = plus.webview.currentWebview(); var value = wv[key]; callback(value); }); } else { var value = urlCom.getParam(key); callback(value); } }, //获取URL所有参数 GetUrlParms: function() { var args = new Object(); var query = location.search.substring(1); //获取查询串 var pairs = query.split("&"); //在逗号处断开 for(var i = 0; i < pairs.length; i++) { var pos = pairs[i].indexOf('='); //查找name=value if(pos == -1) continue; //如果没有找到就跳过 var argname = pairs[i].substring(0, pos); //提取name var value = pairs[i].substring(pos + 1); //提取value args[argname] = decodeURIComponent(value); //存为属性 } return args; }, //是否是普通浏览器打开 isBrowser: !mui.os.plus, //loading弹出层 loading: function() { var box = $('#loading-layout'); if(box.length == 0) { $('body').append('<div id="loading-layout"><div class="loading"></div></div>'); box = $('#loading-layout'); } var box_loading = $('#loading-layout .loading'); var width = box.width(); var height = box.height(); var width_loading = box_loading.width(); var height_loading = box_loading.height(); $('#loading-layout .loading').css('top', (height - height_loading) / 2 + 'px') $('#loading-layout .loading').css('left', (width - width_loading) / 2 + 'px') box.show(); }, //关闭弹出层 loadingClose: function(timer) { setTimeout(function() { $('#loading-layout').remove(); }, (timer ? timer : 0)) }, /******* http 请求 *******/ //请求 get ajax: function(type, url, params, callback, callbackErr, el) { var my = this; if(!config.appCONFIG.netStatus) { my.msg(config.dictionary.strings.NO_NET_POST) if(callbackErr) callbackErr(config.dictionary.strings.NO_NET_POST); return false; } var el_txt = ''; var timer; var timer_sec = 0; if(el) { el_txt = $(el).text(); $(el).attr('disabled', true).text('正在提交'); timer = setInterval(function() { if(timer_sec < 3) { $(el).text($(el).text() + '.'); timer_sec++; } else { $(el).text('正在提交'); timer_sec = 0; } }, 500); } //my.loading(); $.ajax({ url: url, type: type, //GET async: true, //或false,是否异步 data: params, timeout: 15000, //超时时间 dataType: 'jsonp', jsonp: "theFunction", success: function(data, textStatus, jqXHR) { callback(data); }, error: function(xhr, textStatus) { if(textStatus == "error") my.msg(config.dictionary.strings.SERVER_ERROR); else if(textStatus == "timeout") my.msg(config.dictionary.strings.TIMEOUT); else { //console.log(xhr.responseText) var jsonXhr = JSON.parse(xhr.responseText); //令牌错误重新登陆 if(jsonXhr.ExceptionMessage == config.dictionary.strings.INVALID_TOKEN) { my.msg(config.dictionary.strings.INVALID_TOKEN_ERR); } else { my.msg("error:" + jsonXhr.ExceptionMessage); } } if(callbackErr) callbackErr(xhr, textStatus); }, complete: function() { //my.loadingClose(); if(el) { $(el).text(el_txt) $(el).removeAttr('disabled'); clearInterval(timer); } } }) }, //系统自动更新 update: function() { if(window.plus) { this.updateCheck(); } else { document.addEventListener('plusready', this.updateCheck, false); } }, //系统升级检测 updateCheck: function() { var appVer = ''; //app版本 var newVer = ''; //最新版本 //获得当前版本 plus.runtime.getProperty(plus.runtime.appid, function(inf) { appVer = inf.version; $('.copyright').html('陕西中电新盛物流有限公司v' + appVer); //console.log(1) //发起新版本请求检测 var update_url = config.urlCONFIG.get_appupdate + "/version.txt?bust=" + (new Date().getTime()); //console.log(update_url) $.get(update_url, {}, function(res) { var data = JSON.parse(res); newVer = data.version; fileType = 'wgt'; if(appVer != newVer && parseInt(appVer.replaceAll('\\.', '')) < parseInt(newVer.replaceAll('\\.', ''))) { var waiting = plus.nativeUI.showWaiting("有新版本啦,正在下载更新 0%...", { width: '100%', height: '100%', //back: 'none', round: 1, }); //下载更新包 var file_downing = plus.downloader.createDownload(config.urlCONFIG.get_appupdate + "/wgt/" + newVer + "." + fileType + "?_=" + (new Date().getTime()), { filename: "_doc/update/" }, function(d, status) { if(status == 200) { var _filename = d.filename; // 安装更新包 plus.runtime.install(_filename, {}, function() { //更新完毕删除更新包 plus.io.resolveLocalFileSystemURL(_filename, function(entity) { entity.remove(); }, function(error) { debugCom.log(error.message); }); //如果是安卓自动重启应用,ios需要手动重启应用 if(mui.os.android) { waiting.setTitle('更新完成,正在重新打开应用...'); setTimeout(function() { plus.nativeUI.closeWaiting(); plus.runtime.restart(); }, 1000) } else { plus.nativeUI.closeWaiting(); mui.alert('更新完成,请彻底结束应用并重新打开!', '', function() { //plus.runtime.restart(); }) } }, function(e) { waiting.setTitle('更新失败:' + e.message); setTimeout(function() { plus.nativeUI.closeWaiting(); }, 2000); }); } else { mui.toast('下载更新包出现问题:' + status) } }); //下载百分比 file_downing.addEventListener("statechanged", function() { var per = parseInt(file_downing.downloadedSize / file_downing.totalSize * 100); per = (per == NaN ? 0 : per); waiting.setTitle("有新版本啦,正在下载更新 " + per + "%"); }, false); //开始下载 file_downing.start(); } }); }) }, /********验证********/ validaCom: { //验证正则 _regex: { mobile: /^1+\d{10}$/, isIDCard: /^\d{17}[\d|X|x]$|^\d{15}$/, email: /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/, }, //验证手机 isMobile: function(txt) { return this._regex.mobile.test(txt); }, //验证邮箱 isEmail: function(txt) { return this._regex.email.test(txt); }, //身份证验证 isIDCard: function(txt) { return this._regex.isIDCard.test(txt); }, }, /********json操作********/ jsonCom: { //将json转成url参数 jsonToUrlParam: function(param, key) { var my = this; var paramStr = ""; if(param instanceof String || param instanceof Number || param instanceof Boolean) { paramStr += "&" + key + "=" + encodeURIComponent(param); } else { $.each(param, function(i) { var k = key == null ? i : key + (param instanceof Array ? "[" + i + "]" : "." + i); paramStr += '&' + my.jsonToUrlParam(this, k); }); } return paramStr.substr(1); }, //将url参数转成json urlParamToJson: function(url) { if(url.indexOf("?") > -1) { var string_a = url.split('?')[1]; if(string_a.length > 0) { var string = string_a.split('&'); var res = {}; for(var i = 0; i < string.length; i++) { var str = string[i].split('='); res[str[0]] = str[1]; } return res; } else return null; } else return null; } }, /********数据存储********/ dataCom: { set: function(key, data) { localStorage.setItem(key, data); }, get: function(key) { return localStorage.getItem(key); }, remove: function(key) { localStorage.removeItem(key) }, clear: function() { localStorage.clear(); } }, /*********** 网络监测 *************/ netCom: { init: function() { var my = this; //网络检测 mui.plusReady(function() { if(plus.networkinfo.getCurrentType() == plus.networkinfo.CONNECTION_NONE) { config.netStatus = false; layer.msg(config.dictionary.strings.NO_NET); } document.addEventListener("netchange", my.change, false); }); }, change: function() { var my = this; mui.plusReady(function() { //获取当前网络类型 var nt = plus.networkinfo.getCurrentType(); switch(nt) { case plus.networkinfo.CONNECTION_ETHERNET: case plus.networkinfo.CONNECTION_WIFI: case plus.networkinfo.CONNECTION_CELL2G: case plus.networkinfo.CONNECTION_CELL3G: case plus.networkinfo.CONNECTION_CELL4G: if(!config.netStatus) { layer.msg(config.dictionary.strings.YES_NET); } config.netStatus = true; break; default: if(config.netStatus) { layer.msg(config.dictionary.strings.NO_NET); } config.netStatus = false; break; } }); } }, /*********** 用户信息 *************/ account: { getUser: function() { var datauser = localStorage.getItem('datauser'); if(datauser) { return JSON.parse(datauser); } else { return null; } } } } });
这部分直接上代码,都是自己一行一行码出来的,每个方法都非常有用:
- msg: function(msg, icon, timer) 弹出层
- alert: function(msg, icon, callback) 弹出框,带确认按钮,可事件回调
- confrim: function(msg, callback) 确认框,带事件回调
- open: function(url, params, aniShow) 打开新页面,or 页面跳转
- close: function() 关闭当前页面
- exit: function() Android下直接退出,ios不支持
- backExit: function() 点击2次返回退出app
- currPageId: function(callback) 获取当前窗体的ID
- getParam: function(key, callback) 获取上个页面船体过来的参数
- GetUrlParms: function() 获取get url地址里的所有参数,返回数组
- isBrowser:这是个属性,用来判定是否是在浏览器中打开,如果一套代码想兼容app和微信,这个很有用
- loading: function() 自定义的弹出loading,加载数据前显示
- loadingClose: function(timer) 关闭loading
- ajax: function(type, url, params, callback, callbackErr, el) 异步请求数据,支持post、get、put、delete等。
- update: function() 系统自动升级
- updateCheck: function() 自动升级的具体实现
- validaCom:验证规则封装
- jsonCom:操作JSON封装
- dataCom 数据存储封装
- netCom:网络监测封装
-
account:当前登录用户信息封装
define(['_', 'layer', 'config', 'common'], function(_, layer, config) { return { //系统提醒 msg: function(msg, icon, timer) { timer = (timer == undefined ? 1500 : timer*1000); layer.msg(msg, { icon: icon, anim: 0, time: timer }); }, //系统弹出提醒 alert: function(msg, icon, callback) { layer.msg(msg, { title: '', icon: icon, shade: 0.3, shadeClose: false, btnAlign: 'c', btn: ['我知道了'], time: 9999999, yes: function(idx) { if(callback) callback(); layer.close(idx); } }); }, confrim: function(msg, callback) { var my = this; layer.msg(msg, { time: 9999999, icon: 3, shade: 0.3, shadeClose: false, btn: ['确 定', '取 消'], yes: function(index) { if(callback) callback(); layer.close(index); } }); }, //打开新窗体 open: function(url, params, aniShow) { var my = this; if(!my.isBrowser) { //app跳转 if(!aniShow) { var anType = ['slide-in-right', 'slide-in-left', 'slide-in-top', 'slide-in-bottom', 'fade-in', 'zoom-out', 'zoom-fade-out', 'pop-in']; var anIdx = Math.floor((Math.random() * anType.length)); if(mui.os.ios) aniShow = anType[anType.length - 1]; else aniShow = anType[0]; } mui.openWindow({ id: url, url: url, extras: params, createNew: false, show: { autoShow: true, //页面loaded事件发生后自动显示,默认为true aniShow: aniShow, //anType[anIdx], //页面显示动画,默认为”slide-in-right“; duration: 200 //页面动画持续时间,Android平台默认100毫秒,iOS平台默认200毫秒; }, waiting: { autoShow: false, //自动显示等待框,默认为true title: config.dictionary.strings.LOADING, //等待对话框上显示的提示内容 options: { //back:'none', background: 'rgba(0,0,0,0.75)', round: 5, loading: { //icon: '/img/loading-png.png', height: '50px', display: 'inline' } } }, }) } else { //浏览器跳转 var newUrl = url; var newParams; if(params != null) { newParams = my.jsonCom.jsonToUrlParam(params); url += "?" + newParams; } //加随机参数清缓存 if(url.indexOf('?') == -1) url += '?_=' + (new Date().getTime()); else url += '&_=' + (new Date().getTime()); top.location.href = url; } }, //关闭窗体 close: function() { if(!this.isBrowser) { var ws = plus.webview.currentWebview(); plus.webview.close(ws); } else history.back(); }, exit: function() { plus.runtime.quit(); }, //双击返回退出APP backExit: function() { var my = this; if(!my.isBrowser) { var _clickNum = 0; mui.init({ beforeback: function() { _clickNum++; if(_clickNum > 1) { plus.runtime.quit(); } else { my.msg("再按一次退出应用"); } setTimeout(function() { _clickNum = 0; }, 1000); return false; } }); } }, //获取当前页面ID currPageId: function(callback) { if(sysCom.isBrowser) callback(location.href); else { mui.plusReady(function() { callback(plus.webview.getLaunchWebview().getURL()); }); } }, //获取页面参数 getParam: function(key, callback) { if(!sysCom.isBrowser) { mui.plusReady(function() { var wv = plus.webview.currentWebview(); var value = wv[key]; callback(value); }); } else { var value = urlCom.getParam(key); callback(value); } }, //获取URL所有参数 GetUrlParms: function() { var args = new Object(); var query = location.search.substring(1); //获取查询串 var pairs = query.split("&"); //在逗号处断开 for(var i = 0; i < pairs.length; i++) { var pos = pairs[i].indexOf('='); //查找name=value if(pos == -1) continue; //如果没有找到就跳过 var argname = pairs[i].substring(0, pos); //提取name var value = pairs[i].substring(pos + 1); //提取value args[argname] = decodeURIComponent(value); //存为属性 } return args; }, //是否是普通浏览器打开 isBrowser: !mui.os.plus, //loading弹出层 loading: function() { var box = $('#loading-layout'); if(box.length == 0) { $('body').append('<div id="loading-layout"><div class="loading"></div></div>'); box = $('#loading-layout'); } var box_loading = $('#loading-layout .loading'); var width = box.width(); var height = box.height(); var width_loading = box_loading.width(); var height_loading = box_loading.height(); $('#loading-layout .loading').css('top', (height - height_loading) / 2 + 'px') $('#loading-layout .loading').css('left', (width - width_loading) / 2 + 'px') box.show(); }, //关闭弹出层 loadingClose: function(timer) { setTimeout(function() { $('#loading-layout').remove(); }, (timer ? timer : 0)) }, /******* http 请求 *******/ //请求 get ajax: function(type, url, params, callback, callbackErr, el) { var my = this; if(!config.appCONFIG.netStatus) { my.msg(config.dictionary.strings.NO_NET_POST) if(callbackErr) callbackErr(config.dictionary.strings.NO_NET_POST); return false; } var el_txt = ''; var timer; var timer_sec = 0; if(el) { el_txt = $(el).text(); $(el).attr('disabled', true).text('正在提交'); timer = setInterval(function() { if(timer_sec < 3) { $(el).text($(el).text() + '.'); timer_sec++; } else { $(el).text('正在提交'); timer_sec = 0; } }, 500); } //my.loading(); $.ajax({ url: url, type: type, //GET async: true, //或false,是否异步 data: params, timeout: 15000, //超时时间 dataType: 'jsonp', jsonp: "theFunction", success: function(data, textStatus, jqXHR) { callback(data); }, error: function(xhr, textStatus) { if(textStatus == "error") my.msg(config.dictionary.strings.SERVER_ERROR); else if(textStatus == "timeout") my.msg(config.dictionary.strings.TIMEOUT); else { //console.log(xhr.responseText) var jsonXhr = JSON.parse(xhr.responseText); //令牌错误重新登陆 if(jsonXhr.ExceptionMessage == config.dictionary.strings.INVALID_TOKEN) { my.msg(config.dictionary.strings.INVALID_TOKEN_ERR); } else { my.msg("error:" + jsonXhr.ExceptionMessage); } } if(callbackErr) callbackErr(xhr, textStatus); }, complete: function() { //my.loadingClose(); if(el) { $(el).text(el_txt) $(el).removeAttr('disabled'); clearInterval(timer); } } }) }, //系统自动更新 update: function() { if(window.plus) { this.updateCheck(); } else { document.addEventListener('plusready', this.updateCheck, false); } }, //系统升级检测 updateCheck: function() { var appVer = ''; //app版本 var newVer = ''; //最新版本 //获得当前版本 plus.runtime.getProperty(plus.runtime.appid, function(inf) { appVer = inf.version; $('.copyright').html('陕西中电新盛物流有限公司v' + appVer); //console.log(1) //发起新版本请求检测 var update_url = config.urlCONFIG.get_appupdate + "/version.txt?bust=" + (new Date().getTime()); //console.log(update_url) $.get(update_url, {}, function(res) { var data = JSON.parse(res); newVer = data.version; fileType = 'wgt'; if(appVer != newVer && parseInt(appVer.replaceAll('\\.', '')) < parseInt(newVer.replaceAll('\\.', ''))) { var waiting = plus.nativeUI.showWaiting("有新版本啦,正在下载更新 0%...", { width: '100%', height: '100%', //back: 'none', round: 1, }); //下载更新包 var file_downing = plus.downloader.createDownload(config.urlCONFIG.get_appupdate + "/wgt/" + newVer + "." + fileType + "?_=" + (new Date().getTime()), { filename: "_doc/update/" }, function(d, status) { if(status == 200) { var _filename = d.filename; // 安装更新包 plus.runtime.install(_filename, {}, function() { //更新完毕删除更新包 plus.io.resolveLocalFileSystemURL(_filename, function(entity) { entity.remove(); }, function(error) { debugCom.log(error.message); }); //如果是安卓自动重启应用,ios需要手动重启应用 if(mui.os.android) { waiting.setTitle('更新完成,正在重新打开应用...'); setTimeout(function() { plus.nativeUI.closeWaiting(); plus.runtime.restart(); }, 1000) } else { plus.nativeUI.closeWaiting(); mui.alert('更新完成,请彻底结束应用并重新打开!', '', function() { //plus.runtime.restart(); }) } }, function(e) { waiting.setTitle('更新失败:' + e.message); setTimeout(function() { plus.nativeUI.closeWaiting(); }, 2000); }); } else { mui.toast('下载更新包出现问题:' + status) } }); //下载百分比 file_downing.addEventListener("statechanged", function() { var per = parseInt(file_downing.downloadedSize / file_downing.totalSize * 100); per = (per == NaN ? 0 : per); waiting.setTitle("有新版本啦,正在下载更新 " + per + "%"); }, false); //开始下载 file_downing.start(); } }); }) }, /********验证********/ validaCom: { //验证正则 _regex: { mobile: /^1+\d{10}$/, isIDCard: /^\d{17}[\d|X|x]$|^\d{15}$/, email: /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/, }, //验证手机 isMobile: function(txt) { return this._regex.mobile.test(txt); }, //验证邮箱 isEmail: function(txt) { return this._regex.email.test(txt); }, //身份证验证 isIDCard: function(txt) { return this._regex.isIDCard.test(txt); }, }, /********json操作********/ jsonCom: { //将json转成url参数 jsonToUrlParam: function(param, key) { var my = this; var paramStr = ""; if(param instanceof String || param instanceof Number || param instanceof Boolean) { paramStr += "&" + key + "=" + encodeURIComponent(param); } else { $.each(param, function(i) { var k = key == null ? i : key + (param instanceof Array ? "[" + i + "]" : "." + i); paramStr += '&' + my.jsonToUrlParam(this, k); }); } return paramStr.substr(1); }, //将url参数转成json urlParamToJson: function(url) { if(url.indexOf("?") > -1) { var string_a = url.split('?')[1]; if(string_a.length > 0) { var string = string_a.split('&'); var res = {}; for(var i = 0; i < string.length; i++) { var str = string[i].split('='); res[str[0]] = str[1]; } return res; } else return null; } else return null; } }, /********数据存储********/ dataCom: { set: function(key, data) { localStorage.setItem(key, data); }, get: function(key) { return localStorage.getItem(key); }, remove: function(key) { localStorage.removeItem(key) }, clear: function() { localStorage.clear(); } }, /*********** 网络监测 *************/ netCom: { init: function() { var my = this; //网络检测 mui.plusReady(function() { if(plus.networkinfo.getCurrentType() == plus.networkinfo.CONNECTION_NONE) { config.netStatus = false; layer.msg(config.dictionary.strings.NO_NET); } document.addEventListener("netchange", my.change, false); }); }, change: function() { var my = this; mui.plusReady(function() { //获取当前网络类型 var nt = plus.networkinfo.getCurrentType(); switch(nt) { case plus.networkinfo.CONNECTION_ETHERNET: case plus.networkinfo.CONNECTION_WIFI: case plus.networkinfo.CONNECTION_CELL2G: case plus.networkinfo.CONNECTION_CELL3G: case plus.networkinfo.CONNECTION_CELL4G: if(!config.netStatus) { layer.msg(config.dictionary.strings.YES_NET); } config.netStatus = true; break; default: if(config.netStatus) { layer.msg(config.dictionary.strings.NO_NET); } config.netStatus = false; break; } }); } }, /*********** 用户信息 *************/ account: { getUser: function() { var datauser = localStorage.getItem('datauser'); if(datauser) { return JSON.parse(datauser); } else { return null; } } } } });

HBuilder+MUI开发APP实战-司机签收系统(一)登录

如上是界面,UI自己弄去,
【HTML结构代码】-login.html
当我们点击登录的时候需要验证,要实现以下效果:
这个弹层使用的是layer插件,下面我们来上JS代码:
<script src="js/libs/require.js?v=1.0"></script>
<script src="js/require-config-index.js?v=1.0"></script>
<script src="js/app.js?v=1.0"></script>
<script>
requirejs(['common', 'config'], function(com, con) {
//检测升级
com.update();
//如果已经登陆,则直接进入首页
var user = com.account.getUser();
if(user)
{
$('#carCode').val(user.vehCode);
$('#mobile').val(user.driverMobile);
}
//双击退出
com.backExit();
$('button[type="submit"]').click(function() {
var carCode = $('#carCode').val();
var mobile = $('#mobile').val();
var password = $('#password').val();
if(carCode == "") {
com.msg('请输入车牌号')
return false;
}
if(mobile == "") {
com.msg('请输入手机号')
return false;
}
if(password == "") {
com.msg('请输入密码')
return false;
}
com.ajax('get', con.urlCONFIG.get_login, {
'carCode': carCode,
'mobile': mobile,
'password': password
}, function(jsonStr) {
if(jsonStr) {
com.dataCom.set('datauser',JSON.stringify(jsonStr));
com.dataCom.set('datalogin','1');
com.open('index.html');
} else {
com.msg('登录信息错误', 0);
}
}, null, this);
return false;
})
});
</script>
细心的群众可能发现,为何没有对mui.js引用,是的,为了代码更加简洁,编码更加方便,本人将jquery和mui都压缩到了requirejs里。因为requirejs引用js都是异步的,很多童鞋在比如在使用$的时候,jquery还没加载进来,就报错了,所以本人这么做有2个好处:1,减少了文件请求数;2,全局注册了$和mui。
JS中我们多次看到com和con,com和con就是本人封装好的common.js和config.js。
common.js:主要是公共函数封装,比如系统升级,弹层,数据的存取,字符、数据处理等。
config.js:主要是封装一些静态变量。
这一节就讲到这,下节我们会详细讲解封装的关键js:common和config还有app.js,这3个脚本基本在任何APP里都可以共用,使我们开发的关键。
如上是界面,UI自己弄去,
【HTML结构代码】-login.html
当我们点击登录的时候需要验证,要实现以下效果:
这个弹层使用的是layer插件,下面我们来上JS代码:
<script src="js/libs/require.js?v=1.0"></script>
<script src="js/require-config-index.js?v=1.0"></script>
<script src="js/app.js?v=1.0"></script>
<script>
requirejs(['common', 'config'], function(com, con) {
//检测升级
com.update();
//如果已经登陆,则直接进入首页
var user = com.account.getUser();
if(user)
{
$('#carCode').val(user.vehCode);
$('#mobile').val(user.driverMobile);
}
//双击退出
com.backExit();
$('button[type="submit"]').click(function() {
var carCode = $('#carCode').val();
var mobile = $('#mobile').val();
var password = $('#password').val();
if(carCode == "") {
com.msg('请输入车牌号')
return false;
}
if(mobile == "") {
com.msg('请输入手机号')
return false;
}
if(password == "") {
com.msg('请输入密码')
return false;
}
com.ajax('get', con.urlCONFIG.get_login, {
'carCode': carCode,
'mobile': mobile,
'password': password
}, function(jsonStr) {
if(jsonStr) {
com.dataCom.set('datauser',JSON.stringify(jsonStr));
com.dataCom.set('datalogin','1');
com.open('index.html');
} else {
com.msg('登录信息错误', 0);
}
}, null, this);
return false;
})
});
</script>
细心的群众可能发现,为何没有对mui.js引用,是的,为了代码更加简洁,编码更加方便,本人将jquery和mui都压缩到了requirejs里。因为requirejs引用js都是异步的,很多童鞋在比如在使用$的时候,jquery还没加载进来,就报错了,所以本人这么做有2个好处:1,减少了文件请求数;2,全局注册了$和mui。
JS中我们多次看到com和con,com和con就是本人封装好的common.js和config.js。
common.js:主要是公共函数封装,比如系统升级,弹层,数据的存取,字符、数据处理等。
config.js:主要是封装一些静态变量。
这一节就讲到这,下节我们会详细讲解封装的关键js:common和config还有app.js,这3个脚本基本在任何APP里都可以共用,使我们开发的关键。
收起阅读 »
HBuilder+MUI开发APP实战-司机签收系统(前言)
废话不多说,故事不多讲,直接上干货。
本人之前已经有3个DCloud开发APP的经验了,这次刚好有一个小的项目需要快速开发,所以边开发边写了这个教程供大家做开发参考。
本次我们还是按照Dcloud的套路来,但是我们需要用到requireJS来模块化封装下,这样模块化的好处后续我们可以体验到。
基本上使用到的JS会有:mui+Jquery+requireJS+layer+underscore
- requirejs用来模块化封装
- layer用来做弹窗
- underscore用来处理数据
最终目录结构如下:
系统运行起来后的界面:
下一章,我们开始编写代码,初步完成我们这个系统。
废话不多说,故事不多讲,直接上干货。
本人之前已经有3个DCloud开发APP的经验了,这次刚好有一个小的项目需要快速开发,所以边开发边写了这个教程供大家做开发参考。
本次我们还是按照Dcloud的套路来,但是我们需要用到requireJS来模块化封装下,这样模块化的好处后续我们可以体验到。
基本上使用到的JS会有:mui+Jquery+requireJS+layer+underscore
- requirejs用来模块化封装
- layer用来做弹窗
- underscore用来处理数据
最终目录结构如下:
系统运行起来后的界面:
下一章,我们开始编写代码,初步完成我们这个系统。
收起阅读 »
HBuilder开发者资源平台
hCoder资源平台,有很多关于H5+和mui的视频资源,还有个类似mui的前端框架hui.
资源平台链接地址:http://www.hcoder.net/course
hCoder资源平台,有很多关于H5+和mui的视频资源,还有个类似mui的前端框架hui.
资源平台链接地址:http://www.hcoder.net/course

刚接触H5+做了个例子希望大家指点一下哪里该优化
这个是入口,首页分header(分类,可滑动),footer,内容部分通过子页面加载
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css" />
</head>
<body>
<header>
<div id="slider" class="mui-slider mui-fullscreen">
<div id="abc" class="mui-scroll-wrapper mui-slider-indicator mui-segmented-control mui-segmented-control-inverted">
<div class="mui-scroll" id="splitH">
<a class="mui-control-item mui-active" data-index="0">
头条
</a>
<a class="mui-control-item" data-index="1">
娱乐
</a>
<a class="mui-control-item" data-index="2">
体育
</a>
<a class="mui-control-item" data-index="3">
财经
</a>
<a class="mui-control-item" data-index="4">
科技
</a>
<a class="mui-control-item" data-index="5">
军事
</a>
<a class="mui-control-item" data-index="6">
NBA
</a>
<a class="mui-control-item" data-index="7">
国际足球
</a>
<a class="mui-control-item" data-index="8">
中国篮球
</a>
</div>
</div>
</div>
</header>
<div class="mui-content" style="padding-bottom:50px;padding-top:50px;">
</div>
<footer>
<nav class="mui-bar mui-bar-tab">
<a href="main.html" index=0 class="mui-tab-item mui-active" data-index="0">
<span class="mui-icon mui-icon-home"></span>
<span class="mui-tab-label">首页</span>
</a>
<a href="m.html" index=1 class="mui-tab-item" data-index="1">
<span class="mui-icon mui-icon mui-icon-bars"></span>
<span class="mui-tab-label">新闻</span>
</a>
<a class="mui-tab-item" data-index="2">
<span class="mui-icon mui-icon mui-icon-videocam"></span>
<span class="mui-tab-label">视频</span>
</a>
<a href="login.html" class="mui-tab-item" data-index="3">
<span class="mui-icon mui-icon mui-icon-contact"></span>
<span class="mui-tab-label">我</span>
</a>
</nav>
</footer>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script src="js/common.js" type="text/javascript" charset="utf-8"></script>
<script src="js/d1.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
d1.js
mui.init({//初始化加载列表页,d2.html
subpages: [main.h.page('d2', {
top: '44px',
bottom: '50px'
})]
});
mui.plusReady(function() {
indexPage.init();
});
var indexPage = {
tabIndex:0,
init:function(){
var self = this;
mui("#splitH").on('tap', 'a', function() {//header分类点击事件
var index = this.getAttribute("data-index");
if(index==self.tabIndex) return;//重复点击,跳过
self.tabIndex = index;
var embed = plus.webview.getWebviewById('d2');
embed.evalJS("parentParams("+index+");");//调用子页面方法,加载相应列表
});
},
go:function(i){//子类左滑/右滑改变分类的颜色
mui('#abc').scroll().scrollTo(-50*i,0,100);//100毫秒滚动
mui('#splitH a')[this.tabIndex].classList.remove('mui-active');
mui('#splitH a')[i].classList.add('mui-active');
this.tabIndex = i;
}
};
d2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello MUI</title>
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet" href="css/mui.css">
<style>
html,
body {
background-color: #efeff4;
}
.mui-pull-top-tips {
z-index: 999999;
position: absolute;
top: -20px;
left: 50%;
margin-left: -25px;
width: 40px;
height: 40px;
border-radius: 100%;
}
.mui-pull-top-wrapper {
width: 42px;
height: 42px;
display: block;
text-align: center;
background-color: #efeff4;
border: 1px solid #ddd;
border-radius: 25px;
background-clip: padding-box;
box-shadow: 0 4px 10px #bbb;
overflow: hidden;
}
.mui-pull-top-tips.mui-transitioning {
-webkit-transition-duration: 200ms;
transition-duration: 200ms;
}
.mui-pull-top-tips .mui-pull-loading {
margin: 0;
}
.mui-pull-top-wrapper .mui-icon,
.mui-pull-top-wrapper .mui-spinner {
margin-top: 7px;
}
.mui-pull-bottom-tips {
text-align: center;
background-color: #efeff4;
font-size: 15px;
line-height: 40px;
color: #777;
}
.mui-pull-top-canvas {
overflow: hidden;
background-color: #fafafa;
border-radius: 40px;
box-shadow: 0 4px 10px #bbb;
width: 40px;
height: 40px;
margin: 0 auto;
}
.mui-pull-top-canvas canvas {
width: 40px;
}
.ud,
.ud p {
padding: 5px;
color: #000;
}
.ud a {
width: 33.3333%;
float: left;
}
.ud img {
width: 100%;
}
#uda {
margin: 0;
}
#pp div {
border: 0;
}
</style>
</head>
<body>
<div class="mui-content">
<div id="scroll1" class="mui-scroll-wrapper">
<div class="mui-scroll">
<ul class="mui-table-view">
</ul>
</div>
</div>
</div>
</body>
<script src="js/mui.js"></script>
<script src="js/mui.pullToRefresh.js"></script>
<script src="js/mui.pullToRefresh.material.js"></script>
<script>
mui.init();
mui.plusReady(function() {
detail.init();
});
var detail = {
tabIndex: 0,
count: 3,
pullObj: '',
mainPage: '',
titleName: ['头条', '娱乐', '体育', '财经', '科技', '军事', 'NBA', '国际足球','中国篮球'],
init: function() {
this.mainPage = plus.webview.getLaunchWebview();
this.setScroll();
this.pullDown();
this.initGallery();
},
setTabIndex: function(index) {
this.tabIndex = index;
},
setScroll: function() {
var self = this;
mui('.mui-scroll-wrapper').scroll({
bounce: false,
indicators: false, //是否显示滚动条
deceleration: 0.003 //滚动效果越大越灵敏
});
//循环初始化所有下拉刷新,上拉加载。
self.pullObj = mui('.mui-scroll').pullToRefresh({
down: {
callback: function() {
var _self = this;
setTimeout(function() {
var ul = _self.element.querySelector('.mui-table-view');
ul.innerHTML = "";
ul.appendChild(self.getData());
//ul.removeChild(ul.firstChild).insertBefore(self.getData(), ul.firstChild);
_self.endPullDownToRefresh();
}, 1000);
}
},
up: {
callback: function() {
var _self = this;
setTimeout(function() {
var ul = _self.element.querySelector('.mui-table-view');
ul.appendChild(self.getData());
_self.endPullUpToRefresh();
}, 1000);
}
}
});
},
pullDown: function() {
this.pullObj.pullDownLoading();
},
getData: function() {//获取数据
console.log('开始加载...');
var fragment = document.createDocumentFragment();
var li;
for(var i = 0; i < this.count; i++) {
li = document.createElement('li');
li.className = 'mui-table-view-cell';
li.innerHTML = this.titleName[this.tabIndex] + '选项卡子项';
fragment.appendChild(li);
}
return fragment;
}
};
document.addEventListener("swipeleft", function() {
if(detail.tabIndex == detail.titleName.length - 1) return;
detail.tabIndex += 1;
detail.pullDown();
detail.mainPage.evalJS("indexPage.go(" + detail.tabIndex + ");");
console.log("你向左滑动了");
});
document.addEventListener("swiperight", function() {
if(detail.tabIndex == 0) return;
detail.tabIndex += -1;
detail.pullDown();
detail.mainPage.evalJS("indexPage.go(" + detail.tabIndex + ");");
console.log("你向右滑动了");
});
function parentParams(i) {//供父类调用
detail.setTabIndex(i);
detail.pullDown();
}
</script>
</html>
哪里有不足的地方希望大家指出
这个是入口,首页分header(分类,可滑动),footer,内容部分通过子页面加载
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css" />
</head>
<body>
<header>
<div id="slider" class="mui-slider mui-fullscreen">
<div id="abc" class="mui-scroll-wrapper mui-slider-indicator mui-segmented-control mui-segmented-control-inverted">
<div class="mui-scroll" id="splitH">
<a class="mui-control-item mui-active" data-index="0">
头条
</a>
<a class="mui-control-item" data-index="1">
娱乐
</a>
<a class="mui-control-item" data-index="2">
体育
</a>
<a class="mui-control-item" data-index="3">
财经
</a>
<a class="mui-control-item" data-index="4">
科技
</a>
<a class="mui-control-item" data-index="5">
军事
</a>
<a class="mui-control-item" data-index="6">
NBA
</a>
<a class="mui-control-item" data-index="7">
国际足球
</a>
<a class="mui-control-item" data-index="8">
中国篮球
</a>
</div>
</div>
</div>
</header>
<div class="mui-content" style="padding-bottom:50px;padding-top:50px;">
</div>
<footer>
<nav class="mui-bar mui-bar-tab">
<a href="main.html" index=0 class="mui-tab-item mui-active" data-index="0">
<span class="mui-icon mui-icon-home"></span>
<span class="mui-tab-label">首页</span>
</a>
<a href="m.html" index=1 class="mui-tab-item" data-index="1">
<span class="mui-icon mui-icon mui-icon-bars"></span>
<span class="mui-tab-label">新闻</span>
</a>
<a class="mui-tab-item" data-index="2">
<span class="mui-icon mui-icon mui-icon-videocam"></span>
<span class="mui-tab-label">视频</span>
</a>
<a href="login.html" class="mui-tab-item" data-index="3">
<span class="mui-icon mui-icon mui-icon-contact"></span>
<span class="mui-tab-label">我</span>
</a>
</nav>
</footer>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script src="js/common.js" type="text/javascript" charset="utf-8"></script>
<script src="js/d1.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
d1.js
mui.init({//初始化加载列表页,d2.html
subpages: [main.h.page('d2', {
top: '44px',
bottom: '50px'
})]
});
mui.plusReady(function() {
indexPage.init();
});
var indexPage = {
tabIndex:0,
init:function(){
var self = this;
mui("#splitH").on('tap', 'a', function() {//header分类点击事件
var index = this.getAttribute("data-index");
if(index==self.tabIndex) return;//重复点击,跳过
self.tabIndex = index;
var embed = plus.webview.getWebviewById('d2');
embed.evalJS("parentParams("+index+");");//调用子页面方法,加载相应列表
});
},
go:function(i){//子类左滑/右滑改变分类的颜色
mui('#abc').scroll().scrollTo(-50*i,0,100);//100毫秒滚动
mui('#splitH a')[this.tabIndex].classList.remove('mui-active');
mui('#splitH a')[i].classList.add('mui-active');
this.tabIndex = i;
}
};
d2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello MUI</title>
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet" href="css/mui.css">
<style>
html,
body {
background-color: #efeff4;
}
.mui-pull-top-tips {
z-index: 999999;
position: absolute;
top: -20px;
left: 50%;
margin-left: -25px;
width: 40px;
height: 40px;
border-radius: 100%;
}
.mui-pull-top-wrapper {
width: 42px;
height: 42px;
display: block;
text-align: center;
background-color: #efeff4;
border: 1px solid #ddd;
border-radius: 25px;
background-clip: padding-box;
box-shadow: 0 4px 10px #bbb;
overflow: hidden;
}
.mui-pull-top-tips.mui-transitioning {
-webkit-transition-duration: 200ms;
transition-duration: 200ms;
}
.mui-pull-top-tips .mui-pull-loading {
margin: 0;
}
.mui-pull-top-wrapper .mui-icon,
.mui-pull-top-wrapper .mui-spinner {
margin-top: 7px;
}
.mui-pull-bottom-tips {
text-align: center;
background-color: #efeff4;
font-size: 15px;
line-height: 40px;
color: #777;
}
.mui-pull-top-canvas {
overflow: hidden;
background-color: #fafafa;
border-radius: 40px;
box-shadow: 0 4px 10px #bbb;
width: 40px;
height: 40px;
margin: 0 auto;
}
.mui-pull-top-canvas canvas {
width: 40px;
}
.ud,
.ud p {
padding: 5px;
color: #000;
}
.ud a {
width: 33.3333%;
float: left;
}
.ud img {
width: 100%;
}
#uda {
margin: 0;
}
#pp div {
border: 0;
}
</style>
</head>
<body>
<div class="mui-content">
<div id="scroll1" class="mui-scroll-wrapper">
<div class="mui-scroll">
<ul class="mui-table-view">
</ul>
</div>
</div>
</div>
</body>
<script src="js/mui.js"></script>
<script src="js/mui.pullToRefresh.js"></script>
<script src="js/mui.pullToRefresh.material.js"></script>
<script>
mui.init();
mui.plusReady(function() {
detail.init();
});
var detail = {
tabIndex: 0,
count: 3,
pullObj: '',
mainPage: '',
titleName: ['头条', '娱乐', '体育', '财经', '科技', '军事', 'NBA', '国际足球','中国篮球'],
init: function() {
this.mainPage = plus.webview.getLaunchWebview();
this.setScroll();
this.pullDown();
this.initGallery();
},
setTabIndex: function(index) {
this.tabIndex = index;
},
setScroll: function() {
var self = this;
mui('.mui-scroll-wrapper').scroll({
bounce: false,
indicators: false, //是否显示滚动条
deceleration: 0.003 //滚动效果越大越灵敏
});
//循环初始化所有下拉刷新,上拉加载。
self.pullObj = mui('.mui-scroll').pullToRefresh({
down: {
callback: function() {
var _self = this;
setTimeout(function() {
var ul = _self.element.querySelector('.mui-table-view');
ul.innerHTML = "";
ul.appendChild(self.getData());
//ul.removeChild(ul.firstChild).insertBefore(self.getData(), ul.firstChild);
_self.endPullDownToRefresh();
}, 1000);
}
},
up: {
callback: function() {
var _self = this;
setTimeout(function() {
var ul = _self.element.querySelector('.mui-table-view');
ul.appendChild(self.getData());
_self.endPullUpToRefresh();
}, 1000);
}
}
});
},
pullDown: function() {
this.pullObj.pullDownLoading();
},
getData: function() {//获取数据
console.log('开始加载...');
var fragment = document.createDocumentFragment();
var li;
for(var i = 0; i < this.count; i++) {
li = document.createElement('li');
li.className = 'mui-table-view-cell';
li.innerHTML = this.titleName[this.tabIndex] + '选项卡子项';
fragment.appendChild(li);
}
return fragment;
}
};
document.addEventListener("swipeleft", function() {
if(detail.tabIndex == detail.titleName.length - 1) return;
detail.tabIndex += 1;
detail.pullDown();
detail.mainPage.evalJS("indexPage.go(" + detail.tabIndex + ");");
console.log("你向左滑动了");
});
document.addEventListener("swiperight", function() {
if(detail.tabIndex == 0) return;
detail.tabIndex += -1;
detail.pullDown();
detail.mainPage.evalJS("indexPage.go(" + detail.tabIndex + ");");
console.log("你向右滑动了");
});
function parentParams(i) {//供父类调用
detail.setTabIndex(i);
detail.pullDown();
}
</script>
</html>
哪里有不足的地方希望大家指出
收起阅读 »
mui plusReady 不触发问题。
添加。
<script src="html5plus://ready"></script>
添加。
<script src="html5plus://ready"></script>

看到网上介绍的HBuilder的介绍,下载下来尝试. 唉。
看到网上介绍的HBuilder的介绍,下载下来尝试, 装上去试下。
-
绿色版本,很不错啊。
安装上去,运行,界面很简介也不错。
提示很贴心,不必webStorm 差。 -
看一看内存,晕死了都。 700M. 只打开了一个文件。
占用内存,是当时放弃webStrom的主要原因。
唉,都是Eclipse害的。
果断放弃HBuilder, 还是用我的sublime吧。 -
sublime内存占用没超过 100M, 一般稳定在 60M左右,速度又快。
现在是,只要看到 Eclipse 就不敢用啊!
开Eclipse之类的,编译其它程序代码,立马报告 内存不足。公司系统加密,只能用XP, 上不了大内存啊.
看到网上介绍的HBuilder的介绍,下载下来尝试, 装上去试下。
-
绿色版本,很不错啊。
安装上去,运行,界面很简介也不错。
提示很贴心,不必webStorm 差。 -
看一看内存,晕死了都。 700M. 只打开了一个文件。
占用内存,是当时放弃webStrom的主要原因。
唉,都是Eclipse害的。
果断放弃HBuilder, 还是用我的sublime吧。 -
sublime内存占用没超过 100M, 一般稳定在 60M左右,速度又快。
现在是,只要看到 Eclipse 就不敢用啊!
开Eclipse之类的,编译其它程序代码,立马报告 内存不足。公司系统加密,只能用XP, 上不了大内存啊.

MUI仿咸鱼底部tabbar圆形发布按钮样式
<nav class="mui-bar mui-bar-tab footer-nav">
<a class="mui-tab-item mui-active" href="#tabbar">
<span class="mui-icon icon"></span>
<span class="mui-tab-label">首页</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-chat">
<span class="mui-icon icon"></span>
<span class="mui-tab-label">分类</span>
</a>
<a class="mui-tab-item tab-item-center" href="#tabbar-with-contact">
<span class="mui-icon plus"><span class="icon"></span></span>
<span class="mui-tab-label tab-label">发布</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-contact">
<span class="mui-icon icon"></span>
<span class="mui-tab-label">消息</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-map">
<span class="mui-icon icon"></span>
<span class="mui-tab-label">我的</span>
</a>
</nav>
.footer-nav .tab-item-center{
position:relative;
overflow:visible;
text-align:center;
}
.footer-nav .tab-item-center .plus{
display:inline-block;
width:100%;
color:#fff;
position:absolute;
left:0;
top:-25px;
}
.footer-nav .tab-item-center .plus .icon{
width:auto;
height:auto;
padding:10px;
background:#1ba9ba;
border-radius:50%;
border:3px solid #fff;
box-shadow: 0 -2px 3px rgba(100,100,100,.4);
}
.footer-nav .tab-item-center .tab-label{
margin-top:25px;
}
<nav class="mui-bar mui-bar-tab footer-nav">
<a class="mui-tab-item mui-active" href="#tabbar">
<span class="mui-icon icon"></span>
<span class="mui-tab-label">首页</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-chat">
<span class="mui-icon icon"></span>
<span class="mui-tab-label">分类</span>
</a>
<a class="mui-tab-item tab-item-center" href="#tabbar-with-contact">
<span class="mui-icon plus"><span class="icon"></span></span>
<span class="mui-tab-label tab-label">发布</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-contact">
<span class="mui-icon icon"></span>
<span class="mui-tab-label">消息</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-map">
<span class="mui-icon icon"></span>
<span class="mui-tab-label">我的</span>
</a>
</nav>
.footer-nav .tab-item-center{
position:relative;
overflow:visible;
text-align:center;
}
.footer-nav .tab-item-center .plus{
display:inline-block;
width:100%;
color:#fff;
position:absolute;
left:0;
top:-25px;
}
.footer-nav .tab-item-center .plus .icon{
width:auto;
height:auto;
padding:10px;
background:#1ba9ba;
border-radius:50%;
border:3px solid #fff;
box-shadow: 0 -2px 3px rgba(100,100,100,.4);
}
.footer-nav .tab-item-center .tab-label{
margin-top:25px;
}

原生图片剪裁,利用cropper.js插件和5+的图片压缩实现,可直接输出base64或保存本地图片。
如题。理论上完全兼容android和ios。
cropper.js应该很多人用过,是web端图片剪裁的利器。可以对图片进行base64编码,方便上传后台。
5+中的api。plus.zip.compressImage接口,压缩图片保存本地的效率很高,但是没有图形化界面。
于是,我就想 ,把这两个结合起来,做出图形化剪裁的功能来,实现本地存储和base64输出。
结果发现,天作之合,太简单了。
我想说,也许是目前最好的剪裁方案了。(不知道有没有别人提出过这个方法,我先小得意一下)
本人非专业前端,js弱鸡,不会做插件化开发。只能流水式写方法了。
不废话,直接页面代码,我把每一步都写得非常详细,再菜的人应该都能看懂了(而且确实非常简单)。
召唤这个页面的页面代码我就不放了。相信没有那么菜的鸡。
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="css/cropper.min.css" />
<link rel="stylesheet" href="css/mui.min.css" />
<style>
#redo{
position: fixed;
bottom: 20px;
left :20px;
font-size: 30px;
color: #FFFFFF;
}
#undo{
position: fixed;
bottom: 20px;
right :20px;
font-size: 30px;
color: #FFFFFF;
}
html{
background: #000000;
}
.holdcenter{
background-color: #007AFF;
order:auto;
flex: 0 1 auto;
-webkit-flex: 0 1 auto;
align-self: auto;
overflow: hidden;
}
.outer-box{
display: flex;
display: -webkit-flex;
/*height: 100%;*/
/*border: 1px solid #000000;*/
background-color: #000000;
flex-direction: row;
flex-flow: row wrap;
-webkit-flex-flow: row wrap;
/*justify-content: flex-start;*/
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<header class="mui-bar mui-bar-transparent">
<!--<h1 id="patientId" class="mui-title">截取头像</h1>-->
<a id="save" class="mui-icon mui-icon-checkmarkempty mui-pull-right" style="font-size: 3rem;color: #FFFFFF;"></a>
</header>
<div style="" class="outer-box mui-fullscreen">
<div style="" class="holdcenter">
<img style="width: 100%;" id="image" src="images/cbd.jpg">
</div>
<a id="redo" class=" mui-pull-left"><span class="mui-icon mui-icon-redo"></span></a>
<a id="undo" class=" mui-pull-right"><span class="mui-icon mui-icon-undo"></span></a>
</div>
<script type="text/javascript" src="js/mui.min.js" ></script>
<script type="text/javascript" src="js/cropper.min.js" ></script>
<script>
/**
* 本功能灵感来源于 crooper.js。github地址请看js文件
* 利用cropper.js进行图片剪裁。支持旋转。
* 可以直接获取剪裁后的base64。
* 也可以利用cropper的方法,可以获取一系列参数,借用5+API,
* 可以直接保存本地图片,效率非常高。
* 有对cropper.js熟悉的可以进一步研究修改,提供更多可用功能
* 理论上完全兼容android和ios系统。
*/
mui.init({
hardwareAccelerated:true,
});
var image = document.getElementById('image');//获取图片元素
var cropper = null;
var resImg = null; //剪切后图片base64编码资源
//初始化控件的方法
function initCropper(){
cropper = new Cropper(image, {
//aspectRatio: 1/1,16/9,4/3,2/3,NaN(自定义)
aspectRatio: NaN, //不锁定 "剪裁框" 比例(自定义)
dragMode:'crop',
rotatable:true, //是否允许旋转
minCropBoxWidth:0,
minCropBoxHeight:0,
minCanvasWidth:0,
minCanvasHeight:0,
minContainerWidth:200,
minContainerHeight:200,
cropBoxResizable: true, //是否允许 调整 剪裁框 的大小
crop: function(data) {
}
});
}// initCropper end
//保存按钮监听
document.getElementById("save").addEventListener("tap",function(){
//传入true,获取base64字串,不传或者传入false保存本地文件,获取保存路径。
getImg();
});
//右旋转按钮监听
document.getElementById("redo").addEventListener("tap",function(){
cropper.rotate(90);
//这里的旋转角度90数据可自行定义,比方说:15,30,45。支持每次旋转1度
//但是考虑到5+api的旋转只支持90一个单位,所以设定每次旋转90度。
//有兴趣可以去cropper的范列网站https://fengyuanchen.github.io/cropperjs/自己定义旋转角度试试。
//但是227行的5+api旋转参数如何对应需要动脑筋。90度旋转对用户来说应该足够了。
});
//左旋转按钮监听
document.getElementById("undo").addEventListener("tap",function(){
cropper.rotate(-90);
});
//在选择或者拍摄完成后打开此裁剪页面并把图片路径传递到此页面
mui.plusReady(function(){
//imgSrc是webview的扩展参数传过来的图片路径,用io方法转换成本地绝对路径
image.src = plus.io.convertLocalFileSystemURL(plus.webview.currentWebview().imgSrc);
//image.src = "images/muwu.jpg";
initCropper(); //初始化cropper控件
});//plusReady end
/**
* 获取图片的方法
* @param {Boolean} flag
*/
function getImg(flag){
//如果flag传入true,生成base64资源
if(flag){
resImg = cropper.getCroppedCanvas({
width: 300,
height: 300
}).toDataURL();
//纯cropper.js的功能
//resImg 就是base64字符串,可以返回给需要的页面或者上传
console.log(resImg);
//like is “data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAFkCAYAAACadgZ0AAAgAElEQVR4XtS9”
}else{
//否则生成本地图片
//cropper提供的方法,可以获取剪裁范围内的图片的信息,这一个方法就够了。下面的其他方法仅供参考
var cropeddata = cropper.getData();
//console.log(JSON.stringify(cropeddata));
/* 像这样
* {"x":793.6, /左边距,像素,单位px
* "y":297.59999999999997, //上边距
* "width":2380.7999999999997, //选中的部分图片的宽度,px,Number
* "height":2380.7999999999997, //选中部分图片的高度,px,Number
* "rotate":0, //旋转度数,Number
* "scaleX":1, //x轴缩放比例Number
* "scaleY":1} //y轴缩放比例Number
*/
//原始图片信息
var sourceImgDate = cropper.getImageData();
//console.log(JSON.stringify(sourceImgDate));
/* 像这样
* {"naturalWidth":3968, //原始图片宽度,px,像素
"naturalHeight":2976, //原始图片高度,px
"aspectRatio":1.3333333333333333, //纵横比,高宽比
"width":360, //在页面上的显示尺寸
"height":270,
"left":0,
"top":0}
*/
//获取容器(img元素)的信息
var containerData = cropper.getContainerData();
//console.log(JSON.stringify(containerData));
/* 像这样
* {"width":360,"height":276}
*/
//剪裁框的信息
var cropData = cropper.getCropBoxData();
//console.log(JSON.stringify(cropData));
/* 像这样
* {"left":72,"top":30,
* "width":216,
* "height":216}
*/
//获取canvers的信息
var canversData = cropper.getCanvasData();
//console.log(JSON.stringify(canversData));
/* 像这样
* {"left":0,"top":3,
* "width":360,
* "height":270,
* "naturalWidth":3968,
* "naturalHeight":2976}
*/
//接下来使用H5+的图片压缩压缩转换API来完成剪裁和压缩
//http://www.html5plus.org/doc/zh_cn/zip.html
//准备工作
//JSON对象,图片裁剪区域的参数
//注意:4个属性我们都已经通过cropper的getData()方法直接获取到了值,是不是很简单呢
//直接组织数据吧
var ClipImageOptions = {
top:cropeddata.y , //(String 类型 )图片裁剪区域与原图片上边界的偏移距离
//支持像素值(如"10px")、百分比(如"10%");默认值为"0px"。 注意:如果top值超出原图片高度,则图片裁剪失败。
left:cropeddata.x , //(Stirng 类型 )图片裁剪区域与原图片左边界的偏移距离
//支持像素值(如"10px")、百分比(如"10%");默认值为"0px"。 注意:如果left值超出原图片宽度,则图片裁剪失败。
width:cropeddata.width, //(String 类型 )图片裁剪区域的宽度
//支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即从left位置到图片右边界的宽度);默认值为"auto"。 注意:如果left值加width值超出原图片宽度,则使用"auto"值进行裁剪。
height:cropeddata.height //(String 类型 )图片裁剪区域的高度
//支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即从top位置到图片下边界的高度);默认值为"auto"。 注意:如果top值加height值超出原图片高度,则使用"auto"值进行裁剪。
}
//处理旋转角度,因为5+api不接受负值
var rotate = 0;//默认值
if(cropeddata.rotate >= 0){
rotate = cropeddata.rotate;
}else{
switch(cropeddata.rotate){
case -90:
rotate = 270;
break;
case -180:
rotate = 180;
break;
case -270:
rotate = 90;
break;
default:
rotate = 0;
}
}
//获取图片格式
var format = image.src.substring(image.src.lastIndexOf(".")+1);
//console.log(format);
//根据日期生成图片名称
var d = new Date();
var picName = d.getFullYear()+""+(d.getMonth()+1)+""+d.getDate()+""+d.getHours()+""+d.getMinutes()+""+d.getSeconds();
var fullname = picName+"."+format;
console.log(fullname); //完整图片名称
//JSON对象,配置图片压缩转换的参数
var imgOption = {src:image.src, //原始图片路径
dst: "../doc/"+fullname ,//(String 类型 )压缩转换目标图片的路径,这里保存到 私有目录doc
//如“/sdcard/Android/data/io.dcloud.HBuilder/.HBuilder/apps/HBuilder/doc”。
overwrite:true, //覆盖生成新文件
format: '',//(String 类型 )压缩转换后的图片格式,支持"jpg"、"png",如果未指定则使用源图片的格式。
quality:50,//(Number 类型 )压缩图片的质量,可以自己调整
//取值范围为1-100,1表示使用最低的图片质量(转换后的图片文件最小)、100表示使用最高的图片质量(转换后的图片文件最大); 默认值为50。
width:'auto', //(String 类型 )缩放图片的宽度
//支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据height与源图高的缩放比例计算,若未设置height则使用源图高度); 默认值为"auto"。 注意:若设置了width属性值不合法(如"0px"),则不对图片进行缩放操作。
height:'auto', //(String 类型 )缩放图片的高度
//支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据width与源图宽的缩放比例计算,若未设置width则使用源图高度); 默认值为"auto"。 注意:若设置了height属性值不合法(如"0px"),则不对图片进行缩放操作。
rotate:rotate, //(Number 类型 )旋转图片的角度
//支持值:90-表示旋转90度;180-表示旋转180度;270-表示旋转270度。 注意:若设置rotate属性值不合法,则不对图片进行旋转操作。
clip: ClipImageOptions //(ClipImageOptions 类型(json对象) )裁剪图片的区域
//值参考ClipImageOptions定义,若设置clip属性值不合法,则不对图片进行裁剪操作。
}
//开始剪裁
plus.zip.compressImage(
imgOption, //JSON对象,配置图片压缩转换的参数
function(){
//console.log(imgOption.dst);
//console.log("压缩成功");
mui.toast("图片已保存到:"+imgOption.dst,{duration:"long"});
//如果想要绝对路径
var path=plus.io.convertLocalFileSystemURL(imgOption.dst);
console.log(path);
//后续处理
//将imgOption.dst或者path传递给父页面,用来显示或者上传后台,请自行决定
//mui.fire(plus.webview.currentWebview().opener(),"avart",{img:imgOption.dst});
},function(error){
console.log("压缩失败");
}
);
//如果不是存到doc目录,而是其他比较复杂的目录,比如根目录
//用下面的方法。替换plus.io.PRIVATE_DOC就可以
/*plus.io.requestFileSystem(plus.io.PRIVATE_DOC,function(fs){
var filepath = fs.root.fullPath;
//console.log(fs.root.fullPath);
var directEntery = fs.root;
//创建目录,其实这一段并不是必须的,
//plus.zip.compressImage自己会创建文件夹
//相对目录你可以在上面imgOption.dst里面直接写上相对路径"../doc"+fullname
directEntery.getDirectory(
filepath,
{create:true,exclusive:false},
function(direnter){
//如果文件夹已经存在,也会进入这里,所以就不用toast显示了
//mui.toast("创建doc文件夹成功");
},function(e){
mui.toast("创建文件夹失败:"+e.message);
mui.back();
}
);
//把目标路径更新到json对象
imgOption.dst = filepath+fullname;
//开始压缩图片
plus.zip.compressImage(imgOption,
function(){
//console.log(imgOption.dst);
//console.log("压缩成功");
mui.toast("图片已保存到:"+imgOption.dst,{duration:long});
//将imgOption.dst传递给父页面,用来显示或者上传后台
},function(error){
console.log("压缩失败");
});
}); */
}
//最后退出剪裁页面
mui.back();
}
</script>
</body>
</html>
如题。理论上完全兼容android和ios。
cropper.js应该很多人用过,是web端图片剪裁的利器。可以对图片进行base64编码,方便上传后台。
5+中的api。plus.zip.compressImage接口,压缩图片保存本地的效率很高,但是没有图形化界面。
于是,我就想 ,把这两个结合起来,做出图形化剪裁的功能来,实现本地存储和base64输出。
结果发现,天作之合,太简单了。
我想说,也许是目前最好的剪裁方案了。(不知道有没有别人提出过这个方法,我先小得意一下)
本人非专业前端,js弱鸡,不会做插件化开发。只能流水式写方法了。
不废话,直接页面代码,我把每一步都写得非常详细,再菜的人应该都能看懂了(而且确实非常简单)。
召唤这个页面的页面代码我就不放了。相信没有那么菜的鸡。
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="css/cropper.min.css" />
<link rel="stylesheet" href="css/mui.min.css" />
<style>
#redo{
position: fixed;
bottom: 20px;
left :20px;
font-size: 30px;
color: #FFFFFF;
}
#undo{
position: fixed;
bottom: 20px;
right :20px;
font-size: 30px;
color: #FFFFFF;
}
html{
background: #000000;
}
.holdcenter{
background-color: #007AFF;
order:auto;
flex: 0 1 auto;
-webkit-flex: 0 1 auto;
align-self: auto;
overflow: hidden;
}
.outer-box{
display: flex;
display: -webkit-flex;
/*height: 100%;*/
/*border: 1px solid #000000;*/
background-color: #000000;
flex-direction: row;
flex-flow: row wrap;
-webkit-flex-flow: row wrap;
/*justify-content: flex-start;*/
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<header class="mui-bar mui-bar-transparent">
<!--<h1 id="patientId" class="mui-title">截取头像</h1>-->
<a id="save" class="mui-icon mui-icon-checkmarkempty mui-pull-right" style="font-size: 3rem;color: #FFFFFF;"></a>
</header>
<div style="" class="outer-box mui-fullscreen">
<div style="" class="holdcenter">
<img style="width: 100%;" id="image" src="images/cbd.jpg">
</div>
<a id="redo" class=" mui-pull-left"><span class="mui-icon mui-icon-redo"></span></a>
<a id="undo" class=" mui-pull-right"><span class="mui-icon mui-icon-undo"></span></a>
</div>
<script type="text/javascript" src="js/mui.min.js" ></script>
<script type="text/javascript" src="js/cropper.min.js" ></script>
<script>
/**
* 本功能灵感来源于 crooper.js。github地址请看js文件
* 利用cropper.js进行图片剪裁。支持旋转。
* 可以直接获取剪裁后的base64。
* 也可以利用cropper的方法,可以获取一系列参数,借用5+API,
* 可以直接保存本地图片,效率非常高。
* 有对cropper.js熟悉的可以进一步研究修改,提供更多可用功能
* 理论上完全兼容android和ios系统。
*/
mui.init({
hardwareAccelerated:true,
});
var image = document.getElementById('image');//获取图片元素
var cropper = null;
var resImg = null; //剪切后图片base64编码资源
//初始化控件的方法
function initCropper(){
cropper = new Cropper(image, {
//aspectRatio: 1/1,16/9,4/3,2/3,NaN(自定义)
aspectRatio: NaN, //不锁定 "剪裁框" 比例(自定义)
dragMode:'crop',
rotatable:true, //是否允许旋转
minCropBoxWidth:0,
minCropBoxHeight:0,
minCanvasWidth:0,
minCanvasHeight:0,
minContainerWidth:200,
minContainerHeight:200,
cropBoxResizable: true, //是否允许 调整 剪裁框 的大小
crop: function(data) {
}
});
}// initCropper end
//保存按钮监听
document.getElementById("save").addEventListener("tap",function(){
//传入true,获取base64字串,不传或者传入false保存本地文件,获取保存路径。
getImg();
});
//右旋转按钮监听
document.getElementById("redo").addEventListener("tap",function(){
cropper.rotate(90);
//这里的旋转角度90数据可自行定义,比方说:15,30,45。支持每次旋转1度
//但是考虑到5+api的旋转只支持90一个单位,所以设定每次旋转90度。
//有兴趣可以去cropper的范列网站https://fengyuanchen.github.io/cropperjs/自己定义旋转角度试试。
//但是227行的5+api旋转参数如何对应需要动脑筋。90度旋转对用户来说应该足够了。
});
//左旋转按钮监听
document.getElementById("undo").addEventListener("tap",function(){
cropper.rotate(-90);
});
//在选择或者拍摄完成后打开此裁剪页面并把图片路径传递到此页面
mui.plusReady(function(){
//imgSrc是webview的扩展参数传过来的图片路径,用io方法转换成本地绝对路径
image.src = plus.io.convertLocalFileSystemURL(plus.webview.currentWebview().imgSrc);
//image.src = "images/muwu.jpg";
initCropper(); //初始化cropper控件
});//plusReady end
/**
* 获取图片的方法
* @param {Boolean} flag
*/
function getImg(flag){
//如果flag传入true,生成base64资源
if(flag){
resImg = cropper.getCroppedCanvas({
width: 300,
height: 300
}).toDataURL();
//纯cropper.js的功能
//resImg 就是base64字符串,可以返回给需要的页面或者上传
console.log(resImg);
//like is “data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAFkCAYAAACadgZ0AAAgAElEQVR4XtS9”
}else{
//否则生成本地图片
//cropper提供的方法,可以获取剪裁范围内的图片的信息,这一个方法就够了。下面的其他方法仅供参考
var cropeddata = cropper.getData();
//console.log(JSON.stringify(cropeddata));
/* 像这样
* {"x":793.6, /左边距,像素,单位px
* "y":297.59999999999997, //上边距
* "width":2380.7999999999997, //选中的部分图片的宽度,px,Number
* "height":2380.7999999999997, //选中部分图片的高度,px,Number
* "rotate":0, //旋转度数,Number
* "scaleX":1, //x轴缩放比例Number
* "scaleY":1} //y轴缩放比例Number
*/
//原始图片信息
var sourceImgDate = cropper.getImageData();
//console.log(JSON.stringify(sourceImgDate));
/* 像这样
* {"naturalWidth":3968, //原始图片宽度,px,像素
"naturalHeight":2976, //原始图片高度,px
"aspectRatio":1.3333333333333333, //纵横比,高宽比
"width":360, //在页面上的显示尺寸
"height":270,
"left":0,
"top":0}
*/
//获取容器(img元素)的信息
var containerData = cropper.getContainerData();
//console.log(JSON.stringify(containerData));
/* 像这样
* {"width":360,"height":276}
*/
//剪裁框的信息
var cropData = cropper.getCropBoxData();
//console.log(JSON.stringify(cropData));
/* 像这样
* {"left":72,"top":30,
* "width":216,
* "height":216}
*/
//获取canvers的信息
var canversData = cropper.getCanvasData();
//console.log(JSON.stringify(canversData));
/* 像这样
* {"left":0,"top":3,
* "width":360,
* "height":270,
* "naturalWidth":3968,
* "naturalHeight":2976}
*/
//接下来使用H5+的图片压缩压缩转换API来完成剪裁和压缩
//http://www.html5plus.org/doc/zh_cn/zip.html
//准备工作
//JSON对象,图片裁剪区域的参数
//注意:4个属性我们都已经通过cropper的getData()方法直接获取到了值,是不是很简单呢
//直接组织数据吧
var ClipImageOptions = {
top:cropeddata.y , //(String 类型 )图片裁剪区域与原图片上边界的偏移距离
//支持像素值(如"10px")、百分比(如"10%");默认值为"0px"。 注意:如果top值超出原图片高度,则图片裁剪失败。
left:cropeddata.x , //(Stirng 类型 )图片裁剪区域与原图片左边界的偏移距离
//支持像素值(如"10px")、百分比(如"10%");默认值为"0px"。 注意:如果left值超出原图片宽度,则图片裁剪失败。
width:cropeddata.width, //(String 类型 )图片裁剪区域的宽度
//支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即从left位置到图片右边界的宽度);默认值为"auto"。 注意:如果left值加width值超出原图片宽度,则使用"auto"值进行裁剪。
height:cropeddata.height //(String 类型 )图片裁剪区域的高度
//支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即从top位置到图片下边界的高度);默认值为"auto"。 注意:如果top值加height值超出原图片高度,则使用"auto"值进行裁剪。
}
//处理旋转角度,因为5+api不接受负值
var rotate = 0;//默认值
if(cropeddata.rotate >= 0){
rotate = cropeddata.rotate;
}else{
switch(cropeddata.rotate){
case -90:
rotate = 270;
break;
case -180:
rotate = 180;
break;
case -270:
rotate = 90;
break;
default:
rotate = 0;
}
}
//获取图片格式
var format = image.src.substring(image.src.lastIndexOf(".")+1);
//console.log(format);
//根据日期生成图片名称
var d = new Date();
var picName = d.getFullYear()+""+(d.getMonth()+1)+""+d.getDate()+""+d.getHours()+""+d.getMinutes()+""+d.getSeconds();
var fullname = picName+"."+format;
console.log(fullname); //完整图片名称
//JSON对象,配置图片压缩转换的参数
var imgOption = {src:image.src, //原始图片路径
dst: "../doc/"+fullname ,//(String 类型 )压缩转换目标图片的路径,这里保存到 私有目录doc
//如“/sdcard/Android/data/io.dcloud.HBuilder/.HBuilder/apps/HBuilder/doc”。
overwrite:true, //覆盖生成新文件
format: '',//(String 类型 )压缩转换后的图片格式,支持"jpg"、"png",如果未指定则使用源图片的格式。
quality:50,//(Number 类型 )压缩图片的质量,可以自己调整
//取值范围为1-100,1表示使用最低的图片质量(转换后的图片文件最小)、100表示使用最高的图片质量(转换后的图片文件最大); 默认值为50。
width:'auto', //(String 类型 )缩放图片的宽度
//支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据height与源图高的缩放比例计算,若未设置height则使用源图高度); 默认值为"auto"。 注意:若设置了width属性值不合法(如"0px"),则不对图片进行缩放操作。
height:'auto', //(String 类型 )缩放图片的高度
//支持像素值(如"100px")、百分比(如"50%")、自动计算(如"auto",即根据width与源图宽的缩放比例计算,若未设置width则使用源图高度); 默认值为"auto"。 注意:若设置了height属性值不合法(如"0px"),则不对图片进行缩放操作。
rotate:rotate, //(Number 类型 )旋转图片的角度
//支持值:90-表示旋转90度;180-表示旋转180度;270-表示旋转270度。 注意:若设置rotate属性值不合法,则不对图片进行旋转操作。
clip: ClipImageOptions //(ClipImageOptions 类型(json对象) )裁剪图片的区域
//值参考ClipImageOptions定义,若设置clip属性值不合法,则不对图片进行裁剪操作。
}
//开始剪裁
plus.zip.compressImage(
imgOption, //JSON对象,配置图片压缩转换的参数
function(){
//console.log(imgOption.dst);
//console.log("压缩成功");
mui.toast("图片已保存到:"+imgOption.dst,{duration:"long"});
//如果想要绝对路径
var path=plus.io.convertLocalFileSystemURL(imgOption.dst);
console.log(path);
//后续处理
//将imgOption.dst或者path传递给父页面,用来显示或者上传后台,请自行决定
//mui.fire(plus.webview.currentWebview().opener(),"avart",{img:imgOption.dst});
},function(error){
console.log("压缩失败");
}
);
//如果不是存到doc目录,而是其他比较复杂的目录,比如根目录
//用下面的方法。替换plus.io.PRIVATE_DOC就可以
/*plus.io.requestFileSystem(plus.io.PRIVATE_DOC,function(fs){
var filepath = fs.root.fullPath;
//console.log(fs.root.fullPath);
var directEntery = fs.root;
//创建目录,其实这一段并不是必须的,
//plus.zip.compressImage自己会创建文件夹
//相对目录你可以在上面imgOption.dst里面直接写上相对路径"../doc"+fullname
directEntery.getDirectory(
filepath,
{create:true,exclusive:false},
function(direnter){
//如果文件夹已经存在,也会进入这里,所以就不用toast显示了
//mui.toast("创建doc文件夹成功");
},function(e){
mui.toast("创建文件夹失败:"+e.message);
mui.back();
}
);
//把目标路径更新到json对象
imgOption.dst = filepath+fullname;
//开始压缩图片
plus.zip.compressImage(imgOption,
function(){
//console.log(imgOption.dst);
//console.log("压缩成功");
mui.toast("图片已保存到:"+imgOption.dst,{duration:long});
//将imgOption.dst传递给父页面,用来显示或者上传后台
},function(error){
console.log("压缩失败");
});
}); */
}
//最后退出剪裁页面
mui.back();
}
</script>
</body>
</html>
收起阅读 »

整理了一下Mdui,丰富一下Mui的样式
个人觉得Mui的样式不太美观,因此我整理另一款优秀的UI框架Mdui,和Mui可以无缝对接,话不多说,直接上github地址:
https://github.com/BysunLin/Mgui
我不是代码的创造者,我只是搬运工,不过里面也加入了一些我工作中的一些积累,期望可以对入坑的同学有一点点帮助。
tips:如果能顺手加个星那就更好啦!
个人觉得Mui的样式不太美观,因此我整理另一款优秀的UI框架Mdui,和Mui可以无缝对接,话不多说,直接上github地址:
https://github.com/BysunLin/Mgui
我不是代码的创造者,我只是搬运工,不过里面也加入了一些我工作中的一些积累,期望可以对入坑的同学有一点点帮助。
tips:如果能顺手加个星那就更好啦!

android离线打包6.0以上的权限动态申请
页面调用
// android6.0以上权限申请
function requestAndroidPremission(requestCode, func){
if(!permissionUtils){
permissionUtils = plus.android.newObject("com.build.canteen.util.PermissionUtils");
}
requestAndroidPremissionCallBack = function(requestCode){
if(typeof func == 'function'){
func(requestCode);
}
}
// 实现原生接口com.build.canteen.util.PermissionUtils.RequestWebViewPremissionListener对象
var hevent = plus.android.implements( "com.build.canteen.util.PermissionUtils$RequestWebViewPremissionListener", {
"requestPremissionCallBack":function(requestCode){
requestAndroidPremissionCallBack(requestCode)
// console.log( "Invoked Object’s name: "+name ); // 输出“Invoked Object’s name: Tester”
}
});
plus.android.invoke(permissionUtils,'setRequestWebViewPremissionListener',hevent);
plus.android.invoke(permissionUtils,"requestWebViewPremission",requestCode,'requestAndroidPremissionCallBack');
}
android原生代码片段:
// mui 动态权限申请代码 ↓↓↓↓↓↓↓↓↓↓↓↓
//底层隐藏的自定义Activity,重写onRequestPermissionsResult
private static MainActivity mActivity;
//由webview中的js实现此接口,用于权限申请完成后的回调webview的js函数
private RequestWebViewPremissionListener requestWebViewPremissionListener;
public static void setMainActivity(MainActivity aty){
mActivity = aty;
}
public void setRequestWebViewPremissionListener(RequestWebViewPremissionListener requestWebViewPremissionListener){
this.requestWebViewPremissionListener = requestWebViewPremissionListener;
}
public interface RequestWebViewPremissionListener{
void requestPremissionCallBack(int requestCode);
}
//mui调用此方法申请权限
public void requestWebViewPremission(int requestCode){
if(mActivity != null && Build.VERSION.SDK_INT >= 23){
//在Activity中的onRequestPermissionsResult方法被调用
PermissionGrant permissionGrant = new PermissionUtils.PermissionGrant() {
@Override
public void onPermissionGranted(int requestCode) {
if(requestWebViewPremissionListener!=null){
requestWebViewPremissionListener.requestPremissionCallBack(requestCode);
}
}
};
mActivity.setPermissionGrant(permissionGrant);
//安卓原生实现的权限申请
requestPermission(mActivity,requestCode,permissionGrant);
}else if(Build.VERSION.SDK_INT < 23){
if(requestWebViewPremissionListener!=null){
requestWebViewPremissionListener.requestPremissionCallBack(requestCode);
}
}else{
Log.w(TAG,"WebView requestWebViewPremission error ,安卓运行版本:"+Build.VERSION.SDK_INT);
}
}
// mui 动态权限申请代码 ↑↑↑↑↑↑↑↑
写的比较粗糙,还望大神指导!
页面调用
// android6.0以上权限申请
function requestAndroidPremission(requestCode, func){
if(!permissionUtils){
permissionUtils = plus.android.newObject("com.build.canteen.util.PermissionUtils");
}
requestAndroidPremissionCallBack = function(requestCode){
if(typeof func == 'function'){
func(requestCode);
}
}
// 实现原生接口com.build.canteen.util.PermissionUtils.RequestWebViewPremissionListener对象
var hevent = plus.android.implements( "com.build.canteen.util.PermissionUtils$RequestWebViewPremissionListener", {
"requestPremissionCallBack":function(requestCode){
requestAndroidPremissionCallBack(requestCode)
// console.log( "Invoked Object’s name: "+name ); // 输出“Invoked Object’s name: Tester”
}
});
plus.android.invoke(permissionUtils,'setRequestWebViewPremissionListener',hevent);
plus.android.invoke(permissionUtils,"requestWebViewPremission",requestCode,'requestAndroidPremissionCallBack');
}
android原生代码片段:
// mui 动态权限申请代码 ↓↓↓↓↓↓↓↓↓↓↓↓
//底层隐藏的自定义Activity,重写onRequestPermissionsResult
private static MainActivity mActivity;
//由webview中的js实现此接口,用于权限申请完成后的回调webview的js函数
private RequestWebViewPremissionListener requestWebViewPremissionListener;
public static void setMainActivity(MainActivity aty){
mActivity = aty;
}
public void setRequestWebViewPremissionListener(RequestWebViewPremissionListener requestWebViewPremissionListener){
this.requestWebViewPremissionListener = requestWebViewPremissionListener;
}
public interface RequestWebViewPremissionListener{
void requestPremissionCallBack(int requestCode);
}
//mui调用此方法申请权限
public void requestWebViewPremission(int requestCode){
if(mActivity != null && Build.VERSION.SDK_INT >= 23){
//在Activity中的onRequestPermissionsResult方法被调用
PermissionGrant permissionGrant = new PermissionUtils.PermissionGrant() {
@Override
public void onPermissionGranted(int requestCode) {
if(requestWebViewPremissionListener!=null){
requestWebViewPremissionListener.requestPremissionCallBack(requestCode);
}
}
};
mActivity.setPermissionGrant(permissionGrant);
//安卓原生实现的权限申请
requestPermission(mActivity,requestCode,permissionGrant);
}else if(Build.VERSION.SDK_INT < 23){
if(requestWebViewPremissionListener!=null){
requestWebViewPremissionListener.requestPremissionCallBack(requestCode);
}
}else{
Log.w(TAG,"WebView requestWebViewPremission error ,安卓运行版本:"+Build.VERSION.SDK_INT);
}
}
// mui 动态权限申请代码 ↑↑↑↑↑↑↑↑
写的比较粗糙,还望大神指导!
收起阅读 »