HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

这几天对HBuilder使用的感想

mui

HBuilder,刚推出来过后不久,我就开始尝鲜,使用的时候让我感觉很是惊艳,自动提示的让我很满足,什么link 、script、meta标签,刷刷就出来了,这个必须点赞。后来继续尝试WEB 、APP开发,发现能上传自动帮我打包,感觉很轻松,因为我尝试过配置Phongap的环境,一个android,就有些麻烦,更何况还有IOS的。
接着,我用HBuilder来编写PC端的网页,也把这个工具推荐给了我同事们使用,大家都觉得挺好的。
过了一段时间,今年,领导让给写一个APP,我说用原生来开发吧(我这时已经会Android开发了),领导say no,用HTML 5开发,要兼容IOS、Android、WP、微信(微信是一个超级APP,可以算是一个小平台了),另外我给你安排一个专家,帮你做好微信支付、二维码扫描等等功能,我说不用,我知道一个工具,并集成了UI、还有很多开发好的功能,领导很满意,让我先开发一个DEMO出来。
清明节3天假,我第一天就写的差不多了,迅速写好了DEMO大部分工作,也在我的IOS手机上调试完毕,完成度大概80%,遗留了一些优化的工作(不要小瞧这部分),很顺利,很开心。于是在我的Android(小米2s)机器上,我第二天继续调试,我擦!,怎么各种各样的情况出现了,首先领导很重视的二维码扫描功能,我在这部Android机上调了半天,硬是识别不出来,后来是我手不小心抖了下,才发现只有小抖几下才识别的出来。这个我在问答部分也提了,得到官方回复,他们的小米2上是正常的,我不知道会不会与“S”有关系,在二维码扫描方面,扫描速度还是有点不行~~
接着我继续界面的跳转,我比较郁闷,原生Anroid有singleTop、singleTask模式的,我就想让webview重复利用下,例如 首页,我肯定不想让它重复打开吧。查下API,找到了plus.webview.show 方法,不行,IOS的显示不出来,找到了webview.show方法(我想这个两个方法实现逻辑是一样的),结果IOS都无法显示出来,Android到挺正常的,继续查openClosed,IOS的还是不好使,偶那个神哪!在问答区,我发出了提问,官方回复使用zindex,OK,果然能显示出来!但是接着我再首页打开新的页面,mygod,出了个圈圈,就不见踪影,明白了,新打开的界面没有继承打开者zindex属性,得,我只好重新下openWindow方法,将currentWebview,的zindex赋值给要打开的页面,结果还是不行,我想明白了我要取的是topWebview的zindex, 只好查API,没有获取topWebView的方法,得,将show()方法也重写下,并自己记录下topWebview,IOS正常了,达到我要的效果了。
在Android上来试试,Y的,Android倒不干了,使用webview.getStyle.zindex,发现,额,程序刚开始运行的时候得到undifined,而IOS得到的是0。算了算了,给重写的函数加两个判断分支,如果是android,执行原来的方法。呼,脑子终于清静了。
四天的时间,其实还算是挺快的。但是挺有点烦人的。webview的show方法,官方说下一版修复。恩,我也觉得应该将这方面的栈结果顺序维护好。我使用过plus.webview.all()函数,好像如果用show方法,在被show的之后的webview 貌似没被清空。
时间紧迫,我还没对这些缺陷做准确的验证,再提出来。
因此,希望官方提供一个专门的缺陷报告填写页过来,问答的方式 不是感觉很严谨呵。另外,mui的js源码也阅读了下,额,API不够用,当然可以自己写,但是官方的理解肯定深刻一些。5+部分的可否给一些原理图神马的。HB整体的发展路线图、蓝图,也能给一个,让大家也讨论下,让小伙伴们都参加进来,给予意见吧。
我还是挺喜欢HB的,但是这些或多或少的问题能得到解决。

继续阅读 »

HBuilder,刚推出来过后不久,我就开始尝鲜,使用的时候让我感觉很是惊艳,自动提示的让我很满足,什么link 、script、meta标签,刷刷就出来了,这个必须点赞。后来继续尝试WEB 、APP开发,发现能上传自动帮我打包,感觉很轻松,因为我尝试过配置Phongap的环境,一个android,就有些麻烦,更何况还有IOS的。
接着,我用HBuilder来编写PC端的网页,也把这个工具推荐给了我同事们使用,大家都觉得挺好的。
过了一段时间,今年,领导让给写一个APP,我说用原生来开发吧(我这时已经会Android开发了),领导say no,用HTML 5开发,要兼容IOS、Android、WP、微信(微信是一个超级APP,可以算是一个小平台了),另外我给你安排一个专家,帮你做好微信支付、二维码扫描等等功能,我说不用,我知道一个工具,并集成了UI、还有很多开发好的功能,领导很满意,让我先开发一个DEMO出来。
清明节3天假,我第一天就写的差不多了,迅速写好了DEMO大部分工作,也在我的IOS手机上调试完毕,完成度大概80%,遗留了一些优化的工作(不要小瞧这部分),很顺利,很开心。于是在我的Android(小米2s)机器上,我第二天继续调试,我擦!,怎么各种各样的情况出现了,首先领导很重视的二维码扫描功能,我在这部Android机上调了半天,硬是识别不出来,后来是我手不小心抖了下,才发现只有小抖几下才识别的出来。这个我在问答部分也提了,得到官方回复,他们的小米2上是正常的,我不知道会不会与“S”有关系,在二维码扫描方面,扫描速度还是有点不行~~
接着我继续界面的跳转,我比较郁闷,原生Anroid有singleTop、singleTask模式的,我就想让webview重复利用下,例如 首页,我肯定不想让它重复打开吧。查下API,找到了plus.webview.show 方法,不行,IOS的显示不出来,找到了webview.show方法(我想这个两个方法实现逻辑是一样的),结果IOS都无法显示出来,Android到挺正常的,继续查openClosed,IOS的还是不好使,偶那个神哪!在问答区,我发出了提问,官方回复使用zindex,OK,果然能显示出来!但是接着我再首页打开新的页面,mygod,出了个圈圈,就不见踪影,明白了,新打开的界面没有继承打开者zindex属性,得,我只好重新下openWindow方法,将currentWebview,的zindex赋值给要打开的页面,结果还是不行,我想明白了我要取的是topWebview的zindex, 只好查API,没有获取topWebView的方法,得,将show()方法也重写下,并自己记录下topWebview,IOS正常了,达到我要的效果了。
在Android上来试试,Y的,Android倒不干了,使用webview.getStyle.zindex,发现,额,程序刚开始运行的时候得到undifined,而IOS得到的是0。算了算了,给重写的函数加两个判断分支,如果是android,执行原来的方法。呼,脑子终于清静了。
四天的时间,其实还算是挺快的。但是挺有点烦人的。webview的show方法,官方说下一版修复。恩,我也觉得应该将这方面的栈结果顺序维护好。我使用过plus.webview.all()函数,好像如果用show方法,在被show的之后的webview 貌似没被清空。
时间紧迫,我还没对这些缺陷做准确的验证,再提出来。
因此,希望官方提供一个专门的缺陷报告填写页过来,问答的方式 不是感觉很严谨呵。另外,mui的js源码也阅读了下,额,API不够用,当然可以自己写,但是官方的理解肯定深刻一些。5+部分的可否给一些原理图神马的。HB整体的发展路线图、蓝图,也能给一个,让大家也讨论下,让小伙伴们都参加进来,给予意见吧。
我还是挺喜欢HB的,但是这些或多或少的问题能得到解决。

收起阅读 »

分享一个利用融云开发伪IM的思路

IM 融云

在移动互联时代,IM基本都是必备品了,可惜的是DCloud在短期内貌似还没有加入IM系统的可能,最近研究了一下三方的IM模块,在这里和大家分享一个利用融云Web达成伪IM的思路。

1、为什么选择Web版本?
融云在Web版本外还提供iOS和Android版本的SDK,但是需要一定的原生开发能力来进行支持,虽然都是封装好的API接口,开发起来不是很难,但是在我的系统里,暂时是不需要除了文字外的其余多余的功能,为了一些莫名的功能,耗费时间和精力去研究SDK,实在是有些得不偿失,等以后有时间或者需求的时候再去研究,所以需要添加很多IM组件的小伙伴可以绕道了。

2、Web版本的优缺点?
优点:集成简单,只需要简单的几步,就可以集成一套IM系统在APP中。
(1)引入Web版本SDK

http://res.websdk.rong.io/RongIMClient{-版本号}-min.js

(2)初始化web sdk

RongIMClient.init("appkey");

(3)设置链接状态监听器

RongIMClient.setConnectionStatusListener({    
     onChanged: function (status) {}    
}); 

(4)链接融云服务器

RongIMClient.connect("token", {  
     onSuccess: function (userid) { },  
     onError: function (x) { }  
});

(5)设置消息监听器

RongIMClient.getInstance().setOnReceiveMessageListener({  
     onReceived: function (message) { }  
});

(6)得到RongIMClient实例对象,设置私人会话类型

var ins = RongIMClient.getInstance();  
var contype = RongIMClient.ConversationType.PRIVATE;

(7)发送

ins.sendMessage(contype, "targetId", RongIMClient.TextMessage.obtain("发送消息内容"), null, {  
       onSuccess: function () { },  
       onError: function (data) { }  
 });

缺点:无法PUSH,这个实在要吐槽一下,其实融云支持PUSH,但是我和他们交涉良久,他们总是认为Web版本不需要PUSH这样的东西,其实就是简单的在他们服务器上注册用户的deviceToken,就为了注册个deviceToken,就要分别集成iOS和Android两套SDK,实在是麻烦。我让他们加,未果;让他们把SDK再底层的API开放给我,我自己增加注册,也是未果。

3、为什么是伪IM?
这个和无法PUSH是相关的,因为无法PUSH,所以只有用户在打开APP的情况下才能收到对方发送的消息,无法忍受,那么如何解决呢?
方案如下:
(1)在用户退出APP,或者pause的时候,主动断开和融云服务器的连接。
(2)每次发出IM消息的时候,消息要通知到自己的服务器,自己的服务器去融云的服务器获取用户在线状态
(a)如果用户在线,不处理
(b)如果用户不在线,利用个推的PUSH提醒用户打开APP
(3)用户进入APP的时候,重连融云服务器,接受消息。

这样,就可以做到一个简单的IM系统了。服务器端就不在这里详细描述啦^_^

PS1:融云的Web版本其实不止是文字,还有其余的一些,譬如客服,图片等等,集成起来还是比较简单的,当然,如果你的需求比较高,那么还是集成iOS或者Android版本的SDK要更好些。
PS2:还有一些三方IM,我没有仔细的研究过,但是应该大同小异。

继续阅读 »

在移动互联时代,IM基本都是必备品了,可惜的是DCloud在短期内貌似还没有加入IM系统的可能,最近研究了一下三方的IM模块,在这里和大家分享一个利用融云Web达成伪IM的思路。

1、为什么选择Web版本?
融云在Web版本外还提供iOS和Android版本的SDK,但是需要一定的原生开发能力来进行支持,虽然都是封装好的API接口,开发起来不是很难,但是在我的系统里,暂时是不需要除了文字外的其余多余的功能,为了一些莫名的功能,耗费时间和精力去研究SDK,实在是有些得不偿失,等以后有时间或者需求的时候再去研究,所以需要添加很多IM组件的小伙伴可以绕道了。

2、Web版本的优缺点?
优点:集成简单,只需要简单的几步,就可以集成一套IM系统在APP中。
(1)引入Web版本SDK

http://res.websdk.rong.io/RongIMClient{-版本号}-min.js

(2)初始化web sdk

RongIMClient.init("appkey");

(3)设置链接状态监听器

RongIMClient.setConnectionStatusListener({    
     onChanged: function (status) {}    
}); 

(4)链接融云服务器

RongIMClient.connect("token", {  
     onSuccess: function (userid) { },  
     onError: function (x) { }  
});

(5)设置消息监听器

RongIMClient.getInstance().setOnReceiveMessageListener({  
     onReceived: function (message) { }  
});

(6)得到RongIMClient实例对象,设置私人会话类型

var ins = RongIMClient.getInstance();  
var contype = RongIMClient.ConversationType.PRIVATE;

(7)发送

ins.sendMessage(contype, "targetId", RongIMClient.TextMessage.obtain("发送消息内容"), null, {  
       onSuccess: function () { },  
       onError: function (data) { }  
 });

缺点:无法PUSH,这个实在要吐槽一下,其实融云支持PUSH,但是我和他们交涉良久,他们总是认为Web版本不需要PUSH这样的东西,其实就是简单的在他们服务器上注册用户的deviceToken,就为了注册个deviceToken,就要分别集成iOS和Android两套SDK,实在是麻烦。我让他们加,未果;让他们把SDK再底层的API开放给我,我自己增加注册,也是未果。

3、为什么是伪IM?
这个和无法PUSH是相关的,因为无法PUSH,所以只有用户在打开APP的情况下才能收到对方发送的消息,无法忍受,那么如何解决呢?
方案如下:
(1)在用户退出APP,或者pause的时候,主动断开和融云服务器的连接。
(2)每次发出IM消息的时候,消息要通知到自己的服务器,自己的服务器去融云的服务器获取用户在线状态
(a)如果用户在线,不处理
(b)如果用户不在线,利用个推的PUSH提醒用户打开APP
(3)用户进入APP的时候,重连融云服务器,接受消息。

这样,就可以做到一个简单的IM系统了。服务器端就不在这里详细描述啦^_^

PS1:融云的Web版本其实不止是文字,还有其余的一些,譬如客服,图片等等,集成起来还是比较简单的,当然,如果你的需求比较高,那么还是集成iOS或者Android版本的SDK要更好些。
PS2:还有一些三方IM,我没有仔细的研究过,但是应该大同小异。

收起阅读 »

点击小图浏览大图,双击缩放,赶快拿走

功能实现:
点击小图浏览大图,双击放大,滑动切换,上滑或下滑关闭,双指放大或缩小(到了最小是自动关闭),预加载缓冲。
调用的第三方插件,好处就是没有借用jquery,而且滑动,缩放效果超流畅
最底下有效果图和所需文件下载
1,引入CSS及JS

<link rel="stylesheet prefetch" href="../plugin/touchPhotos/photoswipe.css">  
<link rel="stylesheet prefetch" href="../plugin/touchPhotos/default-skin.css">  
<script src="../plugin/touchPhotos/stopExecutionOnTimeout.js"></script>  
<script src="../plugin/touchPhotos/photoswipe.min.js"></script>  
<script src="../plugin/touchPhotos/photoswipe-ui-default.min.js"></script>

2,小图片容器(这里要获取原图地址及图片尺寸),我是通过JSON来获取的,就写个JSON的写法了
//容器 my-simple-gallery,获取图片的宽度和高度

data += '<div class="my-simple-gallery">';  
for(var k=0; k<data.photos.length; k++){  
    data += '<figure itemprop="associatedMedia" itemscope=""><a href="'+data.photos[k].big+'" data-size="'+data.photos[k].size+'"><img src="'+data.photos[k].small+'" ></a></figure>';  
}  
data += '</div>';

自己讲data插入到ID里面了哈
然后就指定浏览图片的那个容器了
initPhotoSwipeFromDOM('.my-simple-gallery');

3.下面的代码写的有点恶心,直接拿去放到模板里面

<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true" style="">
<div class="pswpbg"></div>
<div class="pswp
scroll-wrap">
<div class="pswpcontainer" style="transform: translate3d(0px, 0px, 0px);">
<div class="pswp
item" style="display: block; transform: translate3d(-1792px, 0px, 0px);"><div class="pswpzoom-wrap" style="transform: translate3d(288px, 56px, 0px) scale(1);"></div></div>
<div class="pswp
item" style="transform: translate3d(0px, 0px, 0px);"><div class="pswpzoom-wrap" style="transform: translate3d(473px, 66.8125px, 0px) scale(0.146484375);"></div></div>
<div class="pswp
item" style="display: block; transform: translate3d(1792px, 0px, 0px);"><div class="pswpzoom-wrap" style="transform: translate3d(447px, 44px, 0px) scale(0.6904296875);"></div></div>
</div>
<div class="pswp
ui pswpui--fit pswpui--hidden">
<div class="pswptop-bar">
<div class="pswp
counter">4 / 4</div>
<button class="pswpbutton pswpbutton--close" title="Close (Esc)"></button>
<div class="pswppreloader">
<div class="pswp
preloadericn">
<div class="pswp
preloadercut">
<div class="pswp
preloaderdonut"></div>
</div>
</div>
</div>
</div>
<div class="pswp
caption">
<div class="pswpcaptioncenter"></div>
</div>
</div>
</div>
</div>

4.处理大图的,直接拿去
var initPhotoSwipeFromDOM = function (gallerySelector) {
var parseThumbnailElements = function (el) {
var thumbElements = el.childNodes, numNodes = thumbElements.length, items = [], figureEl, childElements, linkEl, size, item;
for (var i = 0; i < numNodes; i++) {
if (window.CP.shouldStopExecution(1)) {
break;
}
figureEl = thumbElements[i];
if (figureEl.nodeType !== 1) {
continue;
}
linkEl = figureEl.children[0];
size = linkEl.getAttribute('data-size').split('x');
item = {
src: linkEl.getAttribute('href'),
w: parseInt(size[0], 10),
h: parseInt(size[1], 10)
};
if (figureEl.children.length > 1) {
item.title = figureEl.children[1].innerHTML;
}
if (linkEl.children.length > 0) {
item.msrc = linkEl.children[0].getAttribute('src');
}
item.el = figureEl;
items.push(item);
}
window.CP.exitedLoop(1);
return items;
};
var closest = function closest(el, fn) {
return el && (fn(el) ? el : closest(el.parentNode, fn));
};
var onThumbnailsClick = function (e) {
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
var eTarget = e.target || e.srcElement;
var clickedListItem = closest(eTarget, function (el) {
return el.tagName && el.tagName.toUpperCase() === 'FIGURE';
});
if (!clickedListItem) {
return;
}
var clickedGallery = clickedListItem.parentNode, childNodes = clickedListItem.parentNode.childNodes, numChildNodes = childNodes.length, nodeIndex = 0, index;
for (var i = 0; i < numChildNodes; i++) {
if (window.CP.shouldStopExecution(2)) {
break;
}
if (childNodes[i].nodeType !== 1) {
continue;
}
if (childNodes[i] === clickedListItem) {
index = nodeIndex;
break;
}
nodeIndex++;
}
window.CP.exitedLoop(2);
if (index >= 0) {
openPhotoSwipe(index, clickedGallery);
}
return false;
};
var photoswipeParseHash = function () {
var hash = window.location.hash.substring(1), params = {};
if (hash.length < 5) {
return params;
}
var vars = hash.split('&');
for (var i = 0; i < vars.length; i++) {
if (window.CP.shouldStopExecution(3)) {
break;
}
if (!vars[i]) {
continue;
}
var pair = vars[i].split('=');
if (pair.length < 2) {
continue;
}
params[pair[0]] = pair[1];
}
window.CP.exitedLoop(3);
if (params.gid) {
params.gid = parseInt(params.gid, 10);
}
if (!params.hasOwnProperty('pid')) {
return params;
}
params.pid = parseInt(params.pid, 10);
return params;
};
var openPhotoSwipe = function (index, galleryElement, disableAnimation) {
var pswpElement = document.querySelectorAll('.pswp')[0], gallery, options, items;
items = parseThumbnailElements(galleryElement);
options = {
index: index,
galleryUID: galleryElement.getAttribute('data-pswp-uid'),
getThumbBoundsFn: function (index) {
var thumbnail = items[index].el.getElementsByTagName('img')[0], pageYScroll = window.pageYOffset || document.documentElement.scrollTop, rect = thumbnail.getBoundingClientRect();
return {
x: rect.left,
y: rect.top + pageYScroll,
w: rect.width
};
},
history: false,
focus: false
};
if (disableAnimation) {
options.showAnimationDuration = 0;
}
gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
};
var galleryElements = document.querySelectorAll(gallerySelector);
for (var i = 0, l = galleryElements.length; i < l; i++) {
if (window.CP.shouldStopExecution(4)) {
break;
}
galleryElements[i].setAttribute('data-pswp-uid', i + 1);
galleryElements[i].onclick = onThumbnailsClick;
}
window.CP.exitedLoop(4);
var hashData = photoswipeParseHash();
if (hashData.pid > 0 && hashData.gid > 0) {
openPhotoSwipe(hashData.pid - 1, galleryElements[hashData.gid - 1], true);
}
};

继续阅读 »

功能实现:
点击小图浏览大图,双击放大,滑动切换,上滑或下滑关闭,双指放大或缩小(到了最小是自动关闭),预加载缓冲。
调用的第三方插件,好处就是没有借用jquery,而且滑动,缩放效果超流畅
最底下有效果图和所需文件下载
1,引入CSS及JS

<link rel="stylesheet prefetch" href="../plugin/touchPhotos/photoswipe.css">  
<link rel="stylesheet prefetch" href="../plugin/touchPhotos/default-skin.css">  
<script src="../plugin/touchPhotos/stopExecutionOnTimeout.js"></script>  
<script src="../plugin/touchPhotos/photoswipe.min.js"></script>  
<script src="../plugin/touchPhotos/photoswipe-ui-default.min.js"></script>

2,小图片容器(这里要获取原图地址及图片尺寸),我是通过JSON来获取的,就写个JSON的写法了
//容器 my-simple-gallery,获取图片的宽度和高度

data += '<div class="my-simple-gallery">';  
for(var k=0; k<data.photos.length; k++){  
    data += '<figure itemprop="associatedMedia" itemscope=""><a href="'+data.photos[k].big+'" data-size="'+data.photos[k].size+'"><img src="'+data.photos[k].small+'" ></a></figure>';  
}  
data += '</div>';

自己讲data插入到ID里面了哈
然后就指定浏览图片的那个容器了
initPhotoSwipeFromDOM('.my-simple-gallery');

3.下面的代码写的有点恶心,直接拿去放到模板里面

<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true" style="">
<div class="pswpbg"></div>
<div class="pswp
scroll-wrap">
<div class="pswpcontainer" style="transform: translate3d(0px, 0px, 0px);">
<div class="pswp
item" style="display: block; transform: translate3d(-1792px, 0px, 0px);"><div class="pswpzoom-wrap" style="transform: translate3d(288px, 56px, 0px) scale(1);"></div></div>
<div class="pswp
item" style="transform: translate3d(0px, 0px, 0px);"><div class="pswpzoom-wrap" style="transform: translate3d(473px, 66.8125px, 0px) scale(0.146484375);"></div></div>
<div class="pswp
item" style="display: block; transform: translate3d(1792px, 0px, 0px);"><div class="pswpzoom-wrap" style="transform: translate3d(447px, 44px, 0px) scale(0.6904296875);"></div></div>
</div>
<div class="pswp
ui pswpui--fit pswpui--hidden">
<div class="pswptop-bar">
<div class="pswp
counter">4 / 4</div>
<button class="pswpbutton pswpbutton--close" title="Close (Esc)"></button>
<div class="pswppreloader">
<div class="pswp
preloadericn">
<div class="pswp
preloadercut">
<div class="pswp
preloaderdonut"></div>
</div>
</div>
</div>
</div>
<div class="pswp
caption">
<div class="pswpcaptioncenter"></div>
</div>
</div>
</div>
</div>

4.处理大图的,直接拿去
var initPhotoSwipeFromDOM = function (gallerySelector) {
var parseThumbnailElements = function (el) {
var thumbElements = el.childNodes, numNodes = thumbElements.length, items = [], figureEl, childElements, linkEl, size, item;
for (var i = 0; i < numNodes; i++) {
if (window.CP.shouldStopExecution(1)) {
break;
}
figureEl = thumbElements[i];
if (figureEl.nodeType !== 1) {
continue;
}
linkEl = figureEl.children[0];
size = linkEl.getAttribute('data-size').split('x');
item = {
src: linkEl.getAttribute('href'),
w: parseInt(size[0], 10),
h: parseInt(size[1], 10)
};
if (figureEl.children.length > 1) {
item.title = figureEl.children[1].innerHTML;
}
if (linkEl.children.length > 0) {
item.msrc = linkEl.children[0].getAttribute('src');
}
item.el = figureEl;
items.push(item);
}
window.CP.exitedLoop(1);
return items;
};
var closest = function closest(el, fn) {
return el && (fn(el) ? el : closest(el.parentNode, fn));
};
var onThumbnailsClick = function (e) {
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
var eTarget = e.target || e.srcElement;
var clickedListItem = closest(eTarget, function (el) {
return el.tagName && el.tagName.toUpperCase() === 'FIGURE';
});
if (!clickedListItem) {
return;
}
var clickedGallery = clickedListItem.parentNode, childNodes = clickedListItem.parentNode.childNodes, numChildNodes = childNodes.length, nodeIndex = 0, index;
for (var i = 0; i < numChildNodes; i++) {
if (window.CP.shouldStopExecution(2)) {
break;
}
if (childNodes[i].nodeType !== 1) {
continue;
}
if (childNodes[i] === clickedListItem) {
index = nodeIndex;
break;
}
nodeIndex++;
}
window.CP.exitedLoop(2);
if (index >= 0) {
openPhotoSwipe(index, clickedGallery);
}
return false;
};
var photoswipeParseHash = function () {
var hash = window.location.hash.substring(1), params = {};
if (hash.length < 5) {
return params;
}
var vars = hash.split('&');
for (var i = 0; i < vars.length; i++) {
if (window.CP.shouldStopExecution(3)) {
break;
}
if (!vars[i]) {
continue;
}
var pair = vars[i].split('=');
if (pair.length < 2) {
continue;
}
params[pair[0]] = pair[1];
}
window.CP.exitedLoop(3);
if (params.gid) {
params.gid = parseInt(params.gid, 10);
}
if (!params.hasOwnProperty('pid')) {
return params;
}
params.pid = parseInt(params.pid, 10);
return params;
};
var openPhotoSwipe = function (index, galleryElement, disableAnimation) {
var pswpElement = document.querySelectorAll('.pswp')[0], gallery, options, items;
items = parseThumbnailElements(galleryElement);
options = {
index: index,
galleryUID: galleryElement.getAttribute('data-pswp-uid'),
getThumbBoundsFn: function (index) {
var thumbnail = items[index].el.getElementsByTagName('img')[0], pageYScroll = window.pageYOffset || document.documentElement.scrollTop, rect = thumbnail.getBoundingClientRect();
return {
x: rect.left,
y: rect.top + pageYScroll,
w: rect.width
};
},
history: false,
focus: false
};
if (disableAnimation) {
options.showAnimationDuration = 0;
}
gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
};
var galleryElements = document.querySelectorAll(gallerySelector);
for (var i = 0, l = galleryElements.length; i < l; i++) {
if (window.CP.shouldStopExecution(4)) {
break;
}
galleryElements[i].setAttribute('data-pswp-uid', i + 1);
galleryElements[i].onclick = onThumbnailsClick;
}
window.CP.exitedLoop(4);
var hashData = photoswipeParseHash();
if (hashData.pid > 0 && hashData.gid > 0) {
openPhotoSwipe(hashData.pid - 1, galleryElements[hashData.gid - 1], true);
}
};

收起阅读 »

Android平台API等级配置 - minSdkVersion&targetSdkVersion

Android

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-android-minsdkversion

<a id="minsdkversion"></a>

minSdkVersion

minSdkVersion用于指定应用兼容的最低Android版本(API等级)。
如果APP某些功能无法支持低版本Android系统的设备,可以配置minSdkVersion确保APP只能安装到指定Android版本以上的设备。HBuilder|HBuilderX中可在manifest.json中进行配置。

⚠️注意: minSdkVersion升级时只能增加不能降低。minSdkVersion高的apk无法被minSdkVersion低的apk覆盖安装需要注意!!

可视化界面配置

打开项目的manifest.json文件,在 "App常用其它设置" 项中 "Android设置" 下的 minSdkVersion编辑框中输入要支持的最低Android版本号:

源码视图配置

打开项目的manifest.json文件,切换到 "源码视图"

  • 5+APP项目
    在plus->distribute->google节点下添加“minSdkVersion”字段,并配置要支持的最低Android版本号:
    "plus": {  
        "distribute": {  
            "google":{  
                "minSdkVersion": 22  
            }  
        }  
    }
  • uni-app项目
    在"app-plus"->distribute->android节点下添加“minSdkVersion”字段,并配置要支持的最低Android版本号:
    "app-plus": {  
        "distribute": {  
            "android":{  
                "minSdkVersion": 22  
            }  
        }  
    }

Number类型,整数值,应用要求的最低系统版本,必须大于等于19(Android4.4)小于等于23(android 6.0),默认值为19
示例中设置值为22表示应用只能安装在Android5.1及以上设备。

<a id="targetsdkversion"></a>

targetSdkVersion

HBuilder3.2.13版本开始targetSdkVersion默认值由26调整为28
注意:某些uni原生插件可能没有适配好targetSdkVersion为28会引起部分功能异常,碰到这类情况请联系插件开发者进行适配

⚠️注意: targetSdkVersion升级时只能增加不能降低。targetSdkVersion高的apk无法被targetSdkVersion低的apk覆盖安装需要注意!!

targetSdkVersion用于指定应用适配的Android版本(API等级)。
在Android系统中设置低版本的targetSdkVersion会使APP兼容模式运行,也就可能无法用到新系统的特性,甚至在兼容模式下运行可能存在安全漏洞等问题。
随着Android系统的升级,一些应用市场会要求设置较高的targetSdkVersion才可以提交。HBuilder|HBuilderX中可在manifest.json中进行配置。

可视化界面配置

打开项目的manifest.json文件,在 "App常用其它设置" 项中 "Android设置" 下的 targetSdkVersion编辑框中输入要支持的最低Android版本号:

源码视图配置

打开项目的manifest.json文件,切换到 "源码视图"

  • 5+APP项目
    在plus->distribute->google节点下添加“targetSdkVersion”字段:
    "plus": {  
        "distribute": {  
            "google":{  
                "targetSdkVersion": 26  
            }  
        }  
    }
  • uni-app项目
    在"app-plus"->distribute->android节点下添加“targetSdkVersion”字段:
    "app-plus": {  
        "distribute": {  
            "android":{  
                "targetSdkVersion": 26  
            }  
        }  
    }

Number类型,整数值,云端打包默认的targetSdkVersion值为26

  • 5+App项目:最小值为19,最大值29
  • uni-app项目:最小值为26,最大值29

    HBuilderX2.8.3及以下版本targetSdkVersion最大值支持28
    HBuilderX2.8.4+版本targetSdkVersion最大值支持29

Android版本列表

API等级与Android版本对应列表如下:

API等级 Android版本号
14 Android4.0
15 Android4.0.3
16 Android4.1.2
17 Android4.2.2
18 Android4.3.1
19 Android4.4.2
20 Android4.4W.2
21 Android5.0.1
22 Android5.1
24 Android7.0
25 Android7.1.1
26 Android8.0
27 Android8.1
28 Android9.0
29 Android10.0(Android Q)
30 Android11.0

配置完成保存提交App云端打包后才能生效

继续阅读 »

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-android-minsdkversion

<a id="minsdkversion"></a>

minSdkVersion

minSdkVersion用于指定应用兼容的最低Android版本(API等级)。
如果APP某些功能无法支持低版本Android系统的设备,可以配置minSdkVersion确保APP只能安装到指定Android版本以上的设备。HBuilder|HBuilderX中可在manifest.json中进行配置。

⚠️注意: minSdkVersion升级时只能增加不能降低。minSdkVersion高的apk无法被minSdkVersion低的apk覆盖安装需要注意!!

可视化界面配置

打开项目的manifest.json文件,在 "App常用其它设置" 项中 "Android设置" 下的 minSdkVersion编辑框中输入要支持的最低Android版本号:

源码视图配置

打开项目的manifest.json文件,切换到 "源码视图"

  • 5+APP项目
    在plus->distribute->google节点下添加“minSdkVersion”字段,并配置要支持的最低Android版本号:
    "plus": {  
        "distribute": {  
            "google":{  
                "minSdkVersion": 22  
            }  
        }  
    }
  • uni-app项目
    在"app-plus"->distribute->android节点下添加“minSdkVersion”字段,并配置要支持的最低Android版本号:
    "app-plus": {  
        "distribute": {  
            "android":{  
                "minSdkVersion": 22  
            }  
        }  
    }

Number类型,整数值,应用要求的最低系统版本,必须大于等于19(Android4.4)小于等于23(android 6.0),默认值为19
示例中设置值为22表示应用只能安装在Android5.1及以上设备。

<a id="targetsdkversion"></a>

targetSdkVersion

HBuilder3.2.13版本开始targetSdkVersion默认值由26调整为28
注意:某些uni原生插件可能没有适配好targetSdkVersion为28会引起部分功能异常,碰到这类情况请联系插件开发者进行适配

⚠️注意: targetSdkVersion升级时只能增加不能降低。targetSdkVersion高的apk无法被targetSdkVersion低的apk覆盖安装需要注意!!

targetSdkVersion用于指定应用适配的Android版本(API等级)。
在Android系统中设置低版本的targetSdkVersion会使APP兼容模式运行,也就可能无法用到新系统的特性,甚至在兼容模式下运行可能存在安全漏洞等问题。
随着Android系统的升级,一些应用市场会要求设置较高的targetSdkVersion才可以提交。HBuilder|HBuilderX中可在manifest.json中进行配置。

可视化界面配置

打开项目的manifest.json文件,在 "App常用其它设置" 项中 "Android设置" 下的 targetSdkVersion编辑框中输入要支持的最低Android版本号:

源码视图配置

打开项目的manifest.json文件,切换到 "源码视图"

  • 5+APP项目
    在plus->distribute->google节点下添加“targetSdkVersion”字段:
    "plus": {  
        "distribute": {  
            "google":{  
                "targetSdkVersion": 26  
            }  
        }  
    }
  • uni-app项目
    在"app-plus"->distribute->android节点下添加“targetSdkVersion”字段:
    "app-plus": {  
        "distribute": {  
            "android":{  
                "targetSdkVersion": 26  
            }  
        }  
    }

Number类型,整数值,云端打包默认的targetSdkVersion值为26

  • 5+App项目:最小值为19,最大值29
  • uni-app项目:最小值为26,最大值29

    HBuilderX2.8.3及以下版本targetSdkVersion最大值支持28
    HBuilderX2.8.4+版本targetSdkVersion最大值支持29

Android版本列表

API等级与Android版本对应列表如下:

API等级 Android版本号
14 Android4.0
15 Android4.0.3
16 Android4.1.2
17 Android4.2.2
18 Android4.3.1
19 Android4.4.2
20 Android4.4W.2
21 Android5.0.1
22 Android5.1
24 Android7.0
25 Android7.1.1
26 Android8.0
27 Android8.1
28 Android9.0
29 Android10.0(Android Q)
30 Android11.0

配置完成保存提交App云端打包后才能生效

收起阅读 »

授权登录插件配置

OAuth

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-oauth

云端打包登录鉴权功能需要到第三方开发平台申请应用后获取相关配置参数,目前支持的平台包括:

  1. 微信:微信开放平台
  2. QQ:腾讯开放平台
  3. 微博:新浪微博开放平台
  4. 苹果登录:iOS 苹果授权登录(Sign in with Apple)教程
  5. Google登录:HBuilderX3.2.7+版本支持
  6. Facebook登录:HBuilder3.2.7+版本支持

配置参数需要提交云端打包后才能生效,如果需要真机运行生效请使用自定义基座

HBuilderX中配置登录鉴权

从微信/QQ/微博开放平台申请获取配置参数后,需在HBuilderX中配置并提交云端打包才能生效。
老版本HBuilder配置界面有差异,逻辑是一样的,建议更新使用HBuilderX

配置使用登录鉴权模块

打开应用的manifest.json文件,在“App模块配置”项中勾选“OAuth(登录鉴权)”:

配置登录鉴权参数

微信

在manifest.json文件“App模块配置”项的“OAuth(登录鉴权)”下,勾选“微信登录”项,并输入从微信开放平台申请的参数:

QQ

在manifest.json文件“App模块配置”项的“OAuth(登录鉴权)”下,勾选“QQ登录”项,并输入从腾讯QQ开放平台申请的参数:

  • appid:腾讯QQ开放平台申请应用的AppID值。

微博

在manifest.json文件“App模块配置”项的“OAuth(登录鉴权)”下,勾选“新浪微博登录”项,并输入从新浪微博开放平台申请的参数:

  • appkey: "新浪微博平台应用appkey";
  • appsecret: "新浪微博平台应用appsecret";
  • redirect_uri: "新浪微博平台应用授权回调页地址"。

配置完成后Ctrl+S保存提交App云端打包生效。

<a id="secret"></a>

配置参数安全性问题

在HBuilder|HBuilderX中配置的参数云端打包后会保存在apk/ipa中,对于安全性要求高的开发者可能担心存在参数泄露的风险,可以采取以下方式处理。

  • JS代码中动态传参数
    如登录服务AuthService的请求授权认证方法authorize,可以通过第三个参数options动态传入appid、appSecret等。
    这些参数可以加密保存到js代码中或连网从服务器获取(避免保存在本地引起泄露风险,当然需要考虑网络传输过程的安全问题)。

  • 通过服务器完成授权认证
    根据OAuth规范,实际客户端授权只是为了获取授权临时票据(code),这时候可以仅在客户端配置appid参数调用登录服务AuthService的请求授权认证方法authorize获取临时票据,将票据提交到服务器完成后续的操作。
    这种情况授权的参数(如appsecret)仅保存服务器即可,安全性更高。
    在服务器的对接流程需要根据各开放平台的规范要求进行处理,如微信参考:授权后接口调用

这时在HBuilder|HBuilderX中可以填入任意值提交云端打包

继续阅读 »

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-oauth

云端打包登录鉴权功能需要到第三方开发平台申请应用后获取相关配置参数,目前支持的平台包括:

  1. 微信:微信开放平台
  2. QQ:腾讯开放平台
  3. 微博:新浪微博开放平台
  4. 苹果登录:iOS 苹果授权登录(Sign in with Apple)教程
  5. Google登录:HBuilderX3.2.7+版本支持
  6. Facebook登录:HBuilder3.2.7+版本支持

配置参数需要提交云端打包后才能生效,如果需要真机运行生效请使用自定义基座

HBuilderX中配置登录鉴权

从微信/QQ/微博开放平台申请获取配置参数后,需在HBuilderX中配置并提交云端打包才能生效。
老版本HBuilder配置界面有差异,逻辑是一样的,建议更新使用HBuilderX

配置使用登录鉴权模块

打开应用的manifest.json文件,在“App模块配置”项中勾选“OAuth(登录鉴权)”:

配置登录鉴权参数

微信

在manifest.json文件“App模块配置”项的“OAuth(登录鉴权)”下,勾选“微信登录”项,并输入从微信开放平台申请的参数:

QQ

在manifest.json文件“App模块配置”项的“OAuth(登录鉴权)”下,勾选“QQ登录”项,并输入从腾讯QQ开放平台申请的参数:

  • appid:腾讯QQ开放平台申请应用的AppID值。

微博

在manifest.json文件“App模块配置”项的“OAuth(登录鉴权)”下,勾选“新浪微博登录”项,并输入从新浪微博开放平台申请的参数:

  • appkey: "新浪微博平台应用appkey";
  • appsecret: "新浪微博平台应用appsecret";
  • redirect_uri: "新浪微博平台应用授权回调页地址"。

配置完成后Ctrl+S保存提交App云端打包生效。

<a id="secret"></a>

配置参数安全性问题

在HBuilder|HBuilderX中配置的参数云端打包后会保存在apk/ipa中,对于安全性要求高的开发者可能担心存在参数泄露的风险,可以采取以下方式处理。

  • JS代码中动态传参数
    如登录服务AuthService的请求授权认证方法authorize,可以通过第三个参数options动态传入appid、appSecret等。
    这些参数可以加密保存到js代码中或连网从服务器获取(避免保存在本地引起泄露风险,当然需要考虑网络传输过程的安全问题)。

  • 通过服务器完成授权认证
    根据OAuth规范,实际客户端授权只是为了获取授权临时票据(code),这时候可以仅在客户端配置appid参数调用登录服务AuthService的请求授权认证方法authorize获取临时票据,将票据提交到服务器完成后续的操作。
    这种情况授权的参数(如appsecret)仅保存服务器即可,安全性更高。
    在服务器的对接流程需要根据各开放平台的规范要求进行处理,如微信参考:授权后接口调用

这时在HBuilder|HBuilderX中可以填入任意值提交云端打包

收起阅读 »

Android证书的生成和指纹获取

可能iOS下各种证书的繁杂,所以官方只给出了iOS系统下证书的生成说明,Android证书的生成的确很简单,我简单说明一下:
1、安装JDK
2、在cmd下,进入到JDK的bin目录,输入:
keytool -genkey -alias yourapp -keyalg RSA -validity 20000 -keystore yourapp.keystore
说明:yourapp就是证书的别名,20000是证书的有效天数,yourapp.keystore就是生成的证书名字。
3、一路根据指示设置密码,组织等,注意密码是不会显示或者以***代替,但是其实已经输入了。确认后选择Y,生成的证书会在bin目录下。
4、获取证书的指纹,输入:
keytool -list -v -keystore "D:\Program Files\Java\jdk1.8.0_40\bin\yourapp.keystore" -alias yourapp
路径请使用自己安装JDK的路径代替。
这样就可以获取MD5、SHA1的证书指纹。

的确很简单,但是的确有人不会,譬如说我以前就不会,囧。
列出来,以供大家查阅。

继续阅读 »

可能iOS下各种证书的繁杂,所以官方只给出了iOS系统下证书的生成说明,Android证书的生成的确很简单,我简单说明一下:
1、安装JDK
2、在cmd下,进入到JDK的bin目录,输入:
keytool -genkey -alias yourapp -keyalg RSA -validity 20000 -keystore yourapp.keystore
说明:yourapp就是证书的别名,20000是证书的有效天数,yourapp.keystore就是生成的证书名字。
3、一路根据指示设置密码,组织等,注意密码是不会显示或者以***代替,但是其实已经输入了。确认后选择Y,生成的证书会在bin目录下。
4、获取证书的指纹,输入:
keytool -list -v -keystore "D:\Program Files\Java\jdk1.8.0_40\bin\yourapp.keystore" -alias yourapp
路径请使用自己安装JDK的路径代替。
这样就可以获取MD5、SHA1的证书指纹。

的确很简单,但是的确有人不会,譬如说我以前就不会,囧。
列出来,以供大家查阅。

收起阅读 »

【分享】头像类裁剪上传

头像裁剪

夜深了,分享个头像类的裁剪上传,代码写的比较啰嗦。
虽然说用jquery渲染力差,没办法,还是用了。然后借助cropper来完成裁剪

<script src="plugin/avatar/js/jquery.min.js"></script>  
<script src="plugin/avatar/js/cropper.js"></script>  
<link href="plugin/avatar/css/cropper.css" rel="stylesheet">

照片容器

<a href="#picture"><div id="changeAvatar"></div></a>

裁剪照片的容器(样式就自己写了)

<div id="showEdit">  
        <header class="mui-bar mui-bar-nav mui-nav-bg" style="background:none; position:absolute; top:0;">  
            <a class="mui-icon iconfont icon-roundclosefill mui-pull-left" style="color:#ffffff; font-size:36px;" onclick="closeEdit();"></a>  
            <a class="mui-icon iconfont icon-roundcheckfill mui-pull-right" style="color:#ffffff; font-size:36px;" onclick="confirm();"></a>  
        </header>  
        <div id="report"></div>  
    </div>

下面就很简单了,调用下相机和相册选择图片。然后加入cropper的几行代码就搞定了

//拍照  
function getImage() {  
    var cmr = plus.camera.getCamera();  
    cmr.captureImage( function (p) {  
        plus.io.resolveLocalFileSystemURL( p, function ( entry ) {      
            var localurl = entry.toLocalURL();//  
            $("#report").html('<img src="'+localurl+'">');  
            cutImg();  
            mui('#picture').popover('toggle');  
        });  
    });  
}  
//相册选取  
function galleryImgs(){  
    plus.gallery.pick( function(e){  
        $("#report").html('<img src="'+e.files[0]+'">');  
        cutImg();  
        mui('#picture').popover('toggle');  
    }, function ( e ) {  
        //outSet( "取消选择图片" );  
    },{filter:"image",multiple:true});  
}

照片裁剪类:

function cutImg(){    
    $("#showEdit").fadeIn();  
    var $image = $('#report > img');  
    $image.cropper({  
      aspectRatio: 1 / 1,  
      autoCropArea: 0.8  
    });  
}

确定裁剪并上传(base64)

function confirm(){  

    $("#showEdit").fadeOut();  
    var $image = $('#report > img');  
    var dataURL = $image.cropper("getDataURL");  
    $("#changeAvatar").html('<img src="'+dataURL+'" />');  
}  

function postAvatar() {  

    var $image = $('#report > img');  
    var dataURL = $image.cropper("getDataURL");  
    var data = {  
            base64: dataURL  
    };  
    $.post(url,data,function(data){  
        //这里就自己写了哈  
    });  
};

效果

有高手可以补充下的谢谢啦哈

继续阅读 »

夜深了,分享个头像类的裁剪上传,代码写的比较啰嗦。
虽然说用jquery渲染力差,没办法,还是用了。然后借助cropper来完成裁剪

<script src="plugin/avatar/js/jquery.min.js"></script>  
<script src="plugin/avatar/js/cropper.js"></script>  
<link href="plugin/avatar/css/cropper.css" rel="stylesheet">

照片容器

<a href="#picture"><div id="changeAvatar"></div></a>

裁剪照片的容器(样式就自己写了)

<div id="showEdit">  
        <header class="mui-bar mui-bar-nav mui-nav-bg" style="background:none; position:absolute; top:0;">  
            <a class="mui-icon iconfont icon-roundclosefill mui-pull-left" style="color:#ffffff; font-size:36px;" onclick="closeEdit();"></a>  
            <a class="mui-icon iconfont icon-roundcheckfill mui-pull-right" style="color:#ffffff; font-size:36px;" onclick="confirm();"></a>  
        </header>  
        <div id="report"></div>  
    </div>

下面就很简单了,调用下相机和相册选择图片。然后加入cropper的几行代码就搞定了

//拍照  
function getImage() {  
    var cmr = plus.camera.getCamera();  
    cmr.captureImage( function (p) {  
        plus.io.resolveLocalFileSystemURL( p, function ( entry ) {      
            var localurl = entry.toLocalURL();//  
            $("#report").html('<img src="'+localurl+'">');  
            cutImg();  
            mui('#picture').popover('toggle');  
        });  
    });  
}  
//相册选取  
function galleryImgs(){  
    plus.gallery.pick( function(e){  
        $("#report").html('<img src="'+e.files[0]+'">');  
        cutImg();  
        mui('#picture').popover('toggle');  
    }, function ( e ) {  
        //outSet( "取消选择图片" );  
    },{filter:"image",multiple:true});  
}

照片裁剪类:

function cutImg(){    
    $("#showEdit").fadeIn();  
    var $image = $('#report > img');  
    $image.cropper({  
      aspectRatio: 1 / 1,  
      autoCropArea: 0.8  
    });  
}

确定裁剪并上传(base64)

function confirm(){  

    $("#showEdit").fadeOut();  
    var $image = $('#report > img');  
    var dataURL = $image.cropper("getDataURL");  
    $("#changeAvatar").html('<img src="'+dataURL+'" />');  
}  

function postAvatar() {  

    var $image = $('#report > img');  
    var dataURL = $image.cropper("getDataURL");  
    var data = {  
            base64: dataURL  
    };  
    $.post(url,data,function(data){  
        //这里就自己写了哈  
    });  
};

效果

有高手可以补充下的谢谢啦哈

收起阅读 »

夜深了,分享个思路,解决图片“表面”上秒传效果

接触5+有一个月了,也是接触APP开发有一个月了。今天先分享个思路出来,供大家参考。
图片上传传统解决方案:
1.选择图片

  1. 可能还要经过canvas的压缩处理
  2. 传到服务器返回图片url,或者点击发布同时上传
    这样的流程无疑会造成发布时间慢,用户体验性差。
    解决思路,现在还是个思路,明天开始敲
    1.选择图片
  3. 返回图片本地地址
  4. 点击发布写入本地存储(websql),列表页就调用这个本地数据了
  5. 写个js在后台开始慢慢处理数据与服务器的同步
    表面上用户会以为自己发布的图片已经秒速发布成功,还能在列表页看到刚刚发布的内容。实际还在后面慢慢的同步。

有高手可以帮忙完善下思路或者敲两下代码的感激不尽~

继续阅读 »

接触5+有一个月了,也是接触APP开发有一个月了。今天先分享个思路出来,供大家参考。
图片上传传统解决方案:
1.选择图片

  1. 可能还要经过canvas的压缩处理
  2. 传到服务器返回图片url,或者点击发布同时上传
    这样的流程无疑会造成发布时间慢,用户体验性差。
    解决思路,现在还是个思路,明天开始敲
    1.选择图片
  3. 返回图片本地地址
  4. 点击发布写入本地存储(websql),列表页就调用这个本地数据了
  5. 写个js在后台开始慢慢处理数据与服务器的同步
    表面上用户会以为自己发布的图片已经秒速发布成功,还能在列表页看到刚刚发布的内容。实际还在后面慢慢的同步。

有高手可以帮忙完善下思路或者敲两下代码的感激不尽~

收起阅读 »

分享一个检测iOS是否允许使用相机的Native.js

var AVCaptureDevice = plus.ios.importClass("AVCaptureDevice");  
var Status = AVCaptureDevice.authorizationStatusForMediaType("vide");  
if (3 != Status) {  
    var btnArray = ['确定'];  
    mui.confirm(' ','请在设置中允许使用相机',btnArray,function(e) {});  
}

注意此功能在iOS7.0以上设备才支持!

继续阅读 »
var AVCaptureDevice = plus.ios.importClass("AVCaptureDevice");  
var Status = AVCaptureDevice.authorizationStatusForMediaType("vide");  
if (3 != Status) {  
    var btnArray = ['确定'];  
    mui.confirm(' ','请在设置中允许使用相机',btnArray,function(e) {});  
}

注意此功能在iOS7.0以上设备才支持!

收起阅读 »

Native.js可以获取安卓的短信内容吗

Native.JS

想做个验证的功能,客户编辑了内容发到我的手机上,然后获取发过来的短信类容,POST到服务器然后进行绑定操作,不要问为啥不用短信接口给客户发送验证码,特么的太穷了,耗不起啊!

想做个验证的功能,客户编辑了内容发到我的手机上,然后获取发过来的短信类容,POST到服务器然后进行绑定操作,不要问为啥不用短信接口给客户发送验证码,特么的太穷了,耗不起啊!

关于使用中过程中的jQuery代码提示建议

真心很喜欢hbuilder,现在在努力的从sublime往hbuilder转;但是很多时候觉得hbuilder的很多地方还有待完善;不得不得在使用的过程中再打开sublime;例如jQuery的代码提示;
同样是打hover、click、post;回车,生成的代码如下;
hbuilder:
$(fucntion(){
$('#test').hover();
$('#test').click();
$.post()

})
sublime:
$(function(){
$('#test').hover(function() {
/ Stuff to do when the mouse enters the element /
}, function() {
/ Stuff to do when the mouse leaves the element /
});
$('#test').click(function(event) {
/ Act on the event /
});
$.post('/path/to/file', param1: 'value1', function(data, textStatus, xhr) {
/optional stuff to do after success /
});
})
还有就是直接打开远程服务器端的文件;hbuilder不能使用less和jQuery提示;
渴望hbuilder的代码提示功能可以加强;
愿hbuilder越来越完善;

继续阅读 »

真心很喜欢hbuilder,现在在努力的从sublime往hbuilder转;但是很多时候觉得hbuilder的很多地方还有待完善;不得不得在使用的过程中再打开sublime;例如jQuery的代码提示;
同样是打hover、click、post;回车,生成的代码如下;
hbuilder:
$(fucntion(){
$('#test').hover();
$('#test').click();
$.post()

})
sublime:
$(function(){
$('#test').hover(function() {
/ Stuff to do when the mouse enters the element /
}, function() {
/ Stuff to do when the mouse leaves the element /
});
$('#test').click(function(event) {
/ Act on the event /
});
$.post('/path/to/file', param1: 'value1', function(data, textStatus, xhr) {
/optional stuff to do after success /
});
})
还有就是直接打开远程服务器端的文件;hbuilder不能使用less和jQuery提示;
渴望hbuilder的代码提示功能可以加强;
愿hbuilder越来越完善;

收起阅读 »

MUI+HTML5+集成 IOS Weibo APP例子

HBuilder HTML5+ mui

最近闲得蛋痛,无意间发现了这么个东东,看看觉得还行,于是乎准备写个demo来玩玩,这一写不要紧,看到官方的文档,立马蛋都碎了~这~~
想查个API真是翻山越岭,走遍大江南北,什么百度、Google、360翻了个底朝天,就连个简单的demo都没人放出来,真是心碎了,好吧!事以至此还是看官方的组件例子吧,这个CSS啊,JS啊看得是头晕眼花,而且还不带任何关联的,这要写个成型的东东出来逼得死人哇。好在我这个人是个打不死的小强,我就不信了爷还征服不了你,立马菊花一紧,饭也不用吃了,水也不要喝了,烟也不要抽了,盯着个HBuilder码呀码呀码,码到一半都想砸电脑了,低头一看,得了还是别砸了,这尼玛是公司的Mac!认命吧,接着码,突然灵光一闪,醍醐灌顶,我艹,原来是这么回事哇,原来晚上才是IT男的天下,这句话真是一点都没错呀。好吧,经过一天的努力终于有个demo的样子了,收工了,打豆豆!!!!

继续阅读 »

最近闲得蛋痛,无意间发现了这么个东东,看看觉得还行,于是乎准备写个demo来玩玩,这一写不要紧,看到官方的文档,立马蛋都碎了~这~~
想查个API真是翻山越岭,走遍大江南北,什么百度、Google、360翻了个底朝天,就连个简单的demo都没人放出来,真是心碎了,好吧!事以至此还是看官方的组件例子吧,这个CSS啊,JS啊看得是头晕眼花,而且还不带任何关联的,这要写个成型的东东出来逼得死人哇。好在我这个人是个打不死的小强,我就不信了爷还征服不了你,立马菊花一紧,饭也不用吃了,水也不要喝了,烟也不要抽了,盯着个HBuilder码呀码呀码,码到一半都想砸电脑了,低头一看,得了还是别砸了,这尼玛是公司的Mac!认命吧,接着码,突然灵光一闪,醍醐灌顶,我艹,原来是这么回事哇,原来晚上才是IT男的天下,这句话真是一点都没错呀。好吧,经过一天的努力终于有个demo的样子了,收工了,打豆豆!!!!

收起阅读 »