这一篇文章是早年为了解决图片裁剪的探索性文章,现在已经开放出了falsh版及html5版本的图片裁剪插件,各位有时间可以看看:
浮士德html5图片裁剪器2016开源版
浮士德头像裁剪flash版2016福利版
上面两个解决方案已经经过多个项目的成功应用,适用于低级浏览器及现代浏览器,ipad,android,iphone4s,iphone5,iphone5s,iphone6等设备等。
将相应html及js脚本放出来,注意,这是原型,并非立刻可以使用的东西。
<html>
<head>
<title>个人相片title>
<meta charset="utf-8" />
<meta content="width=device-width, initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"/>
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="black" name="apple-mobile-web-app-status-bar-style">
<meta content="telephone=yes" name="format-detection">
<meta content="email=no" name="format-detection">
<script type="text/javascript" src="/static/lib/jquery-1.11.0.min.js">script>
<script type="text/javascript" src="/static/lib/util.min.js">script>
<script type="text/javascript" src="/static/lib/exif.min.js">script>
<script type="text/javascript" src="/static/vendor/ImgTools/ImageOrientationFix.js">script>
<script type="text/javascript" src="/static/vendor/ImgTools/ImageResizer.js">script>
<script type="text/javascript" src="/static/vendor/layer1.8/layer/layer.min.js">script>
<link href="/static/vendor/jQuery.showLoading/css/showLoading.css" rel="stylesheet" media="screen" />
<script type="text/javascript" src="/static/vendor/jQuery.showLoading/js/jquery.showLoading.js">script>
<script type="text/javascript" src="ImageEditor.js">script>
head>
<body>
<div>
<h3>请选择图片:h3>
<div>
<input type="file" style="" id="uploadImage" accept="image/*">
div>
div>
<h2>裁剪器区域h2>
<div id="div_cropper">
<div ui="image-editor-panel">
<canvas ui="background-layout" style="position: absolute; ">canvas>
<canvas ui="cutter-layout" style="position: absolute; ">canvas>
<canvas ui="operation-layout" style="position: absolute; cursor: pointer; ">canvas>
div>
div>
<div class="image-editor-tool-bar">
<button type="button" id="btn_zoom_in">放大图片button>
<button type="button" id="btn_zoom_out">缩小图片button>
<button type="button" id="btn_turn_left">向左转button>
<button type="button" id="btn_turn_right">向右转button>
div>
<div><input type="button" id="btn_save" value="保存图片">div>
<h2>预览结果:h2>
<img src="" id="preview_img"/>
<div id="tips" style="color:green;">div>
<script type="text/javascript" src="example2.js">script>
<div id="debug" style="color: green;">
div>
<img src="daojian_1.png" id="img_test" style="display: none;">
<div style="width:1200px;height: 800px; border: 1px solid red;display: none;">
<canvas id="test_canvas" width="1200" height="800">canvas>
div>
<script type="text/javascript">
var _img=document.getElementById("img_test");
var _canvas=document.getElementById("test_canvas");
var _context=_canvas.getContext("2d");
script>
body>
html>
/**
* 图片裁剪组件,必须跟jquery exif ImageOrientationFix.js 等一起用。
*/
function ImageEditor(opts){
var settings={
cutWidth:150 //裁剪框的宽度。
,cutHeight:200 //裁剪框的高度
,containerWidth:800 //容器宽度
,containerHeight:600 //容器高度
,imageShowWidth:400 //图片默认显示的宽度【会按照要求的宽度及高度等比缩放】
,imageShowHeight:500 //图片默认显示的高度【会按照要求的宽度及高度等比缩放】
,containerElement:"" //容器的默认元素,jquery元素或者原生dom元素。
,showCutterInFirst:true //是否第一时间显示裁剪框---注意,true意味着即使用户没有选择图片,背景层没有显示图片裁剪框也显示。
,saveMode:"ratio" //裁剪图片的模式有两种,一种是 ratio即,在原图片上面按照比例裁剪图片,尺寸不一定固定,一种是 size,严格按照裁剪框的尺寸来保存图片。
};
$.extend(settings,opts);
function _debug(str){
return;
var _div=$("");
_div.text(str);
$("#debug").append(_div);
};
function _clearDebug(){
return;
$("#debug").empty();
}
var __me=this;
//--定义必须用到的dom元素的句柄。
var containerElement=$(settings.containerElement);//整个容器对象,
var panel=containerElement.find('[ui="image-editor-panel"]');//这是包装几个画布的面板。
var canvas_bg=containerElement.find('[ui="background-layout"]')[0];//原生画布对象,这是背景画布,用于绘制图片及缩放,转向等操作。
var canvas_cutter=containerElement.find("[ui='cutter-layout']")[0];//原生画布对象,这是裁剪框对象。用于绘制遮罩层及裁剪框。
var canvas_operation=containerElement.find("[ui='operation-layout']")[0];//原生画布对象,这是操作层对象,用于接受用户的鼠标及手势,然后触发各种事件。
var context_cutter=canvas_cutter.getContext("2d");
var context_bg=canvas_bg.getContext("2d");
var data_origin_image="";//原始图片数据,原始是指经过了ios bug修复剂orientation方向修复以后的base64格式的数据。注意,必要时,假如图片太大,可以先压缩到某个尺寸。
var image_background=new Image();//新建一个背景图的元素用于处理图片旋转等操作。
//--下面预先将背景图片的三个方向都先计算出来。
//window.image_backgroud=image_background;
//--内部运行时数据
var data_cutter={
location:{
x:0
,y:0
}
,size:{
w:0
,h:0
}
,ratio:1
};//裁剪框数据
var data_bg={
angle:0
,img_bg_0:""//0度图片。
,img_bg_90:""//90度图片
,img_bg_180:""//180度旋转图片
,img_bg_270:""//270度旋转图片
,location:{
x:0
,y:0
}
,size:{
w:0
,h:0
}
,originSize:{
w:0
,h:0
}
,zoom:1
};//背景层数据-这个作为原始备份,告诉系统应该如何转换数据。
var data_bg_trans={
angle:0
,location:{
x:0
,y:0
}
,size:{
w:0
,h:0
}
,originSize:{
w:0
,h:0
}
,zoom:1
};//在非正常情况下的位置的数据等,例如,转换成为90,180,270,0等的数据,
var data_container={
size:{
w:0
,h:0
}
};//容器数据
var data_op={
panelInfo:{
absoluteTop:0,
absoluteLeft:0,
offsetWidth:0,
offsetHeight:0
}
,isInDrag:false
,beginPoint:{
x:0
,y:0
}
,point1:{
x:0
,y:0
}
,point2:{
x:0
,y:0
}
//判断是否在裁剪框里面。
,isInCut:false
};//操控层数据。
var appData={
panelSize:{
w:0
,h:0
}
,hasImage:false //是否已经选择了图片,容器里面有没有图片。
};//app内部数据
var innerTools={
browser:{
versions:function(){
var u = navigator.userAgent, app = navigator.appVersion;
return { //移动终端浏览器版本信息
trident: u.indexOf('Trident') > -1, //IE内核
presto: u.indexOf('Presto') > -1, //opera内核
webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核
mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或uc浏览器
iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器
iPad: u.indexOf('iPad') > -1, //是否iPad
webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部
};
}(),
language:(navigator.browserLanguage || navigator.language).toLowerCase()
}
,GetAbsoluteLocationEx:function(element){
if(arguments.length!=1||element==null)
{
return null;
}
var elmt=element;
var offsetTop=elmt.offsetTop;
var offsetLeft=elmt.offsetLeft;
var offsetWidth=elmt.offsetWidth;
var offsetHeight=elmt.offsetHeight;
while(elmt=elmt.offsetParent)
{
// add this judge
if(elmt.style.position=='absolute'||elmt.style.position=='relative'
||(elmt.style.overflow!='visible'&&elmt.style.overflow!=''))
{
break;
}
offsetTop+=elmt.offsetTop;
offsetLeft+=elmt.offsetLeft;
}
var _info={absoluteTop:offsetTop,absoluteLeft:offsetLeft,
offsetWidth:offsetWidth,offsetHeight:offsetHeight};
return _info;
}
};
var app={
init:function(){
var _child=this;
appData.panelSize.w=settings.containerWidth;
appData.panelSize.h=settings.containerHeight;
_child.render_ui();
_child.init_cutter();
_child.initOperationLayout();
}
//--设定容器及其他相关dom的样式。
,render_ui:function(){
containerElement.css({"width":settings.containerWidth+"px","height":settings.containerHeight+"px"});
canvas_bg.width=settings.containerWidth;
canvas_bg.height=settings.containerHeight;
canvas_cutter.width=settings.containerWidth;
canvas_cutter.height=settings.containerHeight;
canvas_operation.width=settings.containerWidth;
canvas_operation.height=settings.containerHeight;
}
//--计算相关数据--初始化裁剪框。
,init_cutter:function(){
var _child=this;
data_cutter.size.w=settings.cutWidth;
data_cutter.size.h=settings.cutHeight;
data_cutter.ratio=settings.cutWidth/settings.cutHeight;
//--计算中间点。
var middle_x=appData.panelSize.w/2;
var middle_y=appData.panelSize.h/2;
var _x=middle_x-data_cutter.size.w/2;
var _y=middle_y-data_cutter.size.h/2;
data_cutter.location.x=_x;
data_cutter.location.y=_y;
if(settings.showCutterInFirst){
_child.updateCutter();
}
}
//--根据cutter的数据更新裁剪框层。
,updateCutter:function(){
var _child=this;
console.log("目前更新裁剪框,数据"+data_cutter.location.x+":x "+data_cutter.location.y);
_child.__clear_cutter_canvas();
_child.__draw_mask();
_child.__draw_cutter();
}
//--清空cutter画布的内容。
,__clear_cutter_canvas:function(){
context_cutter.clearRect(0,0,canvas_cutter.width,canvas_cutter.height);
}
//--渲染cutter
,__draw_cutter:function(){
//
context_cutter.strokeStyle = '#ffffff';
context_cutter.lineWidth = 2;
context_cutter.strokeRect(data_cutter.location.x,data_cutter.location.y,data_cutter.size.w,data_cutter.size.h);
context_cutter.clearRect(data_cutter.location.x,data_cutter.location.y,data_cutter.size.w,data_cutter.size.h);
//context_cutter.clearRect(0,0,canvas_cutter.width,canvas_cutter.height);
}
//--渲染遮罩层
,__draw_mask:function(){
context_cutter.fillStyle = 'rgba(0, 0, 0, 0.3)';
context_cutter.fillRect(0, 0, canvas_cutter.width,canvas_cutter.height);
}
//--对外接口,拖动裁剪框。
,MoveCutter:function(pos_x,pos_y){
var _child=this;
data_cutter.location.x=pos_x;
data_cutter.location.y=pos_y;
_child.updateCutter();
}
//--移动裁剪框。
,MoveCutterByDelta:function(delta_x,delta_y){
var _child=this;
var _new_x= data_cutter.location.x+delta_x;
var _new_y=data_cutter.location.y+delta_y;
//--判断边界。
if(_new_x<0){
_new_x=0;
}
if(_new_y<0){
_new_y=0;
}
if(_new_x>(appData.panelSize.w-data_cutter.size.w)){
_new_x=appData.panelSize.w-data_cutter.size.w;
}
if(_new_y>(appData.panelSize.h-data_cutter.size.h)){
_new_y=appData.panelSize.h-data_cutter.size.h;
}
console.log("新的裁剪框位置是:"+_new_x+" X "+_new_y);
_child.MoveCutter(_new_x,_new_y);
}
//--初始化背景层。背景层需要获得图片的base64字符串先。
,init_background:function(base_64_image){
var _child=this;
_child.init_bg_data(base_64_image,function(finalBase64Image){
_child.updateBackground();
});
}
//--背景图片等图片处理。数据处理等。
,init_bg_data:function(originBase64,callback){
ImageOrientationFix({
image:originBase64
,imgType:"base64"
,onFix:function(base64_str){
data_origin_image=base64_str;
image_background.onload=function(){
appData.hasImage=true;
//--获取相关数据及计算。
data_bg.originSize.w=image_background.naturalWidth;
data_bg.originSize.h=image_background.naturalHeight;
data_bg.angle=0;
data_bg.location.x=0;
data_bg.location.y=0;
data_bg.zoom=1;
data_bg.size.w=data_bg.originSize.w;
data_bg.size.h=data_bg.originSize.h;
image_background.onload=function(){};
console.log("bg层数据");
console.log(data_bg);
//--按照当前显示区域,尽量显示全部图片,计算显示尺寸。
if(data_bg.originSize.w>appData.panelSize.w||data_bg.originSize.h>appData.panelSize.h){
var _max_scale= Math.max(data_bg.originSize.w/appData.panelSize.w,data_bg.originSize.h/appData.panelSize.h);
var _current_w=data_bg.originSize.w/_max_scale;
var _current_h=data_bg.originSize.h/_max_scale;
data_bg.zoom=1/_max_scale;
data_bg.size.w=_current_w;
data_bg.size.h=_current_h;
console.log("bg层计算得到的可以显示区域是:");
console.log(data_bg);
}
//--计算背景层应该显示的位置,尽量放到中间。
data_bg.location.x=(appData.panelSize.w-data_bg.size.w)/2;
data_bg.location.y=(appData.panelSize.h-data_bg.size.h)/2;
//--计算各个状体的图片。
data_bg.img_bg_0=image_background;
data_bg.img_bg_90=new Image();
data_bg.img_bg_180=new Image();
data_bg.img_bg_270=new Image();
var __canvas=document.createElement("canvas");
var __context=__canvas.getContext("2d");
//$(document.body).prepend(__canvas);
//--90度的。
__canvas.width=data_bg.originSize.h;
__canvas.height=data_bg.originSize.w;
__context.save();
__context.rotate(Math.PI/2);
__context.drawImage(image_background,0,0-data_bg.originSize.h);
__context.restore();
data_bg.img_bg_90.src= __canvas.toDataURL();
__context.clearRect(0,0,__canvas.width,__canvas.height);
//--180度的。
__canvas.width=data_bg.originSize.w;
__canvas.height=data_bg.originSize.h;
__context.save();
__context.rotate(Math.PI);
__context.drawImage(image_background,0-data_bg.originSize.w,0-data_bg.originSize.h);
__context.restore();
data_bg.img_bg_180.src= __canvas.toDataURL();
__context.clearRect(0,0,__canvas.width,__canvas.height);
//--270度的。
__canvas.width=data_bg.originSize.h;
__canvas.height=data_bg.originSize.w;
__context.save();
__context.rotate(Math.PI*1.5);
__context.drawImage(image_background,0-data_bg.originSize.w,0);
__context.restore();
data_bg.img_bg_270.src= __canvas.toDataURL();
__context.clearRect(0,0,__canvas.width,__canvas.height);
//--trans 背景数据。
data_bg_trans.angle=data_bg.angle;
data_bg_trans.location.x=data_bg.location.x;
data_bg_trans.location.y=data_bg.location.y;
data_bg_trans.size.w=data_bg.size.w;
data_bg_trans.size.h=data_bg.size.h;
data_bg_trans.originSize.w=data_bg.originSize.w;
data_bg_trans.originSize.h=data_bg.originSize.h;
data_bg_trans.zoom=data_bg.zoom;
if(callback){
callback(base64_str);
}
};
image_background.src=base64_str;
}
});
}
//--清空背景。
,clear_background:function(){
context_bg.clearRect(0,0,canvas_bg.width,canvas_bg.height);
}
//--根据相关数据更新背景层图像。
,updateBackground:function(){
var _child=this;
_child.clear_background();
if(data_bg_trans.angle==0||data_bg_trans.angle==360){
//context.drawImage(img,0,0,img.width,img.height,imgX,imgY,img.width*imgScale,img.height*imgScale);
// context_bg.drawImage(image_background,data_bg.location.x,data_bg.location.y,data_bg.originSize.w,data_bg.originSize.h,0,0,data_bg.size.w,data_bg.size.h);
context_bg.drawImage(image_background,0,0,data_bg_trans.originSize.w,data_bg_trans.originSize.h,data_bg_trans.location.x,data_bg_trans.location.y,data_bg_trans.size.w,data_bg_trans.size.h);
}
else if(data_bg_trans.angle==90){
context_bg.drawImage(data_bg.img_bg_90,0,0,data_bg_trans.originSize.w,data_bg_trans.originSize.h,data_bg_trans.location.x,data_bg_trans.location.y,data_bg_trans.size.w,data_bg_trans.size.h);
}
else if(data_bg_trans.angle==180){
context_bg.drawImage(data_bg.img_bg_180,0,0,data_bg_trans.originSize.w,data_bg_trans.originSize.h,data_bg_trans.location.x,data_bg_trans.location.y,data_bg_trans.size.w,data_bg_trans.size.h);
}
else if(data_bg_trans.angle==270){
context_bg.drawImage(data_bg.img_bg_270,0,0,data_bg_trans.originSize.w,data_bg_trans.originSize.h,data_bg_trans.location.x,data_bg_trans.location.y,data_bg_trans.size.w,data_bg_trans.size.h);
}
}
//--底层api,根据位置移动图片。
,MoveBackground:function(pos_x,pos_y){
data_bg_trans.location.x=pos_x;
data_bg_trans.location.y=pos_y;
var _child=this;
_child.updateBackground();
}
//--通过偏移量来移动图片。
,MoveBackgroundByDelta:function(delta_x,delta_y){
var _child=this;
var _new_x=data_bg_trans.location.x+delta_x;
var _new_y=data_bg_trans.location.y+delta_y;
var _min_x=0;
var _max_x=0;
//--宽度边界判断。
//--假如图片宽度竟然比裁剪框要小,那么宽度最小值是0,
if(data_bg_trans.size.w<=data_cutter.size.w){
_min_x=0;
_max_x=appData.panelSize.w-data_bg_trans.size.w;
}
//--假如现在的图片宽度比整个容器宽度要小或者要大,那么就有:
//else if(data_bg_trans.size.w<=appData.panelSize.w){
//计算得出这时候的x最大值最小值。
//var __min_x=
//}
//--假如现在的图片宽度比整个容器宽度要小或者要大,那么就有:
else{
_min_x=data_cutter.size.w-data_bg_trans.size.w;
_max_x=appData.panelSize.w-data_cutter.size.w;
}
//--高度边界判断。
var _min_y=0;
var _max_y=0;
if(data_bg_trans.size.h<=data_cutter.size.h){
_min_y=0;
_max_y=appData.panelSize.h-data_bg_trans.size.h;
}
else{
_min_y=data_cutter.size.h-data_bg_trans.size.h;
_max_y=appData.panelSize.h-data_cutter.size.h;
}
if(_new_x<_min_x){
_new_x=_min_x;
}
else if(_new_x>_max_x){
_new_x=_max_x;
}
if(_new_y<_min_y){
_new_y=_min_y;
}
else if(_new_y>_max_y){
_new_y=_max_y;
}
console.log("新的图片位置是:"+_new_x+" X "+_new_y);
//_child.MoveCutter(_new_x,_new_y);
_child.MoveBackground(_new_x,_new_y);
}
//--底层api,缩放图片。
,ScaleBackground:function(_scale){
//--在缩放前首先计算得到图片的中心点。
var _middle_x=0;
var _middle_y=0;
//--正常状体下面。
_middle_x=data_bg_trans.location.x+data_bg_trans.size.w/2;
_middle_y=data_bg_trans.location.y+data_bg_trans.size.h/2;
data_bg_trans.zoom=_scale;
data_bg_trans.size.w=data_bg_trans.originSize.w*_scale;
data_bg_trans.size.h=data_bg_trans.originSize.h*_scale;
var __x=_middle_x-(data_bg_trans.size.w)/2;
var __y=_middle_y-(data_bg_trans.size.h)/2;
data_bg_trans.location.x=__x;
data_bg_trans.location.y=__y;
var _child=this;
_child.updateBackground();
}
//--旋转。
,RotateImage:function(angle){
if(angle!=0&&angle!=90&&angle!=180&&angle!=270&&angle!=360){
console.log("不支持该角度。");
return;
}
var preAngle=data_bg_trans.angle;
//--计算原本的中心点。
var _middle_x=0;
var _middle_y=0;
//--正常状体下面。
_middle_x=data_bg_trans.location.x+data_bg_trans.size.w/2;
_middle_y=data_bg_trans.location.y+data_bg_trans.size.h/2;
//--那么一旦改变了角度,需要将各个坐标系都转换过来。
if(angle==0||angle==360){
data_bg_trans.angle=0;
data_bg_trans.originSize.w=data_bg.originSize.w;
data_bg_trans.originSize.h=data_bg.originSize.h;
}
else if(angle==90){
data_bg_trans.angle=90;
data_bg_trans.originSize.w=data_bg.originSize.h;
data_bg_trans.originSize.h=data_bg.originSize.w;
}
else if(angle==180){
data_bg_trans.angle=180;
data_bg_trans.originSize.w=data_bg.originSize.w;
data_bg_trans.originSize.h=data_bg.originSize.h;
}
else if(angle==270){
data_bg_trans.angle=270;
data_bg_trans.originSize.w=data_bg.originSize.h;
data_bg_trans.originSize.h=data_bg.originSize.w;
}
data_bg_trans.size.w=data_bg_trans.originSize.w*data_bg_trans.zoom;
data_bg_trans.size.h=data_bg_trans.originSize.h*data_bg_trans.zoom;
data_bg_trans.location.x=_middle_x-(data_bg_trans.size.w)/2;
data_bg_trans.location.y=_middle_y-(data_bg_trans.size.h)/2;
data_bg_trans.angle=angle;
var _child=this;
_child.updateBackground();
}
//--初始化操控层。
,initOperationLayout:function(){
var _child=this;
data_op.panelInfo=innerTools.GetAbsoluteLocationEx(canvas_operation);
console.log("当前panel的位置信息。");
console.log(data_op.panelInfo);
console.log(innerTools.browser);
if(innerTools.browser.versions.mobile==true||innerTools.browser.versions.mobile==true||innerTools.browser.versions.android||innerTools.browser.versions.iPhone){
_child._init_mobile_operations();
}
else{
_child._init_pc_operations();
}
}
//--pc上面的控制事件。
,_init_pc_operations:function(){
//o是移动对象
var _child=this;
$(canvas_operation).mousedown(function(event){
if(appData.hasImage==false){
return;
}
data_op.isInDrag=true;
console.log("canvas operation mouse down:");
data_op.panelInfo=innerTools.GetAbsoluteLocationEx(canvas_operation);
if(data_op.panelInfo.absoluteLeft==0&&data_op.panelInfo.absoluteTop==0&&data_op.panelInfo.offsetHeight==0&&data_op.panelInfo.offsetWidth==0){
}
//params.flag = true;
if (!event) {
event = window.event;
//防止IE文字选中
canvas_operation.onselectstart = function () {
return false;
}
}
var e = event;
var params_currentX = e.clientX;
var params_currentY = e.clientY;
data_op.beginPoint.x=params_currentX;
data_op.beginPoint.y=params_currentY;
var realX=params_currentX-data_op.panelInfo.absoluteLeft;
var realY=params_currentY-data_op.panelInfo.absoluteTop;
_clearDebug();
_debug("未处理前,realX realY是:"+realX+" x "+realY);
//注意,上面没有考虑到有滚动条的状态,现在添加对滚动条的处理。
//--notice,假如页面有滚动条,每次都滚到不同位置的话,那么这个定位可能会有问题,于是我们需要进行处理。
var _scrollTop=$(document).scrollTop();
if(_scrollTop>0){
realY=realY+_scrollTop;
}
var _scrollLeft=$(document).scrollLeft();
if(_scrollLeft>0){
realX=realX+_scrollLeft;
}
data_op.point1.x=params_currentX;
data_op.point1.y=params_currentY;
data_op.isInCut=_child.isPointInCutter(realX,realY);
_debug("scroll top left信息:"+_scrollTop+" x "+_scrollLeft);
_debug("当前panel位置信息是:"+JSON.stringify(data_op.panelInfo));
_debug("realX realY是:"+realX+" x "+realY);
_debug("裁剪框位置是:"+JSON.stringify(data_cutter));
console.log("当前坐标");
console.log(params_currentX+"x"+params_currentY);
if(data_op.isInCut){
console.log("%c 在裁剪框里面。","color:green;");
}
});
$(document).mouseup(function(){
if(appData.hasImage==false){
return;
}
data_op.isInDrag=false;
console.log("document 鼠标移动上去了。 mouse up");
});
$(document).mousemove(function (event) {
if(appData.hasImage==false){
return;
}
if(data_op.isInDrag==false){
return;
}
var e = event ? event : window.event;
var nowX = e.clientX, nowY = e.clientY;
console.log("%c 移动事件 mousemove中,位置:"+nowX+" x "+nowY+" 是否在裁剪框里面:"+data_op.isInCut,"color:red");
// var disX = nowX - params.currentX, disY = nowY - params.currentY;
//target.style.left = parseInt(params.left) + disX + "px";
//target.style.top = parseInt(params.top) + disY + "px";
//--计算位移量。
data_op.point2.x=nowX;
data_op.point2.y=nowY;
var delta_x=data_op.point2.x-data_op.point1.x;
var delta_y=data_op.point2.y-data_op.point1.y;
data_op.point1.x=nowX;
data_op.point1.y=nowY;
if(data_op.isInCut==true){
//--已经
console.log("现在在重新渲染裁剪框了。"+delta_x+" x "+delta_y);
_child.MoveCutterByDelta(delta_x,delta_y);
}
else{
_child.MoveBackgroundByDelta(delta_x,delta_y);
}
});
}
//--手机端移动端的事件。
,_init_mobile_operations:function(){
var _child=this;
canvas_operation.addEventListener("touchstart",function(event){
if(appData.hasImage==false){
return;
}
var beginX=event.changedTouches[0].pageX;
var beginY=event.changedTouches[0].pageY;
data_op.isInDrag=true;
console.log("canvas operation touch start");
data_op.panelInfo=innerTools.GetAbsoluteLocationEx(canvas_operation);
if(data_op.panelInfo.absoluteLeft==0&&data_op.panelInfo.absoluteTop==0&&data_op.panelInfo.offsetHeight==0&&data_op.panelInfo.offsetWidth==0){
// data_op.panelInfo=innerTools.GetAbsoluteLocationEx(canvas_operation);
}
var e = event;
var params_currentX = beginX;
var params_currentY = beginY;
data_op.beginPoint.x=params_currentX;
data_op.beginPoint.y=params_currentY;
var realX=params_currentX-data_op.panelInfo.absoluteLeft;
var realY=params_currentY-data_op.panelInfo.absoluteTop;
_clearDebug();
_debug("未处理前,realX realY是:"+realX+" x "+realY);
//注意,上面没有考虑到有滚动条的状态,现在添加对滚动条的处理。
//--notice,假如页面有滚动条,每次都滚到不同位置的话,那么这个定位可能会有问题,于是我们需要进行处理。
var _scrollTop=$(document).scrollTop();
if(_scrollTop>0){
//realY=realY+_scrollTop; 移动端不用管,似乎得到的是正确的。
}
var _scrollLeft=$(document).scrollLeft();
if(_scrollLeft>0){
// realX=realX+_scrollLeft; 移动端不用管,似乎得到的是正确的。
}
_debug("scroll top left信息:"+_scrollTop+" x "+_scrollLeft);
_debug("当前panel位置信息是:"+JSON.stringify(data_op.panelInfo));
_debug("realX realY是:"+realX+" x "+realY);
_debug("裁剪框位置是:"+JSON.stringify(data_cutter));
data_op.point1.x=params_currentX;
data_op.point1.y=params_currentY;
data_op.isInCut=_child.isPointInCutter(realX,realY);
console.log("当前坐标");
console.log(params_currentX+"x"+params_currentY);
if(data_op.isInCut){
console.log("%c 在裁剪框里面。","color:green;");
}
event.preventDefault();
event.stopPropagation();
},false);
canvas_operation.addEventListener("touchmove",function(event){
if(appData.hasImage==false){
return;
}
if(data_op.isInDrag==false){
return;
}
event.preventDefault();
event.stopPropagation();
var e = event ? event : window.event;
var beginX=event.changedTouches[0].pageX;
var beginY=event.changedTouches[0].pageY;
var nowX = beginX, nowY = beginY;
console.log("%c 移动事件 mousemove中,位置:"+nowX+" x "+nowY+" 是否在裁剪框里面:"+data_op.isInCut,"color:red");
// var disX = nowX - params.currentX, disY = nowY - params.currentY;
//target.style.left = parseInt(params.left) + disX + "px";
//target.style.top = parseInt(params.top) + disY + "px";
//--计算位移量。
data_op.point2.x=nowX;
data_op.point2.y=nowY;
var delta_x=data_op.point2.x-data_op.point1.x;
var delta_y=data_op.point2.y-data_op.point1.y;
data_op.point1.x=nowX;
data_op.point1.y=nowY;
if(data_op.isInCut==true){
//--已经
console.log("现在在重新渲染裁剪框了。"+delta_x+" x "+delta_y);
_child.MoveCutterByDelta(delta_x,delta_y);
}
else{
_child.MoveBackgroundByDelta(delta_x,delta_y);
}
},false);
canvas_operation.addEventListener("touchend",function(event){
if(appData.hasImage==false){
return;
}
data_op.isInDrag=false;
event.preventDefault();
event.stopPropagation();
},false);
}
//--判断某个点是否在裁剪框里面。
,isPointInCutter:function(point_x,point_y){
var min_x=data_cutter.location.x;
var min_y=data_cutter.location.y;
var max_x=min_x+data_cutter.size.w;
var max_y=min_y+data_cutter.size.h;
if(point_xmax_x||point_ymax_y){
return false;
}
else{
return true;
}
}
,_cut_by_sizing:function(callback){
var __canvas = document.createElement("canvas");
var __context = __canvas.getContext("2d");
__canvas.width = data_cutter.size.w;
__canvas.height = data_cutter.size.h;
var _image=new Image();
_image.onload=function(){
__context.drawImage(_image,data_cutter.location.x,data_cutter.location.y,data_cutter.size.w,data_cutter.size.h,0,0,data_cutter.size.w,data_cutter.size.h);
if(callback){
var _base64=__canvas.toDataURL("image/jpeg");
callback(_base64);
}
};
_image.src=canvas_bg.toDataURL("image/jpeg");
}
,_cut_by_ratio:function(callback){
//--根据当前操作界面上的数据,换算成为图片上真实尺寸。
var _real_x_in_img=data_cutter.location.x-data_bg_trans.location.x;
var _real_y_in_img=data_cutter.location.y-data_bg_trans.location.y;
_real_x_in_img=_real_x_in_img/data_bg_trans.zoom;
_real_y_in_img=_real_y_in_img/data_bg_trans.zoom;
var _real_w=data_cutter.size.w/data_bg_trans.zoom;
var _real_h=data_cutter.size.h/data_bg_trans.zoom;
var __canvas = document.createElement("canvas");
var __context = __canvas.getContext("2d");
__canvas.width = _real_w;
__canvas.height = _real_h;
var _image;
if(data_bg_trans.angle==0||data_bg_trans.angle==360){
_image=data_bg.img_bg_0;
}
else if(data_bg_trans.angle==90){
_image=data_bg.img_bg_90;
}
else if(data_bg_trans.angle==180){
_image=data_bg.img_bg_180;
}
else if(data_bg_trans.angle==270){
_image=data_bg.img_bg_270;
}
__context.drawImage(_image,_real_x_in_img,_real_y_in_img,_real_w,_real_h,0,0,_real_w,_real_h);
var _base64=__canvas.toDataURL("image/jpeg");
callback(_base64);
}
//--裁剪图像,
,cut:function(callback){
var _child=this;
if(settings.saveMode=="ratio"){
_child._cut_by_ratio(callback);
}
else{
_child._cut_by_sizing(callback);
}
}
};
app.init();
//初始化控件。
this.init=function(base64_image_str){
console.log("初始化。");
app.init_background(base64_image_str);
app.updateCutter();
};
//--对外接口,移动裁剪框。
this.MoveCutter=function(pos_x,pos_y){
//--这里至少需要进行边界碰撞的判断。
app.MoveCutter(pos_x,pos_y);
};
//--对外接口,移动图片。
this.MoveImage=function(pos_x,pos_y){
//--这里至少需要进行边界碰撞的判断。
app.MoveBackground(pos_x,pos_y);
};
//--对外接口,缩放图片、
this.ScaleImage=function(_scale){
app.ScaleBackground(_scale);
};
this.RotateImage=function(angle){
app.RotateImage(angle);
};
//--是否已经有图片了。
this.hasImage=function(){
return appData.hasImage;
};
this.show_data_cutter=function(){
console.log(data_cutter);
};
//--获取目前的角度。
this.getImageAngle=function(){
return data_bg_trans.angle;
};
//--获取图片的缩放倍率。
this.getImageRotation=function(){
return data_bg_trans.angle;
};
//--获取缩放倍率。
this.getImageZoom=function(){
return data_bg_trans.zoom;
};
this.cutImg=function(callback){
app.cut(callback);
};
}
var _e_width=$(window).width()-200;
var _e_height=$(window).height()-200;
if(_e_width>800){
_e_width=800;
}
else if(_e_width<450){
_e_width=450;
}
/*
if(_e_height>600){
_e_height=600;
}
else if(_e_height<400){
_e_height=400;
}*/
var _image_editor={};
try{
_image_editor =new ImageEditor({
cutWidth:150 //裁剪框的宽度。
,cutHeight:200 //裁剪框的高度
,containerWidth:_e_width //容器宽度
,containerHeight:_e_height //容器高度
,imageShowWidth:400 //图片默认显示的宽度【会按照要求的宽度及高度等比缩放】
,imageShowHeight:500 //图片默认显示的高度【会按照要求的宽度及高度等比缩放】
,containerElement:$("#div_cropper") //容器的默认元素,jquery元素或者原生dom元素。
});
}
catch (ed){
alert(ed);
}
//--逻辑方法定义
$("#uploadImage").change(function(){
if (document.getElementById("uploadImage").files.length === 0) {
layer.alert("请选择图片!",3);
return; }
var oFile = document.getElementById("uploadImage").files[0];
//if (!rFilter.test(oFile.type)) { alert("You must select a valid image file!"); return; }
/* if(oFile.size>5*1024*1024){
message(myCache.par.lang,{cn:"照片上传:文件不能超过5MB!请使用容量更小的照片。",en:"证书上传:文件不能超过100K!"})
changePanel("result");
return;
}*/
if(!new RegExp("(jpg|jpeg|gif|png)+","gi").test(oFile.type)){
layer.alert("照片上传:文件类型必须是JPG、JPEG、PNG或GIF!",3);
return;
}
var reader = new FileReader();
reader.onload =function(e){
var _img_str=e.target.result;
// img 元素
_image_editor.init(_img_str);
};
reader.readAsDataURL(oFile);
return;
});
$("#btn_zoom_out").click(function(){
if(_image_editor.hasImage()==false){
alert("请先选择图片!");
return;
}
var _zoom=_image_editor.getImageZoom();
if(_zoom<0.5){
alert("最小倍率是0.5,无法继续缩小");
return;
}
_image_editor.ScaleImage(_zoom-0.2);
});
$("#btn_zoom_in").click(function(){
if(_image_editor.hasImage()==false){
alert("请先选择图片!");
return;
}
var _zoom=_image_editor.getImageZoom();
if(_zoom>4){
alert("最大倍率是4,无法继续放大");
return;
}
_image_editor.ScaleImage(_zoom+0.2);
});
$("#btn_turn_left").click(function(){
if(_image_editor.hasImage()==false){
alert("请先选择图片!");
return;
}
var _angle=_image_editor.getImageAngle();
_angle=(_angle+360)-90;
_angle=(_angle)%360;
_image_editor.RotateImage(_angle);
});
$("#btn_turn_right").click(function(){
if(_image_editor.hasImage()==false){
alert("请先选择图片!");
return;
}
var _angle=_image_editor.getImageAngle();
_angle=(_angle+0)+90;
_angle=(_angle)%360;
_image_editor.RotateImage(_angle);
});
$("#btn_save").click(function(){
if(_image_editor.hasImage()==false){
alert("请先选择图片!");
return;
}
_image_editor.cutImg(function(imgStr){
$("#preview_img").attr("src",imgStr);
});
});