--依賴於jQuery;
1、呼叫方式:
view:
<img id="draftPhoto" src="{{photoSrc}}" alt="待截圖圖片" title="待截圖圖片"/>
複製程式碼
這裡的 photoSrc 可以是本地圖片地址、也可以是網路圖片地址(需要跨域)、還可以是Base64編碼圖片
jQuery:
$('#draftPhoto').photoCrop({
img : $scope.tempdraftPhoto,
fixedScale:false,
isHead:false,
callBack:function(data){
if(data && data.success){
//取出返回結果值 - 返回結果值根據情況做取捨
var type = data.type, imgBase64Url = data.imgBase64Url;
console.log(type);
console.log(imgBase64Url);
}else{
tipsShow("截圖失敗, 回撥引數錯誤!");
}
}
});
複製程式碼
2、程式碼實現:
(function ($){
$.fn.photoCrop=function (option) {
//預設引數
var opt={
img:'', //圖片src
fixedScale:9/5, //縮放
isHead:null, //圓形
maxWidth:'860', //最大寬度
maxHeight:'1080', //最大高度
callBack:function () {} //回撥
};
opt=$.extend(opt,option);//覆蓋預設引數
var _this=this;//作用於
var imgSrc=opt.img ? opt.img : _this.attr('src');//圖片Src
//裁剪主介面 - 包括 遮罩 和 圖片顯示 + 操作按鈕
var photoCropBox=$('<div id="photoCropBox" style="position: fixed;width: 100%;height: 100%;top: 0;left: 0;background: rgba(0,0,0,0.5);z-index: 1060;overflow:auto;overflow-y: scroll;">' +
'<canvas id="cropCanvas" style="position: absolute;opacity:1;left: 0;top: 0;"></canvas>' +
'<img id="dataImg" src="'+imgSrc+'" style="opacity: 0;position: absolute;" alt="">' +
'<div id="photoCropBox-panel-box" style="position: relative;width: 100%;height: 100%;">' +
'<div id="photoCropBox-panel" style="opacity:0;background: #eee;border-radius: 5px;max-width: '+opt.maxWidth+'px;position: absolute; top: 40px; text-align: center;">' +
'<div id="photoCropBox-option1" style="text-align: left;padding-left: 30px;padding-top: 20px;position: relative;z-index: 2">' +
'<span id="frontageImg" class="photoCropBox-start">正面截圖</span><span class="photoCropBox-end">確 定</span><span class="photoCropBox-cancel">取 消</span>' +
'</div> ' +
'<div id="photoCropBox-img" style="margin: 30px;display: inline-block;position: relative">' +
'<img src="'+imgSrc+'" style="display: block;max-width: 100%;max-height: '+(opt.maxHeight-100)+'px;"></div>' +
'<div id="photoCropBox-option2" style="text-align: right;padding-right: 50px;padding-bottom: 20px;position: relative;z-index: 2">' +
'<span id="backImg" class="photoCropBox-start">背面截圖</span><span class="photoCropBox-end">確 定</span><span class="photoCropBox-cancel">取 消</span>' +
'</div>' +
'</div>' +
'</div></div>');
$('body').append(photoCropBox);
//原圖顯示容器
var _box=$('#photoCropBox-img');
var imgWidth=_box.find('img').width();
//操作按鈕
$('#photoCropBox-option1 span, #photoCropBox-option2 span').css({
lineHeight:'26px', background:'#888', color:'#eee', display:'inline-block',
paddingLeft:'10px', paddingRight:'10px', marginRight:'8px', cursor:'pointer'
});
//裁剪 - 截圖區域 - 邊框線 + 原圖背景 + 縮放點
var cropBox=$('<div id="photoCropBox-cropBox" style="position: absolute;z-index: 5;cursor: Move;display: none;">' +
'<div id="cropBoxLine" style="overflow: hidden;position: absolute;width: 100%;height: 100%;">' +
'<img src="'+imgSrc+'" style="display: block;width: '+imgWidth+'px;position: absolute;max-height: none;max-width: none;">' +
'<div class="top line" style="width: 100%;height: 1px;top: 0;left: 0;"></div><div class="right line" style="height: 100%;width: 1px;top: 0;right: 0;"></div>' +
'<div class="line bottom" style="width: 100%;height: 1px;bottom: 0px;left: 0"></div><div class="left line" style="height: 100%;width: 1px;top: 0;left: 0;"></div></div>' +
'<div id="cropBoxLine2"><div class="left line2" style="height: 100%;width: 1px;top: 0;left: 0;cursor: w-resize;"></div>' +
'<div class="right line2" style="height: 100%;width: 1px;top: 0;right: 0;cursor: e-resize;"></div>' +
'<div class="top line2" style="width: 100%;height: 1px;top: 0;left: 0;cursor: n-resize;position: absolute"></div>' +
'<div class="bottom line2" style="width: 100%;height: 1px;bottom: 0px;left: 0;cursor: s-resize;"></div>' +
'<div class="left bot" style="left: 0;top: 50%;margin-top: -4px;cursor: w-resize;"></div>' +
'<div class="right bot" style="right: 0;top: 50%;margin-top: -4px;cursor: e-resize;"></div>' +
'<div class="bottom bot" style="bottom: 0;left: 50%;margin-left: -4px;cursor: s-resize;"></div>' +
'<div class="top bot" style="top: 0;left: 50%;margin-left: -4px;cursor: n-resize;"></div>' +
'<div class="left-top bot" style="left: 0;top: 0;cursor: nw-resize;"></div>' +
'<div class="left-bottom bot" style="left: 0;bottom: 0;cursor: sw-resize;"></div>' +
'<div class="right-top bot" style="right: 0;top: 0;cursor: ne-resize;"></div>' +
'<div class="right-bottom bot"style="right: 0;bottom: 0;cursor: se-resize;"></div></div></div>');
//截圖區域背景
var screen=$('<div id="photoCropBox-bg" style="background: rgba(0,0,0,.5);position: absolute;left: 0;top: 0;width: 100%;height: 100%;z-index: 4;cursor: crosshair;display: none;"></div>');
_box.append(cropBox).append(screen);
//裁剪 - 截圖區域DOM
var _corp=$('#photoCropBox-cropBox');
//截圖區域 選擇線
var cropBoxLine=$('#cropBoxLine');
setTimeout(function () {
cropBoxLine.find('img').css('width',_box.find('img').width()+'px');
},20);
//圓形
if(opt.isHead){
cropBoxLine.css({borderRadius:'100%'});
}
$('#photoCropBox-cropBox .line,#photoCropBox-cropBox .line2').css({
position:'absolute', opacity:.5
});
$('#photoCropBox-cropBox .bot').css({
position:'absolute', width:8, height:8,
background:'#0f0', border:'1px #999 solid'
});
setTimeout(function () {
init();
},10);
$(window).on('resize',function () {
setPosition();
});
//取消
$('.photoCropBox-cancel').on('click',function () {
closeBox();
});
//按下 裁剪選擇區域
$('#photoCropBox-bg').on('mousedown',function (e) {
if(opt.fixedScale) {return;} //固定
$('#cropBoxLine2').hide();
var _this=$(this),
_sx=e.pageX,
_sy=e.pageY,
_tx=_this.offset().left,
_ty=_this.offset().top;
$(document).on('mousemove',function (e) {
e.preventDefault();
var _ex=e.pageX,_ey=e.pageY;
getPosition(_ex,_ey,_ty,_tx,_sx,_sy,_this);
});
$(document).on('mouseup',function () {
$(document).unbind('mousemove');
$('#cropBoxLine2').show();
});
});
var lock=false;
//按下裁剪 - 截圖區域
_corp.on('mousedown',function (e) {
if(lock){return;}
var _this=$(this),
_sx=e.pageX,
_sy=e.pageY,
_thisX=parseInt(_this.css('left')),
_thisY=parseInt(_this.css('top')),
_thisW=parseInt(_this.css('width')),
_thisH=parseInt(_this.css('height')),
pW=$('#photoCropBox-bg').width(),
pH=$('#photoCropBox-bg').height();
$(document).on('mousemove',function (e) {
e.preventDefault();
var _ex=e.pageX, _ey=e.pageY, _x=Number(_ex)-Number(_sx), _y=Number(_ey)-Number(_sy);
_x+=_thisX;
_y+=_thisY;
if(_x<0) {_x=0;}
if(_y<0) {_y=0;}
if(_y>pH-_thisH) {_y=Number(pH)-Number(_thisH);}
if(_x>pW-_thisW) {_x=Number(pW)-Number(_thisW);}
resizeCropBox("","",_y,_x,true)
});
$(document).on('mouseup',function () {
$(document).unbind('mousemove');
});
});
//控制大小
$('#cropBoxLine2 .bot').on("mousedown",function (e) {
lock=true;
var _esx=e.pageX, _esy=e.pageY,
_that=$(this),
_this=$('#photoCropBox-bg'),
_tx=_this.offset().left,
_ty=_this.offset().top,
_sx=_corp.offset().left,
_sy=_corp.offset().top;//裁剪框
if(_that.hasClass('right-top')) {_sy+=_corp.height();}
if(_that.hasClass('left-top')){
_sy+=_corp.height();
_sx+=_corp.width();
}
if(_that.hasClass('left-bottom')) {_sx+=_corp.width();}
$(document).on('mousemove',function (e) {
e.preventDefault();
var _ex=e.pageX,_ey=e.pageY;
if(opt.fixedScale){
_ey=Number((Number(_ex)-Number(_esx))/opt.fixedScale)+Number(_esy);
if(_that.hasClass('right-top') || _that.hasClass('left-bottom')){
_ey=Number((Number(_esx)-Number(_ex))/opt.fixedScale)+Number(_esy);
}
}
getPosition(_ex,_ey,_ty,_tx,_sx,_sy,_this);
});
$(document).on('mouseup',function () {
$(document).unbind('mousemove');
lock=false;
})
});
$('#cropBoxLine2 .left,#cropBoxLine2 .top,#cropBoxLine2 .right,#cropBoxLine2 .bottom').on('mousedown',function (e) {
if(opt.fixedScale) {return;} //固定
lock=true;
var _that=$(this),
_this=$('#photoCropBox-bg'),
_tx=_this.offset().left,
_ty=_this.offset().top,
_sx=_corp.offset().left,
_sy=_corp.offset().top,
ch=_corp.height(),
cw=_corp.width();
if(_that.hasClass('top')){
_sy+=ch;
}else if(_that.hasClass('left')) {
_sx+=cw;
}
$(document).on('mousemove',function (e) {
e.preventDefault();
var _ex=e.pageX,_ey=e.pageY;
if(_that.hasClass('top') || _that.hasClass('bottom')){
if(!(Number(_ey)-Number(_sy)>0)){
var _x=Number(_sx)-Number(_tx),_y=Number(_ey)-Number(_ty),_w=cw,_h=-(Number(_ey)-Number(_sy));
if(_y<0) {_y=0;_h=Number(_sy)-Number(_ty);}
}else{
var _x=Number(_sx)-Number(_tx),_y=Number(_sy)-Number(_ty),_w=cw,_h=Number(_ey)-Number(_sy);
if(_h>Number(_this.height())-Number(_y)) {_h=Number(_this.height())-Number(_y);}
}
}else {
if(Number(_ex)-Number(_sx)>0 && Number(_ey)-Number(_sy)>0){
var _x=Number(_sx)-Number(_tx),_y=Number(_sy)-Number(_ty),_w=Number(_ex)-Number(_sx),_h=ch;
if(Number(_w)>Number(_this.width())-Number(_x)) _w=Number(_this.width())-Number(_x);
}else if(!(Number(_ex)-Number(_sx)>0) && Number(_ey)-Number(_sy)>0){
var _x=Number(_ex)-Number(_tx),_y=Number(_sy)-Number(_ty),_w=-(Number(_ex)-Number(_sx)),_h=ch;
if(_x<0) {_x=0;_w=Number(_sx)-Number(_tx);}
}
}
resizeCropBox(_w,_h,_y,_x);
});
$(document).on('mouseup',function () {
$(document).unbind('mousemove');
lock=false;
});
});
var sectionType = "";
//開始裁剪
$('.photoCropBox-start').on('click',function () {
sectionType = this.id;
_corp.css('display','block');
$('#photoCropBox-bg').css('display','block');
init();
});
//確認 裁剪區域
$('.photoCropBox-end').on('click',function () {
if(sectionType){
getImage();
}
closeBox();
});
//初始化
function init() {
setPosition();
if(opt.fixedScale){
if((_box.height()-_box.width()/opt.fixedScale/2)<0){
resizeCropBox(_box.height()*opt.fixedScale,_box.height(),0,(_box.width()-_box.height()*opt.fixedScale)/2);
}else {
resizeCropBox(_box.width()/2,_box.width()/opt.fixedScale/2,(_box.height()-_box.width()/opt.fixedScale/2)/2,_box.width()/4);
}
}else {
//預設選擇區域
if(sectionType == 'frontageImg'){
resizeCropBox(_box.width()-200,_box.height()/2-100,50,100);
}else if(sectionType == 'backImg'){
resizeCropBox(_box.width()-200,_box.height()/2-100,_box.height()/2+50,100);
}else{
resizeCropBox(_box.width()-200,_box.height()-100,50,100);
}
}
if(opt.fixedScale) {
$('.bot.top,.bot.left,.bot.bottom,.bot.right').remove();//固定
}
};
//設定彈出層皮膚位置
function setPosition() {
$('#photoCropBox-panel').css({
left:Math.abs($('#photoCropBox-panel-box').width()-$('#photoCropBox-panel').width())/2+'px',
opacity:1
});
};
//結束x,y 背景x,y
function getPosition(_ex,_ey,_ty,_tx,_sx,_sy,_this) {
if(_ex-_sx>0 && _ey-_sy>0){
var _x=_sx-_tx,_y=_sy-_ty,_w=_ex-_sx,_h=_ey-_sy;
if(_w>_this.width()-_x) {_w=_this.width()-_x;}
if(_h>_this.height()-_y) {_h=_this.height()-_y;}
}else if(!(_ex-_sx>0) && _ey-_sy>0){
var _x=_ex-_tx,_y=_sy-_ty,_w=-(_ex-_sx),_h=_ey-_sy;
if(_x<0) {_x=0;_w=_sx-_tx;}
if(_h>_this.height()-_y) {_h=_this.height()-_y;}
}else if(!(_ex-_sx>0) && !(_ey-_sy>0)){
var _x=_ex-_tx,_y=_ey-_ty,_w=-(_ex-_sx),_h=-(_ey-_sy);
if(_x<0) {_x=0;_w=_sx-_tx;}
if(_y<0) {_y=0;_h=_sy-_ty;}
}else if(_ex-_sx>0 && !(_ey-_sy>0)){
var _x=_sx-_tx,_y=_ey-_ty,_w=_ex-_sx,_h=-(_ey-_sy);
if(_y<0) {_y=0;_h=_sy-_ty;}
if(_w>_this.width()-_x) {_w=_this.width()-_x;}
}
if(opt.fixedScale){
if(_w/opt.fixedScale>_h){
_w=_h*opt.fixedScale;
}else if (_w<opt.fixedScale*_h){
_h=_w/opt.fixedScale;
}
}
resizeCropBox(_w,_h,_y,_x);
};
//畫布
var c=document.getElementById("cropCanvas"),
ctx=c.getContext("2d"),
callBackReturnData = {success : false};
function getImage() {
/**
* 注意這裡的 #dataImg 需要獲取原始寬高, 用於計算與截圖圖片的寬高比
* HTML5提供了一個新屬性naturalWidth/naturalHeight可以直接獲取圖片的原始寬高。這兩個屬性在Firefox/Chrome/Safari/Opera及IE9裡已經實現
*/
var scaleW=cropBoxLine.find('img').width()/document.getElementById('dataImg').naturalWidth,
scaleH=cropBoxLine.find('img').height()/document.getElementById('dataImg').naturalHeight,
//開始剪下的 x 座標位置
sx=parseInt(_corp.css('left'))/scaleW,
//開始剪下的 y 座標位置
sy=parseInt(_corp.css('top'))/scaleH,
//被剪下影像的寬度
swidth=parseInt(_corp.css('width'))/scaleW,
//被剪下影像的高度
sheight=parseInt(_corp.css('height'))/scaleH,
//要使用的影像、畫布
c_img = new Image();
c_img.crossOrigin = 'Anonymous'; //可選值:anonymous,*
c_img.src = imgSrc;
callBackReturnData.type = sectionType;
//畫布寬高 - 縮小2倍
c.width = swidth/2;
c.height = sheight/2;
c_img.onload = function () {
/**
* 1、c_img : 規定要使用的影像、畫布或視訊
* 2、sx : 可選。開始剪下的 x 座標位置
* 3、sy : 可選。開始剪下的 y 座標位置
* 4、swidth : 可選。被剪下影像的寬度
* 5、sheight : 可選。被剪下影像的高度
* 6、0 : 在畫布上放置影像的 x 座標位置
* 7、0 : 在畫布上放置影像的 y 座標位置
* 8、swidth/2 : 可選。要使用的影像的寬度(伸展或縮小影像)
* 9、sheight/2 : 可選。要使用的影像的高度(伸展或縮小影像)
*/
ctx.drawImage(c_img,sx,sy,swidth,sheight,0,0,swidth/2,sheight/2);
//獲取圖片BASE64
var url=c.toDataURL("image/jpeg");
//回撥返回值
callBackReturnData.imgBase64Url = url;
callBackReturnData.success = true;
opt.callBack(callBackReturnData);
};
c_img.onerror=function(){
alert("稿樣圖片請求失敗:CORS policy: 'Access-Control-Allow-Origin' header");
}
};
//寬,高,top,left,m-是否是拖拽
function resizeCropBox(w,h,t,l,m) {
_corp.css(prefix()+'transition','all 0s');
if(!m){
_corp.css({
width:w+'px', height:h+'px',
top:t+'px', left:l+'px'
});
}else {
_corp.css({
top:t+'px', left:l+'px'
});
}
cropBoxLine.find('img').css({
top:-t+'px', left:-l+'px'
});
};
function closeBox() {
$('#photoCropBox').remove();
};
function prefix() {
var prefixes=['','-ms-','-moz-','-webkit-','-o-'],i=0;
while (i < prefixes.length){
if($('body').css(prefixes[i]+'transition')){
return prefixes[i];
}
i++;
}
};
}
})(jQuery);複製程式碼