支持Android iOS,firefox(其它未测)的图片上传客户端预览、缩放、裁切。

var version = '007';
var host = window.location.host;
function $$(id){return document.getElementById(id);}
function l(s){console.log(s);};
function setCookie(name, value, isForever) {
 document.cookie = name + "=" + escape(value) + ";domain="+host + (isForever?";expires="+  (new Date(2099,12,31)).toGMTString():"");
}

function getCookie(name) {
   var search = name + "=";
   if(document.cookie.length > 0) {
      offset = document.cookie.indexOf(search);
      if(offset != -1) {
         offset += search.length;
         end = document.cookie.indexOf(";", offset);
         if(end == -1) end = document.cookie.length;
         return unescape(document.cookie.substring(offset, end));
      }
      else return "";
   }
}

var email = $$('email');
var page = 1;
if(email){
	email.value = 'testFXS@qq.com';
	$$('password').value='123456';
}else page=2;

try{
	document.getElementById("page-intro").innerHTML = "version="+version;
}catch(e){}
var isAndroid = navigator.userAgent.indexOf('Android')!=-1;
var isiPhone = navigator.userAgent.indexOf('iOS')!=-1||navigator.userAgent.indexOf('iPhone')!=-1||navigator.userAgent.indexOf('iPad')!=-1;
var isPc = !(isiPhone || isAndroid);
function $$(id){return document.getElementById(id);}

var px_ratio = typeof(window.devicePixelRatio)=='undefined'?1:window.devicePixelRatio;
var page_width = 320;//页面dom的最大宽度
var w = isAndroid ? window.innerWidth : (window.screen.availWidth-30);
function resetDpi(evt){
	try{
		if(navigator.appVersion.indexOf("Android")!=-1 )	
		{
			var objs = document.getElementsByTagName("meta");
			for(var i=0;i<objs.length; i++)
			{
				if(objs[i].name=="viewport"){
					var setting = 'target-densitydpi=medium-dpi, width='+page_width+', initial-scale=1, user-scalable=yes, minimum-scale='+(document.body.offsetWidth/page_width*1.129)+', maximum-scale=5.0';
					objs[i].content = setting;
					break;
				}
			}
		}
	} catch(e) {
		alert('///////////////////////////////////////////////////error: '+e);
	}
}
function setUsePc(f){
	if(f)
		setCookie('usePc', 'true', true);
	else
		setCookie('usePc', '', true);
	
	window.location.reload();
}
var MAX_IMG_SCALE_WIDTH = 520;
var MAX_IMG_SCALE_HEIGHT = 720;
var IMG_ORIGIN_DATA = '';
var scaleImgCb = scaleCallback;
var CUT_AREA_WIDTH = 280;
var BASE_SCALE_RATE = CUT_AREA_WIDTH/MAX_IMG_SCALE_WIDTH;
var CUT_AREA_HEIGHT = MAX_IMG_SCALE_HEIGHT/MAX_IMG_SCALE_WIDTH*CUT_AREA_WIDTH;

var WINDOW_AVIABLE_HEIGHT = window.screen.availHeight-90;

if(CUT_AREA_HEIGHT+40>WINDOW_AVIABLE_HEIGHT) 
	WINDOW_AVIABLE_HEIGHT = CUT_AREA_HEIGHT+40;

var PREVIEW_TOP = 40;
var eventData;
var myTchMv;
var filename;
var user_scale_rate = 1;
var image_orgin_width = 0;
var image_orgin_height = 0;
var ouser_scale_rate = 1;
function fileChange(e){
	try{
		var file = e.target.files[0];
		var name = file.name;
		filename = name;
		var ext = name.substr(-3).toLocaleLowerCase();
		var type = 'image/jpeg';
		if(ext=='png'){
			type = 'image/png';
		}else if(ext=='gif'){
			type = 'image/gif';
		}else if(ext=='bmp'){
			type = 'image/bmp';
		}
		var reader = new FileReader();
		
		reader.onload = function(o) {
			try{
				eventData = o.target.result;
				var pre = eventData.substr(5);
				if(isAndroid&&pre.indexOf('image/')==-1)
					eventData = 'data:'+type+';' +eventData.substr(5);
				
				var html = 
				'<div style="'+page_width+'px;background-color:#ccc;position:absolute;float:left;left:0;top:0px;height:'+(WINDOW_AVIABLE_HEIGHT)+'px">'
				+'<div id="previewHead" style="line-height:21px;position:absolute;left:0;top:16px;text-align:center;z-index:1;'+page_width+'px">'
				+'	<div style="position: absolute;left: 5px;top: -7px; 50px;"><input type="button" value="上传" id="upBtn" onclick="doUpload();"/><br />'
				+'<img onmousedown="userScaleRate(true,true);if(window.event)window.event.preventDefault();" onmouseup="userScaleRate(true,false)" style="margin-top:6px" src="/resources/images/scale_up.png"></div>'
				+'	<div style="color:#900;font-size:14px;200px;margin:-6px auto 0;text-align:center" id="upheadCenter">滑动来调整图片显示区域</div>'
				+'	<div style="position: absolute;right: 5px;top: -7px; 50px;"><input type="button" value="取消" onclick="doCancel();"id="cancelBtn"/><br />'
				+'<img onmousedown="userScaleRate(false,true);if(window.event)window.event.preventDefault();"onmouseup="userScaleRate(false,false)"  style="margin-top:6px" src="/resources/images/scale_down.png"></div>'
				+'</div>'
				+'<div style="height:'+PREVIEW_TOP+'px;"></div>'
				+'<div id="previewDivInner" style="border:2px solid #eee;padding:0px;margin:0 auto;'+(CUT_AREA_WIDTH)
				+'px;margin:0 auto;height:'+CUT_AREA_HEIGHT+'px;overflow:hidden;background-color:#000">'
				+'	<img onload="cutImgOnload(this)" id="previewImage" src="'+ eventData+'">'
				+'</div>'
			   +'</div>';			
				user_scale_rate = 1;
				ouser_scale_rate = 1;
				$$('preview').innerHTML = ""+html+"";
				$$('upHead').addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
			}catch(e){
				alert("reader.onload="+e);
			}
		};
		reader.readAsDataURL(file);
	}catch(e){alert("fileChange="+e);}
}
function doUpload(){
	try{
		scaleImg(eventData);
		tips('压缩图片中……');
		$$('upBtn').disabled=true;
		$$('cancelBtn').disabled=true;
	}catch(e){alert("doUpload"+e);}
}
function doCancel(){
	if(confirm('确定取消')){
		$$('upDiv').innerHTML = '';
		document.body.removeChild($$('upDiv'));
		$$('body-wrapper').style.display = '';
	}
}
function setScrollTop(y){
	try{
		window.scrollTo(0,y);
	}catch(e){
		alert('setScrollTop='+e);
		return 5;
	}
}
var scaleTo = false;
function userScaleRate(isUp,flag){
	try{
		if(scaleTo||!flag){
			clearTimeout(scaleTo);
			scaleTo = false;
			if(!flag) return;
		}
		
		ouser_scale_rate = user_scale_rate;
		if(isUp)
			user_scale_rate *= 1.02;
		else
			user_scale_rate *= 0.98;
	
		if(
			CUT_AREA_WIDTH>BASE_SCALE_RATE*user_scale_rate*image_orgin_width
			||
			CUT_AREA_HEIGHT>BASE_SCALE_RATE*user_scale_rate*image_orgin_height
			||
			user_scale_rate>1
		){
			user_scale_rate = ouser_scale_rate;
			tips(isUp?"已经到最大":"已经到最小");			
		}else{
			myTchMv.xMove = $$('previewDivInner').scrollLeft;
			myTchMv.yMove = $$('previewDivInner').scrollTop;
			updateCutImageShow();
			scaleTo = setTimeout( function(){userScaleRate(isUp,flag);}, 150);
			tips("倍数:"+(BASE_SCALE_RATE*user_scale_rate).toFixed(2));
		}
		
	}catch(e){
		alert('userScaleRate='+e);
	}
}
function cutImgOnload(image){
	try{
		myTchMv = new touch(g('previewDivInner'),slowmv,true,'previewImg');
		image_orgin_width = image.width;
		image_orgin_height = image.height;
		if(image_orgin_width*BASE_SCALE_RATE*user_scale_rate>CUT_AREA_WIDTH*2 && image_orgin_height*BASE_SCALE_RATE*user_scale_rate>CUT_AREA_HEIGHT*2)
			user_scale_rate = (CUT_AREA_WIDTH*2)/(image_orgin_width*BASE_SCALE_RATE*user_scale_rate);
		updateCutImageShow();
	}catch(e){
		alert('cutImgOnload='+e);
	}
}
function tips(s){
	$$('upheadCenter').innerHTML = s;
}
function updateCutImageShow(){
	try{
		var rate = BASE_SCALE_RATE*user_scale_rate;
		
		$$('previewImage').width = image_orgin_width*rate;
		$$('previewImage').height = image_orgin_height*rate;
		$$('previewImage').style.width = image_orgin_width*rate;
		$$('previewImage').style.height = image_orgin_height*rate;
	}catch(e){
		alert('updateCutImageShow='+e);
	}
}
function showProgress(loaded, total){
	var percent = (loaded / total * 100).toFixed(2) + '%';
	var w = (loaded / total ) * 200;
	tips('<div style="200px;border:1px solid #eee;height:18px; line-height:18px;margin:0 auto"><div style="'+w+'px;height:18px; background-color:#00a; line-height:18px;text-align:center">'+percent+'</div></div>');
}
function scaleCallback(s){
	tips('数据大小:'+Math.floor(s.length/1024)+'K');
	setTimeout(function(){
		var xhr = new XMLHttpRequest();
		if (xhr.upload) {
			// 上传中
			xhr.upload.addEventListener("progress", function(e) {
				showProgress(e.loaded, e.total);
			}, false);

			// 文件上传成功或是失败
			xhr.onreadystatechange = function(e) {
				if (xhr.readyState == 4) {
					if (xhr.status == 200) {
						tips(xhr.responseText);
					} else {
						tips('上传失败');
						//self.onFailure(file, xhr.responseText);		
					}
					$$('upBtn').disabled=false;
					$$('cancelBtn').disabled=false;
				}
			};

			// 开始上传
			xhr.open("POST", 'http://'+window.location.host+'/php/?m=uploadHairStyle', true);
			xhr.setRequestHeader("X_FILENAME", filename);
			var fd = new FormData();
		    fd.append('hairstyle', s);
		    xhr.send(fd);
		    
			//xhr.send(eventData);
		}	
	},1500);
}
function scaleImg(src) {
	try{
		// 创建一个 Image 对象
		var image = new Image();
		// 绑定 load 事件处理器,加载完成后执行
		image.onload = function(){scaleImgOnload(this);};		
		image.width = image_orgin_width;
		image.onerror = function(){
			tips(printEvent(arguments[0]));
		};
		// 设置src属性,浏览器会自动加载。
		// 记住必须先绑定事件,才能设置src属性,否则会出同步问题。
		image.src = src;
	}catch(e){
		alert("scaleImg="+e);
	}
};
function scaleImgOnload(image){
	try{
		//var image = this;
		// 获取 canvas DOM 对象
		var canvas = document.getElementById("myCanvas");
		if(!canvas){
			canvas = document.createElement('canvas');
			canvas.id = "myCanvas";
			canvas.width = MAX_IMG_SCALE_WIDTH;
			canvas.height = MAX_IMG_SCALE_HEIGHT;
			//canvas.style.display = 'none';
			canvas.style.cssText = 'position:absolute;left:330px;top:0px;';
			//$$('preview').style.display = 'none';
			$$('preview').appendChild(canvas);
		}

		var rate = BASE_SCALE_RATE*user_scale_rate;

		var ctx = canvas.getContext("2d");s=3;
		ctx.clearRect(0, 0, MAX_IMG_SCALE_WIDTH, MAX_IMG_SCALE_HEIGHT);		
		
		var sx=parseInt(myTchMv.xMove/rate);
		var sy=parseInt(myTchMv.yMove/rate);  
		var sw=parseInt(CUT_AREA_WIDTH/rate);
		var sh=parseInt(CUT_AREA_HEIGHT/rate);
		var sParam = ('sx='+sx + ",sy=" + sy +",
sw="+ sw +",sh="+ sh+",rate="+rate+",move("+myTchMv.xMove+","+myTchMv.yMove+")");
		console.log(sParam);
		ctx.drawImage(image, sx, sy, sw, sh, 0, 0, MAX_IMG_SCALE_WIDTH, MAX_IMG_SCALE_HEIGHT);
		
		var data = canvas.toDataURL();
		scaleCallback(data);s=8;
	}catch(e){
		alert("scaleImgOnload="+e);
	}
}
function uploadInit(){
	var upDiv = $$('upDiv');
	if(!upDiv){
		upDiv = document.createElement("div");
		upDiv.id = 'upDiv';
		upDiv.style.cssText = 'float:left; background-color:#f9f9f9;';
		upDiv.innerHTML = '<div style="margin:0 auto;316px;min-height:640px;border:1px solid #eee;background-color:#f9f9f9;border-radius:5px;"><div id="upHead" style="background-color:#aaa;line-height:24px; height:24px; text-indent:12px; font-weight:bold;color:#090">发型上传</div>'+
		'<div id="step_2" style="">'
		+'<input type="file" id="file1" onchange="fileChange(event)"></div><div id="preview" style="float:left;'+page_width+'px"></div>'
		+'</div><div id="dbg"></div></div>';
		document.body.appendChild(upDiv);
		setScrollTop(0);
		$$('body-wrapper').style.display = 'none';
	}
	upDiv.style.display = '';
}

function getRadioParam(name){
	var obj;
	var i = 1;
	while(true){
		obj = $$(name+'_'+(i++));
		if(!obj) return'';
		if(obj.checked) return obj.value;
	}
}
function nextStep(){
	$$('step_1').style.display='none';
	$$('step_2').style.display='';
}
isPc = false;
try{
	var setUsePcVersion = getCookie('usePc');
	l('setUsePcVersion='+setUsePcVersion);
	if(!isPc && !setUsePcVersion){
		window.onload = function(e){
			resetDpi(e);
		};
		
	}else if(!isPc) document.getElementById("page-intro").innerHTML = '<a href="javascript:setUsePc(false);">切换到手机版</a> - '+version + ' '+navigator.userAgent;
}catch(e){
	alert("e="+e);
}


function printVar(v)
{
	if(v==null) return 'null';
	var type = typeof(v);
	var rtn = '';
	switch(type)
	{
		case 'boolean':
			if(v)
				rtn='true';
			else
				rtn='false';
			break;
		case 'object':
			var i = 0;
			if(typeof(v.length)=='undefined')
			{
				rtn = '{';
				for(var x in v)
				{
					if(i==0)
						rtn+=x+':'+printVar(v[x]);
					else
						rtn+=','+x+':'+printVar(v[x]);
					i++;
				}
				rtn += '}';
			}else{
				rtn = '[';
				for(var i=0;i<v.length;i++)
				{
					if(i==0)
						rtn+=printVar(v[i]);
					else
						rtn+=','+printVar(v[i]);
				}
				rtn += ']';
			}
			break;
		case 'string':
			rtn = '"'+v.replace(/"/g,'\"').replace(/
/g,"\r\n")+'"';
			break;
		case 'number':
		default:
			rtn = v;
	}
	return rtn;
}
function printEvent(evt)
{
	try
	{
		var tmp = '';
		for(var i in evt)
		{
			tmp += i+':';
			var v = evt[i]+'';
			if(v=='[object HTMLDivElement]')
			{
				tmp+=' <b>div</b> - '+evt[i].id+'<br/>';
			}
			else if(''+(evt[i])=='[object TouchList]')
			{
				tmp+=' <br/>    <b>touchlist</b>:<div style="border:1px solid red; margin:1px"> ';
				for(var x in evt[i])
				{
					if(''+(evt[i][x])=='[object Touch]')
					{
						tmp+='<br>    ----'+x+':'+' <b>Touch</b><br/><div style="border:1px solid blue;margin:1px">';
						for(var y in evt[i][x])
						{
							if(evt[i][x][y]=='[object HTMLDivElement]')
							{
								tmp+='    ----'+y+':<b>div</b> - '+evt[i][x][y].id+'<br/>';
							}else tmp+='<br>    ----'+y+':'+evt[i][x][y]+'<br/>';
						}
						tmp+='</div>';
					}else
						tmp+='<br>     '+x+':'+evt[i][x]+'<br/>';
				}
				tmp+='</div>';
			}else if(typeof(evt[i])=='number'){				
				tmp+='<font color="green">'+v+'</font><br/>';
			}			
			else tmp+=''+v+'<br/>';
		}
		return tmp;
	}catch(e){
		alert(e);
	}
}
function getxy(e){
	var a=new Array();
	var t=e.offsetTop;
	var l=e.offsetLeft;
	var w=e.offsetWidth;
	var h=e.offsetHeight;
	while(e=e.offsetParent){
		t+=e.offsetTop;
		l+=e.offsetLeft;
	}
	a[0]=w;a[1]=h;
	a[2]=l;a[3]=t;
	return a;
}
function touch(obj,func)
{
	try{
		if(arguments.length>2)
			this.leftRightOnly = arguments[2];
		else
			this.leftRightOnly = false;
		
		if(arguments.length>4){//4,5个参数设置后会帮你设定子元素的宽度,帮助滚动效果
			var fchild = g(arguments[3]);
			if(fchild){
				var fchildCTagName = arguments[4];
				var childs = fchild.getElementsByTagName(fchildCTagName);
				var w = 0;
				
				for(var i=0;i<childs.length;i++){
					var xy = getxy(childs[i]);
					w += xy[0];
				}
				fchild.style.width = w+"px";
			}
		}
		
		this.yMove = 0;
		this.xMove = 0;
		this.swipe_function[obj.id] = func;
		this.id = obj.id;
		if(!this.id){
			alert("第一个参数必须有一个id");
			return;
		}
		this.isPc = navigator.userAgent.indexOf('Windows')!=-1||navigator.platform.indexOf('Mac')!=-1;
		this.startFlag = false;
		obj.data = this;
		
		if(this.isPc){
			this.bind(obj,'mousedown',function(e){this.data.touchstart(e);});
			this.bind(obj,'mouseup',function(e){this.data.touchend(e);});
			this.bind(obj,'mouseout',function(e){this.data.touchend(e);});
			this.bind(obj,'mousemove',function(e){this.data.touchmove(e);});
		}else{
			this.bind(obj,'touchstart',function(e){this.data.touchstart(e);});
			this.bind(obj,'touchend',function(e){this.data.touchend(e);});
			this.bind(obj,'touchmove',function(e){this.data.touchmove(e);});
		}
	}catch(e){
		alert("touch: "+e);
	}
}
touch.prototype.tch_start = {};
touch.prototype.tch_mv = {};
touch.prototype.swipe_function = {};
touch.prototype.bind = function(obj,evt,fun)
{
	if(typeof obj.attachEvent != 'undefined')
	{
		obj.attachEvent('on'+evt,fun);
	}else{
		obj.addEventListener(evt,fun,true);
	}
};
touch.prototype.touchstart=function(evt)
{
	try{
		var tch;
		if(this.isPc)
			tch = evt;
		else
			tch = evt['touches'][0];
		var id = "";

		if(this.isPc)
			id = this.id;
		else
			id  = tch.target.id;

		this.tch_start[id] = [tch.clientX,tch.clientY];
		l("this.tch_start[id]="+this.tch_start[id]+",id="+id);
		this.startFlag = true;
		evt.preventDefault();
	}catch(e){
		alert('this.tch_start='+this.tch_start+'<br />'+e);
	}
};
touch.prototype.touchend=function (evt)
{
	try{
		if(!this.startFlag) return;
		if(!this.isPc && (typeof(evt.changedTouches)=='undefined'||evt.changedTouches.length<1)) return;
		
		var id = "";
		
		if(this.isPc)
			id  = this.id;
		else
			id = evt.changedTouches[0].target.id;

		var pid = evt.currentTarget.id;
		var now = this.tch_mv[id];		
		var start = this.tch_start[id];

		l('end= '+start+","+now+",id="+id);

		var xdiff = now[0]-start[0];
		var ydiff = now[1]-start[1];
		
		var f = this.swipe_function[pid];
		evt.preventDefault();
		this.startFlag = false;
		if(Math.abs(xdiff)>Math.abs(ydiff))
		{
			if(xdiff<0)
			{
				this.swipe(pid,'left',xdiff,f);
				return;
			}		
			if(xdiff>0)
			{
				this.swipe(pid,'right',xdiff,f);
				return;
			}
		}else{
			if(ydiff<0)
			{
				this.swipe(pid,'up',ydiff,f);
				return;
			}			
			if(ydiff>0)
			{
				this.swipe(pid,'down',ydiff,f);
				return;
			}
		}
	}catch(e){
		alert('touchend error='+e);
	}
};
touch.prototype.touchmove=function(evt)
{
	try{
		if(!this.startFlag) return;
		var id,tch;
		if(this.isPc){
			id = this.id;
			tch = evt;
		}else{
			tch = evt['touches'][0];
			id  = tch.target.id; 
		}
		var now = [tch.clientX,tch.clientY];
		this.tch_mv[id] = now;
		
		if(this.leftRightOnly)
		{
			var start = this.tch_start[id];
			l('move='+start+","+now+",id="+id);
			var xdiff = start[1] - now[1];
			var ydiff = start[0] - now[0];
			var obj   = g(this.id);
			obj.scrollTop += xdiff;
			obj.scrollLeft += ydiff;
			start[0] = now[0];
			start[1] = now[1];
			
			this.xMove = obj.scrollLeft;
			this.yMove = obj.scrollTop;
			tips('偏移:'+this.xMove+","+this.yMove);
		}
		evt.preventDefault();
	}catch(e){
		console.log('touchmove error='+e);
		//l(printEvent(evt));
	}
};
touch.prototype.swipe = function(pid,dir,xydiff,func)
{
}

function g(id)
{
	return document.getElementById(id);
}
var swiping = false;
var step = 16;
function slowmv(pid,v,v1)
{
}

直接调用:uploadInit();


 

原文地址:https://www.cnblogs.com/lein317/p/5067531.html