HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

看到网上介绍的HBuilder的介绍,下载下来尝试. 唉。

看到网上介绍的HBuilder的介绍,下载下来尝试, 装上去试下。

  1. 绿色版本,很不错啊。
    安装上去,运行,界面很简介也不错。
    提示很贴心,不必webStorm 差。

  2. 看一看内存,晕死了都。 700M. 只打开了一个文件。
    占用内存,是当时放弃webStrom的主要原因。
    唉,都是Eclipse害的。
    果断放弃HBuilder, 还是用我的sublime吧。

  3. sublime内存占用没超过 100M, 一般稳定在 60M左右,速度又快。

    现在是,只要看到 Eclipse 就不敢用啊!
    开Eclipse之类的,编译其它程序代码,立马报告 内存不足。

    公司系统加密,只能用XP, 上不了大内存啊.

继续阅读 »

看到网上介绍的HBuilder的介绍,下载下来尝试, 装上去试下。

  1. 绿色版本,很不错啊。
    安装上去,运行,界面很简介也不错。
    提示很贴心,不必webStorm 差。

  2. 看一看内存,晕死了都。 700M. 只打开了一个文件。
    占用内存,是当时放弃webStrom的主要原因。
    唉,都是Eclipse害的。
    果断放弃HBuilder, 还是用我的sublime吧。

  3. sublime内存占用没超过 100M, 一般稳定在 60M左右,速度又快。

    现在是,只要看到 Eclipse 就不敢用啊!
    开Eclipse之类的,编译其它程序代码,立马报告 内存不足。

    公司系统加密,只能用XP, 上不了大内存啊.

收起阅读 »

MUI仿咸鱼底部tabbar圆形发布按钮样式

tabbar

<nav class="mui-bar mui-bar-tab footer-nav">
<a class="mui-tab-item mui-active" href="#tabbar">
<span class="mui-icon icon">&#xe62b;</span>
<span class="mui-tab-label">首页</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-chat">
<span class="mui-icon icon">&#xe602;</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">&#xe60d;</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">&#xe647;</span>
<span class="mui-tab-label">消息</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-map">
<span class="mui-icon icon">&#xe655;</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">&#xe62b;</span>
<span class="mui-tab-label">首页</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-chat">
<span class="mui-icon icon">&#xe602;</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">&#xe60d;</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">&#xe647;</span>
<span class="mui-tab-label">消息</span>
</a>
<a class="mui-tab-item" href="#tabbar-with-map">
<span class="mui-icon icon">&#xe655;</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

个人觉得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以上的权限动态申请

App离线打包 权限 Android

页面调用

// 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 动态权限申请代码  ↑↑↑↑↑↑↑↑
写的比较粗糙,还望大神指导!
收起阅读 »

福利!原生tabbar代码分享

tabbar

由于众所周知的原因,html写的tabbar十分卡顿,一直在寻求更高效的解决方案(用户才不管什么情怀不情怀,只认性能)

现在分享用js调用原生画tabbar的功能,看附件.

一来分享给大家,少走弯路;二来给自己做个备份.

由于众所周知的原因,html写的tabbar十分卡顿,一直在寻求更高效的解决方案(用户才不管什么情怀不情怀,只认性能)

现在分享用js调用原生画tabbar的功能,看附件.

一来分享给大家,少走弯路;二来给自己做个备份.

求混合开发 需要把geturl获取到的地址传到php数据库

需要把geturl获取到的地址传到php数据库
function getURL() {

alert( "页面地址为:"+embed.getURL() );

}
把上面这段代码获取到的url发送到PHP的数据库 现在页面有用户ID的变量 变量已经赋值好 用户登陆以后就能得到用户ID 把获取到的URL 发送到数据库的url字段保存到对应的用户下即可 有能做的大神联系 QQ95026686

继续阅读 »

需要把geturl获取到的地址传到php数据库
function getURL() {

alert( "页面地址为:"+embed.getURL() );

}
把上面这段代码获取到的url发送到PHP的数据库 现在页面有用户ID的变量 变量已经赋值好 用户登陆以后就能得到用户ID 把获取到的URL 发送到数据库的url字段保存到对应的用户下即可 有能做的大神联系 QQ95026686

收起阅读 »

MUI 用了这么久感觉没有一个单独的文档来说明各种mui的css类

更新MUI

MUI 用了这么久感觉没有一个单独的文档来说明各种mui的css类,都是在文档中偶尔夹杂进行点说明,或者是我太笨没发现。比如:mui-action-menu是干什么的,mui-bar我知道是标题栏的,加上它后标栏就置顶不会动了,还有很多MUI的CSS类不知道怎么用,也不知道是什么意思。或者在MUI 文档加个搜索功能,一个一个点开来用浏览器搜也比较麻烦。

继续阅读 »

MUI 用了这么久感觉没有一个单独的文档来说明各种mui的css类,都是在文档中偶尔夹杂进行点说明,或者是我太笨没发现。比如:mui-action-menu是干什么的,mui-bar我知道是标题栏的,加上它后标栏就置顶不会动了,还有很多MUI的CSS类不知道怎么用,也不知道是什么意思。或者在MUI 文档加个搜索功能,一个一个点开来用浏览器搜也比较麻烦。

收起阅读 »

android 单个大文件断点续传

最近公司项目需求做大文件的单点续传

分享下

java类代码

后台异步切割文件 切完返回true

/**  
     * 切割文件保存到指定目录 根据指定名称保存   
     * @param pWebview  
     * @param array  
     */  
    public void cutFile(final IWebview pWebview, JSONArray array){  
        final String CallBackID = array.optString(0);  
        final String filePath = array.optString(2);  
        final String cutPath = array.optString(3);  

        AsyncTask<String, Void, String> execute = new AsyncTask<String, Void, String>() {  
            public void execute(String taskId, String filePath, String cutPath) {  
            }  

            @Override  
            protected String doInBackground(String... params) {  
                java.net.HttpURLConnection connection = null;  

                byte[] buffer = new byte[readStep];  
                FileInputStream file = null;  
                File f =new File(filePath);  
                String fileName=f.getName();  
                try {  
                    file = new FileInputStream(filePath);  
                    int len = 0;  
                    int AllLen = 0;  
                    try {  
                        FileInputStream fs = new FileInputStream(filePath);  
                        fileSize = fs.available();  
                        AllLen = fileSize / (readStep);  
                        if(fileSize % (readStep) > 0){  
                            AllLen++;  
                        }  
                    } catch (IOException e) {  
                        // TODO Auto-generated catch block  
                        e.printStackTrace();  
                    }  
                    int nowCount = 1;  
                    while ((len = file.read(buffer)) > 0) {  
                        String strFilePath = cutPath+fileName+".part";  
                        try {  
                            File cutfile = new File(strFilePath);  
                            if (!cutfile.exists()) {  
                                Log.e("TestFile", "Create the file:" + strFilePath);  
                                cutfile.getParentFile().mkdirs();  
                                cutfile.createNewFile();  
                            }  
                            RandomAccessFile raf = new RandomAccessFile(cutfile, "rwd");  
                            raf.seek(0);  
                            raf.write(buffer,0,(int)len);  
                            raf.close();  
                        } catch (Exception e) {  
                            Log.e("TestFile", "Error on write File:" + e);  
                        }  
                        nowCount++;  
                    };  
                } catch (FileNotFoundException e) {  
                    e.printStackTrace();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  

                return "abc";  
            }  

            protected void onPostExecute(String result) {  
                Log.e("result",result);  
                if(result == "abc"){  
                    JSONArray newArray = new JSONArray();  
                    newArray.put(true);  
                    JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, true);  
                }  

            }  

        }.execute();  

    }

后台异步提交文件夹中所有文件碎片

/**  
     *  
     * @param pWebview  
     * @param array  
     *  
     *    taskId    temp[0]  
     *    AllLen    temp[1]  
     *    nowCount  temp[2]  
     */  
    public void sendTempFile(IWebview pWebview, JSONArray array){  
        String CallBackID = array.optString(0);  
        String cutPath = array.optString(1);  
        String URLPath = array.optString(2);  

        byte[] buffer = new byte[readStep];  
        File file = new File(cutPath);  
        File[] fs = file.listFiles();  
        for (File f : fs){  
            String newString = f.getName().toString().replace(".part","");  

            Pattern pen = Pattern.compile("_");  

            String[] temp = pen.split(newString);  

            String fileName = temp[3];  
            Log.e("fileName",temp[3]);  
            //获取文件大小  
            FileInputStream fst = null;  
            try {  
                fst = new FileInputStream(f.getPath());  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            }  
            try {  
                fileSize = fst.available();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            //执行异步上传提交  
            asyncSendTempFiles(URLPath+"&task_id="+temp[0]+"&fileSize="+fileSize,f.getPath(),fileName,buffer,0,Integer.parseInt(temp[1]),Integer.parseInt(temp[2]),pWebview,CallBackID);  
        }  
    }  

    public void asyncSendTempFiles(final String urlPath, final String filePath, final String fileName, final byte[] buffer, final int count, final int allLength, final int nowCount, final IWebview pWebview, final String CallBackID){  

        AsyncTask<String, Void, String> execute = new AsyncTask<String, Void, String>() {  
            public void execute(String urlPath, String filePath, String fileName, byte[] buffer, int count, int allLength, int nowCount) {  
            }  

            @Override  
            protected String doInBackground(String... params) {  
                java.net.HttpURLConnection connection = null;  

                try {  
                    Log.e("urlPath",urlPath+"&allLength="+allLength+"&nowCount="+nowCount+"&fileName="+URLEncoder.encode(fileName, "UTF-8"));  
                    URL url = new URL(urlPath+"&allLength="+allLength+"&nowCount="+nowCount+"&fileName="+URLEncoder.encode(fileName, "UTF-8"));  
                    connection = (java.net.HttpURLConnection) url.openConnection();  
                    connection.setRequestMethod("POST");  
                    connection.setUseCaches(false);  
                    connection.setDoOutput(true);  

                    FileInputStream is = new FileInputStream(filePath);  
                    byte[] b = new byte[is.available()];  
                    Log.e("available",is.available()+"");  
                    is.read(b);  
                    OutputStream os = connection.getOutputStream();  
                    os.write(b);  
                    os.flush();  
                    os.close();  
                    if(connection.getResponseCode() == 200){  
                        Log.e("ResponseMessage",connection.getResponseMessage());  
                        return changeInputStream(connection.getInputStream(),"UTF-8");  
                    }else{  
                    }  
                } catch (IOException e) {  
                    Log.e("urlPath","url error");  
                    e.printStackTrace();  
                }  
                return "";  
            }  

            protected void onPostExecute(String result) {  
                Log.e("result",result);  
                try {  
                    JSONObject jsonObject = new JSONObject(result);  
                    //int resultCode = jsonObject.getInt("resultcode");  
                    String data = jsonObject.getString("status");  
                    Log.e("result-data",data);  
                    if(data == "0"){  
                        //传输成功 删除当前文件  
                        File file=new File(filePath);  
                        //文件是否存在  
                        if(file.exists())  
                        {  
                            file.delete();  
                            Log.e("result-data","文件已经被删除了");  
                        }  
                    }  

                } catch (JSONException e) {  
                    Log.e("result",result);  
                    e.printStackTrace();  
                }  
//                JSONArray newArray = new JSONArray();  
//                newArray.put(result);  
//                JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, true);  

            }  

        }.execute();  
    }  

    /**  
     * 将一个输入流转换成指定编码的字符串  
     *  
     * @param inputStream  
     * @param encode  
     * @return  
     */  
    private static String changeInputStream(InputStream inputStream,  
                                            String encode) {  

        // 内存流  
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
        byte[] data = new byte[1024];  
        int len = 0;  
        String result = null;  
        if (inputStream != null) {  
            try {  
                while ((len = inputStream.read(data)) != -1) {  
                    byteArrayOutputStream.write(data, 0, len);  
                }  
                result = new String(byteArrayOutputStream.toByteArray(), encode);  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
        return result;  
    }  
继续阅读 »

最近公司项目需求做大文件的单点续传

分享下

java类代码

后台异步切割文件 切完返回true

/**  
     * 切割文件保存到指定目录 根据指定名称保存   
     * @param pWebview  
     * @param array  
     */  
    public void cutFile(final IWebview pWebview, JSONArray array){  
        final String CallBackID = array.optString(0);  
        final String filePath = array.optString(2);  
        final String cutPath = array.optString(3);  

        AsyncTask<String, Void, String> execute = new AsyncTask<String, Void, String>() {  
            public void execute(String taskId, String filePath, String cutPath) {  
            }  

            @Override  
            protected String doInBackground(String... params) {  
                java.net.HttpURLConnection connection = null;  

                byte[] buffer = new byte[readStep];  
                FileInputStream file = null;  
                File f =new File(filePath);  
                String fileName=f.getName();  
                try {  
                    file = new FileInputStream(filePath);  
                    int len = 0;  
                    int AllLen = 0;  
                    try {  
                        FileInputStream fs = new FileInputStream(filePath);  
                        fileSize = fs.available();  
                        AllLen = fileSize / (readStep);  
                        if(fileSize % (readStep) > 0){  
                            AllLen++;  
                        }  
                    } catch (IOException e) {  
                        // TODO Auto-generated catch block  
                        e.printStackTrace();  
                    }  
                    int nowCount = 1;  
                    while ((len = file.read(buffer)) > 0) {  
                        String strFilePath = cutPath+fileName+".part";  
                        try {  
                            File cutfile = new File(strFilePath);  
                            if (!cutfile.exists()) {  
                                Log.e("TestFile", "Create the file:" + strFilePath);  
                                cutfile.getParentFile().mkdirs();  
                                cutfile.createNewFile();  
                            }  
                            RandomAccessFile raf = new RandomAccessFile(cutfile, "rwd");  
                            raf.seek(0);  
                            raf.write(buffer,0,(int)len);  
                            raf.close();  
                        } catch (Exception e) {  
                            Log.e("TestFile", "Error on write File:" + e);  
                        }  
                        nowCount++;  
                    };  
                } catch (FileNotFoundException e) {  
                    e.printStackTrace();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  

                return "abc";  
            }  

            protected void onPostExecute(String result) {  
                Log.e("result",result);  
                if(result == "abc"){  
                    JSONArray newArray = new JSONArray();  
                    newArray.put(true);  
                    JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, true);  
                }  

            }  

        }.execute();  

    }

后台异步提交文件夹中所有文件碎片

/**  
     *  
     * @param pWebview  
     * @param array  
     *  
     *    taskId    temp[0]  
     *    AllLen    temp[1]  
     *    nowCount  temp[2]  
     */  
    public void sendTempFile(IWebview pWebview, JSONArray array){  
        String CallBackID = array.optString(0);  
        String cutPath = array.optString(1);  
        String URLPath = array.optString(2);  

        byte[] buffer = new byte[readStep];  
        File file = new File(cutPath);  
        File[] fs = file.listFiles();  
        for (File f : fs){  
            String newString = f.getName().toString().replace(".part","");  

            Pattern pen = Pattern.compile("_");  

            String[] temp = pen.split(newString);  

            String fileName = temp[3];  
            Log.e("fileName",temp[3]);  
            //获取文件大小  
            FileInputStream fst = null;  
            try {  
                fst = new FileInputStream(f.getPath());  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            }  
            try {  
                fileSize = fst.available();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            //执行异步上传提交  
            asyncSendTempFiles(URLPath+"&task_id="+temp[0]+"&fileSize="+fileSize,f.getPath(),fileName,buffer,0,Integer.parseInt(temp[1]),Integer.parseInt(temp[2]),pWebview,CallBackID);  
        }  
    }  

    public void asyncSendTempFiles(final String urlPath, final String filePath, final String fileName, final byte[] buffer, final int count, final int allLength, final int nowCount, final IWebview pWebview, final String CallBackID){  

        AsyncTask<String, Void, String> execute = new AsyncTask<String, Void, String>() {  
            public void execute(String urlPath, String filePath, String fileName, byte[] buffer, int count, int allLength, int nowCount) {  
            }  

            @Override  
            protected String doInBackground(String... params) {  
                java.net.HttpURLConnection connection = null;  

                try {  
                    Log.e("urlPath",urlPath+"&allLength="+allLength+"&nowCount="+nowCount+"&fileName="+URLEncoder.encode(fileName, "UTF-8"));  
                    URL url = new URL(urlPath+"&allLength="+allLength+"&nowCount="+nowCount+"&fileName="+URLEncoder.encode(fileName, "UTF-8"));  
                    connection = (java.net.HttpURLConnection) url.openConnection();  
                    connection.setRequestMethod("POST");  
                    connection.setUseCaches(false);  
                    connection.setDoOutput(true);  

                    FileInputStream is = new FileInputStream(filePath);  
                    byte[] b = new byte[is.available()];  
                    Log.e("available",is.available()+"");  
                    is.read(b);  
                    OutputStream os = connection.getOutputStream();  
                    os.write(b);  
                    os.flush();  
                    os.close();  
                    if(connection.getResponseCode() == 200){  
                        Log.e("ResponseMessage",connection.getResponseMessage());  
                        return changeInputStream(connection.getInputStream(),"UTF-8");  
                    }else{  
                    }  
                } catch (IOException e) {  
                    Log.e("urlPath","url error");  
                    e.printStackTrace();  
                }  
                return "";  
            }  

            protected void onPostExecute(String result) {  
                Log.e("result",result);  
                try {  
                    JSONObject jsonObject = new JSONObject(result);  
                    //int resultCode = jsonObject.getInt("resultcode");  
                    String data = jsonObject.getString("status");  
                    Log.e("result-data",data);  
                    if(data == "0"){  
                        //传输成功 删除当前文件  
                        File file=new File(filePath);  
                        //文件是否存在  
                        if(file.exists())  
                        {  
                            file.delete();  
                            Log.e("result-data","文件已经被删除了");  
                        }  
                    }  

                } catch (JSONException e) {  
                    Log.e("result",result);  
                    e.printStackTrace();  
                }  
//                JSONArray newArray = new JSONArray();  
//                newArray.put(result);  
//                JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, true);  

            }  

        }.execute();  
    }  

    /**  
     * 将一个输入流转换成指定编码的字符串  
     *  
     * @param inputStream  
     * @param encode  
     * @return  
     */  
    private static String changeInputStream(InputStream inputStream,  
                                            String encode) {  

        // 内存流  
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
        byte[] data = new byte[1024];  
        int len = 0;  
        String result = null;  
        if (inputStream != null) {  
            try {  
                while ((len = inputStream.read(data)) != -1) {  
                    byteArrayOutputStream.write(data, 0, len);  
                }  
                result = new String(byteArrayOutputStream.toByteArray(), encode);  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
        return result;  
    }  
收起阅读 »

初学一个多月,终于制作完成了一个简陋的app并上架了!

上架 App

首先,感谢社区里的大神们和QQ群里的大神们的帮助,自己摸爬滚打制作的简易APP终于上线了。

苹果的app store也顺利上线!

感觉自己又有信心了!

首先,感谢社区里的大神们和QQ群里的大神们的帮助,自己摸爬滚打制作的简易APP终于上线了。

苹果的app store也顺利上线!

感觉自己又有信心了!

【公告】关于HBuilder 8.1.2不能正常启动,Android平台地图滑动卡顿、地图POI搜索后不显示数据等问题的解决办法

公告 HTML5+ Runtime HBuilder

IDE

HBuilder不能正常启动

HBuilder启动时长时间停留在启动界面或闪退。

Android

Android平台地图滑动卡顿

Android平台下,创建plus.maps.Map控件时,不设置position参数默认使用static,会使得地图控件滑动非常卡顿,影响使用

Android平台修复地图POI搜索后不显示数据的问题

Android平台下,plus.maps.Map控件中搜索地点后数据不能正确标识在地图

解决办法

8.1.3及以上版本的HBuilder已修复以上问题,请更新或下载最新版HBuilder。

继续阅读 »

IDE

HBuilder不能正常启动

HBuilder启动时长时间停留在启动界面或闪退。

Android

Android平台地图滑动卡顿

Android平台下,创建plus.maps.Map控件时,不设置position参数默认使用static,会使得地图控件滑动非常卡顿,影响使用

Android平台修复地图POI搜索后不显示数据的问题

Android平台下,plus.maps.Map控件中搜索地点后数据不能正确标识在地图

解决办法

8.1.3及以上版本的HBuilder已修复以上问题,请更新或下载最新版HBuilder。

收起阅读 »