HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

给的例子也不调试完整,还要这样坑下初学者呀

你们的例子:
mui.ajax('http://server-name/login.php',{
data:{
username:'username',
password:'password'
},
dataType:'json',//服务器返回json格式数据
type:'post',//HTTP请求类型
timeout:10000,//超时时间设置为10秒;
headers:{'Content-Type':'application/json'}
success:function(data){
//服务器返回响应,根据响应结果,分析是否登录成功;
...
},
error:function(xhr,type,errorThrown){
//异常处理;
console.log(type);
}
});

继续阅读 »

你们的例子:
mui.ajax('http://server-name/login.php',{
data:{
username:'username',
password:'password'
},
dataType:'json',//服务器返回json格式数据
type:'post',//HTTP请求类型
timeout:10000,//超时时间设置为10秒;
headers:{'Content-Type':'application/json'}
success:function(data){
//服务器返回响应,根据响应结果,分析是否登录成功;
...
},
error:function(xhr,type,errorThrown){
//异常处理;
console.log(type);
}
});

收起阅读 »

怎么从零基础开始学习hbuilder+mui+h5+跨平台app开发?

HBuilder mui HelloH5 视频教程

推荐国内首推的跨平台移动APP开发专业培训机构-东翌学院是Dcloud的合作培训机构,跨平台APP开发整体课程在线直播+课程源码+全套视频,最新最全的APP开发,HB和MUI的全套视频,零基础都可以学习,更有高级进修课程,30天最快速的开发跨平台APP!
咨询报名QQ:2971611409 Tel:17090057793
欢迎有意向学习的朋友加好友咨询!谢谢Dcloud提供这么好的平台!

继续阅读 »

推荐国内首推的跨平台移动APP开发专业培训机构-东翌学院是Dcloud的合作培训机构,跨平台APP开发整体课程在线直播+课程源码+全套视频,最新最全的APP开发,HB和MUI的全套视频,零基础都可以学习,更有高级进修课程,30天最快速的开发跨平台APP!
咨询报名QQ:2971611409 Tel:17090057793
欢迎有意向学习的朋友加好友咨询!谢谢Dcloud提供这么好的平台!

收起阅读 »

【示例】App引导页的制作

示例 技术分享 Storage 引导页 mui

注意:本文为5+App的引导页制作方法,uni-app另行制作,推荐使用nvue制作,也可以参考插件市场已经封装的插件https://ext.dcloud.net.cn/plugin?id=192

启动页和引导页

首先澄清一下“启动界面”(splash)和“引导页”(guide)的概念,因为许多刚接触App开发的朋友会搞不清楚这两者分别是什么。
以Hello mui为例,第一次打开的时候是这样的:


首屏中MUI字样的图片就是splash,后面几个切换动画的界面则是guide。从第二次开始,再打开就直接进入App主界面了。
splash是每次启动都会看到的(每次打开QQ都会看到一只企鹅),但是guide是否展示是可控的(微博启动后经常会有广告页)。
ps:目前还不支持移除或动态设置splash。

示例实现

切回正题,一起来看一下类Hello mui这种引导页如何利用MUI&HTML5+进行制作。

App入口页

按照Hello mui这种启动页的逻辑:首次启动展示引导页,之后启动不再展示。那么就意味着,我们需要一个标识来确定,App是否已经启动过。
通过5+的storage模块的方法,我们可以在本地存储一个key来做为已经启动过App的标识。那么,我们在入口这里,就可以读取这个key,来决定是否展示引导页。

var launchFlag = plus.storage.getItem("launchFlag");  
if(launchFlag) {  
    mui.openWindow({  
        url: "main.html",  
        id: "main",  
        extras: {  
            mark: "index" //额外的参数,仅仅是个标识,实际开发中不用;  
        }  
    });  
} else {  
    mui.openWindow({  
        url: "guide.html",  
        id: "guide"  
    });  
}  

手动关闭splash

实际开发中,通常需要设置手动关闭splash(HBuilder7.1版本后启动界面不调用此方法超过6秒后会自动关闭),来控制App内容展示的时机。防止入口判定逻辑未结束就进行展示,造成白屏。

引导页

利用mui的slider组件,来制作一套引导信息。
如果使用图片的话,建议大家按照iPhone6 Plus的尺寸制作(其实就是往大了做),然后利用5+提供的方法计算屏幕正确的宽高,设置图片的宽高来撑满屏幕。相关文档及示例:
Screen模块管理设备屏幕信息
获取系统状态栏高度
深入理解高度。获取屏幕、webview、软键盘高度

var sh = plus.navigator.getStatusbarHeight();  
var h = plus.screen.resolutionHeight;  
var w = plus.screen.resolutionWidth;  
var imgs = document.querySelectorAll(".guide-img");  
for(var i = 0, len = imgs.length; i < len; i++) {  
    imgs[i].style.height = (h - sh) + "px";  
    imgs[i].style.width = w + "px";  
}  

在最后一个引导界面提供一个App主界面入口,也就是“开始体验”这种按钮。点击“开始体验”的同时,设置表示App已经启动过的标识。

plus.storage.setItem("launchFlag", "true");  

主界面

从第二次开始,启动应用直接进入主界面。

在主界面,额外提供了一个清除已经启动信息重启应用的功能,方便大家进行测试。

广告页

广告页其实也可以算是guide,只不过它引导的是广告信息。广告页只会在适当的时机出现,这个时机是由后端来决定的(通常情况下)。
广告页制作的逻辑:
1、入口处向后端发起请求,来得知是否存在广告;
2、若存在,则同时获取广告内容等信息;
3、广告内容按照固定的模板进行渲染,完成后关闭splash;
4、广告页持续特定的时间(通常就3-5秒)或提供按钮关闭,进入App主界面。

源码

附上源码,真机运行即可。

继续阅读 »

注意:本文为5+App的引导页制作方法,uni-app另行制作,推荐使用nvue制作,也可以参考插件市场已经封装的插件https://ext.dcloud.net.cn/plugin?id=192

启动页和引导页

首先澄清一下“启动界面”(splash)和“引导页”(guide)的概念,因为许多刚接触App开发的朋友会搞不清楚这两者分别是什么。
以Hello mui为例,第一次打开的时候是这样的:


首屏中MUI字样的图片就是splash,后面几个切换动画的界面则是guide。从第二次开始,再打开就直接进入App主界面了。
splash是每次启动都会看到的(每次打开QQ都会看到一只企鹅),但是guide是否展示是可控的(微博启动后经常会有广告页)。
ps:目前还不支持移除或动态设置splash。

示例实现

切回正题,一起来看一下类Hello mui这种引导页如何利用MUI&HTML5+进行制作。

App入口页

按照Hello mui这种启动页的逻辑:首次启动展示引导页,之后启动不再展示。那么就意味着,我们需要一个标识来确定,App是否已经启动过。
通过5+的storage模块的方法,我们可以在本地存储一个key来做为已经启动过App的标识。那么,我们在入口这里,就可以读取这个key,来决定是否展示引导页。

var launchFlag = plus.storage.getItem("launchFlag");  
if(launchFlag) {  
    mui.openWindow({  
        url: "main.html",  
        id: "main",  
        extras: {  
            mark: "index" //额外的参数,仅仅是个标识,实际开发中不用;  
        }  
    });  
} else {  
    mui.openWindow({  
        url: "guide.html",  
        id: "guide"  
    });  
}  

手动关闭splash

实际开发中,通常需要设置手动关闭splash(HBuilder7.1版本后启动界面不调用此方法超过6秒后会自动关闭),来控制App内容展示的时机。防止入口判定逻辑未结束就进行展示,造成白屏。

引导页

利用mui的slider组件,来制作一套引导信息。
如果使用图片的话,建议大家按照iPhone6 Plus的尺寸制作(其实就是往大了做),然后利用5+提供的方法计算屏幕正确的宽高,设置图片的宽高来撑满屏幕。相关文档及示例:
Screen模块管理设备屏幕信息
获取系统状态栏高度
深入理解高度。获取屏幕、webview、软键盘高度

var sh = plus.navigator.getStatusbarHeight();  
var h = plus.screen.resolutionHeight;  
var w = plus.screen.resolutionWidth;  
var imgs = document.querySelectorAll(".guide-img");  
for(var i = 0, len = imgs.length; i < len; i++) {  
    imgs[i].style.height = (h - sh) + "px";  
    imgs[i].style.width = w + "px";  
}  

在最后一个引导界面提供一个App主界面入口,也就是“开始体验”这种按钮。点击“开始体验”的同时,设置表示App已经启动过的标识。

plus.storage.setItem("launchFlag", "true");  

主界面

从第二次开始,启动应用直接进入主界面。

在主界面,额外提供了一个清除已经启动信息重启应用的功能,方便大家进行测试。

广告页

广告页其实也可以算是guide,只不过它引导的是广告信息。广告页只会在适当的时机出现,这个时机是由后端来决定的(通常情况下)。
广告页制作的逻辑:
1、入口处向后端发起请求,来得知是否存在广告;
2、若存在,则同时获取广告内容等信息;
3、广告内容按照固定的模板进行渲染,完成后关闭splash;
4、广告页持续特定的时间(通常就3-5秒)或提供按钮关闭,进入App主界面。

源码

附上源码,真机运行即可。

收起阅读 »

上传图片需要base64编码,Android和IOS完全兼容,也是弄了好久。

bitmap base64
 之前用H5的canvas来获取,但是只有Android可用,IOS不行,后来说用文件读取的形式,发现很慢,也麻烦,最后用bitmap,封装好的,直接用,两个平台都兼容。  

----分享一下^:^

function GetBase64Code(path) //path绝对路径  
{  
        var bitmap = new plus.nativeObj.Bitmap("test"); //test标识谁便取  
        // 从本地加载Bitmap图片  
        bitmap.load(path,function(){  
            var base4=bitmap.toBase64Data();  
            var datastr=base4.split(',',3)  
            if(datastr.length>1)  
            {  
               pics.push(datastr[1]);  
            }else  
            {  
               pics.push(datastr[0]);  
            }  
            console.log('加载图片:'+base4);  
        },function(e){  
            console.log('加载图片失败:'+JSON.stringify(e));  
        });  
}
继续阅读 »
 之前用H5的canvas来获取,但是只有Android可用,IOS不行,后来说用文件读取的形式,发现很慢,也麻烦,最后用bitmap,封装好的,直接用,两个平台都兼容。  

----分享一下^:^

function GetBase64Code(path) //path绝对路径  
{  
        var bitmap = new plus.nativeObj.Bitmap("test"); //test标识谁便取  
        // 从本地加载Bitmap图片  
        bitmap.load(path,function(){  
            var base4=bitmap.toBase64Data();  
            var datastr=base4.split(',',3)  
            if(datastr.length>1)  
            {  
               pics.push(datastr[1]);  
            }else  
            {  
               pics.push(datastr[0]);  
            }  
            console.log('加载图片:'+base4);  
        },function(e){  
            console.log('加载图片失败:'+JSON.stringify(e));  
        });  
}
收起阅读 »

个人全职承接 APP,thinkphp 接口+后台,完整项目 !保证质量 !

全职承接 APP,thinkphp 接口+后台,完整项目 !保证质量 !

QQ:2714055313,439396545!

两个QQ都可以联系!

全职承接 APP,thinkphp 接口+后台,完整项目 !保证质量 !

QQ:2714055313,439396545!

两个QQ都可以联系!

【示例】webview模式选项卡实现滑动切换

示例 选项卡 技术分享 Webview

关于选项卡切换,相信大家都不陌生。hello mui中提供了多种选项卡切换的实现方式,不过大体分为div模式(单页)以及webviedw模式(多个页面)。div模式中又提供了可左右拖动实现切换的模式,如图:

在实际开发中,数据量只会多不会少,因此我们通常都会采用webview模式选项卡。与此同时,许多同学依旧希望能够实现滑动来实现选项卡的切换。就像这样:

可能大家会说,这个滑动并不是那么灵敏。那是因为我控制的角度范围较小(更加精确方便的范围还在进一步测试),实际开发中大家可以根据自己的需求来修改这个范围。
一、main.html
在主页面,我们需要做许多事情,创建自窗口对象(不然切什么换),底部选项点击切换(这是基本的切换),自定义事件切换(子窗口滑动事件来触发)。
其中关键的地方,在于切换。切换,我们要切什么,换什么这才是选项卡切换的核心。
切,有两种切法,点击和滑动。
换,换子窗口,换标题,换底部高亮文字。

<!doctype html>  
<html>  

    <head>  
        <meta charset="UTF-8">  
        <title></title>  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <link href="http://ask.dcloud.net.cn/css/mui.min.css" rel="stylesheet" />  
    </head>  

    <body>  
        <header class="mui-bar mui-bar-nav">  
            <h1 class="mui-title">首页</h1>  
        </header>  
        <nav class="mui-bar mui-bar-tab">  
            <a 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 class="mui-tab-item" data-index="1">  
                <span class="mui-icon mui-icon-phone"></span>  
                <span class="mui-tab-label">电话</span>  
            </a>  
            <a class="mui-tab-item" data-index="2">  
                <span class="mui-icon mui-icon-email"></span>  
                <span class="mui-tab-label">邮件</span>  
            </a>  
            <a class="mui-tab-item" data-index="3">  
                <span class="mui-icon mui-icon-gear"></span>  
                <span class="mui-tab-label">设置</span>  
            </a>  
        </nav>  
        <script src="js/mui.min.js"></script>  
        <script type="text/javascript">  
            mui.init();  
            mui.plusReady(function() {  
                /**  
                 * 当前窗口对象,即父窗口;  
                 * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.currentWebview  
                 */  
                var self = plus.webview.currentWebview();  
                // 子窗口地址数组  
                var subpages = ["home.html", "phone.html", "email.html", "gear.html"];  
                // 子窗口样式  
                var subStyles = {  
                    top: "45px",  
                    bottom: "50px"  
                };  
                // 子窗口数量  
                var subLen = subpages.length;  
                // 子窗口对象数组  
                var subWvs = [];  
                // 标题栏  
                var title = document.querySelector(".mui-title");  
                // 底部选项  
                var tabs = document.querySelectorAll(".mui-tab-item");  
                // 底部文字  
                var labels = document.querySelectorAll(".mui-tab-label");  
                // 当前页面索引,初始化为0;  
                var activeIndex = 0;  
                // 目标页面索引,初始化为当前页面索引;  
                var targetIndex = activeIndex;  
                // 创建子页面  
                for(var i = 0; i < subLen; i  ) {  
                    /**  
                     * 创建窗口对象,并将索引做为额外的参数传递;  
                     * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.create  
                     */  
                    var subWv = plus.webview.create(subpages[i], cutWebviewId(subpages[i]), subStyles, {  
                        index: i  
                    });  
                    // 窗口对象添加至数组  
                    subWvs.push(subWv);  
                    if(i > 0) {  
                        /**  
                         * 隐藏非第一页的窗口对象  
                         * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.hide  
                         */  
                        subWv.hide("none");  
                    }  
                    /**  
                     * 向父窗口添加子窗口  
                     * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.append  
                     */  
                    self.append(subWv);  
                }  
                // 底部选项卡点击切换事件  
                for(var j = 0, jlen = tabs.length; j < jlen; j  ) {  
                    tabs[j].addEventListener("tap", function() {  
                        // 获取当前结点的索引  
                        targetIndex = this.getAttribute("data-index");  
                        // 转换为number类型  
                        targetIndex = parseInt(targetIndex, 10);  
                        if(targetIndex == activeIndex) {  
                            return;  
                        }  
                        // 切换页面  
                        switchPage("tap", activeIndex, targetIndex);  
                    });  
                }  
                // 子页面滑动切换事件  
                window.addEventListener("swipe_event", function(event) {  
                    // 获取方向以及索引  
                    var direction = event.detail.direction;  
                    activeIndex = event.detail.index;  
                    if(direction == "left") {  
                        // 如果是最后一个页面,则不做左滑切换;  
                        if(activeIndex == subLen - 1) {  
                            console.log("最右边一页了");  
                            return;  
                        }  
                        // 目标页面的索引为后面一位  
                        targetIndex = activeIndex   1;  
                    } else {  
                        // 如果是第一个页面,则不做右滑切换;  
                        if(activeIndex == 0) {  
                            console.log("最左边一页了");  
                            return;  
                        }  
                        // 目标页面的索引为前面一位  
                        targetIndex = activeIndex - 1;  
                    }  
                    // 切换页面  
                    switchPage("switch", activeIndex, targetIndex);  
                });  

                /**  
                 * 切换页面  
                 * @param {String} _event 事件类型  
                 * @param {Number} _active 当前页面索引  
                 * @param {Number} _target 目标页面索引  
                 */  
                function switchPage(_event, _active, _target) {  
                    /**  
                     * 目标页面展示  
                     * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.show  
                     */  
                    subWvs[_target].show("fade-in");  
                    // 顶部文字替换  
                    title.innerText = labels[_target].innerText;  
                    // 如果是滑动事件,则手动切换高亮选项;  
                    if(_event == "switch") {  
                        tabs[_active].classList.remove("mui-active");  
                        tabs[_target].classList.add("mui-active");  
                    }  
                    // 之前展示的页面隐藏  
                    subWvs[_active].hide("none");  
                    // 更新当前页索引  
                    activeIndex = _target;  
                }  
            });  

            /**  
             * 截取url地址,获取窗口的id;  
             * @param {String} url html文件的路径  
             * @param {String} wvId webviewObject的id  
             */  
            function cutWebviewId(url) {  
                var startIndex = url.lastIndexOf("/");  
                var endIndex = url.lastIndexOf(".html");  
                var wvId = url.substring(startIndex   1, endIndex);  
                return wvId;  
            }  
        </script>  
    </body>  

</html>

明确了我们要干什么,我们来看下切换的这个函数:

/**  
 * 切换页面  
 * @param {String} _event 事件类型  
 * @param {Number} _active 当前页面索引  
 * @param {Number} _target 目标页面索引  
 */  
function switchPage(_event, _active, _target) {  
    /**  
     * 目标页面展示  
     * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.show  
     */  
    subWvs[_target].show("fade-in");  
    // 顶部文字替换  
    title.innerText = labels[_target].innerText;  
    // 如果是滑动事件,则手动切换高亮选项;  
    if(_event == "switch") {  
        tabs[_active].classList.remove("mui-active");  
        tabs[_target].classList.add("mui-active");  
    }  
    // 之前展示的页面隐藏  
    subWvs[_active].hide("none");  
    // 更新当前页索引  
    activeIndex = _target;  
}  

_event代表切的方式,_active代表当前展示的窗口索引,_target代表目标窗口的索引。
首先将目标窗口show出来,然后替换顶部标题的文字内容。然后判定下切的方式,如果是滑动切换,我们需要自己来对classList进行操作,完成选项卡高亮的转换。最后,我们需要把之前展示的选项卡隐藏掉,并且把当前窗口的索引值赋给中间量。
二、sub.js
所有的子页面都引入这个JS文件,内容如下:

mui.init();  
mui.plusReady(function() {  
    // 获取当前窗口对象  
    var self = plus.webview.currentWebview();  
    // 读取传递过来的参数  
    var index = self.index;  
    /**  
     * 获取父窗口对象  
     * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.parent  
     */  
    var parent = self.parent();  
    // 左滑事件  
    document.addEventListener("swipeleft", function(event) {  
        var angle = event.detail.angle;  
        angle = Math.abs(angle);  
        /**  
         * 控制滑动的角度,为避免误操作,可自定义限制滑动角度;  
         */  
        if(angle > 175 && angle < 185) {  
            parentEvent(parent, index, "left");  
        }  
    });  
    // 右滑事件  
    document.addEventListener("swiperight", function(event) {  
        var angle = event.detail.angle;  
        angle = Math.abs(angle);  
        /**  
         * 控制滑动的角度,为避免误操作,可自定义限制滑动角度;  
         */  
        if(angle < 4) {  
            parentEvent(parent, index, "right");  
        }  
    });  
});  

/**  
 * 触发父窗口自定义事件  
 * @param {Object} wvobj 目标窗口对象  
 * @param {Number} index 索引值  
 * @param {String} direction 方向  
 */  
function parentEvent(wvobj, index, direction) {  
    /**  
     * 触发自定义事件  
     * http://dev.dcloud.net.cn/mui/event/#customevent  
     */  
    mui.fire(wvobj, "swipe_event", {  
        direction: direction,  
        index: index  
    });  
}  

内容简单明了,就是监听左滑和右滑事件,然后去触发父窗口的自定义切换事件。关键点在于event.detail.angle,这个是mui自己封装的一个属性,用来表示滑动的角度(具体的值,大家可以自己滑动时候多测试测试)。大家也可以尝试下,不对滑动角度进行控制,切换会过于灵敏,影响到其他正常的操作。
文笔功力有限,有哪些地方不是很明了,还请见谅,也希望能提出您宝贵的意见,我会继续改进。
最后,附上源码,真机运行即可。

继续阅读 »

关于选项卡切换,相信大家都不陌生。hello mui中提供了多种选项卡切换的实现方式,不过大体分为div模式(单页)以及webviedw模式(多个页面)。div模式中又提供了可左右拖动实现切换的模式,如图:

在实际开发中,数据量只会多不会少,因此我们通常都会采用webview模式选项卡。与此同时,许多同学依旧希望能够实现滑动来实现选项卡的切换。就像这样:

可能大家会说,这个滑动并不是那么灵敏。那是因为我控制的角度范围较小(更加精确方便的范围还在进一步测试),实际开发中大家可以根据自己的需求来修改这个范围。
一、main.html
在主页面,我们需要做许多事情,创建自窗口对象(不然切什么换),底部选项点击切换(这是基本的切换),自定义事件切换(子窗口滑动事件来触发)。
其中关键的地方,在于切换。切换,我们要切什么,换什么这才是选项卡切换的核心。
切,有两种切法,点击和滑动。
换,换子窗口,换标题,换底部高亮文字。

<!doctype html>  
<html>  

    <head>  
        <meta charset="UTF-8">  
        <title></title>  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <link href="http://ask.dcloud.net.cn/css/mui.min.css" rel="stylesheet" />  
    </head>  

    <body>  
        <header class="mui-bar mui-bar-nav">  
            <h1 class="mui-title">首页</h1>  
        </header>  
        <nav class="mui-bar mui-bar-tab">  
            <a 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 class="mui-tab-item" data-index="1">  
                <span class="mui-icon mui-icon-phone"></span>  
                <span class="mui-tab-label">电话</span>  
            </a>  
            <a class="mui-tab-item" data-index="2">  
                <span class="mui-icon mui-icon-email"></span>  
                <span class="mui-tab-label">邮件</span>  
            </a>  
            <a class="mui-tab-item" data-index="3">  
                <span class="mui-icon mui-icon-gear"></span>  
                <span class="mui-tab-label">设置</span>  
            </a>  
        </nav>  
        <script src="js/mui.min.js"></script>  
        <script type="text/javascript">  
            mui.init();  
            mui.plusReady(function() {  
                /**  
                 * 当前窗口对象,即父窗口;  
                 * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.currentWebview  
                 */  
                var self = plus.webview.currentWebview();  
                // 子窗口地址数组  
                var subpages = ["home.html", "phone.html", "email.html", "gear.html"];  
                // 子窗口样式  
                var subStyles = {  
                    top: "45px",  
                    bottom: "50px"  
                };  
                // 子窗口数量  
                var subLen = subpages.length;  
                // 子窗口对象数组  
                var subWvs = [];  
                // 标题栏  
                var title = document.querySelector(".mui-title");  
                // 底部选项  
                var tabs = document.querySelectorAll(".mui-tab-item");  
                // 底部文字  
                var labels = document.querySelectorAll(".mui-tab-label");  
                // 当前页面索引,初始化为0;  
                var activeIndex = 0;  
                // 目标页面索引,初始化为当前页面索引;  
                var targetIndex = activeIndex;  
                // 创建子页面  
                for(var i = 0; i < subLen; i  ) {  
                    /**  
                     * 创建窗口对象,并将索引做为额外的参数传递;  
                     * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.create  
                     */  
                    var subWv = plus.webview.create(subpages[i], cutWebviewId(subpages[i]), subStyles, {  
                        index: i  
                    });  
                    // 窗口对象添加至数组  
                    subWvs.push(subWv);  
                    if(i > 0) {  
                        /**  
                         * 隐藏非第一页的窗口对象  
                         * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.hide  
                         */  
                        subWv.hide("none");  
                    }  
                    /**  
                     * 向父窗口添加子窗口  
                     * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.append  
                     */  
                    self.append(subWv);  
                }  
                // 底部选项卡点击切换事件  
                for(var j = 0, jlen = tabs.length; j < jlen; j  ) {  
                    tabs[j].addEventListener("tap", function() {  
                        // 获取当前结点的索引  
                        targetIndex = this.getAttribute("data-index");  
                        // 转换为number类型  
                        targetIndex = parseInt(targetIndex, 10);  
                        if(targetIndex == activeIndex) {  
                            return;  
                        }  
                        // 切换页面  
                        switchPage("tap", activeIndex, targetIndex);  
                    });  
                }  
                // 子页面滑动切换事件  
                window.addEventListener("swipe_event", function(event) {  
                    // 获取方向以及索引  
                    var direction = event.detail.direction;  
                    activeIndex = event.detail.index;  
                    if(direction == "left") {  
                        // 如果是最后一个页面,则不做左滑切换;  
                        if(activeIndex == subLen - 1) {  
                            console.log("最右边一页了");  
                            return;  
                        }  
                        // 目标页面的索引为后面一位  
                        targetIndex = activeIndex   1;  
                    } else {  
                        // 如果是第一个页面,则不做右滑切换;  
                        if(activeIndex == 0) {  
                            console.log("最左边一页了");  
                            return;  
                        }  
                        // 目标页面的索引为前面一位  
                        targetIndex = activeIndex - 1;  
                    }  
                    // 切换页面  
                    switchPage("switch", activeIndex, targetIndex);  
                });  

                /**  
                 * 切换页面  
                 * @param {String} _event 事件类型  
                 * @param {Number} _active 当前页面索引  
                 * @param {Number} _target 目标页面索引  
                 */  
                function switchPage(_event, _active, _target) {  
                    /**  
                     * 目标页面展示  
                     * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.show  
                     */  
                    subWvs[_target].show("fade-in");  
                    // 顶部文字替换  
                    title.innerText = labels[_target].innerText;  
                    // 如果是滑动事件,则手动切换高亮选项;  
                    if(_event == "switch") {  
                        tabs[_active].classList.remove("mui-active");  
                        tabs[_target].classList.add("mui-active");  
                    }  
                    // 之前展示的页面隐藏  
                    subWvs[_active].hide("none");  
                    // 更新当前页索引  
                    activeIndex = _target;  
                }  
            });  

            /**  
             * 截取url地址,获取窗口的id;  
             * @param {String} url html文件的路径  
             * @param {String} wvId webviewObject的id  
             */  
            function cutWebviewId(url) {  
                var startIndex = url.lastIndexOf("/");  
                var endIndex = url.lastIndexOf(".html");  
                var wvId = url.substring(startIndex   1, endIndex);  
                return wvId;  
            }  
        </script>  
    </body>  

</html>

明确了我们要干什么,我们来看下切换的这个函数:

/**  
 * 切换页面  
 * @param {String} _event 事件类型  
 * @param {Number} _active 当前页面索引  
 * @param {Number} _target 目标页面索引  
 */  
function switchPage(_event, _active, _target) {  
    /**  
     * 目标页面展示  
     * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.show  
     */  
    subWvs[_target].show("fade-in");  
    // 顶部文字替换  
    title.innerText = labels[_target].innerText;  
    // 如果是滑动事件,则手动切换高亮选项;  
    if(_event == "switch") {  
        tabs[_active].classList.remove("mui-active");  
        tabs[_target].classList.add("mui-active");  
    }  
    // 之前展示的页面隐藏  
    subWvs[_active].hide("none");  
    // 更新当前页索引  
    activeIndex = _target;  
}  

_event代表切的方式,_active代表当前展示的窗口索引,_target代表目标窗口的索引。
首先将目标窗口show出来,然后替换顶部标题的文字内容。然后判定下切的方式,如果是滑动切换,我们需要自己来对classList进行操作,完成选项卡高亮的转换。最后,我们需要把之前展示的选项卡隐藏掉,并且把当前窗口的索引值赋给中间量。
二、sub.js
所有的子页面都引入这个JS文件,内容如下:

mui.init();  
mui.plusReady(function() {  
    // 获取当前窗口对象  
    var self = plus.webview.currentWebview();  
    // 读取传递过来的参数  
    var index = self.index;  
    /**  
     * 获取父窗口对象  
     * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.parent  
     */  
    var parent = self.parent();  
    // 左滑事件  
    document.addEventListener("swipeleft", function(event) {  
        var angle = event.detail.angle;  
        angle = Math.abs(angle);  
        /**  
         * 控制滑动的角度,为避免误操作,可自定义限制滑动角度;  
         */  
        if(angle > 175 && angle < 185) {  
            parentEvent(parent, index, "left");  
        }  
    });  
    // 右滑事件  
    document.addEventListener("swiperight", function(event) {  
        var angle = event.detail.angle;  
        angle = Math.abs(angle);  
        /**  
         * 控制滑动的角度,为避免误操作,可自定义限制滑动角度;  
         */  
        if(angle < 4) {  
            parentEvent(parent, index, "right");  
        }  
    });  
});  

/**  
 * 触发父窗口自定义事件  
 * @param {Object} wvobj 目标窗口对象  
 * @param {Number} index 索引值  
 * @param {String} direction 方向  
 */  
function parentEvent(wvobj, index, direction) {  
    /**  
     * 触发自定义事件  
     * http://dev.dcloud.net.cn/mui/event/#customevent  
     */  
    mui.fire(wvobj, "swipe_event", {  
        direction: direction,  
        index: index  
    });  
}  

内容简单明了,就是监听左滑和右滑事件,然后去触发父窗口的自定义切换事件。关键点在于event.detail.angle,这个是mui自己封装的一个属性,用来表示滑动的角度(具体的值,大家可以自己滑动时候多测试测试)。大家也可以尝试下,不对滑动角度进行控制,切换会过于灵敏,影响到其他正常的操作。
文笔功力有限,有哪些地方不是很明了,还请见谅,也希望能提出您宝贵的意见,我会继续改进。
最后,附上源码,真机运行即可。

收起阅读 »

怎么从零基础开始学习hbuilder+mui+h5+跨平台app开发?

视频教程 HelloH5 mui HBuilder

推荐国内首推的跨平台移动APP开发专业培训机构-东翌学院是Dcloud的合作培训机构,跨平台APP开发整体课程在线直播+课程源码+全套视频,最新最全的APP开发,HB和MUI的全套视频,零基础都可以学习,更有高级进修课程,30天最快速的开发跨平台APP!
咨询报名QQ:2971611409 Tel:17090057793上课链接
欢迎有意向学习的朋友加好友咨询!谢谢Dcloud提供这么好的平台!

继续阅读 »

推荐国内首推的跨平台移动APP开发专业培训机构-东翌学院是Dcloud的合作培训机构,跨平台APP开发整体课程在线直播+课程源码+全套视频,最新最全的APP开发,HB和MUI的全套视频,零基础都可以学习,更有高级进修课程,30天最快速的开发跨平台APP!
咨询报名QQ:2971611409 Tel:17090057793上课链接
欢迎有意向学习的朋友加好友咨询!谢谢Dcloud提供这么好的平台!

收起阅读 »

【示例】创建属于当前应用的相册

示例 相册 技术分享 Camera

图片上传,是现在许多手机应用避不开的功能。常见的图片上传,是通过手机相册,或者摄像头拍照来完成对图片的选择。
就像下面的图这样:


但是,有的应用只是单纯地想调用摄像头拍照,然后去选择那些拍摄获取的图片,并且有事没事还可以看看之前拍了哪些照片,然后直接拿去就用了,不用每次都调用摄像头。
例如这样:

这样的需求,就相当于我们要创建一个属于当前应用自己的相册,不和系统相册一起玩了。
现在我们来看下具体的实现:
一、camera.html

<!doctype html>  
<html>  

    <head>  
        <meta charset="UTF-8">  
        <title></title>  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <style type="text/css">  
            .img-content {  
                text-align: center;  
            }  

            #img_view {  
                width: 300px;  
                height: 300px;  
            }  
            .camera-div {  
                margin-top: 20px;  
            }  
        </style>  
    </head>  

    <body>  
        <header class="mui-bar mui-bar-nav">  
            <h1 class="mui-title">相机</h1>  
        </header>  
        <div class="mui-content">  
            <div class="img-content">  
                <!--做为预览图片的元素-->  
                <img src="img/shuijiao.jpg" id="img_view" />  
                <div><span>点击上图选择图片</span></div>  
            </div>  
            <div class="camera-div">  
                <button type="button" class="mui-btn mui-btn-yellow mui-btn-block" id="get_camera">拍照</button>  
            </div>  
        </div>  
        <script src="js/mui.min.js"></script>  
        <script type="text/javascript">  
            mui.init();  
            mui.plusReady(function() {  
                var cameraUrl = "_doc/camera/"; //拍照后图片保存的地址  
                // 调用摄像头事件  
                document.getElementById("get_camera").addEventListener("tap", function() {  
                    /**  
                     * 获取摄像头对象  
                     * http://www.html5plus.org/doc/zh_cn/camera.html#plus.camera.getCamera  
                     */  
                    var camera = plus.camera.getCamera();  
                    /**  
                     * 进行拍照操作  
                     * http://www.html5plus.org/doc/zh_cn/camera.html#plus.camera.Camera.captureImage  
                     */  
                    camera.captureImage(function(captureFile) {  
                        // 拍照完成后,进入选择照片的页面;  
                        showImages(cameraUrl);  
                    }, function(error) {  
                        console.log("拍照错误,错误编码:" + error.code);  
                        console.log("拍照错误,错误描述信息:" + error.message);  
                    }, {  
                        filename: cameraUrl  
                    });  
                });  
                var imgEl = document.getElementById("img_view"); //img元素节点  
                // 点击图片,查看对应目录下的图片;这里只是为了演示读取文件,实际开发中可以参考;  
                imgEl.addEventListener("tap", function() {  
                    showImages(cameraUrl);  
                });  
                /**  
                 * 自定义事件,预览选择好的图片;  
                 * http://dev.dcloud.net.cn/mui/event/#customevent  
                 */  
                window.addEventListener("change_image", function(event) {  
                    var imgUrl = event.detail.imgUrl;  
                    imgEl.src = imgUrl;  
                });  
            });  

            /**  
             * 展示指定目录下的图片  
             * @param {String} targetUrl 目录地址  
             */  
            function showImages(targetUrl) {  
                // 第一步,获取目标目录对象;  
                /**  
                 * 通过URL参数获取目录对象或文件对象  
                 * http://www.html5plus.org/doc/zh_cn/io.html#plus.io.resolveLocalFileSystemURL  
                 */  
                plus.io.resolveLocalFileSystemURL(targetUrl, function(entry) {  
                    // 第二步,创建读取目录的对象;  
                    /**  
                     * 创建目录读取对象  
                     * http://www.html5plus.org/doc/zh_cn/io.html#plus.io.DirectoryEntry.createReader  
                     */  
                    var reader = entry.createReader();  
                    // 第三步,读取目录下的对象;  
                    /**  
                     * 获取当前目录中的所有文件和子目录  
                     * http://www.html5plus.org/doc/zh_cn/io.html#plus.io.DirectoryReader.readEntries  
                     */  
                    reader.readEntries(function(subFiles) {  
                        var imgArr = [];  
                        // 第四步,获取目录下对象的路径;  
                        /**  
                         * 将读取到的文件的路径,添加至数组中;  
                         * http://www.html5plus.org/doc/zh_cn/io.html#plus.io.DirectoryEntry.fullPath  
                         */  
                        for(var i = 0, len = subFiles.length; i < len; i++) {  
                            imgArr.push(subFiles[i].fullPath);  
                        }  
                        // 第五步,去查看摄像头拍摄的图片;  
                        /**  
                         * 打开预览图片的页面,并将图片的地址传过去;  
                         * http://dev.dcloud.net.cn/mui/window/#openwindow  
                         */  
                        mui.openWindow({  
                            url: "camera_gallery.html",  
                            id: "camera_gallery",  
                            extras: {  
                                imgArr: imgArr  
                            }  
                        });  
                    }, function(error) {  
                        console.log("文件操作失败信息:" + error);  
                    });  
                }, function(error) {  
                    console.log("读取本地目录失败,失败信息:" + error);  
                });  
            }  
        </script>  
    </body>  

</html>

大家注意到第42行的变量cameraUrl,这个变量的值,就是我们应用自己相册的路径啦。
调用摄像头逻辑:
1、点击“拍照”按钮,创建摄像头对象;
2、摄像头拍照,在拍照方法的回调中,我们通过相册的路径访问到相册下的文件;
3、创建目录读取对象,用于读取目录下的文件及子目录;
4、获取当前目录下的文件,并将文件系统的绝对路径取出,放置在一个数组中;
5、打开新窗口,并将文件路径的数组传过去。
直接打开本应用相册逻辑:
与上面不同的地方,就是省去了打开摄像头的操作,直接根据目录路径访问即可。
二、camera_gallery.html

<!doctype html>  
<html>  

    <head>  
        <meta charset="UTF-8">  
        <title></title>  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <style type="text/css">  
            .mui-table-view.mui-grid-view .mui-table-view-cell .mui-media-object {  
                height: 150px;  
            }  

            .mui-grid-view.mui-grid-9 .mui-media .mui-icon {  
                position: absolute;  
                right: 15px;  
                top: 15px;  
                z-index: 1;  
                color: yellow;  
            }  

            #sure_img {  
                margin-top: 10px;  
            }  
        </style>  
    </head>  

    <body>  
        <header class="mui-bar mui-bar-nav">  
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
            <a class="mui-pull-right" id="sure_img">确定</a>  
            <h1 class="mui-title">相机相册</h1>  
        </header>  
        <div class="mui-content">  
            <ul class="mui-table-view mui-grid-view mui-grid-9">  
                <!--<li class="mui-table-view-cell mui-media mui-col-xs-6">  
                    <img class="mui-media-object" src="../../img/shuijiao.jpg">  
                    <span class="mui-icon mui-icon-star-filled"></span>  
                </li>-->  
            </ul>  
        </div>  
        <script src="js/mui.min.js"></script>  
        <script src="js/mui.lazyload.js"></script>  
        <script src="js/mui.lazyload.img.js"></script>  
        <script type="text/javascript">  
            mui.init();  
            mui.plusReady(function() {  
                var currentNode = null; //当前选中的元素节点对象  
                var targetImage = ""; //选中的图片路径  
                /**  
                 * 获取当前窗口对象  
                 * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.currentWebview  
                 */  
                var self = plus.webview.currentWebview();  
                var imgArr = self.imgArr;  
                /**  
                 * 动态拼接,图文表格;  
                 * http://dcloud.io/hellomui/examples/slider-table-default.html  
                 * 使用懒加载;  
                 * http://dcloud.io/hellomui/examples/lazyload-image.html  
                 */  
                /**  
                 * 懒加载比较关键的三个点:  
                 * 1、引入mui.lazyload.js以及mui.lazyload.img.js文件;  
                 * 2、img标签中使用data-lazyload来存储实际要展示的图片路径;  
                 * 3、用mui选择器获取文档节点,进行懒加载初始化操作;  
                 */  
                var html = "";  
                for(var i = 0, len = imgArr.length; i < len; i++) {  
                    html += '<li class="mui-table-view-cell mui-media mui-col-xs-6">' +  
                        '<img class="mui-media-object" data-lazyload="' + imgArr[i] + '" /></li>';  
                }  
                // 拼接目标节点的内容  
                document.querySelector(".mui-table-view").innerHTML = html;  
                // 懒加载初始化  
                mui(document).imageLazyload({  
                    placeholder: "img/text.png"  
                });  
                /**  
                 * 添加选择图片事件  
                 */  
                mui(".mui-table-view").on("tap", ".mui-table-view-cell", function() {  
                    // 第一步,替换选中图片路径  
                    targetImage = this.querySelector(".mui-media-object").src;  
                    // 第二步,判断是否已经有图片被选中;若有,则移除之前的星星,因为此例子仅做单选;  
                    if(currentNode) {  
                        currentNode.removeChild(currentNode.querySelector("span"));  
                    }  
                    // 第三步,创建一个span元素节点,在图片右上角添加一个黄色的填充星星;  
                    var spanNode = document.createElement("span");  
                    spanNode.classList.add("mui-icon");  
                    spanNode.classList.add("mui-icon-star-filled");  
                    this.appendChild(spanNode);  
                    // 第四步,替换当前被选中节点对象;  
                    currentNode = this;  
                });  
                // 确定选择的图片  
                document.getElementById("sure_img").addEventListener("tap", function() {  
                    if(targetImage) {  
                        /**  
                         * 获取当前窗口的创建者  
                         * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.opener  
                         */  
                        var opener = self.opener();  
                        /**  
                         * 触发目标窗口对象的事件,替换图片;  
                         * http://dev.dcloud.net.cn/mui/event/#customevent  
                         */  
                        mui.fire(opener, "change_image", {  
                            imgUrl: targetImage  
                        });  
                        // 返回上一页  
                        mui.back();  
                    } else {  
                        mui.toast("请选择图片");  
                    }  
                });  
            });  
        </script>  
    </body>  

</html>  

这就是我们应用自己的相册咯,这里仅仅做单选的示例,多选大家自己扩展咯,道理是一样的。
1、获取到上一级传过来的所有文件的地址,动态拼接出所有的图片;
2、用mui的事件绑定对图片进行批量事件绑定:在我们点击图片的时候,右上角添加一颗小星星用来标记当前图片;
3、选好图片了,点击右上角的“确认”,并利用自定义事件将选中的图片地址传到上一级页面,替换之前预览的图片;
4、之后你想对这个图片干什么,就看自己的业务需求了。
最后,附上源码,真机运行即可。

继续阅读 »

图片上传,是现在许多手机应用避不开的功能。常见的图片上传,是通过手机相册,或者摄像头拍照来完成对图片的选择。
就像下面的图这样:


但是,有的应用只是单纯地想调用摄像头拍照,然后去选择那些拍摄获取的图片,并且有事没事还可以看看之前拍了哪些照片,然后直接拿去就用了,不用每次都调用摄像头。
例如这样:

这样的需求,就相当于我们要创建一个属于当前应用自己的相册,不和系统相册一起玩了。
现在我们来看下具体的实现:
一、camera.html

<!doctype html>  
<html>  

    <head>  
        <meta charset="UTF-8">  
        <title></title>  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <style type="text/css">  
            .img-content {  
                text-align: center;  
            }  

            #img_view {  
                width: 300px;  
                height: 300px;  
            }  
            .camera-div {  
                margin-top: 20px;  
            }  
        </style>  
    </head>  

    <body>  
        <header class="mui-bar mui-bar-nav">  
            <h1 class="mui-title">相机</h1>  
        </header>  
        <div class="mui-content">  
            <div class="img-content">  
                <!--做为预览图片的元素-->  
                <img src="img/shuijiao.jpg" id="img_view" />  
                <div><span>点击上图选择图片</span></div>  
            </div>  
            <div class="camera-div">  
                <button type="button" class="mui-btn mui-btn-yellow mui-btn-block" id="get_camera">拍照</button>  
            </div>  
        </div>  
        <script src="js/mui.min.js"></script>  
        <script type="text/javascript">  
            mui.init();  
            mui.plusReady(function() {  
                var cameraUrl = "_doc/camera/"; //拍照后图片保存的地址  
                // 调用摄像头事件  
                document.getElementById("get_camera").addEventListener("tap", function() {  
                    /**  
                     * 获取摄像头对象  
                     * http://www.html5plus.org/doc/zh_cn/camera.html#plus.camera.getCamera  
                     */  
                    var camera = plus.camera.getCamera();  
                    /**  
                     * 进行拍照操作  
                     * http://www.html5plus.org/doc/zh_cn/camera.html#plus.camera.Camera.captureImage  
                     */  
                    camera.captureImage(function(captureFile) {  
                        // 拍照完成后,进入选择照片的页面;  
                        showImages(cameraUrl);  
                    }, function(error) {  
                        console.log("拍照错误,错误编码:" + error.code);  
                        console.log("拍照错误,错误描述信息:" + error.message);  
                    }, {  
                        filename: cameraUrl  
                    });  
                });  
                var imgEl = document.getElementById("img_view"); //img元素节点  
                // 点击图片,查看对应目录下的图片;这里只是为了演示读取文件,实际开发中可以参考;  
                imgEl.addEventListener("tap", function() {  
                    showImages(cameraUrl);  
                });  
                /**  
                 * 自定义事件,预览选择好的图片;  
                 * http://dev.dcloud.net.cn/mui/event/#customevent  
                 */  
                window.addEventListener("change_image", function(event) {  
                    var imgUrl = event.detail.imgUrl;  
                    imgEl.src = imgUrl;  
                });  
            });  

            /**  
             * 展示指定目录下的图片  
             * @param {String} targetUrl 目录地址  
             */  
            function showImages(targetUrl) {  
                // 第一步,获取目标目录对象;  
                /**  
                 * 通过URL参数获取目录对象或文件对象  
                 * http://www.html5plus.org/doc/zh_cn/io.html#plus.io.resolveLocalFileSystemURL  
                 */  
                plus.io.resolveLocalFileSystemURL(targetUrl, function(entry) {  
                    // 第二步,创建读取目录的对象;  
                    /**  
                     * 创建目录读取对象  
                     * http://www.html5plus.org/doc/zh_cn/io.html#plus.io.DirectoryEntry.createReader  
                     */  
                    var reader = entry.createReader();  
                    // 第三步,读取目录下的对象;  
                    /**  
                     * 获取当前目录中的所有文件和子目录  
                     * http://www.html5plus.org/doc/zh_cn/io.html#plus.io.DirectoryReader.readEntries  
                     */  
                    reader.readEntries(function(subFiles) {  
                        var imgArr = [];  
                        // 第四步,获取目录下对象的路径;  
                        /**  
                         * 将读取到的文件的路径,添加至数组中;  
                         * http://www.html5plus.org/doc/zh_cn/io.html#plus.io.DirectoryEntry.fullPath  
                         */  
                        for(var i = 0, len = subFiles.length; i < len; i++) {  
                            imgArr.push(subFiles[i].fullPath);  
                        }  
                        // 第五步,去查看摄像头拍摄的图片;  
                        /**  
                         * 打开预览图片的页面,并将图片的地址传过去;  
                         * http://dev.dcloud.net.cn/mui/window/#openwindow  
                         */  
                        mui.openWindow({  
                            url: "camera_gallery.html",  
                            id: "camera_gallery",  
                            extras: {  
                                imgArr: imgArr  
                            }  
                        });  
                    }, function(error) {  
                        console.log("文件操作失败信息:" + error);  
                    });  
                }, function(error) {  
                    console.log("读取本地目录失败,失败信息:" + error);  
                });  
            }  
        </script>  
    </body>  

</html>

大家注意到第42行的变量cameraUrl,这个变量的值,就是我们应用自己相册的路径啦。
调用摄像头逻辑:
1、点击“拍照”按钮,创建摄像头对象;
2、摄像头拍照,在拍照方法的回调中,我们通过相册的路径访问到相册下的文件;
3、创建目录读取对象,用于读取目录下的文件及子目录;
4、获取当前目录下的文件,并将文件系统的绝对路径取出,放置在一个数组中;
5、打开新窗口,并将文件路径的数组传过去。
直接打开本应用相册逻辑:
与上面不同的地方,就是省去了打开摄像头的操作,直接根据目录路径访问即可。
二、camera_gallery.html

<!doctype html>  
<html>  

    <head>  
        <meta charset="UTF-8">  
        <title></title>  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <style type="text/css">  
            .mui-table-view.mui-grid-view .mui-table-view-cell .mui-media-object {  
                height: 150px;  
            }  

            .mui-grid-view.mui-grid-9 .mui-media .mui-icon {  
                position: absolute;  
                right: 15px;  
                top: 15px;  
                z-index: 1;  
                color: yellow;  
            }  

            #sure_img {  
                margin-top: 10px;  
            }  
        </style>  
    </head>  

    <body>  
        <header class="mui-bar mui-bar-nav">  
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
            <a class="mui-pull-right" id="sure_img">确定</a>  
            <h1 class="mui-title">相机相册</h1>  
        </header>  
        <div class="mui-content">  
            <ul class="mui-table-view mui-grid-view mui-grid-9">  
                <!--<li class="mui-table-view-cell mui-media mui-col-xs-6">  
                    <img class="mui-media-object" src="../../img/shuijiao.jpg">  
                    <span class="mui-icon mui-icon-star-filled"></span>  
                </li>-->  
            </ul>  
        </div>  
        <script src="js/mui.min.js"></script>  
        <script src="js/mui.lazyload.js"></script>  
        <script src="js/mui.lazyload.img.js"></script>  
        <script type="text/javascript">  
            mui.init();  
            mui.plusReady(function() {  
                var currentNode = null; //当前选中的元素节点对象  
                var targetImage = ""; //选中的图片路径  
                /**  
                 * 获取当前窗口对象  
                 * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.currentWebview  
                 */  
                var self = plus.webview.currentWebview();  
                var imgArr = self.imgArr;  
                /**  
                 * 动态拼接,图文表格;  
                 * http://dcloud.io/hellomui/examples/slider-table-default.html  
                 * 使用懒加载;  
                 * http://dcloud.io/hellomui/examples/lazyload-image.html  
                 */  
                /**  
                 * 懒加载比较关键的三个点:  
                 * 1、引入mui.lazyload.js以及mui.lazyload.img.js文件;  
                 * 2、img标签中使用data-lazyload来存储实际要展示的图片路径;  
                 * 3、用mui选择器获取文档节点,进行懒加载初始化操作;  
                 */  
                var html = "";  
                for(var i = 0, len = imgArr.length; i < len; i++) {  
                    html += '<li class="mui-table-view-cell mui-media mui-col-xs-6">' +  
                        '<img class="mui-media-object" data-lazyload="' + imgArr[i] + '" /></li>';  
                }  
                // 拼接目标节点的内容  
                document.querySelector(".mui-table-view").innerHTML = html;  
                // 懒加载初始化  
                mui(document).imageLazyload({  
                    placeholder: "img/text.png"  
                });  
                /**  
                 * 添加选择图片事件  
                 */  
                mui(".mui-table-view").on("tap", ".mui-table-view-cell", function() {  
                    // 第一步,替换选中图片路径  
                    targetImage = this.querySelector(".mui-media-object").src;  
                    // 第二步,判断是否已经有图片被选中;若有,则移除之前的星星,因为此例子仅做单选;  
                    if(currentNode) {  
                        currentNode.removeChild(currentNode.querySelector("span"));  
                    }  
                    // 第三步,创建一个span元素节点,在图片右上角添加一个黄色的填充星星;  
                    var spanNode = document.createElement("span");  
                    spanNode.classList.add("mui-icon");  
                    spanNode.classList.add("mui-icon-star-filled");  
                    this.appendChild(spanNode);  
                    // 第四步,替换当前被选中节点对象;  
                    currentNode = this;  
                });  
                // 确定选择的图片  
                document.getElementById("sure_img").addEventListener("tap", function() {  
                    if(targetImage) {  
                        /**  
                         * 获取当前窗口的创建者  
                         * http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.opener  
                         */  
                        var opener = self.opener();  
                        /**  
                         * 触发目标窗口对象的事件,替换图片;  
                         * http://dev.dcloud.net.cn/mui/event/#customevent  
                         */  
                        mui.fire(opener, "change_image", {  
                            imgUrl: targetImage  
                        });  
                        // 返回上一页  
                        mui.back();  
                    } else {  
                        mui.toast("请选择图片");  
                    }  
                });  
            });  
        </script>  
    </body>  

</html>  

这就是我们应用自己的相册咯,这里仅仅做单选的示例,多选大家自己扩展咯,道理是一样的。
1、获取到上一级传过来的所有文件的地址,动态拼接出所有的图片;
2、用mui的事件绑定对图片进行批量事件绑定:在我们点击图片的时候,右上角添加一颗小星星用来标记当前图片;
3、选好图片了,点击右上角的“确认”,并利用自定义事件将选中的图片地址传到上一级页面,替换之前预览的图片;
4、之后你想对这个图片干什么,就看自己的业务需求了。
最后,附上源码,真机运行即可。

收起阅读 »

【示例】5+实现简单的内置浏览器制作

示例 外部网站 技术分享 Webview 浏览器 内置浏览器

需求描述

在当前App中打开一个外部网站,并在外部网站可以进行前进、后退以及立即返回当前webview等操作。

需求分析

依据上述需求的描述,可以理解为该App需要一个内置浏览器,用于访问外部网站。为什么会这样理解呢?
做为一个程序猿(媛),尤其是前端程序猿(媛),对浏览器一定不会陌生。常规的浏览器,可以大致两大部分:菜单栏和页面展示区。
再回到之前的需求描述部分,前进、后退以及返回App功能,可以当作菜单栏;外部网站部分,当作页面展示区。

实现思路

mui提供了父子页面的思路来解决卡头卡尾页面的不流畅,同样可以利用这种结构来实现这个简单的内置浏览器。
父页面作为菜单栏,子页面作为页面展示区。并且通过父页面的元素,来控制子页面中展示部分的切换以及父页面的关闭。

功能实现

下面以访问百度为例,制作一个简单的内置浏览器。

创建浏览器

其实,mui中的父子页面形式,是通过HTML5+API提供的获取当前窗口的WebviewObject对象创建新的Webview窗口,以及在Webview窗口中添加子窗口实现的。

var self = plus.webview.currentWebview();  
var baiduWV = plus.webview.create("http://www.baidu.com", "baidu", {  
    top: "44px",  
    bottom: 0  
});  
self.append(baiduWV);  

页面前进

HTML5+API提供了查询Webview窗口是否可前进以及前进到上次加载的页面方法,依据这两个方法控制子窗口中页面的前进。

baiduWV.canForward(function(event) {  
    var canForward = event.canForward;  
    if(canForward) {  
        baiduWV.forward();  
    } else {  
        alert("不能前进!");  
    }  
});  

页面后退

HTML5+API相应的,也提供了查询Webview窗口是否可后退以及后退到上次加载的页面方法,依据这两个方法控制子窗口中页面的后退。

baiduWV.canBack(function(event) {  
    var canBack = event.canBack;  
    if(canBack) {  
        baiduWV.back();  
    } else {  
        alert("到头了,要关闭页面了!");  
        // 执行重写前的back方法  
        old_back();  
    }  
});  

关闭浏览器

关闭就相对简单了,直接直接mui.back()就可以了,或者更方便得方法就是给元素添加.mui-action-back类。

<h1 class="mui-title mui-action-back" id="close_page">直接关闭当前页面</h1>  

示例效果

源码

附上源码,真机运行即可。

继续阅读 »

需求描述

在当前App中打开一个外部网站,并在外部网站可以进行前进、后退以及立即返回当前webview等操作。

需求分析

依据上述需求的描述,可以理解为该App需要一个内置浏览器,用于访问外部网站。为什么会这样理解呢?
做为一个程序猿(媛),尤其是前端程序猿(媛),对浏览器一定不会陌生。常规的浏览器,可以大致两大部分:菜单栏和页面展示区。
再回到之前的需求描述部分,前进、后退以及返回App功能,可以当作菜单栏;外部网站部分,当作页面展示区。

实现思路

mui提供了父子页面的思路来解决卡头卡尾页面的不流畅,同样可以利用这种结构来实现这个简单的内置浏览器。
父页面作为菜单栏,子页面作为页面展示区。并且通过父页面的元素,来控制子页面中展示部分的切换以及父页面的关闭。

功能实现

下面以访问百度为例,制作一个简单的内置浏览器。

创建浏览器

其实,mui中的父子页面形式,是通过HTML5+API提供的获取当前窗口的WebviewObject对象创建新的Webview窗口,以及在Webview窗口中添加子窗口实现的。

var self = plus.webview.currentWebview();  
var baiduWV = plus.webview.create("http://www.baidu.com", "baidu", {  
    top: "44px",  
    bottom: 0  
});  
self.append(baiduWV);  

页面前进

HTML5+API提供了查询Webview窗口是否可前进以及前进到上次加载的页面方法,依据这两个方法控制子窗口中页面的前进。

baiduWV.canForward(function(event) {  
    var canForward = event.canForward;  
    if(canForward) {  
        baiduWV.forward();  
    } else {  
        alert("不能前进!");  
    }  
});  

页面后退

HTML5+API相应的,也提供了查询Webview窗口是否可后退以及后退到上次加载的页面方法,依据这两个方法控制子窗口中页面的后退。

baiduWV.canBack(function(event) {  
    var canBack = event.canBack;  
    if(canBack) {  
        baiduWV.back();  
    } else {  
        alert("到头了,要关闭页面了!");  
        // 执行重写前的back方法  
        old_back();  
    }  
});  

关闭浏览器

关闭就相对简单了,直接直接mui.back()就可以了,或者更方便得方法就是给元素添加.mui-action-back类。

<h1 class="mui-title mui-action-back" id="close_page">直接关闭当前页面</h1>  

示例效果

源码

附上源码,真机运行即可。

收起阅读 »

怎么从零基础开始学习hbuilder+mui+h5+跨平台app开发?

mui HBuilder

推荐国内首推的跨平台移动APP开发专业培训机构-东翌学院是Dcloud的合作培训机构,跨平台APP开发整体课程在线直播+课程源码+全套视频,最新最全的APP开发,HB和MUI的全套视频,零基础都可以学习,更有高级进修课程,30天最快速的开发跨平台APP!
咨询报名QQ:2971611409 Tel:17090057793上课地址
欢迎有意向学习的朋友加好友咨询!谢谢Dcloud提供这么好的平台!

继续阅读 »

推荐国内首推的跨平台移动APP开发专业培训机构-东翌学院是Dcloud的合作培训机构,跨平台APP开发整体课程在线直播+课程源码+全套视频,最新最全的APP开发,HB和MUI的全套视频,零基础都可以学习,更有高级进修课程,30天最快速的开发跨平台APP!
咨询报名QQ:2971611409 Tel:17090057793上课地址
欢迎有意向学习的朋友加好友咨询!谢谢Dcloud提供这么好的平台!

收起阅读 »

【交流分享】Native.js获取设备当前网速

技术分享 源码 Native.JS

2.3开始android提供了一个流量统计类, android.net.TrafficStats,通过使用这个类提供的方法,就可以获取设备流量。
下面为该类中的常用方法,欢迎大家完善补充

static long getMobileRxBytes() //获取通过Mobile连接收到的字节总数,不包含WiFi
static long getMobileRxPackets() //获取Mobile连接收到的数据包总数
static long getMobileTxBytes() //Mobile发送的总字节数
static long getMobileTxPackets() //Mobile发送的总数据包数
static long getTotalRxBytes() //获取总的接受字节数,包含Mobile和WiFi等
static long getTotalRxPackets() //总的接受数据包数,包含Mobile和WiFi等
static long getTotalTxBytes() //总的发送字节数,包含Mobile和WiFi等
static long getTotalTxPackets() //发送的总数据包数,包含Mobile和WiFi等
static long getUidRxBytes(int uid) //获取某个网络UID的接受字节数,某一个进程的总接收量
static long getUidTxBytes(int uid) //获取某个网络UID的发送字节数,某一个进程的总发送量

实现方法

        var TrafficStats;  //TrafficStats类实例对象  
        var total_data;    //总共接收到的流量  
        var traffic_data;  //一定时间内接收到的流量  
        var intervalId;    //定时器的返回值,用于控制计时器的停止  
        document.addEventListener('plusready', function(){  
            //console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。"  
            TrafficStats = plus.android.importClass("android.net.TrafficStats");  
            total_data = TrafficStats.getTotalRxBytes();  
            intervalId = window.setInterval("getNetSpeed()", 1000);   
        });  

        /**  
         * 核心方法  
         */  
        function getNetSpeed(){  
            traffic_data = TrafficStats.getTotalRxBytes() - total_data;  
            total_data = TrafficStats.getTotalRxBytes();  
            document.getElementById("net").value = bytesToSize(traffic_data);  
            console.log(bytesToSize(traffic_data));  
        }  

        //将byte自动转换为其他单位  
        function bytesToSize(bytes) {  
            if (bytes === 0) return '0 B/s';  
            var k = 1000, // or 1024  
                sizes = ['B/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s', 'PB/s', 'EB/s', 'ZB/s', 'YB/s'],  
                i = Math.floor(Math.log(bytes) / Math.log(k));  
           return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];  
        }       

运行截图

附件下载

继续阅读 »

2.3开始android提供了一个流量统计类, android.net.TrafficStats,通过使用这个类提供的方法,就可以获取设备流量。
下面为该类中的常用方法,欢迎大家完善补充

static long getMobileRxBytes() //获取通过Mobile连接收到的字节总数,不包含WiFi
static long getMobileRxPackets() //获取Mobile连接收到的数据包总数
static long getMobileTxBytes() //Mobile发送的总字节数
static long getMobileTxPackets() //Mobile发送的总数据包数
static long getTotalRxBytes() //获取总的接受字节数,包含Mobile和WiFi等
static long getTotalRxPackets() //总的接受数据包数,包含Mobile和WiFi等
static long getTotalTxBytes() //总的发送字节数,包含Mobile和WiFi等
static long getTotalTxPackets() //发送的总数据包数,包含Mobile和WiFi等
static long getUidRxBytes(int uid) //获取某个网络UID的接受字节数,某一个进程的总接收量
static long getUidTxBytes(int uid) //获取某个网络UID的发送字节数,某一个进程的总发送量

实现方法

        var TrafficStats;  //TrafficStats类实例对象  
        var total_data;    //总共接收到的流量  
        var traffic_data;  //一定时间内接收到的流量  
        var intervalId;    //定时器的返回值,用于控制计时器的停止  
        document.addEventListener('plusready', function(){  
            //console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。"  
            TrafficStats = plus.android.importClass("android.net.TrafficStats");  
            total_data = TrafficStats.getTotalRxBytes();  
            intervalId = window.setInterval("getNetSpeed()", 1000);   
        });  

        /**  
         * 核心方法  
         */  
        function getNetSpeed(){  
            traffic_data = TrafficStats.getTotalRxBytes() - total_data;  
            total_data = TrafficStats.getTotalRxBytes();  
            document.getElementById("net").value = bytesToSize(traffic_data);  
            console.log(bytesToSize(traffic_data));  
        }  

        //将byte自动转换为其他单位  
        function bytesToSize(bytes) {  
            if (bytes === 0) return '0 B/s';  
            var k = 1000, // or 1024  
                sizes = ['B/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s', 'PB/s', 'EB/s', 'ZB/s', 'YB/s'],  
                i = Math.floor(Math.log(bytes) / Math.log(k));  
           return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];  
        }       

运行截图

附件下载

收起阅读 »

hbuilder/dcloud 用itools安卓模拟器调试app

HTML5+ 移动APP 默认话题

以前一直用hbuilder做web页面
后来发现hbuilder可以做webapp
官方给的文档是用谷歌的安卓模拟器 但是对国人来说 界面不太友好
后来自己试了 海马玩模拟器 又试了夜神模拟器 都是启动有点慢 界面不够清爽
然后发现了itools安卓模拟器 界面清爽干净 启动速度快

下面说下用hbuilder连接itools安卓模拟器的方法
itools模拟器的adb端口是54001

1.首先打开cmd

  1. 然后输出cd/ 回到根目录
  2. 然后

itools操作
cd Program Files (x86)\ThinkSky\iToolsAVM\tools (这是itools的adb目录)
.\adb connect 127.0.0.1:54001
.\adb devices

hbuilder 操作
cd HBuilder\tools (这是hbulider的adb目录)
.\adb connect 127.0.0.1:54001
.\adb devices

操作完成以后就可以用模拟器调试了

继续阅读 »

以前一直用hbuilder做web页面
后来发现hbuilder可以做webapp
官方给的文档是用谷歌的安卓模拟器 但是对国人来说 界面不太友好
后来自己试了 海马玩模拟器 又试了夜神模拟器 都是启动有点慢 界面不够清爽
然后发现了itools安卓模拟器 界面清爽干净 启动速度快

下面说下用hbuilder连接itools安卓模拟器的方法
itools模拟器的adb端口是54001

1.首先打开cmd

  1. 然后输出cd/ 回到根目录
  2. 然后

itools操作
cd Program Files (x86)\ThinkSky\iToolsAVM\tools (这是itools的adb目录)
.\adb connect 127.0.0.1:54001
.\adb devices

hbuilder 操作
cd HBuilder\tools (这是hbulider的adb目录)
.\adb connect 127.0.0.1:54001
.\adb devices

操作完成以后就可以用模拟器调试了

收起阅读 »