mui图片预览(perviewimage)的优化
mui图片预览(perviewimage)的优化
更好的显示效果看这http://www.cnblogs.com/phillyx/p/5164231.html
主要对mui图片全屏预览插件做了以下三点补充
1.添加了预览图片文字说明,使用的时候需要添加以下css及DOM属性
.mui-slider-img-content {
position: absolute;
bottom: 10px;
left: 10px;
right: 10px;
color: white;
text-align: center;
line-height: 21px
}
<img src="../images/yuantiao.jpg" data-preview-src="" data-preview-group="2" data-content="这里是文字说明"/>
2.如果图片过宽或过长,预加载图片(上一张或下一张)时,会和当前显示的图片重叠
原来的效果是这样

主要对缩放进行了更改
proto._initImgData = function(itemData, imgEl) {
if (!itemData.sWidth) {
var img = itemData.el;
itemData.sWidth = img.offsetWidth;
itemData.sHeight = img.offsetHeight;
var offset = $.offset(img);
itemData.sTop = offset.top;
itemData.sLeft = offset.left;
//缩放判断,解决预加载图片时,图片过大,和当前显示图片重叠的问题
//未更改之前缩放比例能达到2.5倍以上
var scale = Math.max(itemData.sWidth / window.innerWidth, itemData.sHeight / window.innerHeight);
itemData.sScale = scale > 1 ? 0.977 : scale;
}
imgEl.style.webkitTransform = 'translate3d(0,0,0) scale(' + itemData.sScale + ')';
};
3.解决了预加载页面返回(mui.back)重新加载数据并打开时,预览无用的问题
主要应用场景是这样的:
- view是预加载的,返回时view隐藏,DOM重置,
- 如果不清除当前预览对象previmage的话,加载数据后打开当前页面,重新调用mui.previewImage()无效,依然是第一次的预览的
DOM结果 - 因为插件源码决定了该对象是不变的
var previewImageApi = null; $.previewImage = function(options) { if (!previewImageApi) { previewImageApi = new PreviewImage(options); } return previewImageApi; }; - 有朋友会问,为毛要预加载,为什么不通过loadurl或其他方式刷新页面(或DOM)?
- 就为了优化性能,秒开页面,整个详情页的代码前前后后改了一个多星期
- 我不可能因为插件的不完整而放弃优化的成果。
- 所以就有了以下的代码
//释放当前对象及清除DOM proto.dispose = function() { var prevdom = document.getElementById("__MUI_PREVIEWIMAGE"); prevdom && prevdom.parentNode.removeChild(prevdom); previewImageApi = null; };
具体代码在这https://github.com/phillyx/mui/blob/master/examples/hello-mui/examples/imageviewer.html
mui图片预览(perviewimage)的优化
更好的显示效果看这http://www.cnblogs.com/phillyx/p/5164231.html
主要对mui图片全屏预览插件做了以下三点补充
1.添加了预览图片文字说明,使用的时候需要添加以下css及DOM属性
.mui-slider-img-content {
position: absolute;
bottom: 10px;
left: 10px;
right: 10px;
color: white;
text-align: center;
line-height: 21px
}
<img src="../images/yuantiao.jpg" data-preview-src="" data-preview-group="2" data-content="这里是文字说明"/>
2.如果图片过宽或过长,预加载图片(上一张或下一张)时,会和当前显示的图片重叠
原来的效果是这样

主要对缩放进行了更改
proto._initImgData = function(itemData, imgEl) {
if (!itemData.sWidth) {
var img = itemData.el;
itemData.sWidth = img.offsetWidth;
itemData.sHeight = img.offsetHeight;
var offset = $.offset(img);
itemData.sTop = offset.top;
itemData.sLeft = offset.left;
//缩放判断,解决预加载图片时,图片过大,和当前显示图片重叠的问题
//未更改之前缩放比例能达到2.5倍以上
var scale = Math.max(itemData.sWidth / window.innerWidth, itemData.sHeight / window.innerHeight);
itemData.sScale = scale > 1 ? 0.977 : scale;
}
imgEl.style.webkitTransform = 'translate3d(0,0,0) scale(' + itemData.sScale + ')';
};
3.解决了预加载页面返回(mui.back)重新加载数据并打开时,预览无用的问题
主要应用场景是这样的:
- view是预加载的,返回时view隐藏,DOM重置,
- 如果不清除当前预览对象previmage的话,加载数据后打开当前页面,重新调用mui.previewImage()无效,依然是第一次的预览的
DOM结果 - 因为插件源码决定了该对象是不变的
var previewImageApi = null; $.previewImage = function(options) { if (!previewImageApi) { previewImageApi = new PreviewImage(options); } return previewImageApi; }; - 有朋友会问,为毛要预加载,为什么不通过loadurl或其他方式刷新页面(或DOM)?
- 就为了优化性能,秒开页面,整个详情页的代码前前后后改了一个多星期
- 我不可能因为插件的不完整而放弃优化的成果。
- 所以就有了以下的代码
//释放当前对象及清除DOM proto.dispose = function() { var prevdom = document.getElementById("__MUI_PREVIEWIMAGE"); prevdom && prevdom.parentNode.removeChild(prevdom); previewImageApi = null; };
具体代码在这https://github.com/phillyx/mui/blob/master/examples/hello-mui/examples/imageviewer.html
收起阅读 »关于H5电子签名的实现。
最近一个项目需要客户在提交单据的时候,附带签名。度娘了一下。果然还是有这个JQuery插件的。学名:jSignature
好了,废话不多说。先来个截图(见附件)。这玩意功能还是比较强大的。支持各种设置和各种姿势的导出。可惜是在JQuery里的,得先引用JQuery.
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jSignature.min.js"></script>
<!--[if lt IE 9]>
<script type="text/javascript" src="js/flashcanvas.js"></script>
<![endif]-->
下面就简单了,给一个dom.比如这样的:
<div id="signature" style="height: 100%;"></div>
最后呢,就是初始化一下。可以这样的:
$(document).ready(function() {
$("#signature").jSignature()
});
要是想导出呢,这里是Base64,就要这样的:
var datapair = $("#signature").jSignature("getData", "image");
var array = datapair.splice(",");
mui.toast(array[1]);
好了,其他也就没什么 了。更多了解就去看 api 吧。
最后在附上js包,希望对大家有帮助。
最近一个项目需要客户在提交单据的时候,附带签名。度娘了一下。果然还是有这个JQuery插件的。学名:jSignature
好了,废话不多说。先来个截图(见附件)。这玩意功能还是比较强大的。支持各种设置和各种姿势的导出。可惜是在JQuery里的,得先引用JQuery.
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jSignature.min.js"></script>
<!--[if lt IE 9]>
<script type="text/javascript" src="js/flashcanvas.js"></script>
<![endif]-->
下面就简单了,给一个dom.比如这样的:
<div id="signature" style="height: 100%;"></div>
最后呢,就是初始化一下。可以这样的:
$(document).ready(function() {
$("#signature").jSignature()
});
要是想导出呢,这里是Base64,就要这样的:
var datapair = $("#signature").jSignature("getData", "image");
var array = datapair.splice(",");
mui.toast(array[1]);
好了,其他也就没什么 了。更多了解就去看 api 吧。
最后在附上js包,希望对大家有帮助。
修复mui中多选项卡切换时,隐藏选项卡初始化属性不正确的问题.
同页面中多选项卡切换显示时,由于隐藏的选项卡无法获得offsetWidth属性,导致初始隐藏的选项卡后期显示时,选项卡标签条无法根据正确的当前项滚动.
此方法属于补救措施,不修改mui.js源文件.具体事件绑定因项目架构而异,以下只作比方.
假设A, B, C, D控制4个选项卡的显/隐.每个选项卡包含N个子项.
4个选项卡分别为A_s, B_s, C_s, D_s
document.getElementById(A).addEventListener('tap', function (){
var slider_id = document.querySelector(A_s).getAttribute('data-slider');
var slider_data = mui.data[slider_id];
var progressBarWidth = slider_data.progressBarWidth;
if (!progressBarWidth) {
slider_data.progressBarWidth = document.querySelector(A_s).querySelector('.mui-slider-progress-bar').offsetWidth;
}
})
修复前:
修复后:
同页面中多选项卡切换显示时,由于隐藏的选项卡无法获得offsetWidth属性,导致初始隐藏的选项卡后期显示时,选项卡标签条无法根据正确的当前项滚动.
此方法属于补救措施,不修改mui.js源文件.具体事件绑定因项目架构而异,以下只作比方.
假设A, B, C, D控制4个选项卡的显/隐.每个选项卡包含N个子项.
4个选项卡分别为A_s, B_s, C_s, D_s
document.getElementById(A).addEventListener('tap', function (){
var slider_id = document.querySelector(A_s).getAttribute('data-slider');
var slider_data = mui.data[slider_id];
var progressBarWidth = slider_data.progressBarWidth;
if (!progressBarWidth) {
slider_data.progressBarWidth = document.querySelector(A_s).querySelector('.mui-slider-progress-bar').offsetWidth;
}
})
修复前:
修复后:
配合下拉刷新、上拉加载的返回顶部demo(适用任何页面)
看到很多人提到了这个问题,正好自己也需要返回顶部的操作,总结了下各处的问题与回答,把实现的代码放出来,供参考。
下拉刷新、上拉加载的容器和返回顶部按钮,按钮默认不显示:
<div id="pullrefresh" class="mui-scroll-wrapper">
<div class="mui-scroll">
<ul id="list" class="mui-table-view"></ul>
</div>
</div>
<a id="scrollToTop" class="backTop hide">
<span class="mui-icon mui-icon-arrowup"></span>
</a>
按钮对应的css:
.hide {
display: none;
}
.backTop {
background: #DDDDDD;
border-radius: 50%;
position: fixed;
right: 10px;
bottom: 15px;
width: 38px;
height: 38px;
z-index: 9999;
text-align: center;
font-size: 18px;
color: #666666;
padding-top: 8px;
opacity: 0.8;
}
js中添加事件监听:
var scrollToTopBox = document.getElementById('scrollToTop');
//返回按钮tap
scrollToTopBox.addEventListener('tap', function(e) {
e.stopPropagation();
mui('#pullrefresh').pullRefresh().scrollTo(0, 0, 100);//滚动到顶部
});
//Android上监听原生滚动,iOS上监听div滚动,上拉超过一屏后显示按钮,否则隐藏,可自行在条件判断中修改
if (mui.os.android) {
window.addEventListener('scroll', function(e) {
if (window.pageYOffset >= window.innerHeight && scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.remove('hide');
else if (window.pageYOffset < window.innerHeight && !scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.add('hide');
});
} else {
document.getElementById('pullrefresh').addEventListener('scroll', function() {
if (mui('#pullrefresh').pullRefresh().y <= window.innerHeight * (-1) && scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.remove('hide');
else if (mui('#pullrefresh').pullRefresh().y > window.innerHeight * (-1) && !scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.add('hide');
});
}
该方法也可用于任何需要返回顶部的页面,做一下适当的修改,此时不区分Android和iOS,代码如下:
var scrollToTopBox = document.getElementById('scrollToTop');
scrollToTopBox.addEventListener('tap', function(e) {
e.stopPropagation();
mui('body').pullRefresh().scrollTo(0, 0, 100);
});
window.addEventListener('scroll', function() {
if (window.pageYOffset >= window.innerHeight && scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.remove('hide');
else if (window.pageYOffset < window.innerHeight && !scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.add('hide');
}); 看到很多人提到了这个问题,正好自己也需要返回顶部的操作,总结了下各处的问题与回答,把实现的代码放出来,供参考。
下拉刷新、上拉加载的容器和返回顶部按钮,按钮默认不显示:
<div id="pullrefresh" class="mui-scroll-wrapper">
<div class="mui-scroll">
<ul id="list" class="mui-table-view"></ul>
</div>
</div>
<a id="scrollToTop" class="backTop hide">
<span class="mui-icon mui-icon-arrowup"></span>
</a>
按钮对应的css:
.hide {
display: none;
}
.backTop {
background: #DDDDDD;
border-radius: 50%;
position: fixed;
right: 10px;
bottom: 15px;
width: 38px;
height: 38px;
z-index: 9999;
text-align: center;
font-size: 18px;
color: #666666;
padding-top: 8px;
opacity: 0.8;
}
js中添加事件监听:
var scrollToTopBox = document.getElementById('scrollToTop');
//返回按钮tap
scrollToTopBox.addEventListener('tap', function(e) {
e.stopPropagation();
mui('#pullrefresh').pullRefresh().scrollTo(0, 0, 100);//滚动到顶部
});
//Android上监听原生滚动,iOS上监听div滚动,上拉超过一屏后显示按钮,否则隐藏,可自行在条件判断中修改
if (mui.os.android) {
window.addEventListener('scroll', function(e) {
if (window.pageYOffset >= window.innerHeight && scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.remove('hide');
else if (window.pageYOffset < window.innerHeight && !scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.add('hide');
});
} else {
document.getElementById('pullrefresh').addEventListener('scroll', function() {
if (mui('#pullrefresh').pullRefresh().y <= window.innerHeight * (-1) && scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.remove('hide');
else if (mui('#pullrefresh').pullRefresh().y > window.innerHeight * (-1) && !scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.add('hide');
});
}
该方法也可用于任何需要返回顶部的页面,做一下适当的修改,此时不区分Android和iOS,代码如下:
var scrollToTopBox = document.getElementById('scrollToTop');
scrollToTopBox.addEventListener('tap', function(e) {
e.stopPropagation();
mui('body').pullRefresh().scrollTo(0, 0, 100);
});
window.addEventListener('scroll', function() {
if (window.pageYOffset >= window.innerHeight && scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.remove('hide');
else if (window.pageYOffset < window.innerHeight && !scrollToTopBox.classList.contains('hide'))
scrollToTopBox.classList.add('hide');
}); 收起阅读 »
Android Studio 离线打包
android studio 版本1.5
android studio新建工程
libs 添加需要的jar包
src/main/assets/apps/对应的id/www/项目
src/main/assets/data 从 Android-SDK/SDK/assets/data 拷贝来的
src/main/java/io/dcloud/RInformation.java 从 Android-SDK\SDK\src 拷贝来的
src/main/res 从 Android-SDK\SDK\res 拷贝来的
ps: 1.5下面只有一个drawable,剩下的是mipmap-hdpi、mipmap-mdpi等等,所以是拷贝的文件内容,而不是整个文件夹
androidmanifest.xml中application
<application
android:allowBackup="true"
android:icon="@mipmap/icon"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name="io.dcloud.PandoraEntry"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:launchMode="singleTask"
android:screenOrientation="user"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="io.dcloud.PandoraEntryActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:hardwareAccelerated="true"
android:label="5+Debug"
android:launchMode="singleTask"
android:screenOrientation="user"
android:theme="@style/DCloudTheme"
android:windowSoftInputMode="adjustResize" >
</activity>
<service
android:name="io.dcloud.common.adapter.io.MiniServerService"
android:exported="true" />
</application>
activity,service 中 android:name 依赖的是pdr.jar
不知道这个jar包是做什么的,少引用时出错了。猜测和图片有关
universal-image-loader-1.9.0.jar
其他的可以参考如下链接:
SDK下载地址:http://ask.dcloud.net.cn/article/103
Android平台离线打包插件配置:http://ask.dcloud.net.cn/article/216
还有这个文章: http://ask.dcloud.net.cn/question/15183
android studio 版本1.5
android studio新建工程
libs 添加需要的jar包
src/main/assets/apps/对应的id/www/项目
src/main/assets/data 从 Android-SDK/SDK/assets/data 拷贝来的
src/main/java/io/dcloud/RInformation.java 从 Android-SDK\SDK\src 拷贝来的
src/main/res 从 Android-SDK\SDK\res 拷贝来的
ps: 1.5下面只有一个drawable,剩下的是mipmap-hdpi、mipmap-mdpi等等,所以是拷贝的文件内容,而不是整个文件夹
androidmanifest.xml中application
<application
android:allowBackup="true"
android:icon="@mipmap/icon"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name="io.dcloud.PandoraEntry"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:launchMode="singleTask"
android:screenOrientation="user"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="io.dcloud.PandoraEntryActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:hardwareAccelerated="true"
android:label="5+Debug"
android:launchMode="singleTask"
android:screenOrientation="user"
android:theme="@style/DCloudTheme"
android:windowSoftInputMode="adjustResize" >
</activity>
<service
android:name="io.dcloud.common.adapter.io.MiniServerService"
android:exported="true" />
</application>
activity,service 中 android:name 依赖的是pdr.jar
不知道这个jar包是做什么的,少引用时出错了。猜测和图片有关
universal-image-loader-1.9.0.jar
其他的可以参考如下链接:
SDK下载地址:http://ask.dcloud.net.cn/article/103
Android平台离线打包插件配置:http://ask.dcloud.net.cn/article/216
还有这个文章: http://ask.dcloud.net.cn/question/15183
将tap模拟成原生click体验
将tap模拟成原生click体验
mui提供了tap事件替换了html5的click事件,解决了300ms延时的问题。不过相比原生app的click体验还是有些许差距的。
仅用微信为例,只有当手指离开屏幕时才触发click事件,如果对象绑定了长按事件,则触发长按操作,离开时不再触发单击事件。
这些逻辑无论是android, ios或者仅有1%的windows mobile都已经封装好了,根本不用关心。
那么,我们应该怎么来实现呢?
下面是详细的填坑历程。。。。。。
坑1.通过原生的touch来实现
//直接对dom添加touchend,这种方法只能针对位置不变且并没有添加longtap事件的DOM有效
//如果在listview中,你上下滑动,那就歇菜了。
//那么自然而然就想到了touch.target的位移,并做出判断是下滑还是单击。
//自己去写复杂度、代码量估计会很可观。
//因此就想到了了在原有的框架代码上去实现。
//下面就到了坑2
document.getElementById("").('touchend', function() {
//
});
坑2.更改mui.gestures.tap.js
坑2.1 自定义事件侦听机制
mui没有提供类似于jq.data('events')获取事件列表的机制,另外官方也推荐使用addEventListener去绑定事件。
我要去获取当前DOM的事件列表应该怎么做呢?
你问我问毛要去获取DOM的事件列表,,,
呵呵,我总要知道DOM有木有绑定longtap事件好做规避吧
csdn的这个帖子看似有用
http://bbs.csdn.net/topics/390250552
function addEvent(dom,type,fn) {
if(document.addEventListener) {
dom.addEventListener(type, fn, false);
} else if(document.attachEvent) {
dom.attachEvent('on' + type, fn);
} else {
dom['on' + type] = fn;
};
dom[""+type]=!0;
}
实际上并没有什么卵用
思想是好的.....
我总不能每次addEventListener都去调一下这个方法吧!
坑2.2 使用getEventListeners
找啊找,终于找到了getEventListeners()这个全局方法,在chrome和safari控制台中测试都木有问题。
喜出望外......
这下终于能解决问题了
于是有了以下的方法
var getEvents = function(obj) {
console.log(getEventListeners(obj));
return typeof(getEventListeners) == "function" && getEventListeners(obj);
}
var hasEventype = function(obj, e) {
var es = getEvents(obj);
console.log(es[e]);
return es && !!es[e];
}
调用下试试
if (!hasEventype(target, 'longtap')) {}
报错
getEventListeners is undefined
R U kidding?!!!!
你丫在逗我.............
我瞬间感受到了深深地恶意
原来这个方法只能在控制台中用,
呵呵,人艰不拆......
坑2.3 使用全局变量规避
给mui添加一个全局变量isLongTapAtived,看变量名就知道什么意思吧
在mui.gestures.longtap.js中初始化,在handle中激活
(function($, name) {
$.isLongTapAtived = false;//初始化
var timer;
var handle = function(event, touch) {
switch (event.type) {
case $.EVENT_START:
clearTimeout(timer);
timer = setTimeout(function() {
$.trigger(session.target, name, touch);
//激活了
$.isLongTapAtived = true;
}, options.holdTimeout);
break;
}
};
});
})(mui, 'longtap');
在mui.gestures.tap.js中判断有无激活
var handle = function(event, touch) {
var session = $.gestures.session;
var options = this.options;
switch (event.type) {
case $.EVENT_END:
//......
if (touch.distance < options.tapMaxDistance) {
if (touch.deltaTime < options.tapMaxTime) {
//.....
} else {
//如果当前对象添加了长按侦听,略过,否则仍然视为tap事件
//if (!hasEventype(target, 'longtap')) {
if (!$.isLongTapAtived) {
//如果没有longtap事件,离开屏幕是触发tap事件
$.trigger(target, name, touch);
}
//重置
$.isLongTapAtived = false;
}
}
break;
}
};
想法是美好的,现实是他么残酷的。无论有无longtap事件,都要走一遍longtap的handle代码
于是 $.isLongTapAtived === true;
于是 永远trigger tap 事件
呵呵,想死的心都有了
路子看来走对了,但是应该怎么做???
终极解决方案
mui.isLongTapAtived依然添加,只是在每一次DOM添加的longtap事件内激活
document.querySelector("#").addEventListener('longtap',function(){
mui.isLongTapAtived=true;
console.log('你触发了longtap事件');
});
这样对开发者是不友好的,不过暂时没办法,只能如此取舍了
代码已提交至https://github.com/phillyx/mui/
并推送给官方
博客已同步至http://www.cnblogs.com/phillyx/p/5157850.html
觉得不错就打赏一下吧
将tap模拟成原生click体验
mui提供了tap事件替换了html5的click事件,解决了300ms延时的问题。不过相比原生app的click体验还是有些许差距的。
仅用微信为例,只有当手指离开屏幕时才触发click事件,如果对象绑定了长按事件,则触发长按操作,离开时不再触发单击事件。
这些逻辑无论是android, ios或者仅有1%的windows mobile都已经封装好了,根本不用关心。
那么,我们应该怎么来实现呢?
下面是详细的填坑历程。。。。。。
坑1.通过原生的touch来实现
//直接对dom添加touchend,这种方法只能针对位置不变且并没有添加longtap事件的DOM有效
//如果在listview中,你上下滑动,那就歇菜了。
//那么自然而然就想到了touch.target的位移,并做出判断是下滑还是单击。
//自己去写复杂度、代码量估计会很可观。
//因此就想到了了在原有的框架代码上去实现。
//下面就到了坑2
document.getElementById("").('touchend', function() {
//
});
坑2.更改mui.gestures.tap.js
坑2.1 自定义事件侦听机制
mui没有提供类似于jq.data('events')获取事件列表的机制,另外官方也推荐使用addEventListener去绑定事件。
我要去获取当前DOM的事件列表应该怎么做呢?
你问我问毛要去获取DOM的事件列表,,,
呵呵,我总要知道DOM有木有绑定longtap事件好做规避吧
csdn的这个帖子看似有用
http://bbs.csdn.net/topics/390250552
function addEvent(dom,type,fn) {
if(document.addEventListener) {
dom.addEventListener(type, fn, false);
} else if(document.attachEvent) {
dom.attachEvent('on' + type, fn);
} else {
dom['on' + type] = fn;
};
dom[""+type]=!0;
}
实际上并没有什么卵用
思想是好的.....
我总不能每次addEventListener都去调一下这个方法吧!
坑2.2 使用getEventListeners
找啊找,终于找到了getEventListeners()这个全局方法,在chrome和safari控制台中测试都木有问题。
喜出望外......
这下终于能解决问题了
于是有了以下的方法
var getEvents = function(obj) {
console.log(getEventListeners(obj));
return typeof(getEventListeners) == "function" && getEventListeners(obj);
}
var hasEventype = function(obj, e) {
var es = getEvents(obj);
console.log(es[e]);
return es && !!es[e];
}
调用下试试
if (!hasEventype(target, 'longtap')) {}
报错
getEventListeners is undefined
R U kidding?!!!!
你丫在逗我.............
我瞬间感受到了深深地恶意
原来这个方法只能在控制台中用,
呵呵,人艰不拆......
坑2.3 使用全局变量规避
给mui添加一个全局变量isLongTapAtived,看变量名就知道什么意思吧
在mui.gestures.longtap.js中初始化,在handle中激活
(function($, name) {
$.isLongTapAtived = false;//初始化
var timer;
var handle = function(event, touch) {
switch (event.type) {
case $.EVENT_START:
clearTimeout(timer);
timer = setTimeout(function() {
$.trigger(session.target, name, touch);
//激活了
$.isLongTapAtived = true;
}, options.holdTimeout);
break;
}
};
});
})(mui, 'longtap');
在mui.gestures.tap.js中判断有无激活
var handle = function(event, touch) {
var session = $.gestures.session;
var options = this.options;
switch (event.type) {
case $.EVENT_END:
//......
if (touch.distance < options.tapMaxDistance) {
if (touch.deltaTime < options.tapMaxTime) {
//.....
} else {
//如果当前对象添加了长按侦听,略过,否则仍然视为tap事件
//if (!hasEventype(target, 'longtap')) {
if (!$.isLongTapAtived) {
//如果没有longtap事件,离开屏幕是触发tap事件
$.trigger(target, name, touch);
}
//重置
$.isLongTapAtived = false;
}
}
break;
}
};
想法是美好的,现实是他么残酷的。无论有无longtap事件,都要走一遍longtap的handle代码
于是 $.isLongTapAtived === true;
于是 永远trigger tap 事件
呵呵,想死的心都有了
路子看来走对了,但是应该怎么做???
终极解决方案
mui.isLongTapAtived依然添加,只是在每一次DOM添加的longtap事件内激活
document.querySelector("#").addEventListener('longtap',function(){
mui.isLongTapAtived=true;
console.log('你触发了longtap事件');
});
这样对开发者是不友好的,不过暂时没办法,只能如此取舍了
代码已提交至https://github.com/phillyx/mui/
并推送给官方
博客已同步至http://www.cnblogs.com/phillyx/p/5157850.html
觉得不错就打赏一下吧
收起阅读 »【交流分享】解决IOS列表滑动不流畅的问题
很简单的列表:
<body>
<div class="list">
<h1>图片</h1>
<img sr c="xxx.jpg" />
...这里是20个<h1><img>...
<h1>图片</h1>
<img sr c="xxx.jpg" />
</div>
</body>
上述很简单的图文列表运行在IOS上列表滑动起来总是不流畅,但是在Android运行就很快;就算把img删掉,只剩h1文字列表,在IOS上滑起来都有点卡顿,手指只要离开屏幕,列表就停了,没有继续惯性滚动一段距离;
分享一下我的解决办法:
方法一: 使用原生div的滚动
如果像上面代码一样,不使用mui框架,则加入以下css:
body,
html {
height: 100%;
-webkit-overflow-scrolling: touch;//允许独立的滚动区域和触摸回弹
}
.list{
height: 100%;
overflow-y: scroll;//使用原生div滚动
}
如果使用mui框架,则
引入mui.css, 把上面<div class="list">变成 <div class="mui-content">; 加入以下css:
body,
html {
height: 100%;
}
.mui-content{
height: 100%;
overflow-y: scroll;
}
方法二: 使用mui的区域滚动
参考:http://dev.dcloud.net.cn/mui/ui/#scroll
但是这种方式,体验不如上面css的; 按照我们公司IOS同事的话来讲:你会感觉滑动飞得太假;当然也能解决问题;
最后附上源码案例, 很简单, 导入到HBuilder就可以在IOS上运行了
很简单的列表:
<body>
<div class="list">
<h1>图片</h1>
<img sr c="xxx.jpg" />
...这里是20个<h1><img>...
<h1>图片</h1>
<img sr c="xxx.jpg" />
</div>
</body>
上述很简单的图文列表运行在IOS上列表滑动起来总是不流畅,但是在Android运行就很快;就算把img删掉,只剩h1文字列表,在IOS上滑起来都有点卡顿,手指只要离开屏幕,列表就停了,没有继续惯性滚动一段距离;
分享一下我的解决办法:
方法一: 使用原生div的滚动
如果像上面代码一样,不使用mui框架,则加入以下css:
body,
html {
height: 100%;
-webkit-overflow-scrolling: touch;//允许独立的滚动区域和触摸回弹
}
.list{
height: 100%;
overflow-y: scroll;//使用原生div滚动
}
如果使用mui框架,则
引入mui.css, 把上面<div class="list">变成 <div class="mui-content">; 加入以下css:
body,
html {
height: 100%;
}
.mui-content{
height: 100%;
overflow-y: scroll;
}
方法二: 使用mui的区域滚动
参考:http://dev.dcloud.net.cn/mui/ui/#scroll
但是这种方式,体验不如上面css的; 按照我们公司IOS同事的话来讲:你会感觉滑动飞得太假;当然也能解决问题;
最后附上源码案例, 很简单, 导入到HBuilder就可以在IOS上运行了
收起阅读 »DCloud学习资料【自用】
1、首先记住以下3个常用网站:
DCloud官网:http://www.dcloud.io/
MUI官网:http://dev.dcloud.net.cn/mui/
HTML5+联盟:http://www.html5plus.org/
2、学习顺序
(1)MUI、5+、Native.js等相关知识参照DCloud官方文档
(2)5+API,即HTML5+联盟中的HTML5+规范
(3)MUI
3、资源汇总
MUI-FAQ:http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/122
APP优化技巧:http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/25
视频教程:http://edu.yuantuan.com/classroom/5/courses
4、官方相关视频
如何让Android手机的HTML5 App性能体验接近原生 王安(DCloud CEO
http://v.youku.com/v_show/id_XNzYyNzI3NDQw.html
mui—让HTML5达到原生体验的高性能框架 崔红保(Dcloud 前端工程
http://v.youku.com/v_show/id_XNzYyOTEyMjcy.html?from=s1.8-1-1.2
Native.js,让js像原生一样强大+++江树源(数字天堂CTO)
http://v.youku.com/v_show/id_XNzYzNTcwNDI4.html
(最新)DCloud流应用大会:http://e.vhall.com/944470274
1、首先记住以下3个常用网站:
DCloud官网:http://www.dcloud.io/
MUI官网:http://dev.dcloud.net.cn/mui/
HTML5+联盟:http://www.html5plus.org/
2、学习顺序
(1)MUI、5+、Native.js等相关知识参照DCloud官方文档
(2)5+API,即HTML5+联盟中的HTML5+规范
(3)MUI
3、资源汇总
MUI-FAQ:http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/122
APP优化技巧:http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/25
视频教程:http://edu.yuantuan.com/classroom/5/courses
4、官方相关视频
如何让Android手机的HTML5 App性能体验接近原生 王安(DCloud CEO
http://v.youku.com/v_show/id_XNzYyNzI3NDQw.html
mui—让HTML5达到原生体验的高性能框架 崔红保(Dcloud 前端工程
http://v.youku.com/v_show/id_XNzYyOTEyMjcy.html?from=s1.8-1-1.2
Native.js,让js像原生一样强大+++江树源(数字天堂CTO)
http://v.youku.com/v_show/id_XNzYzNTcwNDI4.html
(最新)DCloud流应用大会:http://e.vhall.com/944470274
收起阅读 »【交流分享】Android独立应用方式集成HTML5+SDK,Widget方式离线打包,空项目讲解
最近忙着微信和m站,还有流应用开发,好久没有写文章了.
公司打算把原生app全部改写成html5,方便升级版本,毕竟IOS更新审核太久,耽误运营推广;
我的项目百度地图,友盟推送,反馈,统计,千牛商家聊天都是得用原生的,所以以后用MUI写好html后,得集成到原生项目中去.
首先吐槽下官方的集成方式所提到的概念:
Widget方式: 按照字面的意思就是,html相当于小部件一样和原生代码放一块,在需要的时候调用;
独立应用方式: 这个就是Widget方式,概念真多
Webview方式: 只能打开一个界面,不能打开新界面,这个没搞懂使用场景~~(>_<)~~我暂且把这个概念忘了,别搞混
当你打开官方http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/38 又多了个概念: 离线打包
当你运行官方集成案例的时候,又多了个Runtime集成方式; 小白迟早会疯掉的
总之,按照我的理解:
1.如果你的项目原生代码和html混合着用,那么选择Widget方式集成,也就是独立应用方式;
2.如果你的项目是HBuilder写的纯html,没有原生代码,那么用Runtime集成方式,比较简单;
离线打包的概念是相对于HBuilder在线云打包而言的; 我们选上面各种集成方式用eclipse,Android Studio 或者XCode把html编译成安装包就属于离线打包了;这样避免云打包排队或者服务器挂掉的时候,自己还能编译安装包,照常发布更新版本;
ok,理清了官方的概念,你也基本懂了我写的标题:
Android独立应用方式集成HTML5 SDK,Widget方式离线打包,空项目讲解
一.准备
1.打开HBuilder,新建-->移动APP-->勾选"Hello mui",项目名叫"HelloMui";(我以官方mui项目来举例了,到时自行改为自己的项目);
2.打开eclipse,打开你的Android项目;(我这里是新建了一个Android项目,名字叫Widget; 如果你还没配置Android开发环境,则点这里http://jingyan.baidu.com/article/bea41d437a41b6b4c51be6c1.html );
- 去官方下载最新的sdk: http://ask.dcloud.net.cn/article/103 解压,里面有个名字叫'SDK'的文件夹
二.拷贝
1.把下载的官方SDK文件夹里的res文件夹拷贝到Android项目的res,合并;注意不要替换你项目的资源,不然你配的图标和写的strings.xml就没了
说明: res里面有NativeUI用到的图片资源: 进度条,对话框,动画样式,照片选择,底部弹出框,logo,启动页等等;http://www.html5plus.org/doc/zh_cn/nativeui.html
2.把SDK\assets中的data文件夹到eclipse项目中的assets
3.在eclipse的assets目录中创建apps; 在apps中创建一个文件夹,名字和你HBuilder的项目名相同;我这里就叫HelloMui; 在HelloMui中创建www文件夹; 把HBuilder项目拷贝到www文件夹下;
注意: apps和www文件夹名字是固定的,结构也是固定的,不然读取不到html
4.修改manifest.json和control.xml中的id为你的项目名;我这里是HelloMui
5.拷贝SDK\libs里面的jar包到eclipse项目下的libs;如图:
说明:
pdr.jar, ui.jar, nineoldandroids-2.4.0.jar是Webview基础包,必须导入
因为HelloMui项目中获取设备信息网络状态,需引入device.jar;
设置了浏览器运行环境,需引入navigatorui.jar(设置了状态栏,创建快捷方式,log输出,设置cookie都需引入此包)
使用了plus.storage,需引入nopermission.jar
其实在具体的项目中,这些包远远不够的:
比如ajax联网,需引入xhr.jar
全量更新和差量更新,需引入downloader.jar,invocation.jar
原生对话框和底部弹出或者toast,需引入nativeui.jar
设置用户头像,用到拍照,打开相册,需引入camera.jar,gallery.jar
具体请参照: http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/216
6.打开eclipse项目的AndroidManifest.xml,配置权限,具体请参照官方SDK里的Feature-Android.xls文件
<!-- 联网 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 使用存储卡 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
7.把HBuilder-Integrate\src下的io文件夹,拷贝到eclipse项目的src
8.把Android-SDK\HBuilder-Integrate\src\com\HBuilder\integrate\SDK_WebApp.java 拷贝到eclipse项目的src包名下,并修改122行的appBasePath, 为assets的app路径
9.SDK_WebApp.java里面的FrameLayout是用来承载html的,可以放到任何你想放到的位置,比如点击一个按钮,弹窗或者打开新Activity展示; 我这里的话,直接用activity展示,并在AndroidManifest.xml设置启动就打开本界面
10.ok 完了 ,运行吧. 附上eclipse项目源码
最近忙着微信和m站,还有流应用开发,好久没有写文章了.
公司打算把原生app全部改写成html5,方便升级版本,毕竟IOS更新审核太久,耽误运营推广;
我的项目百度地图,友盟推送,反馈,统计,千牛商家聊天都是得用原生的,所以以后用MUI写好html后,得集成到原生项目中去.
首先吐槽下官方的集成方式所提到的概念:
Widget方式: 按照字面的意思就是,html相当于小部件一样和原生代码放一块,在需要的时候调用;
独立应用方式: 这个就是Widget方式,概念真多
Webview方式: 只能打开一个界面,不能打开新界面,这个没搞懂使用场景~~(>_<)~~我暂且把这个概念忘了,别搞混
当你打开官方http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/38 又多了个概念: 离线打包
当你运行官方集成案例的时候,又多了个Runtime集成方式; 小白迟早会疯掉的
总之,按照我的理解:
1.如果你的项目原生代码和html混合着用,那么选择Widget方式集成,也就是独立应用方式;
2.如果你的项目是HBuilder写的纯html,没有原生代码,那么用Runtime集成方式,比较简单;
离线打包的概念是相对于HBuilder在线云打包而言的; 我们选上面各种集成方式用eclipse,Android Studio 或者XCode把html编译成安装包就属于离线打包了;这样避免云打包排队或者服务器挂掉的时候,自己还能编译安装包,照常发布更新版本;
ok,理清了官方的概念,你也基本懂了我写的标题:
Android独立应用方式集成HTML5 SDK,Widget方式离线打包,空项目讲解
一.准备
1.打开HBuilder,新建-->移动APP-->勾选"Hello mui",项目名叫"HelloMui";(我以官方mui项目来举例了,到时自行改为自己的项目);
2.打开eclipse,打开你的Android项目;(我这里是新建了一个Android项目,名字叫Widget; 如果你还没配置Android开发环境,则点这里http://jingyan.baidu.com/article/bea41d437a41b6b4c51be6c1.html );
- 去官方下载最新的sdk: http://ask.dcloud.net.cn/article/103 解压,里面有个名字叫'SDK'的文件夹
二.拷贝
1.把下载的官方SDK文件夹里的res文件夹拷贝到Android项目的res,合并;注意不要替换你项目的资源,不然你配的图标和写的strings.xml就没了
说明: res里面有NativeUI用到的图片资源: 进度条,对话框,动画样式,照片选择,底部弹出框,logo,启动页等等;http://www.html5plus.org/doc/zh_cn/nativeui.html
2.把SDK\assets中的data文件夹到eclipse项目中的assets
3.在eclipse的assets目录中创建apps; 在apps中创建一个文件夹,名字和你HBuilder的项目名相同;我这里就叫HelloMui; 在HelloMui中创建www文件夹; 把HBuilder项目拷贝到www文件夹下;
注意: apps和www文件夹名字是固定的,结构也是固定的,不然读取不到html
4.修改manifest.json和control.xml中的id为你的项目名;我这里是HelloMui
5.拷贝SDK\libs里面的jar包到eclipse项目下的libs;如图:
说明:
pdr.jar, ui.jar, nineoldandroids-2.4.0.jar是Webview基础包,必须导入
因为HelloMui项目中获取设备信息网络状态,需引入device.jar;
设置了浏览器运行环境,需引入navigatorui.jar(设置了状态栏,创建快捷方式,log输出,设置cookie都需引入此包)
使用了plus.storage,需引入nopermission.jar
其实在具体的项目中,这些包远远不够的:
比如ajax联网,需引入xhr.jar
全量更新和差量更新,需引入downloader.jar,invocation.jar
原生对话框和底部弹出或者toast,需引入nativeui.jar
设置用户头像,用到拍照,打开相册,需引入camera.jar,gallery.jar
具体请参照: http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/216
6.打开eclipse项目的AndroidManifest.xml,配置权限,具体请参照官方SDK里的Feature-Android.xls文件
<!-- 联网 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 使用存储卡 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
7.把HBuilder-Integrate\src下的io文件夹,拷贝到eclipse项目的src
8.把Android-SDK\HBuilder-Integrate\src\com\HBuilder\integrate\SDK_WebApp.java 拷贝到eclipse项目的src包名下,并修改122行的appBasePath, 为assets的app路径
9.SDK_WebApp.java里面的FrameLayout是用来承载html的,可以放到任何你想放到的位置,比如点击一个按钮,弹窗或者打开新Activity展示; 我这里的话,直接用activity展示,并在AndroidManifest.xml设置启动就打开本界面
10.ok 完了 ,运行吧. 附上eclipse项目源码
收起阅读 »离线打包下打开浏览器调试模式
由于自己编写了一些插件,所以不得不采取离线打包的方式来发布应用,在这个过程中,被不能浏览器调试浪费了不少时间,最后狠下心反编译了官方云打包的apk,发现需要修改一个配置文件
配置文件的位置:assets\data\control.xml
作如下修改即可打开调试模式
<hbuilder version="1.9.9.21259" debug="true">
<apps>
<app
appid="HBuilder"
appver="1.5.3" />
</apps>
</hbuilder> 由于自己编写了一些插件,所以不得不采取离线打包的方式来发布应用,在这个过程中,被不能浏览器调试浪费了不少时间,最后狠下心反编译了官方云打包的apk,发现需要修改一个配置文件
配置文件的位置:assets\data\control.xml
作如下修改即可打开调试模式
<hbuilder version="1.9.9.21259" debug="true">
<apps>
<app
appid="HBuilder"
appver="1.5.3" />
</apps>
</hbuilder> 收起阅读 »
















