
分享移动端图片压缩上传(整理修改微社区图片上传,带UI,带demo,demo服务器端用php)
20160411更新:
使同个页面可以配置调用多个上传图片
20160418更新:
修复上传进度条不准
增加上传样式2,调整部分样式
一些配置问题:
objUploadImg.uploadMaxW = 2000; //生成图片的最大宽度
objUploadImg.uploadMaxH = 2000; //生成图片的最大高度
*建议这两项默认800800
objUploadImg.uploadPicMore = true;//是否允许多图上传 默认单张上传
即便开启,安卓也只支持单张上传
objUploadImg.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10
最好不要过多,因为图片在前端用H5 <canvas> 处理,测试过配置最大宽高为2000px时,iPhone6微信端一次上传20张会出现微信自动关闭;如果同个页面调用多个上传方法,一次上传的最大张数之和最好不超过10张**
其他的自行查看附件demo,随便贴几段代码,注意JS代码的引用位置
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>图片上传</title>
<link rel="stylesheet" href="css/mobile-uploadImg.css">
<script src="js/jquery-1.9.0.js"></script>
<script src="js/mobile-uploadCompresserImg.js"></script>
<script src="js/mobile-uploadImg.js"></script>
</head>
<body style="background: #f5f5f5;">
<div style="margin:20px 10px;">
<form method="post" action="">
<div id="uploadImgForm">
<div class="mbupload_frame">
<div class="mbupload_photoList">
<ul>
<li class="mbupload_on mbupload_addPic mbupload_addImg"></li>
</ul>
<p class="mbupload_textTip mbupload_f12">还可上传<span class="mbupload_onlyUploadNum"></span>张照片呦~</p>
</div>
<div class="mbupload_bgimg">
<div class="iconSendImg mbupload_addImg" style="background:url(images/upload_carbg.png) no-repeat 50% 50%;"></div>
</div>
</div>
</div>
<div style="margin-top:20px;">
<div id="uploadImgForm2" class="uploadImgStyle2">
<div class="mbupload_frame">
<div class="mbupload_photoList">
<ul>
<li class="mbupload_on mbupload_addPic mbupload_addImg"></li>
</ul>
<p class="mbupload_textTip mbupload_f12">还可上传<span class="mbupload_onlyUploadNum"></span>张照片呦~</p>
</div>
<div class="mbupload_bgimg">
<div class="iconSendImg mbupload_addImg" style="background:url(images/upload_licensebg.png) no-repeat 50% 50%;"></div>
</div>
</div>
</div>
</div>
</form>
</div>
<script type="text/javascript">
var objUploadImgForm = {};
objUploadImgForm.uploadUrl = "<?php echo('http://'.$_SERVER['HTTP_HOST'].'/uploads.php') ?>";//上传图片的地址
objUploadImgForm.formHtmlId = "#uploadImgForm";//上传图片的ID
objUploadImgForm.maxUpload = 20;//上传图片的最大张数
objUploadImgForm.uploadMaxW = 2000; //生成图片的最大宽度
objUploadImgForm.uploadMaxH = 2000; //生成图片的最大高度
objUploadImgForm.uploadQuality = 1; //目标jpg图片输出质量
objUploadImgForm.uploadPicSize = 8;//上传限制图片大小(MB) 默认8M
objUploadImgForm.uploadPicMore = true;//是否允许多图上传 默认单张上传
objUploadImgForm.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10
objUploadImgForm.uploadDefaultImgUrl = "images/defaultImg.png";//压缩图片时的默认图片地址
mobileUploadImg(objUploadImgForm);
</script>
<script type="text/javascript">
var objUploadImgForm2 = {};
objUploadImgForm2.uploadUrl = "<?php echo('http://'.$_SERVER['HTTP_HOST'].'/uploads.php') ?>";//上传图片的地址
objUploadImgForm2.formHtmlId = "#uploadImgForm2";//上传图片的ID
objUploadImgForm2.maxUpload = 1;//上传图片的最大张数
objUploadImgForm2.uploadMaxW = 800; //生成图片的最大宽度
objUploadImgForm2.uploadMaxH = 800; //生成图片的最大高度
objUploadImgForm2.uploadQuality = 1; //目标jpg图片输出质量
objUploadImgForm2.uploadPicSize = 8;//上传限制图片大小(MB) 默认8M
objUploadImgForm2.uploadPicMore = true;//是否允许多图上传 默认单张上传
objUploadImgForm2.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10
objUploadImgForm2.uploadDefaultImgUrl = "images/defaultImg.png";//压缩图片时的默认图片地址
mobileUploadImg(objUploadImgForm2);
</script>
</body>
</html>
/**
* @filename mobile-uploadImg
* @description
* 作者: 418239385(418239385@qq.com)
* 创建时间: 2016-4-6 14:38:03
* 修改记录:
*
**/
//------------------------------------------------------------------------------
function mobileUploadImg(opts)
{
if(opts == null){
objGlobal.DIC.dialog({content:'请配置上传图片的相关参数!', autoClose:false, okValue:"确定", isMask:true});
return;
}
var objUploadImg = {};
var opts = opts || {};
//上传图片的表单ID
objUploadImg.formHtmlId = opts.formHtmlId || "";
//最大上传图片量
objUploadImg.maxUpload = opts.maxUpload || 8;
//生成图片的最大宽度
objUploadImg.uploadMaxW = opts.uploadMaxW || 800;
//生成图片的最大高度
objUploadImg.uploadMaxH = opts.uploadMaxH || 800;
//目标jpg图片输出质量
objUploadImg.uploadQuality = opts.uploadQuality || 1;
//上传限制图片体积(MB) 默认8M
objUploadImg.uploadPicSize = opts.uploadPicSize || 8;
//是否允许多图上传 默认单张上传
objUploadImg.uploadPicMore = opts.uploadPicMore || false;
//多图上传时,一次上传的最大张数 默认10
objUploadImg.onceMaxUpload = opts.onceMaxUpload || 10;
// 上传图片地址
objUploadImg.uploadUrl = opts.uploadUrl || "";
//压缩图片时的默认图片地址
objUploadImg.uploadDefaultImgUrl = opts.uploadDefaultImgUrl || "";
//多图上传时,上传第一张到最后一张的状态
objUploadImg.isMoreBusy = false;
// 上传信息 主要是 id 对应信息
objUploadImg.uploadInfo = {};
// 上传队列,里面保存的是 id
objUploadImg.uploadQueue = [];
// 预览队列,里面保存的是 id
objUploadImg.previewQueue = [];
// 请求对象
objUploadImg.xhr = {};
// 是否有图片正在压缩
objUploadImg.isEncoderBusy = false;
// 是否有任务正在上传
objUploadImg.isBusy = false;
if(objUploadImg.formHtmlId.length <= 0){
objGlobal.DIC.dialog({content:'请配置上传图片的容器ID!', autoClose:false, okValue:"确定", isMask:true});
return;
}
if(objUploadImg.uploadUrl.length <= 0){
objGlobal.DIC.dialog({content:'请配置上传图片的URL地址!', autoClose:false, okValue:"确定", isMask:true});
return;
}
objUploadImg.countUpload = function() {
var num = 0;
$.each(objUploadImg.uploadInfo, function(i, n) {
if (n) {
++ num;
}
});
return num;
};
// 图片预览
objUploadImg.uploadPreview = function(id) {
var reader = new FileReader();
var uploadBase64;
var conf = {}, file = objUploadImg.uploadInfo[id].file;
conf = {
maxW: objUploadImg.uploadMaxW, //目标宽
maxH: objUploadImg.uploadMaxH, //目标高
quality: objUploadImg.uploadQuality, //目标jpg图片输出质量
};
reader.onload = function(e) {
var result = this.result;
// 如果是jpg格式图片,读取图片拍摄方向,自动旋转
if (file.type == 'image/jpeg'){
try {
var jpg = new objJpegMeata.JpegMeta.JpegFile(result, file.name);
} catch (e) {
objGlobal.DIC.dialog({content:'图片不是正确的图片数据', autoClose:true});
$(objUploadImg.formHtmlId + ' #li' + id).remove();
objUploadImg.isEncoderBusy = false;
return false;
}
if (jpg.tiff && jpg.tiff.Orientation) {
//设置旋转
conf = $.extend(conf, {
orien: jpg.tiff.Orientation.value
});
}
}
// 压缩
if (objImageCompresser.ImageCompresser.support()) {
var img = new Image();
img.onload = function() {
try {
uploadBase64 = objImageCompresser.ImageCompresser.getImageBase64(this, conf);
} catch (e) {
objGlobal.DIC.dialog({content:'压缩图片失败', autoClose:true});
$(objUploadImg.formHtmlId + ' #li' + id).remove();
objUploadImg.isEncoderBusy = false;
return false;
}
if (uploadBase64.indexOf('data:image') < 0) {
objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});
$(objUploadImg.formHtmlId + ' #li' + id).remove();
objUploadImg.isEncoderBusy = false;
return false;
}
objUploadImg.uploadInfo[id].file = uploadBase64;
$(objUploadImg.formHtmlId + ' #li' + id).find('img').attr('src', uploadBase64);
objUploadImg.uploadQueue.push(id);
}
img.onerror = function() {
objGlobal.DIC.dialog({content:'解析图片数据失败', autoClose:true});
$(objUploadImg.formHtmlId + ' #li' + id).remove();
objUploadImg.isEncoderBusy = false;
return false;
}
img.src = objImageCompresser.ImageCompresser.getFileObjectURL(file);
} else {
uploadBase64 = result;
if (uploadBase64.indexOf('data:image') < 0) {
objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});
$(objUploadImg.formHtmlId + ' #li' + id).remove();
objUploadImg.isEncoderBusy = false;
return false;
}
objUploadImg.uploadInfo[id].file = uploadBase64;
$(objUploadImg.formHtmlId + ' #li' + id).find('img').attr('src', uploadBase64);
objUploadImg.uploadQueue.push(id);
}
}
reader.readAsBinaryString(objUploadImg.uploadInfo[id].file);
};
// 创建上传请求
objUploadImg.createUpload = function(id, type, uploadTimer) {
if (!objUploadImg.uploadInfo[id]) {
objUploadImg.isEncoderBusy = false;
objUploadImg.isBusy = false;
return false;
}
// 移除图片压缩中...
$(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskTxt').remove();
// 图片posturl
var uploadUrl = objUploadImg.uploadUrl;
// 产生进度条
var progressHtml = '<div class="mbupload_progress mbupload_brSmall" id="mbupload_progress'+id+'"><div class="mbupload_proBar" style="width:0%;"></div></div>';
$(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskLay').after(progressHtml);
var formData = new FormData();
formData.append('upload_pic', objUploadImg.uploadInfo[id].file);
formData.append('upload_name', objUploadImg.uploadInfo[id].oldFileInfo.name);
formData.append('upload_id', id);
var progress = function(e) {
if (e.target.response) {
var result = $.parseJSON(e.target.response);
if (result.errCode != 0) {
// $('#content').val(result.errCode);
objGlobal.DIC.dialog({content:'网络不稳定,请稍后重新操作', autoClose:true});
removePic(id);
//更新剩余上传数
objUploadImg.uploadRemaining();
return false;
}
}
var progress = $(objUploadImg.formHtmlId + ' #mbupload_progress' + id).find('.mbupload_proBar');
if (e.total == e.loaded) {
var percent = 100;
} else {
var percent = 100*(e.loaded / e.total);
}
// 控制进度条不要超出
if (percent > 100) {
percent = 100;
}
progress.width(percent + '%');
//progress.animate({'width': '95%'}, 1500);
setTimeout(function(){
if (percent == 100) {
donePic(id);
var pLength = 0, nLength = 0;
if(objUploadImg.uploadPicMore){
pLength = objUploadImg.previewQueue.length;
nLength = objUploadImg.uploadQueue.length;
}
if(uploadTimer && pLength <= 0 && nLength <= 0){
clearInterval(uploadTimer);
}
}
}, 400);
}
var removePic = function(id) {
donePic(id);
$('#li' + id).remove();
}
var donePic = function(id) {
objUploadImg.isEncoderBusy = false;
objUploadImg.isBusy = false;
if(objUploadImg.uploadPicMore && (objUploadImg.previewQueue.length <= 0) &&
(objUploadImg.uploadQueue.length <= 0)){
objUploadImg.isMoreBusy = false;
}
if (typeof objUploadImg.uploadInfo[id] != 'undefined') {
objUploadImg.uploadInfo[id].isDone = true;
}
if (typeof objUploadImg.xhr[id] != 'undefined') {
objUploadImg.xhr[id] = null;
}
}
var complete = function(e) {
var progress = $(objUploadImg.formHtmlId + ' #mbupload_progress' + id).find('.mbupload_proBar');
progress.css('width', '100%');
if($(objUploadImg.formHtmlId + ' #li' + id)){
$(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskTxt').remove();
}
$(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskLay').remove();
$(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_progress').remove();
// 上传结束
donePic(id);
var result = $.parseJSON(e.target.response);
if (result.errCode == 0) {
var input = '<input type="hidden" id="input' + result.data.id + '" name="picIds[]" value="' + result.data.picId + '">';
if(type == 'replyForm'){
$('#replyForm').append(input);
}else{
$(objUploadImg.formHtmlId).append(input);
}
} else {
objGlobal.DIC.dialog({content:'网络不稳定,请稍后重新操作', autoClose:true});
removePic(id);
//更新剩余上传数
objUploadImg.uploadRemaining();
delete objUploadImg.uploadInfo[id];
// 如果传略失败,上传个数少于限制张数则再显示加号
if (objUploadImg.countUpload() < objUploadImg.maxUpload) {
$(objUploadImg.formHtmlId + ' .mbupload_addPic').show();
}
}
}
var failed = function() {
objGlobal.DIC.dialog({content:'网络断开,请稍后重新操作', autoClose:true});
removePic(id)
}
var abort = function() {
objGlobal.DIC.dialog({content:'上传已取消', autoClose:true});
removePic(id)
}
// 创建 ajax 请求
objUploadImg.xhr[id] = new XMLHttpRequest();
objUploadImg.xhr[id].addEventListener("progress", progress, false);
objUploadImg.xhr[id].upload.addEventListener("progress", progress, false);
objUploadImg.xhr[id].addEventListener("load", complete, false);
objUploadImg.xhr[id].addEventListener("abort", abort, false);
objUploadImg.xhr[id].addEventListener("error", failed, false);
objUploadImg.xhr[id].open("POST", uploadUrl);
objUploadImg.xhr[id].send(formData);
};
// 不能上传系统提示
objUploadImg.checkUploadBySysVer = function() {
var mb_os = objGlobal.checkUA();
if (mb_os.ios && mb_os.version.toString() < '6.0') {
objGlobal.DIC.dialog({content:'手机系统不支持传图,请升级到ios6.0以上', autoClose:true});
return false;
}
if (mb_os.wx && mb_os.wxVersion.toString() < '5.2') {
objGlobal.DIC.dialog({content:'当前微信版本不支持传图,请升级到最新版', autoClose:true});
return false;
}
return true;
};
//根据是否可以多图上传生成对应的input
objUploadImg.uploadAddInput = function(){
var input = "", fistInput = "";
if(objUploadImg.uploadPicMore){
input = '<input type="file" class="mbupload_on mbupload_uploadFile" accept="image/*" multiple="">';
fistInput = '<input type="file" class="fistUpload" accept="image/*" multiple="">';
}else{
input = '<input type="file" class="mbupload_on mbupload_uploadFile" accept="image/*" single="">';
fistInput = '<input type="file" class="fistUpload" accept="image/*" single="">';
}
$(objUploadImg.formHtmlId + ' .mbupload_addPic').append(input);
$(objUploadImg.formHtmlId + ' .iconSendImg').append(fistInput);
};
//剩余上传数
objUploadImg.uploadRemaining = function(){
var uploadNum = 0;
uploadNum = $(objUploadImg.formHtmlId + ' .mbupload_photoList').find('li').length;
var canOnlyUploadNum = objUploadImg.maxUpload;
if(uploadNum <= objUploadImg.maxUpload)
{
canOnlyUploadNum = objUploadImg.maxUpload - uploadNum + 1;
}
else
{
canOnlyUploadNum = 0;
}
//当上传出错则显示第一上传页面
if(canOnlyUploadNum == objUploadImg.maxUpload)
{
$(objUploadImg.formHtmlId + ' .mbupload_photoList').hide();
$(objUploadImg.formHtmlId + ' .mbupload_bgimg').show();
}
//更新剩余可上传图片数
$(objUploadImg.formHtmlId + ' .mbupload_onlyUploadNum').html(canOnlyUploadNum);
};
// 检查图片大小
objUploadImg.checkPicSize = function(file) {
var uploadPicSize = objUploadImg.uploadPicSize*1024*1024;
if (file.size > uploadPicSize) {
return false;
}
return true;
};
// 检查图片类型
objUploadImg.checkPicType = function(file) {
var photoReg = (/\.png$|\.bmp$|\.jpg$|\.jpeg$|\.gif$/i);
if(!photoReg.test(file.name)){
return false;
}else{
return true;
}
};
var uploadTimer = null;
var initUpload = function()
{
// 上传图片的绑定
$(objUploadImg.formHtmlId + ' .mbupload_addImg').on("click", function(){
if(!objUploadImg.checkUploadBySysVer()){
return false;
}
});
$(objUploadImg.formHtmlId + ' .mbupload_uploadFile').on("click", function(){
var thisObj = $(this);
if (objUploadImg.isEncoderBusy) {
return false;
}
else if (objUploadImg.isBusy) {
objGlobal.DIC.dialog({content:'上传中,请稍后添加', autoClose:true});
return false;
}
else if (objUploadImg.isMoreBusy) {
objGlobal.DIC.dialog({content:'上传中,请稍后添加', autoClose:true});
return false;
}
});
//首次点击图片的图标,触发一次手机的默认上传事件
$('body').on('change', objUploadImg.formHtmlId + ' .fistUpload', function(e){
$(objUploadImg.formHtmlId + ' .mbupload_photoList').show();
$(objUploadImg.formHtmlId + ' .mbupload_bgimg').hide();
});
// 文件表单发生变化时
$('body').on('change', objUploadImg.formHtmlId + ' .mbupload_uploadFile,' + objUploadImg.formHtmlId + ' .fistUpload', function(e) {
//执行图片预览、压缩定时器
uploadTimer = setInterval(function() {
// 预览
setTimeout(function() {
if (!objUploadImg.isEncoderBusy && objUploadImg.previewQueue.length) {
var jobId = objUploadImg.previewQueue.shift();
objUploadImg.isEncoderBusy = true;
objUploadImg.uploadPreview(jobId);
}
}, 1);
// 上传
setTimeout(function() {
if (!objUploadImg.isBusy && objUploadImg.uploadQueue.length) {
var jobId = objUploadImg.uploadQueue.shift();
objUploadImg.isBusy = true;
if(objUploadImg.uploadPicMore){
objUploadImg.isMoreBusy = true;
}
objUploadImg.createUpload(jobId, objUploadImg.formHtmlId, uploadTimer);
}
}, 10);
}, 300);
e = e || window.event;
var fileList = e.target.files;
if (!fileList.length) {
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
return false;
}
if (objUploadImg.uploadPicMore && (fileList.length > objUploadImg.onceMaxUpload)) {
objGlobal.DIC.dialog({content:'上传图片一次最多只能选' + objUploadImg.onceMaxUpload + '张', autoClose:true});
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
return false;
}
if (objUploadImg.uploadPicMore && (fileList.length > (objUploadImg.maxUpload - objUploadImg.countUpload()))) {
objGlobal.DIC.dialog({content:'你最多只能上传' + objUploadImg.maxUpload + '张照片', autoClose:true});
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
return false;
}
for (var i = 0; i < fileList.length; i++) {
if (objUploadImg.countUpload() >= objUploadImg.maxUpload) {
objGlobal.DIC.dialog({content:'你最多只能上传' + objUploadImg.maxUpload + '张照片', autoClose:true});
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
break;
}
var file = fileList[i];
if (!objUploadImg.checkPicType(file)) {
objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
continue;
}
// console.log(file);
if (!objUploadImg.checkPicSize(file)) {
objGlobal.DIC.dialog({content:'图片大小超过'+ objUploadImg.uploadPicSize + 'MB', autoClose:true});
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
continue;
}
var id = Date.now() + i;
// 增加到上传对象中, 上传完成后,修改为 true
objUploadImg.uploadInfo[id] = {
oldFileInfo: file,
file: file,
isDone: false,
};
var html = '<li id="li' + id + '"><div class="mbupload_photoCut"><img src="' + objUploadImg.uploadDefaultImgUrl + '" class="attchImg" alt="photo"></div>' +
'<div class="mbupload_maskLay"></div>' +
'<div class="mbupload_maskTxt">图片压缩中...</div>' +
'<a href="javascript:;" class="mbupload_cBtn mbupload_pa mbupload_db" title="" _id="'+id+'">关闭</a></li>';
$(objUploadImg.formHtmlId + ' .mbupload_addPic').before(html);
objUploadImg.previewQueue.push(id);
// 图片已经上传了 最大限制 张数,隐藏 + 号
if (objUploadImg.countUpload() >= objUploadImg.maxUpload) {
$(objUploadImg.formHtmlId + ' .mbupload_addPic').hide();
}
//更新剩余上传数
setTimeout(function(){
objUploadImg.uploadRemaining();
}, 400);
}
// 把输入框清空
$(this).val('');
});
$(objUploadImg.formHtmlId + ' .mbupload_photoList').on('click', '.mbupload_cBtn', function() {
var id = $(this).attr('_id');
// 取消这个请求
if (objUploadImg.xhr[id]) {
objUploadImg.xhr[id].abort();
}
// 图片删除
$(objUploadImg.formHtmlId + ' #li' + id).remove();
// 表单中删除
$(objUploadImg.formHtmlId + ' #input' + id).remove();
objUploadImg.uploadInfo[id] = null;
// 图片变少了,显示+号
if (objUploadImg.countUpload() < objUploadImg.maxUpload) {
$(objUploadImg.formHtmlId + ' .mbupload_addPic').show();
}
//更新剩余上传数
objUploadImg.uploadRemaining();
//当删除所有图片后隐藏添加图片的图标
if($(objUploadImg.formHtmlId + ' .mbupload_photoList').find('li').length < 2){
$(objUploadImg.formHtmlId + ' .mbupload_photoList').hide();
$(objUploadImg.formHtmlId + ' .mbupload_bgimg').show();
}
});
};
objUploadImg.uploadAddInput();
objUploadImg.uploadRemaining();
initUpload();
};
20160411更新:
使同个页面可以配置调用多个上传图片
20160418更新:
修复上传进度条不准
增加上传样式2,调整部分样式
一些配置问题:
objUploadImg.uploadMaxW = 2000; //生成图片的最大宽度
objUploadImg.uploadMaxH = 2000; //生成图片的最大高度
*建议这两项默认800800
objUploadImg.uploadPicMore = true;//是否允许多图上传 默认单张上传
即便开启,安卓也只支持单张上传
objUploadImg.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10
最好不要过多,因为图片在前端用H5 <canvas> 处理,测试过配置最大宽高为2000px时,iPhone6微信端一次上传20张会出现微信自动关闭;如果同个页面调用多个上传方法,一次上传的最大张数之和最好不超过10张**
其他的自行查看附件demo,随便贴几段代码,注意JS代码的引用位置
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>图片上传</title>
<link rel="stylesheet" href="css/mobile-uploadImg.css">
<script src="js/jquery-1.9.0.js"></script>
<script src="js/mobile-uploadCompresserImg.js"></script>
<script src="js/mobile-uploadImg.js"></script>
</head>
<body style="background: #f5f5f5;">
<div style="margin:20px 10px;">
<form method="post" action="">
<div id="uploadImgForm">
<div class="mbupload_frame">
<div class="mbupload_photoList">
<ul>
<li class="mbupload_on mbupload_addPic mbupload_addImg"></li>
</ul>
<p class="mbupload_textTip mbupload_f12">还可上传<span class="mbupload_onlyUploadNum"></span>张照片呦~</p>
</div>
<div class="mbupload_bgimg">
<div class="iconSendImg mbupload_addImg" style="background:url(images/upload_carbg.png) no-repeat 50% 50%;"></div>
</div>
</div>
</div>
<div style="margin-top:20px;">
<div id="uploadImgForm2" class="uploadImgStyle2">
<div class="mbupload_frame">
<div class="mbupload_photoList">
<ul>
<li class="mbupload_on mbupload_addPic mbupload_addImg"></li>
</ul>
<p class="mbupload_textTip mbupload_f12">还可上传<span class="mbupload_onlyUploadNum"></span>张照片呦~</p>
</div>
<div class="mbupload_bgimg">
<div class="iconSendImg mbupload_addImg" style="background:url(images/upload_licensebg.png) no-repeat 50% 50%;"></div>
</div>
</div>
</div>
</div>
</form>
</div>
<script type="text/javascript">
var objUploadImgForm = {};
objUploadImgForm.uploadUrl = "<?php echo('http://'.$_SERVER['HTTP_HOST'].'/uploads.php') ?>";//上传图片的地址
objUploadImgForm.formHtmlId = "#uploadImgForm";//上传图片的ID
objUploadImgForm.maxUpload = 20;//上传图片的最大张数
objUploadImgForm.uploadMaxW = 2000; //生成图片的最大宽度
objUploadImgForm.uploadMaxH = 2000; //生成图片的最大高度
objUploadImgForm.uploadQuality = 1; //目标jpg图片输出质量
objUploadImgForm.uploadPicSize = 8;//上传限制图片大小(MB) 默认8M
objUploadImgForm.uploadPicMore = true;//是否允许多图上传 默认单张上传
objUploadImgForm.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10
objUploadImgForm.uploadDefaultImgUrl = "images/defaultImg.png";//压缩图片时的默认图片地址
mobileUploadImg(objUploadImgForm);
</script>
<script type="text/javascript">
var objUploadImgForm2 = {};
objUploadImgForm2.uploadUrl = "<?php echo('http://'.$_SERVER['HTTP_HOST'].'/uploads.php') ?>";//上传图片的地址
objUploadImgForm2.formHtmlId = "#uploadImgForm2";//上传图片的ID
objUploadImgForm2.maxUpload = 1;//上传图片的最大张数
objUploadImgForm2.uploadMaxW = 800; //生成图片的最大宽度
objUploadImgForm2.uploadMaxH = 800; //生成图片的最大高度
objUploadImgForm2.uploadQuality = 1; //目标jpg图片输出质量
objUploadImgForm2.uploadPicSize = 8;//上传限制图片大小(MB) 默认8M
objUploadImgForm2.uploadPicMore = true;//是否允许多图上传 默认单张上传
objUploadImgForm2.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10
objUploadImgForm2.uploadDefaultImgUrl = "images/defaultImg.png";//压缩图片时的默认图片地址
mobileUploadImg(objUploadImgForm2);
</script>
</body>
</html>
/**
* @filename mobile-uploadImg
* @description
* 作者: 418239385(418239385@qq.com)
* 创建时间: 2016-4-6 14:38:03
* 修改记录:
*
**/
//------------------------------------------------------------------------------
function mobileUploadImg(opts)
{
if(opts == null){
objGlobal.DIC.dialog({content:'请配置上传图片的相关参数!', autoClose:false, okValue:"确定", isMask:true});
return;
}
var objUploadImg = {};
var opts = opts || {};
//上传图片的表单ID
objUploadImg.formHtmlId = opts.formHtmlId || "";
//最大上传图片量
objUploadImg.maxUpload = opts.maxUpload || 8;
//生成图片的最大宽度
objUploadImg.uploadMaxW = opts.uploadMaxW || 800;
//生成图片的最大高度
objUploadImg.uploadMaxH = opts.uploadMaxH || 800;
//目标jpg图片输出质量
objUploadImg.uploadQuality = opts.uploadQuality || 1;
//上传限制图片体积(MB) 默认8M
objUploadImg.uploadPicSize = opts.uploadPicSize || 8;
//是否允许多图上传 默认单张上传
objUploadImg.uploadPicMore = opts.uploadPicMore || false;
//多图上传时,一次上传的最大张数 默认10
objUploadImg.onceMaxUpload = opts.onceMaxUpload || 10;
// 上传图片地址
objUploadImg.uploadUrl = opts.uploadUrl || "";
//压缩图片时的默认图片地址
objUploadImg.uploadDefaultImgUrl = opts.uploadDefaultImgUrl || "";
//多图上传时,上传第一张到最后一张的状态
objUploadImg.isMoreBusy = false;
// 上传信息 主要是 id 对应信息
objUploadImg.uploadInfo = {};
// 上传队列,里面保存的是 id
objUploadImg.uploadQueue = [];
// 预览队列,里面保存的是 id
objUploadImg.previewQueue = [];
// 请求对象
objUploadImg.xhr = {};
// 是否有图片正在压缩
objUploadImg.isEncoderBusy = false;
// 是否有任务正在上传
objUploadImg.isBusy = false;
if(objUploadImg.formHtmlId.length <= 0){
objGlobal.DIC.dialog({content:'请配置上传图片的容器ID!', autoClose:false, okValue:"确定", isMask:true});
return;
}
if(objUploadImg.uploadUrl.length <= 0){
objGlobal.DIC.dialog({content:'请配置上传图片的URL地址!', autoClose:false, okValue:"确定", isMask:true});
return;
}
objUploadImg.countUpload = function() {
var num = 0;
$.each(objUploadImg.uploadInfo, function(i, n) {
if (n) {
++ num;
}
});
return num;
};
// 图片预览
objUploadImg.uploadPreview = function(id) {
var reader = new FileReader();
var uploadBase64;
var conf = {}, file = objUploadImg.uploadInfo[id].file;
conf = {
maxW: objUploadImg.uploadMaxW, //目标宽
maxH: objUploadImg.uploadMaxH, //目标高
quality: objUploadImg.uploadQuality, //目标jpg图片输出质量
};
reader.onload = function(e) {
var result = this.result;
// 如果是jpg格式图片,读取图片拍摄方向,自动旋转
if (file.type == 'image/jpeg'){
try {
var jpg = new objJpegMeata.JpegMeta.JpegFile(result, file.name);
} catch (e) {
objGlobal.DIC.dialog({content:'图片不是正确的图片数据', autoClose:true});
$(objUploadImg.formHtmlId + ' #li' + id).remove();
objUploadImg.isEncoderBusy = false;
return false;
}
if (jpg.tiff && jpg.tiff.Orientation) {
//设置旋转
conf = $.extend(conf, {
orien: jpg.tiff.Orientation.value
});
}
}
// 压缩
if (objImageCompresser.ImageCompresser.support()) {
var img = new Image();
img.onload = function() {
try {
uploadBase64 = objImageCompresser.ImageCompresser.getImageBase64(this, conf);
} catch (e) {
objGlobal.DIC.dialog({content:'压缩图片失败', autoClose:true});
$(objUploadImg.formHtmlId + ' #li' + id).remove();
objUploadImg.isEncoderBusy = false;
return false;
}
if (uploadBase64.indexOf('data:image') < 0) {
objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});
$(objUploadImg.formHtmlId + ' #li' + id).remove();
objUploadImg.isEncoderBusy = false;
return false;
}
objUploadImg.uploadInfo[id].file = uploadBase64;
$(objUploadImg.formHtmlId + ' #li' + id).find('img').attr('src', uploadBase64);
objUploadImg.uploadQueue.push(id);
}
img.onerror = function() {
objGlobal.DIC.dialog({content:'解析图片数据失败', autoClose:true});
$(objUploadImg.formHtmlId + ' #li' + id).remove();
objUploadImg.isEncoderBusy = false;
return false;
}
img.src = objImageCompresser.ImageCompresser.getFileObjectURL(file);
} else {
uploadBase64 = result;
if (uploadBase64.indexOf('data:image') < 0) {
objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});
$(objUploadImg.formHtmlId + ' #li' + id).remove();
objUploadImg.isEncoderBusy = false;
return false;
}
objUploadImg.uploadInfo[id].file = uploadBase64;
$(objUploadImg.formHtmlId + ' #li' + id).find('img').attr('src', uploadBase64);
objUploadImg.uploadQueue.push(id);
}
}
reader.readAsBinaryString(objUploadImg.uploadInfo[id].file);
};
// 创建上传请求
objUploadImg.createUpload = function(id, type, uploadTimer) {
if (!objUploadImg.uploadInfo[id]) {
objUploadImg.isEncoderBusy = false;
objUploadImg.isBusy = false;
return false;
}
// 移除图片压缩中...
$(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskTxt').remove();
// 图片posturl
var uploadUrl = objUploadImg.uploadUrl;
// 产生进度条
var progressHtml = '<div class="mbupload_progress mbupload_brSmall" id="mbupload_progress'+id+'"><div class="mbupload_proBar" style="width:0%;"></div></div>';
$(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskLay').after(progressHtml);
var formData = new FormData();
formData.append('upload_pic', objUploadImg.uploadInfo[id].file);
formData.append('upload_name', objUploadImg.uploadInfo[id].oldFileInfo.name);
formData.append('upload_id', id);
var progress = function(e) {
if (e.target.response) {
var result = $.parseJSON(e.target.response);
if (result.errCode != 0) {
// $('#content').val(result.errCode);
objGlobal.DIC.dialog({content:'网络不稳定,请稍后重新操作', autoClose:true});
removePic(id);
//更新剩余上传数
objUploadImg.uploadRemaining();
return false;
}
}
var progress = $(objUploadImg.formHtmlId + ' #mbupload_progress' + id).find('.mbupload_proBar');
if (e.total == e.loaded) {
var percent = 100;
} else {
var percent = 100*(e.loaded / e.total);
}
// 控制进度条不要超出
if (percent > 100) {
percent = 100;
}
progress.width(percent + '%');
//progress.animate({'width': '95%'}, 1500);
setTimeout(function(){
if (percent == 100) {
donePic(id);
var pLength = 0, nLength = 0;
if(objUploadImg.uploadPicMore){
pLength = objUploadImg.previewQueue.length;
nLength = objUploadImg.uploadQueue.length;
}
if(uploadTimer && pLength <= 0 && nLength <= 0){
clearInterval(uploadTimer);
}
}
}, 400);
}
var removePic = function(id) {
donePic(id);
$('#li' + id).remove();
}
var donePic = function(id) {
objUploadImg.isEncoderBusy = false;
objUploadImg.isBusy = false;
if(objUploadImg.uploadPicMore && (objUploadImg.previewQueue.length <= 0) &&
(objUploadImg.uploadQueue.length <= 0)){
objUploadImg.isMoreBusy = false;
}
if (typeof objUploadImg.uploadInfo[id] != 'undefined') {
objUploadImg.uploadInfo[id].isDone = true;
}
if (typeof objUploadImg.xhr[id] != 'undefined') {
objUploadImg.xhr[id] = null;
}
}
var complete = function(e) {
var progress = $(objUploadImg.formHtmlId + ' #mbupload_progress' + id).find('.mbupload_proBar');
progress.css('width', '100%');
if($(objUploadImg.formHtmlId + ' #li' + id)){
$(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskTxt').remove();
}
$(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskLay').remove();
$(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_progress').remove();
// 上传结束
donePic(id);
var result = $.parseJSON(e.target.response);
if (result.errCode == 0) {
var input = '<input type="hidden" id="input' + result.data.id + '" name="picIds[]" value="' + result.data.picId + '">';
if(type == 'replyForm'){
$('#replyForm').append(input);
}else{
$(objUploadImg.formHtmlId).append(input);
}
} else {
objGlobal.DIC.dialog({content:'网络不稳定,请稍后重新操作', autoClose:true});
removePic(id);
//更新剩余上传数
objUploadImg.uploadRemaining();
delete objUploadImg.uploadInfo[id];
// 如果传略失败,上传个数少于限制张数则再显示加号
if (objUploadImg.countUpload() < objUploadImg.maxUpload) {
$(objUploadImg.formHtmlId + ' .mbupload_addPic').show();
}
}
}
var failed = function() {
objGlobal.DIC.dialog({content:'网络断开,请稍后重新操作', autoClose:true});
removePic(id)
}
var abort = function() {
objGlobal.DIC.dialog({content:'上传已取消', autoClose:true});
removePic(id)
}
// 创建 ajax 请求
objUploadImg.xhr[id] = new XMLHttpRequest();
objUploadImg.xhr[id].addEventListener("progress", progress, false);
objUploadImg.xhr[id].upload.addEventListener("progress", progress, false);
objUploadImg.xhr[id].addEventListener("load", complete, false);
objUploadImg.xhr[id].addEventListener("abort", abort, false);
objUploadImg.xhr[id].addEventListener("error", failed, false);
objUploadImg.xhr[id].open("POST", uploadUrl);
objUploadImg.xhr[id].send(formData);
};
// 不能上传系统提示
objUploadImg.checkUploadBySysVer = function() {
var mb_os = objGlobal.checkUA();
if (mb_os.ios && mb_os.version.toString() < '6.0') {
objGlobal.DIC.dialog({content:'手机系统不支持传图,请升级到ios6.0以上', autoClose:true});
return false;
}
if (mb_os.wx && mb_os.wxVersion.toString() < '5.2') {
objGlobal.DIC.dialog({content:'当前微信版本不支持传图,请升级到最新版', autoClose:true});
return false;
}
return true;
};
//根据是否可以多图上传生成对应的input
objUploadImg.uploadAddInput = function(){
var input = "", fistInput = "";
if(objUploadImg.uploadPicMore){
input = '<input type="file" class="mbupload_on mbupload_uploadFile" accept="image/*" multiple="">';
fistInput = '<input type="file" class="fistUpload" accept="image/*" multiple="">';
}else{
input = '<input type="file" class="mbupload_on mbupload_uploadFile" accept="image/*" single="">';
fistInput = '<input type="file" class="fistUpload" accept="image/*" single="">';
}
$(objUploadImg.formHtmlId + ' .mbupload_addPic').append(input);
$(objUploadImg.formHtmlId + ' .iconSendImg').append(fistInput);
};
//剩余上传数
objUploadImg.uploadRemaining = function(){
var uploadNum = 0;
uploadNum = $(objUploadImg.formHtmlId + ' .mbupload_photoList').find('li').length;
var canOnlyUploadNum = objUploadImg.maxUpload;
if(uploadNum <= objUploadImg.maxUpload)
{
canOnlyUploadNum = objUploadImg.maxUpload - uploadNum + 1;
}
else
{
canOnlyUploadNum = 0;
}
//当上传出错则显示第一上传页面
if(canOnlyUploadNum == objUploadImg.maxUpload)
{
$(objUploadImg.formHtmlId + ' .mbupload_photoList').hide();
$(objUploadImg.formHtmlId + ' .mbupload_bgimg').show();
}
//更新剩余可上传图片数
$(objUploadImg.formHtmlId + ' .mbupload_onlyUploadNum').html(canOnlyUploadNum);
};
// 检查图片大小
objUploadImg.checkPicSize = function(file) {
var uploadPicSize = objUploadImg.uploadPicSize*1024*1024;
if (file.size > uploadPicSize) {
return false;
}
return true;
};
// 检查图片类型
objUploadImg.checkPicType = function(file) {
var photoReg = (/\.png$|\.bmp$|\.jpg$|\.jpeg$|\.gif$/i);
if(!photoReg.test(file.name)){
return false;
}else{
return true;
}
};
var uploadTimer = null;
var initUpload = function()
{
// 上传图片的绑定
$(objUploadImg.formHtmlId + ' .mbupload_addImg').on("click", function(){
if(!objUploadImg.checkUploadBySysVer()){
return false;
}
});
$(objUploadImg.formHtmlId + ' .mbupload_uploadFile').on("click", function(){
var thisObj = $(this);
if (objUploadImg.isEncoderBusy) {
return false;
}
else if (objUploadImg.isBusy) {
objGlobal.DIC.dialog({content:'上传中,请稍后添加', autoClose:true});
return false;
}
else if (objUploadImg.isMoreBusy) {
objGlobal.DIC.dialog({content:'上传中,请稍后添加', autoClose:true});
return false;
}
});
//首次点击图片的图标,触发一次手机的默认上传事件
$('body').on('change', objUploadImg.formHtmlId + ' .fistUpload', function(e){
$(objUploadImg.formHtmlId + ' .mbupload_photoList').show();
$(objUploadImg.formHtmlId + ' .mbupload_bgimg').hide();
});
// 文件表单发生变化时
$('body').on('change', objUploadImg.formHtmlId + ' .mbupload_uploadFile,' + objUploadImg.formHtmlId + ' .fistUpload', function(e) {
//执行图片预览、压缩定时器
uploadTimer = setInterval(function() {
// 预览
setTimeout(function() {
if (!objUploadImg.isEncoderBusy && objUploadImg.previewQueue.length) {
var jobId = objUploadImg.previewQueue.shift();
objUploadImg.isEncoderBusy = true;
objUploadImg.uploadPreview(jobId);
}
}, 1);
// 上传
setTimeout(function() {
if (!objUploadImg.isBusy && objUploadImg.uploadQueue.length) {
var jobId = objUploadImg.uploadQueue.shift();
objUploadImg.isBusy = true;
if(objUploadImg.uploadPicMore){
objUploadImg.isMoreBusy = true;
}
objUploadImg.createUpload(jobId, objUploadImg.formHtmlId, uploadTimer);
}
}, 10);
}, 300);
e = e || window.event;
var fileList = e.target.files;
if (!fileList.length) {
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
return false;
}
if (objUploadImg.uploadPicMore && (fileList.length > objUploadImg.onceMaxUpload)) {
objGlobal.DIC.dialog({content:'上传图片一次最多只能选' + objUploadImg.onceMaxUpload + '张', autoClose:true});
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
return false;
}
if (objUploadImg.uploadPicMore && (fileList.length > (objUploadImg.maxUpload - objUploadImg.countUpload()))) {
objGlobal.DIC.dialog({content:'你最多只能上传' + objUploadImg.maxUpload + '张照片', autoClose:true});
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
return false;
}
for (var i = 0; i < fileList.length; i++) {
if (objUploadImg.countUpload() >= objUploadImg.maxUpload) {
objGlobal.DIC.dialog({content:'你最多只能上传' + objUploadImg.maxUpload + '张照片', autoClose:true});
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
break;
}
var file = fileList[i];
if (!objUploadImg.checkPicType(file)) {
objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
continue;
}
// console.log(file);
if (!objUploadImg.checkPicSize(file)) {
objGlobal.DIC.dialog({content:'图片大小超过'+ objUploadImg.uploadPicSize + 'MB', autoClose:true});
//更新剩余上传数
objUploadImg.uploadRemaining();
$(this).val('');
continue;
}
var id = Date.now() + i;
// 增加到上传对象中, 上传完成后,修改为 true
objUploadImg.uploadInfo[id] = {
oldFileInfo: file,
file: file,
isDone: false,
};
var html = '<li id="li' + id + '"><div class="mbupload_photoCut"><img src="' + objUploadImg.uploadDefaultImgUrl + '" class="attchImg" alt="photo"></div>' +
'<div class="mbupload_maskLay"></div>' +
'<div class="mbupload_maskTxt">图片压缩中...</div>' +
'<a href="javascript:;" class="mbupload_cBtn mbupload_pa mbupload_db" title="" _id="'+id+'">关闭</a></li>';
$(objUploadImg.formHtmlId + ' .mbupload_addPic').before(html);
objUploadImg.previewQueue.push(id);
// 图片已经上传了 最大限制 张数,隐藏 + 号
if (objUploadImg.countUpload() >= objUploadImg.maxUpload) {
$(objUploadImg.formHtmlId + ' .mbupload_addPic').hide();
}
//更新剩余上传数
setTimeout(function(){
objUploadImg.uploadRemaining();
}, 400);
}
// 把输入框清空
$(this).val('');
});
$(objUploadImg.formHtmlId + ' .mbupload_photoList').on('click', '.mbupload_cBtn', function() {
var id = $(this).attr('_id');
// 取消这个请求
if (objUploadImg.xhr[id]) {
objUploadImg.xhr[id].abort();
}
// 图片删除
$(objUploadImg.formHtmlId + ' #li' + id).remove();
// 表单中删除
$(objUploadImg.formHtmlId + ' #input' + id).remove();
objUploadImg.uploadInfo[id] = null;
// 图片变少了,显示+号
if (objUploadImg.countUpload() < objUploadImg.maxUpload) {
$(objUploadImg.formHtmlId + ' .mbupload_addPic').show();
}
//更新剩余上传数
objUploadImg.uploadRemaining();
//当删除所有图片后隐藏添加图片的图标
if($(objUploadImg.formHtmlId + ' .mbupload_photoList').find('li').length < 2){
$(objUploadImg.formHtmlId + ' .mbupload_photoList').hide();
$(objUploadImg.formHtmlId + ' .mbupload_bgimg').show();
}
});
};
objUploadImg.uploadAddInput();
objUploadImg.uploadRemaining();
initUpload();
};
收起阅读 »

iOS键盘弹出后PopPicker出现的临时解决方法
原因:和iOS中其他有input的地方出现错乱的情况一样,poppicker的样式使用了fixed:
.mui-poppicker {
position: fixed;
}
在mui.poppicker.css中。
所以,分别在poppicker的显示和隐藏代码中对poppicker的display做处理。这里的显示和隐藏其实是修改poppicker的样式bottom,分别是0px和-300px,配合了动画的css,并没有改变display,所以,键盘弹出时poppicker露了出来。
解决方法:
mui.poppicker.js中增加初始化、show和hide方法中display的改变。
```javascript
//init构造函数最后增加两行:
self.panel.style.display = 'none';
self.body.style.display = 'none';
//显示
show: function(callback) {
var self = this;
//增加以下2行
self.panel.style.display = 'block';
self.body.style.display = 'block';
self.callback = callback;
self.mask.show();
document.body.classList.add($.className('poppicker-active-for-page'));
self.panel.classList.add($.className('active'));
//处理物理返回键
self.__back = $.back;
$.back = function() {
self.hide();
};
},
//隐藏
hide: function() {
var self = this;
if (self.disposed) return;
self.panel.classList.remove($.className('active'));
self.mask.close();
document.body.classList.remove($.className('poppicker-active-for-page'));
//增加以下2行
self.panel.style.display = 'none';
self.body.style.display = 'none';
//处理物理返回键
$.back=self.__back;
}
原因:和iOS中其他有input的地方出现错乱的情况一样,poppicker的样式使用了fixed:
.mui-poppicker {
position: fixed;
}
在mui.poppicker.css中。
所以,分别在poppicker的显示和隐藏代码中对poppicker的display做处理。这里的显示和隐藏其实是修改poppicker的样式bottom,分别是0px和-300px,配合了动画的css,并没有改变display,所以,键盘弹出时poppicker露了出来。
解决方法:
mui.poppicker.js中增加初始化、show和hide方法中display的改变。
```javascript
//init构造函数最后增加两行:
self.panel.style.display = 'none';
self.body.style.display = 'none';
//显示
show: function(callback) {
var self = this;
//增加以下2行
self.panel.style.display = 'block';
self.body.style.display = 'block';
self.callback = callback;
self.mask.show();
document.body.classList.add($.className('poppicker-active-for-page'));
self.panel.classList.add($.className('active'));
//处理物理返回键
self.__back = $.back;
$.back = function() {
self.hide();
};
},
//隐藏
hide: function() {
var self = this;
if (self.disposed) return;
self.panel.classList.remove($.className('active'));
self.mask.close();
document.body.classList.remove($.className('poppicker-active-for-page'));
//增加以下2行
self.panel.style.display = 'none';
self.body.style.display = 'none';
//处理物理返回键
$.back=self.__back;
}
收起阅读 »

上拉加载的坑爹联想!
用Hbuild编辑器做上啦加载,被坑爹的联想害了一整天,无力吐槽,endPullupToRefresh(),就这个关闭方法,操,联想出来的是这样的endPullUpToRefresh,看哪个up,联想出来的是大写的,我就无语了,又遇到相同情况的注意一下!!!
用Hbuild编辑器做上啦加载,被坑爹的联想害了一整天,无力吐槽,endPullupToRefresh(),就这个关闭方法,操,联想出来的是这样的endPullUpToRefresh,看哪个up,联想出来的是大写的,我就无语了,又遇到相同情况的注意一下!!!

[源码分享]wordpress转APP玩具
Wordpress-Mobile-Application
利用wordpress
作为后台,构建App
源码地址:github
用到的技术
html5+:http://www.dcloud.io/docs/api/
mui: http://dcloudio.github.io/mui/
hbuilder:[http://www.dcloud.io] (http://www.dcloud.io/)
构建方法
- 安装
wordpress
- 为
wordpress
安装wordpress rest api
(2.0版本及以上) - 在
wordpress
后台:设置/固定链接设置为文章格式 - 更改
/js/app.js
里面的name
和菜单名称和对应的id
(可在example.com/wp-json/wp/v2/categories
查看) 下载hbuilde
,选择文件/打开目录(打开本项目代码目录),双击manifest.json
设置app
名称和id
,修改app
图标和启动图。- 点击发行,发行为原生应用,设置好开发者证书,然后打包。
打包成功后会自动下载到本地目录,这样一个App
就制作好了。
项目截图
License
The MIT License (MIT)
Copyright (c) 2016 Zhen.Wang
Wordpress-Mobile-Application
利用wordpress
作为后台,构建App
源码地址:github
用到的技术
html5+:http://www.dcloud.io/docs/api/
mui: http://dcloudio.github.io/mui/
hbuilder:[http://www.dcloud.io] (http://www.dcloud.io/)
构建方法
- 安装
wordpress
- 为
wordpress
安装wordpress rest api
(2.0版本及以上) - 在
wordpress
后台:设置/固定链接设置为文章格式 - 更改
/js/app.js
里面的name
和菜单名称和对应的id
(可在example.com/wp-json/wp/v2/categories
查看) 下载hbuilde
,选择文件/打开目录(打开本项目代码目录),双击manifest.json
设置app
名称和id
,修改app
图标和启动图。- 点击发行,发行为原生应用,设置好开发者证书,然后打包。
打包成功后会自动下载到本地目录,这样一个App
就制作好了。
项目截图
License
The MIT License (MIT)
Copyright (c) 2016 Zhen.Wang
收起阅读 »
5+App、wap2app的video、视频播放开发注意
此文不适于uni-app,仅适于5+app
5+App、wap2app的视频播放有3种解决方案,使用HTML5的自带video、原生视频播放,以及使用Native.js调用外部播放器。
- HTML5自带video标签,可以播放符合HTML5规范的视频格式。
注意不含flv、ra等三方商业公司的规范格式。
HTML5的video在Android上有较多浏览器兼容性问题,这里有篇网友分享的经典文章讲述了HTML5 video的使用注意,http://ask.dcloud.net.cn/article/569
注意事项,Android上使用video标签播放视频时,务必打开硬件加速,否则只有声音没有画面。
HBuilder8.8.4以前的版本,在Android5的部分rom上是默认关闭硬件加速的,此时需强制打开硬件加速。创建webview时style里有个hardwareAccelerated参数,设置为true。
硬件加速的详解参考文档http://ask.dcloud.net.cn/article/55
视频全屏播放时有时不能自动横屏最大化,参考http://ask.dcloud.net.cn/article/1077
HTML5自带video,如果想实现手势拖动进度,这里有篇参考文章http://ask.dcloud.net.cn/article/13263,但受限于HTML5的性能,拖动无法流畅跟手。
从HBuilderX 2.5.3起,Android上新增了x5内核,使用x5播放视频,表现优于Webview自带的video标签。使用x5详见:https://ask.dcloud.net.cn/article/36806
iOS的视频播放,使用uiWebview和wkWebview有不同效果,wkWebview的视频播放自带AirPlay功能,可以直接连接电视。但需要注意wkWebview和uiWebview的差异,详见http://ask.dcloud.net.cn/article/1318
-
原生视频
很多开发者对于HTML5自带视频有几处不满:
a) 支持格式不丰富,比如flv
b) 全屏后手势拖动不流畅,不能顺滑的拖动进度和音量、亮度
在开发者提供直播推流时,5+引擎引入了专业视频解码库,也就顺便提供了plus.video的原生视频播放能力。
但plus.video的原生视频播放会增加不少包体积,需要开发者自己平衡好需求。
5+App里原生视频控件需要使用js创建,参考http://www.html5plus.org/doc/zh_cn/video.html
uni-app里的video组件,默认不是HTML的video,默认就是原生video。
使用原生video注意它的层级较高,覆盖原生控件,在5+app里使用plus.nativeObj.view,在uni-app里使用cover-view、plus.nativeObj.view、subnvue都可以,如果是nvue,那不存在层级问题,并且全屏后的视频也可以随意自定义界面。从体验角度,最好的是nvue的video。 -
除了HTML5的video,开发者也可以在Android上使用Native.js调用系统播放器来放视频。
但视频的播放进度等状态无法回传给js层。
参考http://ask.dcloud.net.cn/question/614
此文不适于uni-app,仅适于5+app
5+App、wap2app的视频播放有3种解决方案,使用HTML5的自带video、原生视频播放,以及使用Native.js调用外部播放器。
- HTML5自带video标签,可以播放符合HTML5规范的视频格式。
注意不含flv、ra等三方商业公司的规范格式。
HTML5的video在Android上有较多浏览器兼容性问题,这里有篇网友分享的经典文章讲述了HTML5 video的使用注意,http://ask.dcloud.net.cn/article/569
注意事项,Android上使用video标签播放视频时,务必打开硬件加速,否则只有声音没有画面。
HBuilder8.8.4以前的版本,在Android5的部分rom上是默认关闭硬件加速的,此时需强制打开硬件加速。创建webview时style里有个hardwareAccelerated参数,设置为true。
硬件加速的详解参考文档http://ask.dcloud.net.cn/article/55
视频全屏播放时有时不能自动横屏最大化,参考http://ask.dcloud.net.cn/article/1077
HTML5自带video,如果想实现手势拖动进度,这里有篇参考文章http://ask.dcloud.net.cn/article/13263,但受限于HTML5的性能,拖动无法流畅跟手。
从HBuilderX 2.5.3起,Android上新增了x5内核,使用x5播放视频,表现优于Webview自带的video标签。使用x5详见:https://ask.dcloud.net.cn/article/36806
iOS的视频播放,使用uiWebview和wkWebview有不同效果,wkWebview的视频播放自带AirPlay功能,可以直接连接电视。但需要注意wkWebview和uiWebview的差异,详见http://ask.dcloud.net.cn/article/1318
-
原生视频
很多开发者对于HTML5自带视频有几处不满:
a) 支持格式不丰富,比如flv
b) 全屏后手势拖动不流畅,不能顺滑的拖动进度和音量、亮度
在开发者提供直播推流时,5+引擎引入了专业视频解码库,也就顺便提供了plus.video的原生视频播放能力。
但plus.video的原生视频播放会增加不少包体积,需要开发者自己平衡好需求。
5+App里原生视频控件需要使用js创建,参考http://www.html5plus.org/doc/zh_cn/video.html
uni-app里的video组件,默认不是HTML的video,默认就是原生video。
使用原生video注意它的层级较高,覆盖原生控件,在5+app里使用plus.nativeObj.view,在uni-app里使用cover-view、plus.nativeObj.view、subnvue都可以,如果是nvue,那不存在层级问题,并且全屏后的视频也可以随意自定义界面。从体验角度,最好的是nvue的video。 -
除了HTML5的video,开发者也可以在Android上使用Native.js调用系统播放器来放视频。
但视频的播放进度等状态无法回传给js层。
参考http://ask.dcloud.net.cn/question/614

modal 弹出浮层的使用方法
.mui-modal {top:300px !important;}
.mui-content{overflow-y:auto;}
.mui-modal {top:300px !important;} 用来控制距离顶部高度
.mui-content{overflow-y:auto;} 用来控制内容溢出后的自动上下滚动
就是浮层的背景遮罩效果暂时还不知道怎么弄
mui是好东西,但是文档真的太弱了,这个modal 都是藏在例子中的。。。。
再提供下这个例子的路径 :examples/modals.html
.mui-modal {top:300px !important;}
.mui-content{overflow-y:auto;}
.mui-modal {top:300px !important;} 用来控制距离顶部高度
.mui-content{overflow-y:auto;} 用来控制内容溢出后的自动上下滚动
就是浮层的背景遮罩效果暂时还不知道怎么弄
mui是好东西,但是文档真的太弱了,这个modal 都是藏在例子中的。。。。
再提供下这个例子的路径 :examples/modals.html
收起阅读 »
安利一个小应用,以wordpress为后台的博客/资讯应用

HBuilder常用js汇总
/*
* 服务器的地址
*/
var strservicef = '';
var strservices = '';
/*
* 主要的公共函数
*/
var Fun_App = {
/**
* 完整的打开新页面方法
* @param {Object} _url
*/
OpenPage: function(id, gethtmlurl,action,sendvalue) {
var page = mui.preload({
url:gethtmlurl,
id: gethtmlurl,
});
var getid = document.getElementById(id);
getid.addEventListener('tap', function() {
mui.openWindow({
url:gethtmlurl,
id:gethtmlurl,
styles:{
top:"44px",
bottom:"50px",
width:"100%",
height:"100%"
},
extras:{
kid:sendvalue
},
show:{
autoShow:true,//页面loaded事件发生后自动显示,默认为true
aniShow:action,//页面显示动画,默认为”slide-in-right“;
duration:100//页面动画持续时间,Android平台默认100毫秒,iOS平台默认200毫秒;
},
waiting:{
autoShow:true,//自动显示等待框,默认为true
title:"正在加载..."//等待对话框上显示的提示内容
}
})
});
},
/*
* 页面间传值的获取
*/
getextrasdata: function(kid){
var self = plus.webview.currentWebview();
return self.kid;
},
/*
* ajax 数据请求方法
*/
ExAjax: function(url, rdata) {
mui.ajax({
url: url,
type: "post",
data: rdata.config,
dataType: 'json',
timeout:10000,
success: function(data) {
rdata.fun_Success(data);
},
error: function(xhr, type, errorThrown) {
console.log(JSON.stringify(xhr) + type + "---" + errorThrown);
}
});
},
/*
* 数据存储的函数
*/
storagedata: function(kname,sdata){
localStorage.setItem(kname,sdata);
},
/*
* 数据读取
*/
getdata: function(kname){
return localStorage.getItem(kname);
},
/*
* 数据删除
*/
deldata: function(kname){
localStorage.removeItem(kname);
},
/*
* 手势配置
*/
gesture: function(){
var gs = {
gestureConfig:{
tap: true, //默认为true
doubletap: true, //默认为false
longtap: true, //默认为false
swipe: true, //默认为true
drag: true //默认为true
}
};
return gs;
},
/*
* 隐藏滚动条
*/
delscroll: function(){
plus.webview.currentWebview().setStyle({
scrollIndicator: 'none',
});
},
/*
* 返回键退出程序
* 1秒内,连续两次按返回键,则退出应用
*/
FunBackQuitAppL: function(){
var backFirst = null;
this.QuitApp = function() {
//首次按键,提示‘再按一次退出应用’
if (!backFirst) {
backFirst = new Date().getTime();
mui.toast('再按一次退出应用程序');
setTimeout(function() {
backFirst = null;
}, 1000);
} else {
if ((new Date()).getTime() - backFirst < 1000) {
plus.runtime.quit();
}
}
}
}
}
/*
* 服务器的地址
*/
var strservicef = '';
var strservices = '';
/*
* 主要的公共函数
*/
var Fun_App = {
/**
* 完整的打开新页面方法
* @param {Object} _url
*/
OpenPage: function(id, gethtmlurl,action,sendvalue) {
var page = mui.preload({
url:gethtmlurl,
id: gethtmlurl,
});
var getid = document.getElementById(id);
getid.addEventListener('tap', function() {
mui.openWindow({
url:gethtmlurl,
id:gethtmlurl,
styles:{
top:"44px",
bottom:"50px",
width:"100%",
height:"100%"
},
extras:{
kid:sendvalue
},
show:{
autoShow:true,//页面loaded事件发生后自动显示,默认为true
aniShow:action,//页面显示动画,默认为”slide-in-right“;
duration:100//页面动画持续时间,Android平台默认100毫秒,iOS平台默认200毫秒;
},
waiting:{
autoShow:true,//自动显示等待框,默认为true
title:"正在加载..."//等待对话框上显示的提示内容
}
})
});
},
/*
* 页面间传值的获取
*/
getextrasdata: function(kid){
var self = plus.webview.currentWebview();
return self.kid;
},
/*
* ajax 数据请求方法
*/
ExAjax: function(url, rdata) {
mui.ajax({
url: url,
type: "post",
data: rdata.config,
dataType: 'json',
timeout:10000,
success: function(data) {
rdata.fun_Success(data);
},
error: function(xhr, type, errorThrown) {
console.log(JSON.stringify(xhr) + type + "---" + errorThrown);
}
});
},
/*
* 数据存储的函数
*/
storagedata: function(kname,sdata){
localStorage.setItem(kname,sdata);
},
/*
* 数据读取
*/
getdata: function(kname){
return localStorage.getItem(kname);
},
/*
* 数据删除
*/
deldata: function(kname){
localStorage.removeItem(kname);
},
/*
* 手势配置
*/
gesture: function(){
var gs = {
gestureConfig:{
tap: true, //默认为true
doubletap: true, //默认为false
longtap: true, //默认为false
swipe: true, //默认为true
drag: true //默认为true
}
};
return gs;
},
/*
* 隐藏滚动条
*/
delscroll: function(){
plus.webview.currentWebview().setStyle({
scrollIndicator: 'none',
});
},
/*
* 返回键退出程序
* 1秒内,连续两次按返回键,则退出应用
*/
FunBackQuitAppL: function(){
var backFirst = null;
this.QuitApp = function() {
//首次按键,提示‘再按一次退出应用’
if (!backFirst) {
backFirst = new Date().getTime();
mui.toast('再按一次退出应用程序');
setTimeout(function() {
backFirst = null;
}, 1000);
} else {
if ((new Date()).getTime() - backFirst < 1000) {
plus.runtime.quit();
}
}
}
}
}
收起阅读 »

切图网招聘 响应式前端 数名
要求 能基于 css3 多媒体查询做 响应式网站 ,18~ 30 岁,男女不限, 要求会用 hbuilder 进行开发。 联系qq/微信:6135833 , 地址 在荆州。
要求 能基于 css3 多媒体查询做 响应式网站 ,18~ 30 岁,男女不限, 要求会用 hbuilder 进行开发。 联系qq/微信:6135833 , 地址 在荆州。

DCloud发布gostream.js,一行代码把wap流量转App流量

Wap流量转化太低,流量主伤不起
随着移动App的兴起,越来越多的网站开始把自身的wap站流量导向自己的App,但是传统的导流方法还是比较老套,比如在网站的首页挂个“下载客户端”的按钮,但这种方式的转化率很低,大多都是百分之几。
但是用户依旧会光临你的wap站,是因为用户还需要内容,并且市场上浏览器、搜索引擎的流量仍然是巨大的。但是用户却不想花费1分钟下载安装沉重的App,怎么解决?
DCloud公司现在提供了一个免费的gostream.js,把这个js嵌入到你的wap页面里,用户访问你的wap站时,可以直接秒装流应用并打开(流应用是什么下面讲),同时还会在用户的Android手机桌面安装图标,实现wap站之前梦寐以求的桌面留存。
(只需引入如下js文件,即可实现wap流量转App)
gostream.js是什么黑科技?
Wap流量秒转App流量,这么神奇?
这种世界级难题竟然被解决了?这是什么原理呢?
这里需要先引入一个概念叫流应用。
流应用是DCloud公司的产品,一种把App安装包大幅压缩并且流式下载安装到手机上的技术。一个流应用的体积一般只有几百k,并且是边用边下,只需先下载几十K,应用就可以启动,然后用户一边使用App一边系统在后台持续下载完成。就像我们在线看流媒体电影,也是边看边播。
流应用是随着移动互联网带宽升级及新技术突破而引来的创新模式。
而gostream.js则基于流应用更进一步。
在wap站上内嵌这个js,这个js可以检测手机上有没有流应用引擎,如果有的话,可以直接启动流应用引擎,秒装秒开流应用。
对,流应用的边用边下需要手机已经安装了流应用引擎,这个客户端引擎配合DCloud的专利技术的流应用服务器才能实现边用边下。
那么问题来了,流应用引擎有多少装机量呢?如果量不够,实际导流效果还是不会好啊。
答案是:DCloud的流应用引擎已经有上亿装机量,目前的检测数据是每3台Android设备就有1台能检测到流应用引擎。
如何体验效果?
用你的手机浏览器访问http://dcloud.io/demo/gostream/,如果你手机上没有流应用引擎,会提示你安装引擎。
这里是体验视频:http://v.qq.com/page/t/9/8/t0190xh3198.html
gostream.js其他更多用途
除了wap站导流到流应用,gostream.js还能用于更多导流方案。
1. 分享导流,通过在分享的url页面里挂gostream.js,可以实现通过社交途径带动应用发行。
2. 广告sdk导流,广告sdk导流到wap时体验差,导流到App时折损高。那么在导流到wap时引入gostream.js,即可降低折损、增强体验。
3. App互导流,在App中集成流应用引擎或检测手机端的流应用引擎,均可实现更高效的导流方案。
本质上流应用是一种极高效率、优质体验的导流技术,随着移动互联网第一拨流量红利的结束,流应用打开了新的流量蓝海!
更多详情,请点击>>http://ask.dcloud.net.cn/article/579
附录:DCloud CEO在Google for publishers论坛的演讲:揭秘H5流量为什么不值钱?
2016年3月1日,Google在北京举行Google for publishers论坛。活动吸引了数百位广告主、流量主和开发者参加。DCloud创始人王安在会上分享的H5流量为什么低廉以及如何提升H5流量价值等问题,深受参会人员关注。
下文为DCloud创始人王安分享的观点:
大家都知道,目前H5的流量按pv卖,一个pv几毛钱,而App的流量按下载或激活卖,一个下载几元,一个激活可能十几元。为什么H5的流量比App便宜这么多?大家想过没有。
有人说H5获取容易但体验不行,所以流量便宜。App获取不容易,但体验好,所以流量贵。
简单看是这个意思,但深入分析进去,不是体验差可以概括的。从数据运营的角度看,H5从入口流量开始,注册转换、付费转换、留存都远低于App。广告主买来的H5流量,很难留住用户和持续变现,这倒逼着广告主无法支付给H5流量过高的采购价格。
难道H5流量廉价的现状就无法改变了吗?其实不是。摸清病,就可以对症下药。
1. 优化HTML5的功能和体验,达到原生效果
先从体验开始说起,大家提到DCloud一般都能想到,DCloud之前最著名的就是解决HTML5“性工能”缺失问题,是的,这几年DCloud通过Hbuilder、HTML5+、MUI几个免费和开源的产品,把HTML5的性能、工具、能力做到跟原生接近,普通用户难以感知区别。
包括流畅的窗体切换动画、长列表滚动、下拉刷新这些用户体验优化,还有40万原生API的调用,这些问题都已解决了。具体怎么实现以前经常讲,这里就不讲了,没听过的可以上我们官网看,http://www.DCloud.io
2. 优化HTML5的运营折损
除了感性的体验优化,我们更在数据运营层面做了很多优化来避免折损。
经过强化的HTML5+,用户用手机号注册时也可以截获短信验证码启动填入输入框,也可以调用微信、QQ、微博单点登陆,在注册环节的折损和原生App保持一致。
除了注册,在支付环节也一样,经过强化的HTML5+也可以调起支付宝、微信原生支付以及苹果应用内支付IAP。
这样HTML5+从入口流量开始,到注册转换和付费转换,是不会比原生有差距的。
3. 提升留存
然后剩下问题就是留存了。
H5与App相比,留存率低一般2个原因:
a) 体验不好下次不用了。这个上面提到已经解决了。
b) 另一个重要原因是H5页面在桌面没有图标。
这里我要引入一个概念,叫“流应用”,也是DCloud的重要产品,目前有上亿装机量。
用户在访问一个浏览器网页时,是不会在桌面留存图标的,那叫在线浏览。流应用虽然是使用经过强化的HTML5+开发,但引入了安装的概念,在桌面留有图标。但这种安装呢,又不像原生App安装那么麻烦,流应用和流媒体的概念类似,有缓冲和边用边下的概念,一点你就能用,但边用边装,一会儿就整个App安装完毕了。
大家可以在360手机助手里体验,手机上打开360手机助手,搜索大众点评外卖,可以看到列表里的按钮不叫下载了,叫“秒开”,一点后,App直接启动并同时安装在桌面。
参考体验视频:http://v.qq.com/page/i/c/f/i0171dyo7cf.html
所以,留存率低于原生的问题也解决了。
经过强化的HTML5+,通过流应用方式驻留在桌面,在功能体验和运营数据上都可以达到原生App标准。HTML5的流量价值将可以和原生狠狠拼一把了。
有人问了,通过应用市场加载流应用虽然挺好,但我原来的浏览器里的H5流量怎么利用和提价啊。
Good question!
以往的做法是wap站上挂一个banner引导用户下载原生App,实际上转化率非常低。
现在DCloud提供了一个免费的js,gostream.js,把这个js嵌入到你的H5页面里,这个js检测到手机有流应用引擎时,可以直接秒开流应用并安装到手机里。刚才讲了我们的流应用引擎已经有上亿装机量,目前我们的测试数据是每3台Android设备就有一台检测到流应用引擎。
具体的集成地址是:<script src="http://cdn.dcloud.net.cn/gostream.min.js?Appid=HelloMUI">
注意Appid的值更换为自己的流应用的Appid。
So,就是这么简单,就可以把wap流量变成App流量。
技术人员在这里看到了很酷的新技术,广告主看到了更高效的推广方式,渠道也可以看了很多商机,我们目前的渠道合作分成政策也很优惠。
大家可以继续关注我们的公众号或访问我们DCloud的网站深入了解。
Wap流量转化太低,流量主伤不起
随着移动App的兴起,越来越多的网站开始把自身的wap站流量导向自己的App,但是传统的导流方法还是比较老套,比如在网站的首页挂个“下载客户端”的按钮,但这种方式的转化率很低,大多都是百分之几。
但是用户依旧会光临你的wap站,是因为用户还需要内容,并且市场上浏览器、搜索引擎的流量仍然是巨大的。但是用户却不想花费1分钟下载安装沉重的App,怎么解决?
DCloud公司现在提供了一个免费的gostream.js,把这个js嵌入到你的wap页面里,用户访问你的wap站时,可以直接秒装流应用并打开(流应用是什么下面讲),同时还会在用户的Android手机桌面安装图标,实现wap站之前梦寐以求的桌面留存。
(只需引入如下js文件,即可实现wap流量转App)
gostream.js是什么黑科技?
Wap流量秒转App流量,这么神奇?
这种世界级难题竟然被解决了?这是什么原理呢?
这里需要先引入一个概念叫流应用。
流应用是DCloud公司的产品,一种把App安装包大幅压缩并且流式下载安装到手机上的技术。一个流应用的体积一般只有几百k,并且是边用边下,只需先下载几十K,应用就可以启动,然后用户一边使用App一边系统在后台持续下载完成。就像我们在线看流媒体电影,也是边看边播。
流应用是随着移动互联网带宽升级及新技术突破而引来的创新模式。
而gostream.js则基于流应用更进一步。
在wap站上内嵌这个js,这个js可以检测手机上有没有流应用引擎,如果有的话,可以直接启动流应用引擎,秒装秒开流应用。
对,流应用的边用边下需要手机已经安装了流应用引擎,这个客户端引擎配合DCloud的专利技术的流应用服务器才能实现边用边下。
那么问题来了,流应用引擎有多少装机量呢?如果量不够,实际导流效果还是不会好啊。
答案是:DCloud的流应用引擎已经有上亿装机量,目前的检测数据是每3台Android设备就有1台能检测到流应用引擎。
如何体验效果?
用你的手机浏览器访问http://dcloud.io/demo/gostream/,如果你手机上没有流应用引擎,会提示你安装引擎。
这里是体验视频:http://v.qq.com/page/t/9/8/t0190xh3198.html
gostream.js其他更多用途
除了wap站导流到流应用,gostream.js还能用于更多导流方案。
1. 分享导流,通过在分享的url页面里挂gostream.js,可以实现通过社交途径带动应用发行。
2. 广告sdk导流,广告sdk导流到wap时体验差,导流到App时折损高。那么在导流到wap时引入gostream.js,即可降低折损、增强体验。
3. App互导流,在App中集成流应用引擎或检测手机端的流应用引擎,均可实现更高效的导流方案。
本质上流应用是一种极高效率、优质体验的导流技术,随着移动互联网第一拨流量红利的结束,流应用打开了新的流量蓝海!
更多详情,请点击>>http://ask.dcloud.net.cn/article/579
附录:DCloud CEO在Google for publishers论坛的演讲:揭秘H5流量为什么不值钱?
2016年3月1日,Google在北京举行Google for publishers论坛。活动吸引了数百位广告主、流量主和开发者参加。DCloud创始人王安在会上分享的H5流量为什么低廉以及如何提升H5流量价值等问题,深受参会人员关注。
下文为DCloud创始人王安分享的观点:
大家都知道,目前H5的流量按pv卖,一个pv几毛钱,而App的流量按下载或激活卖,一个下载几元,一个激活可能十几元。为什么H5的流量比App便宜这么多?大家想过没有。
有人说H5获取容易但体验不行,所以流量便宜。App获取不容易,但体验好,所以流量贵。
简单看是这个意思,但深入分析进去,不是体验差可以概括的。从数据运营的角度看,H5从入口流量开始,注册转换、付费转换、留存都远低于App。广告主买来的H5流量,很难留住用户和持续变现,这倒逼着广告主无法支付给H5流量过高的采购价格。
难道H5流量廉价的现状就无法改变了吗?其实不是。摸清病,就可以对症下药。
1. 优化HTML5的功能和体验,达到原生效果
先从体验开始说起,大家提到DCloud一般都能想到,DCloud之前最著名的就是解决HTML5“性工能”缺失问题,是的,这几年DCloud通过Hbuilder、HTML5+、MUI几个免费和开源的产品,把HTML5的性能、工具、能力做到跟原生接近,普通用户难以感知区别。
包括流畅的窗体切换动画、长列表滚动、下拉刷新这些用户体验优化,还有40万原生API的调用,这些问题都已解决了。具体怎么实现以前经常讲,这里就不讲了,没听过的可以上我们官网看,http://www.DCloud.io
2. 优化HTML5的运营折损
除了感性的体验优化,我们更在数据运营层面做了很多优化来避免折损。
经过强化的HTML5+,用户用手机号注册时也可以截获短信验证码启动填入输入框,也可以调用微信、QQ、微博单点登陆,在注册环节的折损和原生App保持一致。
除了注册,在支付环节也一样,经过强化的HTML5+也可以调起支付宝、微信原生支付以及苹果应用内支付IAP。
这样HTML5+从入口流量开始,到注册转换和付费转换,是不会比原生有差距的。
3. 提升留存
然后剩下问题就是留存了。
H5与App相比,留存率低一般2个原因:
a) 体验不好下次不用了。这个上面提到已经解决了。
b) 另一个重要原因是H5页面在桌面没有图标。
这里我要引入一个概念,叫“流应用”,也是DCloud的重要产品,目前有上亿装机量。
用户在访问一个浏览器网页时,是不会在桌面留存图标的,那叫在线浏览。流应用虽然是使用经过强化的HTML5+开发,但引入了安装的概念,在桌面留有图标。但这种安装呢,又不像原生App安装那么麻烦,流应用和流媒体的概念类似,有缓冲和边用边下的概念,一点你就能用,但边用边装,一会儿就整个App安装完毕了。
大家可以在360手机助手里体验,手机上打开360手机助手,搜索大众点评外卖,可以看到列表里的按钮不叫下载了,叫“秒开”,一点后,App直接启动并同时安装在桌面。
参考体验视频:http://v.qq.com/page/i/c/f/i0171dyo7cf.html
所以,留存率低于原生的问题也解决了。
经过强化的HTML5+,通过流应用方式驻留在桌面,在功能体验和运营数据上都可以达到原生App标准。HTML5的流量价值将可以和原生狠狠拼一把了。
有人问了,通过应用市场加载流应用虽然挺好,但我原来的浏览器里的H5流量怎么利用和提价啊。
Good question!
以往的做法是wap站上挂一个banner引导用户下载原生App,实际上转化率非常低。
现在DCloud提供了一个免费的js,gostream.js,把这个js嵌入到你的H5页面里,这个js检测到手机有流应用引擎时,可以直接秒开流应用并安装到手机里。刚才讲了我们的流应用引擎已经有上亿装机量,目前我们的测试数据是每3台Android设备就有一台检测到流应用引擎。
具体的集成地址是:<script src="http://cdn.dcloud.net.cn/gostream.min.js?Appid=HelloMUI">
注意Appid的值更换为自己的流应用的Appid。
So,就是这么简单,就可以把wap流量变成App流量。
技术人员在这里看到了很酷的新技术,广告主看到了更高效的推广方式,渠道也可以看了很多商机,我们目前的渠道合作分成政策也很优惠。
大家可以继续关注我们的公众号或访问我们DCloud的网站深入了解。

揭秘H5流量为什么不如App值钱?
3月1日,Google在其北京办公室举行Google for publishers论坛 。活动吸引了数百位广告主、流量主和开发者参加。DCloud创始人王安在会上分享的H5流量为什么低廉以及如何提升H5流量价值等问题,深受参会人员关注。
下文为DCloud创始人王安分享的观点:
大家都知道,目前H5的流量按pv卖,一个pv几毛钱,而App的流量按下载或激活卖,一个下载几元,一个激活可能十几元。为什么H5的流量比App便宜这么多?大家想过没有。
有人说H5获取容易但体验不行,所以流量便宜。App获取不容易,但体验好,所以流量贵。
简单看是这个意思,但深入分析进去,不是体验差可以概括的。从数据运营的角度看,H5从入口流量开始,注册转换、付费转换、留存都远低于App。广告主买来的H5流量,很难留住用户和持续变现,这倒逼着广告主无法支付给H5流量过高的采购价格。
难道H5流量廉价的现状就无法改变了吗?其实不是。摸清病,就可以对症下药。
1.优化HTML5的功能和体验,达到原生效果
先从体验开始说起,大家提到DCloud一般都能想到,哦,那家可以解决HTML5“性工能”缺失的公司,是的,这几年DCloud通过Hbuilder、HTML5 、MUI几个免费和开源的产品,把HTML5的性能、工具、能力做到跟原生接近,普通用户难以感知区别。
包括流畅的窗体切换动画、长列表滚动、下拉刷新这些用户体验优化,还有40万原生API的调用,这些问题都已解决了。具体怎么实现以前经常讲,这里就不讲了,没听过的可以上我们官网看,http://www.DCloud.io
2.优化HTML5的运营折损
除了感性的体验优化,我们更在数据运营层面做了很多优化来避免折损。
经过强化的HTML5 ,用户用手机号注册时也可以截获短信验证码启动填入输入框,也可以调用微信、QQ、微博单点登陆,在注册环节的折损和原生App保持一致。
除了注册,在支付环节也一样,经过强化的HTML5 也可以调起支付宝、微信原生支付以及苹果应用内支付IAP。
这样HTML5 从入口流量开始,到注册转换和付费转换,是不会比原生有差距的。
3.提升留存
然后剩下问题就是留存了。
H5与App相比,留存率低一般2个原因:
a) 体验不好下次不用了。这个上面提到已经解决了。
b) 另一个重要原因是H5页面在桌面没有图标。
这里我要引入一个概念,叫“流应用”,也是DCloud的重要产品,目前有上亿装机量。
用户在访问一个浏览器网页时,是不会在桌面留存图标的,那叫在线浏览。流应用虽然是使用经过强化的HTML5 开发,但引入了安装的概念,在桌面留有图标。但这种安装呢,又不像原生App安装那么麻烦,流应用和流媒体的概念类似,有缓冲和边用边下的概念,一点你就能用,但边用边装,一会儿就整个App安装完毕了。
大家可以在360手机助手里体验,手机上打开360手机助手,搜索大众点评外卖,可以看到列表里的按钮不叫下载了,叫“秒开”,一点后,App直接启动并同时安装在桌面。
参考体验视频:
http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_i0171dyo7cf.html
所以,留存率低于原生的问题也解决了。
经过强化的HTML5 ,通过流应用方式驻留在桌面,在功能体验和运营数据上都可以达到原生App标准。HTML5的流量价值将可以和原生狠狠拼一把了。
有人问了,通过应用市场加载流应用虽然挺好,但我原来的浏览器里的H5流量怎么利用和提价啊。
Good question!
DCloud提供了一个免费的js,把这个js嵌入到你的H5页面里,这个js检测到手机有流应用引擎时,可以直接秒开流应用并安装到手机里。刚才讲了我们的流应用引擎已经有一亿多装机量,目前我们的测试数据是每3台Android设备就有一台检测到流应用引擎。
技术人员在这里看到了很酷的新技术,广告主看到了更高效的推广方式,渠道也可以看了很多商机,我们目前的渠道合作分成政策也很优惠。
大家可以继续关注我们的公众号或访问我们DCloud的网站深入了解。
后记:
流应用安装的意义不止是为了桌面驻留。
b/s的网页有几个问题,无网会404白屏,加载页面时是数据和界面一起下载,这导致流量大,切换页面慢,中间容易白屏。
而App是c/s结构的,其界面是在本地的,从服务器只取很小的json,流量小,切换页面快。这也是App体验比web好的重要原因之一。
但传统App的安装过程很复杂,一个app从下载开始,到安装完毕成功启动,需要耗时一分钟,激活率一般只有50%。
流应用是边用边下的,所以既保持了c/s的App级别的优质用户体验,又避免了下载安装启动的激活折损。流应用同时结合了c/s和b/s的优势又避免了他们的缺点,这才是下一代移动互联网代表的方向。
3月1日,Google在其北京办公室举行Google for publishers论坛 。活动吸引了数百位广告主、流量主和开发者参加。DCloud创始人王安在会上分享的H5流量为什么低廉以及如何提升H5流量价值等问题,深受参会人员关注。
下文为DCloud创始人王安分享的观点:
大家都知道,目前H5的流量按pv卖,一个pv几毛钱,而App的流量按下载或激活卖,一个下载几元,一个激活可能十几元。为什么H5的流量比App便宜这么多?大家想过没有。
有人说H5获取容易但体验不行,所以流量便宜。App获取不容易,但体验好,所以流量贵。
简单看是这个意思,但深入分析进去,不是体验差可以概括的。从数据运营的角度看,H5从入口流量开始,注册转换、付费转换、留存都远低于App。广告主买来的H5流量,很难留住用户和持续变现,这倒逼着广告主无法支付给H5流量过高的采购价格。
难道H5流量廉价的现状就无法改变了吗?其实不是。摸清病,就可以对症下药。
1.优化HTML5的功能和体验,达到原生效果
先从体验开始说起,大家提到DCloud一般都能想到,哦,那家可以解决HTML5“性工能”缺失的公司,是的,这几年DCloud通过Hbuilder、HTML5 、MUI几个免费和开源的产品,把HTML5的性能、工具、能力做到跟原生接近,普通用户难以感知区别。
包括流畅的窗体切换动画、长列表滚动、下拉刷新这些用户体验优化,还有40万原生API的调用,这些问题都已解决了。具体怎么实现以前经常讲,这里就不讲了,没听过的可以上我们官网看,http://www.DCloud.io
2.优化HTML5的运营折损
除了感性的体验优化,我们更在数据运营层面做了很多优化来避免折损。
经过强化的HTML5 ,用户用手机号注册时也可以截获短信验证码启动填入输入框,也可以调用微信、QQ、微博单点登陆,在注册环节的折损和原生App保持一致。
除了注册,在支付环节也一样,经过强化的HTML5 也可以调起支付宝、微信原生支付以及苹果应用内支付IAP。
这样HTML5 从入口流量开始,到注册转换和付费转换,是不会比原生有差距的。
3.提升留存
然后剩下问题就是留存了。
H5与App相比,留存率低一般2个原因:
a) 体验不好下次不用了。这个上面提到已经解决了。
b) 另一个重要原因是H5页面在桌面没有图标。
这里我要引入一个概念,叫“流应用”,也是DCloud的重要产品,目前有上亿装机量。
用户在访问一个浏览器网页时,是不会在桌面留存图标的,那叫在线浏览。流应用虽然是使用经过强化的HTML5 开发,但引入了安装的概念,在桌面留有图标。但这种安装呢,又不像原生App安装那么麻烦,流应用和流媒体的概念类似,有缓冲和边用边下的概念,一点你就能用,但边用边装,一会儿就整个App安装完毕了。
大家可以在360手机助手里体验,手机上打开360手机助手,搜索大众点评外卖,可以看到列表里的按钮不叫下载了,叫“秒开”,一点后,App直接启动并同时安装在桌面。
参考体验视频:
http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_i0171dyo7cf.html
所以,留存率低于原生的问题也解决了。
经过强化的HTML5 ,通过流应用方式驻留在桌面,在功能体验和运营数据上都可以达到原生App标准。HTML5的流量价值将可以和原生狠狠拼一把了。
有人问了,通过应用市场加载流应用虽然挺好,但我原来的浏览器里的H5流量怎么利用和提价啊。
Good question!
DCloud提供了一个免费的js,把这个js嵌入到你的H5页面里,这个js检测到手机有流应用引擎时,可以直接秒开流应用并安装到手机里。刚才讲了我们的流应用引擎已经有一亿多装机量,目前我们的测试数据是每3台Android设备就有一台检测到流应用引擎。
技术人员在这里看到了很酷的新技术,广告主看到了更高效的推广方式,渠道也可以看了很多商机,我们目前的渠道合作分成政策也很优惠。
大家可以继续关注我们的公众号或访问我们DCloud的网站深入了解。
后记:
流应用安装的意义不止是为了桌面驻留。
b/s的网页有几个问题,无网会404白屏,加载页面时是数据和界面一起下载,这导致流量大,切换页面慢,中间容易白屏。
而App是c/s结构的,其界面是在本地的,从服务器只取很小的json,流量小,切换页面快。这也是App体验比web好的重要原因之一。
但传统App的安装过程很复杂,一个app从下载开始,到安装完毕成功启动,需要耗时一分钟,激活率一般只有50%。
流应用是边用边下的,所以既保持了c/s的App级别的优质用户体验,又避免了下载安装启动的激活折损。流应用同时结合了c/s和b/s的优势又避免了他们的缺点,这才是下一代移动互联网代表的方向。
收起阅读 »
增加分栏目方法 title
一个页面有很多栏目,增加分栏目的方法如下,这个代码是从mui的列表里抄的
1、在页面内增加样式
<style>
.title{
margin: 20px 15px 7px;
color: #6d6d72;
font-size: 15px;}
</style>
2、增加分栏目
<div class="title">
热卖商品
</div>
一个页面有很多栏目,增加分栏目的方法如下,这个代码是从mui的列表里抄的
1、在页面内增加样式
<style>
.title{
margin: 20px 15px 7px;
color: #6d6d72;
font-size: 15px;}
</style>
2、增加分栏目
<div class="title">
热卖商品
</div>
收起阅读 »