在线p图制作—H5拍照程序运行开发经历的那些坑儿_抠图换背景软件_免费logo图片生成器_图章制作软件_在线生成ico图标_人工智能抠图

抠图换背景软件_免费logo图片生成器_图章制作软件_在线生成ico图标_人工智能抠图移动版

建站首页 / 案例 / 平面广告 /

在线p图制作—H5拍照程序运行开发经历的那些坑儿

In on 19:57:12 by 万技术性员 一、最新项目详细介绍

1.1、最新项目状况:
它是一个在移动智能化终端设备独立自主创新应用的最新项目,顾客在浏览器端(手机上手机微信/手Q)便可以开展与金秀贤的合照,希望依据那般一种趣味性性体会,造成顾客的共享资源与共享的热潮。

1.2、系统软件手机软件要求:
ios6-ios7、android3.0-android4.3、android4.4+(非webview内)

1.3、体会详尽详细地址:

二、基本技术性性方案计划方案确立

在最新项目初期最开始启动了技术性性预演,确立基本技术性性方案计划方案(*非最终解决方案计划方案):

2.1、得到顾客照片数据信息信息内容
2.1.1、最开始放弃了积极主动得到顾客拍攝头的getUserMedia,因为移动智能化终端设备可用率太低;
2.1.2、确立运用Input操纵得到照片文本文档、运用FileReader加载照片数据信息信息内容,android3.0+、ios6.0+都可以以以可用。
[标识:內容1]

2.2、撰写转化成照片
2.2.1、放弃运用canvas撰写(即将图像数据信息信息内容加载到canvas内进行处理)照片,考虑到到到开发设计设计方案成本费费成高;
2.2.2、选用dom撰写(img标志),接着运用html2canvas,方便快捷存储数据信息信息内容。

2.3、存储并递交照片
确立运用canvas的toDataURL插孔,提交base64数据信息信息内容到互联网网络服务器。

三、碰到的这种坑儿

按照确立的技术性性方案计划方案一开始推行,一开始碰到一个个难点,一些难点可以避开,一些难点仅有颠覆重来。

3.1、照片方向反了(下列图所显示信息)

难点描述:
手执设备机器设备不一样方向所拍摄的照片方向不一样,照片的方向全是不一样,但相册图片照片时候自动式纠正,这一难点在ios和android上面存在。
难点解决:
3.1.1、将相片数据信息信息内容转换成二进制数据信息信息内容,方便快捷得到相片的exif信息内容內容;(这儿我引入了 )
3.1.2、得到相片的exif信息内容內容;(这儿我运用了 )
3.1.3、依据相片exif信息内容內容,得到相片拍摄时要持设备机器设备方向orientation。
关键编号:

// 加载相片数据信息信息内容
var fr = new FileReader();
fr.readAsDataURL(file); 
fr.onload = function(fe){ 
 var result = this.result;
 var img = new Image();
 var exif;
 img.onload = function() {
 var orientation = exif ? exif.Orientation : 1;
 // 辨别拍照设备机器设备有着方向调整照片角度
 switch(orientation) {
 case 3: 
 imgRotation = 180; 
 break;
 case 6: 
 imgRotation = 90; 
 break;
 case 8: 
 imgRotation = 270; 
 break;
 // 转换二进制数据信息信息内容
 var base64 = result.replace(/^.*?,/,'');
 var binary = atob(base64); 
 var binaryData = new BinaryFile(binary);
 // 得到exif信息内容內容
 exif = EXIF.readFromBinaryFile(binaryData);
 img.src = result;
};

3.2、html2canvas难点重重的的
难点状况:
为什么要用呢,因为大伙儿务必将顾客转化成照片后的base64数据信息信息内容提交互联网网络服务器,因而大伙儿务必依据转换为canvas得到照片数据信息信息内容。
难点详尽信息内容:
3.2.1、相片运用css3 transform旋转了相片方向,但最终html2canvas三d3D渲染结果却未存储旋转信息内容內容;
3.2.2、html2canvas的三d3D渲染起止点为网页页面网页页面右上角,而且不能以变动设置;
3.2.3、ios大图图片照片被挤扁了。
难点解决:
但最终因为碰到过量无法避开的难点,不能没舍弃html2canvas的方案计划方案,全部变成canvas开发设计设计方案。
3.3、ios大图图片照片被挤扁了
难点详尽信息内容: 当照片超过2M时,ios会出现挤扁的情况(下列图所显示信息)

难点解决:
得到相片实际占有率,更改相片的占有率。() 务必注意的是,ratio的得到是依据检测清楚度alpha,务必过滤png相片,这在stack overflow的讨论上没有人确立明确提出。
关键编号:
var getRatio = function(img) {
 if(/png$/i.test(img.src)) {
 return 1;
 var iw = img.naturalWidth, ih = img.naturalHeight;
 var canvas = document.createElement('canvas');
 canvas.width = 1;
 canvas.height = ih;
 var ctx = canvas.getContext('2d');
 ctx.drawImage(img, 0, 0);
 var data = ctx.getImageData(0, 0, 1, ih).data;
 var sy = 0;
 var ey = ih;
 var py = ih;
 while (py sy) {
 var alpha = data[(py - 1) * 4 + 3];
 if (alpha === 0) {
 ey = py;
 } else {
 sy = py;
 py = (ey + sy) 1;
 var ratio = (py / ih);
 return (ratio===0)?1:ratio;
}

3.4、照片太模糊不清不清啦,我认为提高高精密度!
难点描述:

如圖所显示信息,便于减少本地运作运行内存消耗,最新项目最初采用规格型号是320x270。在最新项目公布后,在确保运作运行内存占据可是高的情况下,一开始尝试开发设计设计方案超清方案计划方案,检验详尽详细地址下列:

在时兴设备机器设备上检验,特点并沒有非常大难点,但当互连网变换为3g时,检验相片合并递交时间8-12s,是本来时间的3倍左右,因而检验了一下3g互连网的递交速度:

 


平常会留意顾客的完全免费免费下载速度,但对递交速度没太在意,640x540相片的base64数据信息信息内容规格为125kb左右,加上廷时,3g当然自然环境下平均值递交时间是5s左右。因而,递交速度变为了超清方案计划方案的薄弱点。

解决方案计划方案:
3.4.1、手中机手机微信和手Q当然自然环境中检测顾客当然自然环境倘若为wifi,则打开超清方案计划方案,但由于在这里里个互联网营销推广的方法很多,当然自然环境复杂,实际上不可以完全解决难点,因而放弃了该点理方式;
3.4.2、在递交前对base64数据信息信息内容进行文本变小,目前早已尝试lz77变小,未公布。

3.5、canvas toDataURL bug
难点描述:
已检验,至少手上机QQ浏览器中,canvas总体目标运用toDataURL方法得到不了一切数据信息信息内容。
难点解决:
运用将相片清楚度数据信息信息内容转换为base64数据信息信息内容。
关键编号:

_public.toDataURL = function(callback){
 var self = this;
 // 去除撰写状况的原素
 self.unSelect();
 // 已测手机上上QQ浏览器canvas.toDataURL不大好,运用jeegEncoder
 window.setTimeout(function(){
 var encoder = new JPEGEncoder();
 var data = encoder.encode(self.canvas.getContext('2d').getImageData(0,0,self.stage.width,self.stage.height), 90);
 callback.call(self, data);
 }, 1000/self.config.fps)

3.6、当getElementOffset碰到transform
难点编号:
Quark.getElementOffset = function(elem)
 var left = elem.offsetLeft, top = elem.offsetTop;
 while((elem = elem.offsetParent) elem != document.body elem != document)
 left += elem.offsetLeft;
 top += elem.offsetTop;
 return {left:left, top:top};
};
难点描述:
当整体总体目标原素的上级领导领导干部原素中有运用transform:translate(x,y)时,用如上的方法全是导致offset计算歪斜确,这一bug在普遍canvas构架EaseJS、QuarkJS,DOM类库Zepto上面存在。我最新项目中运用的是QuarkJS,碰到具体难点是表演演出舞台恶变恶性事件坐标倾斜确,由于是构架中的bug,前前后左右后前前后后足足花了一大半天时间才核实到。
难点解决:
offsetLeft或offsetTop务必减去translate的偏差。

四、最新项目总结
 

4.1、最终技术性性方案计划方案
4.1.1、得到顾客照片数据信息信息内容 运用Input操纵得到照片文本文档、运用FileReader加载照片数据信息信息内容,android3.0+、ios6.0+都可以以以可用。
4.1.2、撰写转化成照片
4.1.2.1、运用canvas撰写相片,运用canvas构架为QuarkJS;
4.1.2.2、运用binaryajax和exif得到照片信息内容內容,用于解决ios bug和照片方向调整;
4.1.3、存储并递交照片
4.1.3.1、运用JPEGEncoder转换为base64数据信息信息内容;
4.1.3.2、运用lz77进行数据信息信息内容变小


4.2、体会

这一最新项目进行得实际上不完满,亲自亲身经历过1次颠复整体方案计划方案再次写过、1次构架bug改错、多次系统软件手机软件和浏览器的bug修复,由于在网上并没有该类相对性性健全的应用,找不到可参考案例,吐槽空闲,也总结出一些体会:

4.2.1、对于独立自主创新类的应用,初期技术性性预演太重要,不能以只是探索可行性;
4.2.2、选择一个健全的构架太重要,QuarkJS虽然本身架构十分好并且很轻量,但运用它的整个过程中还是碰到过许多bug或不完善的地区,并且文字文本文档不祥之兆细;
4.2.3、务必善于应用现阶段技术性性。这一最新项目中运用了许多第三方构架来解决独特难点,倘若没有这类,最新项目周期时间時间将会十分长。
4.2.4、H5从图像到音响到视频,也是有过量制造行业十分非常值得探索,有十分大能挖掘的应用使用价值,想想全是有点儿小兴奋呢!

4.3、相片撰写类整体编号

/**
 * @author Brucewan
 * @version 1.0
 * @date 
 * @description 相片撰写器
 * @extends tg.Base
 * @name tg.ImageEditor
 * @requires zepto.js
 * @requires base.js
 * @class
tg.add('tg.ImageEditor:tg.Base', function() {
 * public 作用域
 * @alias tg.ImageEditor#
 * @ignore
 var _public = this;
 var _private = {};
 * public static作用域
 * @alias tg.ImageEditor.
 * @ignore
 var _static = this.constructor;

_public.constructor = function(config) { this.config = Zepto.extend(true, {}, _static.config, config); // 关键主要参数接纳 this.init(); // 手机软件默认设置设定配置 _static.config = { width: 320, height: 320, fps: 60
var context = new Quark.CanvasContext({canvas:canvas}); self.stage = new Quark.Stage({width:config.width, height:config.height, context:context}); self.canvas = canvas; self.context = context; // register stage events var em = this.em = new Quark.EventManager(); em.registerStage(self.stage, ['touchstart', 'touchmove', 'touchend'], true, true); self.stage.stageX = config.stageX !== window.undefined ? config.stageX : self.stage.stageX; self.stage.stageY = config.stageY !== window.undefined ? config.stageY : self.stage.stageY; var timer = new Quark.Timer(1000/config.fps); timer.addListener(self.stage); timer.addListener(Quark.Tween); timer.start(); var bg = new Q.Graphics({width:config.width, height:config.height}); bg.beginFill("#fff").drawRect(0, 0, config.width, config.height).endFill().cache(); self.stage.addChild(bg) _private.attach.call(self);
if(e.eventTarget e.eventTarget.parent.enEditable) { e.eventTarget.parent.enEditable(); self.activeTarget = e.eventTarget.parent; self.stage.addEventListener('touchmove', function(e){ var touches = e.rawEvent.touches || e.rawEvent.changedTouches; if(e.eventTarget (e.eventTarget.parent == self.activeTarget) touches[1]) { var dis = Math.sqrt(Math.pow(touches[1].pageX - touches[0].pageX, 2) + Math.pow(touches[1].pageY - touches[0].pageY, 2) ); if(self.activeTarget.mcScale.touchDis) { var scale = dis / self.activeTarget.mcScale.touchDis -1; if( self.activeTarget.getCurrentWidth() 100 scale 0) { scale = 0; self.activeTarget.scaleX += scale; self.activeTarget.scaleY += scale; self.activeTarget.mcScale.touchDis = dis; self.stage.addEventListener('touchend', function(){ if(self.activeTarget self.activeTarget.mcScale) { delete self.activeTarget.mcScale.touchDis;
var iw = img.naturalWidth, ih = img.naturalHeight; var canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = ih; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); var data = ctx.getImageData(0, 0, 1, ih).data; var sy = 0; var ey = ih; var py = ih; while (py sy) { var alpha = data[(py - 1) * 4 + 3]; if (alpha === 0) { ey = py; } else { sy = py; py = (ey + sy) 1; var ratio = (py / ih); return (ratio===0)?1:ratio; var ratio = getRatio(img);
if(/iphone|ipod|ipad/i.test(navigator.userAgent)) { alert('iPhone系统软件手机软件下尚未可用你以那麼萌!萌!达!姿势拍照!'); return; break;
imgContainer = new Quark.DisplayObjectContainer({width: imgWidth, height: imgHeight}); imgContainer.x = posX; imgContainer.y = posY;
img = new Quark.Bitmap({image:img, regX:imgRegX, regY:imgRegY}); img.rotation = imgRotation; img.x = imgX; img.y = 0; img.scaleX = imgScale * ratio; img.scaleY = imgScale;
var rect = config.iconScale.rect; mcScale = new Quark.MovieClip({image:iconScaleImg}); mcScale.addFrame([{rect: rect}]); mcScale.x = imgWidth - rect[2]; mcScale.y = 0; mcScale.alpha = 0.5; mcScale.visible = false; mcScale.addEventListener('touchstart', function(e){ mcScale.scaleable = true; mcScale.startX = e.eventX; mcScale.startY = e.eventY; mcScale.alpha = 0.8; var curW = imgContainer.getCurrentWidth(); var scaleMove = function(e){ if(mcScale.scaleable) { // 放缩 var disX = e.eventX - mcScale.startX; var scaleX = (curW+disX)/imgContainer.width; if( imgContainer.getCurrentWidth() 100 imgContainer.scaleX scaleX) { return; imgContainer.scaleX = scaleX; imgContainer.scaleY = scaleX; // 旋转 var disOriX = e.eventX - imgContainer.x; var disOriY = e.eventY- imgContainer.y; var rotate = Math.atan2(disOriY,disOriX) * 360 / (2 * Math.PI); imgContainer.rotation = parseInt(rotate/1)*1; var scaleEnd = function(e) { mcScale.scaleable = false; mcScale.alpha = 0.5; self.stage.removeEventListener('touchmove', scaleMove); self.stage.removeEventListener('touchend', scaleEnd); self.stage.addEventListener('touchmove', scaleMove); self.stage.addEventListener('touchend', scaleEnd); imgContainer.mcScale = mcScale; imgContainer.addChild(mcScale); iconScaleImg.src = config.iconScale.url; var border = new Q.Graphics({width:imgWidth+10, height:imgHeight+10, x:-5, y:-5}); border.lineStyle(5, "#aaa").beginFill("#fff").drawRect(5, 5, imgWidth, imgHeight).endFill().cache(); border.alpha = 0.5; border.visible = false; imgContainer.addChild(border); if(config.iconClose) { var iconCloseImg = new Image(); iconCloseImg.onload = function(){ var rect = config.iconClose.rect; mcClose = new Quark.MovieClip({image:iconCloseImg}); mcClose.addFrame([{rect: rect}]); mcClose.x = 0; mcClose.y = 0; mcClose.alpha = 0.5; mcClose.visible = false; mcClose.addEventListener('touchstart', function(e){ mcClose.alpha = 0.8; }); mcClose.addEventListener('touchend', function(e){ self.stage.removeChild(imgContainer); }); self.stage.addEventListener('touchend', function(e){ mcClose.alpha = 0.5; imgContainer.addChild(mcClose); iconCloseImg.src = config.iconClose.url;
img.curW = imgContainer.getCurrentWidth(); img.curH = imgContainer.getCurrentHeight(); img.moveabled = true; img.startX = e.eventX; img.startY = e.eventY; fnMove = function(e){ // 不是是双指按住 var isScale = e.rawEvent e.rawEvent.touches[1]; if(img.moveabled !isScale) { var disX = e.eventX - img.startX; var disY = e.eventY - img.startY; var setX = imgContainer.x + disX; var setY = imgContainer.y + disY; var diffX = 0, diffY = 0; if(setX -img.curW/2 + 5 disX 0) { setX = -img.curW/2; if(setY -img.curH/2 + 5 disY 0) { setY = -img.curH/2; if(setX -img.curW/2 + self.stage.width - 5 disX 0) { setX = self.stage.width - img.curW/2; if(setY self.stage.height - 5 disY 0) { setY = self.stage.height; imgContainer.x = setX; imgContainer.y = setY; img.startX = e.eventX; img.startY = e.eventY; fnEnd = function(){ img.moveabled = false; self.stage.addEventListener('touchmove'); self.stage.addEventListener('touchend'); self.stage.addEventListener('touchmove', fnMove); self.stage.addEventListener('touchend', fnEnd);
mcScale.scaleY = 1/imgContainer.scaleY; mcScale.x = border.getCurrentWidth() - 10 - mcScale.getCurrentWidth(); if(mcClose mcClose.scaleX) { mcClose.scaleX = 1/imgContainer.scaleX; mcClose.scaleY = 1/imgContainer.scaleY; mcClose.x = 0;
// 已测手机上上QQ浏览器canvas.toDataURL不大好,运用jeegEncoder window.setTimeout(function(){ var encoder = new JPEGEncoder(); var data = encoder.encode(self.canvas.getContext('2d').getImageData(0,0,self.stage.width,self.stage.height), 90); callback.call(self, data); }, 1000/self.config.fps)

(责任编辑:admin)