图片处理

1.translate(-16px,3px) scale(2.6) rotate(90deg)有顺序要求,其值为用户操作后获取到的
2.选区大小为240*240,显示时选区与图片中心重合
3.该函数在处理旋转90°/270°+移动时选区映射存在问题,其它条件下可使用
插件完整代码如下:
 
/*
**图片查看器V2.0
**2017/12/27
**
*/

function imgViewer(option) {
this.img = null
this.param = {
x: 0, y: 0, x1: 0, y1: 1
}
this.curImgStatus = {
curScale: 1.0,
curRotate: 0,
curMoveX: 0,
curMoveY: 0,
}
this.isMove = false
this.RESPCODE = {
success: 1,
failure: -1
}
}

imgViewer.prototype = {
/*reset:function(){
this.param = {
x: 0, y: 0, x1: 0, y1: 1
}
this.curImgStatus = {
curScale: 1.0,
curRotate: 0,
curMoveX: 0,
curMoveY: 0,
}
this.img.style.transform = this.getStyle();
},*/
getStyle: function () {
var that = this
return [
'translate(', that.curImgStatus.curMoveX, 'px,', that.curImgStatus.curMoveY, 'px) ',
'scale(', that.curImgStatus.curScale, ') ',
'rotate(', that.curImgStatus.curRotate, 'deg)'
].join('')
},

init: function (imgId) {
var that = this
if (!that.img) {
that.img = document.getElementById(imgId);
that.bindEvent()
}
},
bindEvent: function () {
var that = this
that.img.onmousedown = that.img.ontouchstart = (function () {
return function (e) {
that.stopEvent(e)
that.imgMouseDown(e)
}
})()

that.img.onmouseup = that.img.ontouchend = (function () {
return function (e) {
that.stopEvent(e)
that.imgMouseUp(e)
}
})()

that.img.onmousemove = that.img.ontouchmove = (function () {
return function (e) {
that.stopEvent(e)
that.imgMouseMove(e)
}
})()
},
stopEvent: function (e) {
if (e.preventDefault) {
e.preventDefault()
}
e.stopPropagation()
},

imgMouseDown: function (e) {
var that = this
that.isMove = true
that.param.x = e.clientX || e.touches[0].clientX
that.param.y = e.clientY || e.touches[0].clientY
},

imgMouseUp: function (e) {
var that = this
that.isMove = false
},

imgMouseMove: function (e) {
var that = this
if (that.isMove) {
that.param.x1 = (e.clientX || e.touches[0].clientX) - that.param.x
that.param.y1 = (e.clientY || e.touches[0].clientY) - that.param.y
that.curImgStatus.curMoveX += that.param.x1
that.curImgStatus.curMoveY += that.param.y1
that.param.x = e.clientX || e.touches[0].clientX
that.param.y = e.clientY || e.touches[0].clientY
that.img.style.transform = that.getStyle()
}
},
bigFn: function () {
var that = this
if (that.curImgStatus.curScale.toFixed(2) < 3.2) {
that.curImgStatus.curScale += 0.2
that.img.style.transform = that.getStyle()
return that.RESPCODE.success
}
else {
return that.RESPCODE.failure
}
},

smallFn: function () {
var that = this
if (that.curImgStatus.curScale.toFixed(2) > 0.4) {
that.curImgStatus.curScale -= 0.2
that.img.style.transform = that.getStyle()
return that.RESPCODE.success
}
else {
return that.RESPCODE.failure
}
},

rotateFn: function (angle) {
var that = this
//将旋转指定角度并将角度值转化为0-360度之间以便处理
var destRotate = that.curImgStatus.curRotate;
destRotate += angle || 90
destRotate = destRotate % 360;
destRotate = destRotate >= 0 ? destRotate : destRotate + 360;
that.curImgStatus.curRotate = destRotate;
that.img.style.transform = that.getStyle()

},
reset: function () {
var that = this;
that.param = {
x: 0, y: 0, x1: 0, y1: 1
}
that.curImgStatus = {
curScale: 1.0,
curRotate: 0,
curMoveX: 0,
curMoveY: 0,
}
that.img.style.transform = that.getStyle();
},
getSize: function () {
var that = this;
var status = that.curImgStatus;
var sw = that.img.naturalWidth;
var sh = that.img.naturalHeight;
return { sw: sw, sh: sh };
},
cutPhoto: function () {
//变换: translate(-16px,3px) scale(2.6) rotate(90deg)[deg:0-360]
var that = this;
var size = that.getSize();
var img = that.img;
var status = that.curImgStatus;
var canvas = $('<canvas width="' + size.sw + '" height="' + size.sh + '"></canvas>')[0],
canvas1 = $('<canvas width="240" height="240"></canvas>')[0],
ctx = canvas.getContext('2d'),
ctx1 = canvas1.getContext('2d');
ctx.clearRect(0, 0, size.sw, size.sh)
ctx1.clearRect(0, 0, 240, 240)
var destLength = parseInt(240 / status.curScale);

//裁剪框四个点,最后一个点处理0%360=360bug
var startPointArr = [{ x: -120, y: -120 }, { x: 120, y: -120 }, { x: 120, y: 120 }, { x: -120, y: 120 }]
//根据旋转角度旋转起始点
var startPoint = startPointArr[status.curRotate / 90];
//平移操作
var x = parseInt(startPoint.x - status.curMoveX);
var y = parseInt(startPoint.y - status.curMoveY);
//缩放操作
x = parseInt(x / status.curScale);
y = parseInt(y / status.curScale);

//旋转操作
// x = parseInt(x * Math.cos(deg) + y * Math.sin(deg));
// y = parseInt(y * Math.cos(deg) - x * Math.sin(deg));
// 以下代码等同上述代码,这里去掉取值误差,更为精确
var t = 1;
switch (status.curRotate) {
case 90:
t = x; x = y; y = -t;
break;
case 180:
x = -x;
y = -y;
break;
case 270:
t = x; x = -y; y = t;
break;
default:
}
//移动原点至画布左上角
x = x + size.sw / 2;
y = y + size.sh / 2;
//切片图片
ctx.drawImage(that.img, x, y, destLength, destLength, 0, 0, 240, 240);
//整体切割
var dataImg = ctx.getImageData(0, 0, 240, 240);
ctx1.putImageData(dataImg, 0, 0, 0, 0, 240, 240);
canvas1 = that.rotate(canvas1, status.curRotate);
var data = canvas1.toDataURL();
that.reset();
return data;
},
rotate: function (canva, degrees) {
var angle = degrees * Math.PI / 180;
var ctx = canva.getContext("2d");
var img = document.createElement('canvas');
var center = {
x: canva.width / 2,
y: canva.height / 2
};
this.copy(canva, img);
ctx.clearRect(0, 0, canva.width, canva.height);
ctx.translate(center.x, center.y);
ctx.rotate(angle);
ctx.translate(-center.x, -center.y);
ctx.drawImage(img, 0, 0, canva.width, canva.height);
return canva;
},
copy: function (canva, target) {
var ctx = target.getContext("2d");
var fromCtx = canva.getContext('2d');
var dataImg = fromCtx.getImageData(0, 0, canva.width, canva.height);
target.width = canva.width;
target.height = canva.height;
ctx.putImageData(dataImg, 0, 0);
return target;
}
};
imgViewer.prototype.constructor = imgViewer
 
html:
<div class="edit-box">
<div class="cross-center" id="photo-container">
<img id="photo-edit" ng-src="{{photoEditing.url}}" />
</div>
<!-- 选区 -->
<div class="cross-center edit-area" ng-mousedown="photoMouseDown($event)" ng-mousemove="photoMouseMove($event)" ng-mouseup="photoMouseUp($event)"
ng-mouseleave="photoMouseUp($event)">
</div>
</div>
其中,cross-center的代码如下:
cross-center{
top:50%;
left:50%;
position:absolute;
tranform:translate(-50%,-50%);
其它css类在此不做展示。
 
js部分参考代码如下:
//input type="file" 选择文件后回调
$scope.handleFiles = function (files) {
var file = files;
Object.keys(files).forEach((key) => {
let reader = new FileReader();
reader.onload = function () {
let url = reader.result;
$timeout(() => {
var name = files[key].name;
$scope.photoList.push({ url: url, name: name });
}, 0)
};
reader.readAsDataURL(files[key]);
});
}
 
//编辑头像
$scope.imgViewer = new imgViewer();
$scope.imgViewer.init('photo-edit');
//编辑图片操作
$scope.photoMouseDown = function (e) {
$scope.imgViewer.imgMouseDown(e);
}
$scope.photoMouseMove = function (e) {
$scope.imgViewer.imgMouseMove(e);
}
$scope.photoMouseUp = function (e) {
$scope.imgViewer.imgMouseUp(e);
}
$scope.photoBigger = function () {
$scope.imgViewer.bigFn() == -1 ? $scope.upLimit = true : $scope.upLimit = false;
$scope.downLimit = false;
}
$scope.photoSmaller = function () {
$scope.imgViewer.smallFn() == -1 ? $scope.downLimit = true : $scope.downLimit = false;
$scope.upLimit = false;
}
$scope.photoRotate = function (angle) {
$scope.imgViewer.rotateFn(angle);
}
//裁剪图片
$scope.photoSave = function () {
$timeout(() => {
$scope.photoEditing.url = $scope.imgViewer.cutPhoto();
$scope.photoEditing.status = 1;
}, 0);
}
 
//将获取的数据转化为文件并使用七牛上传
function toFile(photo) {
photo.data = dataURLtoBlob(photo.url);
$scope.qiniuUploader.addFile($scope.photoList[$scope.uploadCount].data, photo.name);
}
function dataURLtoBlob(dataurl) { //将base64格式图片转换为文件形式
var arr = dataurl.split(',');
var mime = arr[0].match(/:(.*?);/)[1];
var bstr = atob(arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
 
 
插件的完成基于同事开发的图片查看器以及高中一位同学的协助,在此对他们的工作以及帮助表达感谢。如需转载,请注明出处。如有疑问可在下方留言。
posted @ 2018-03-13 16:48  yuxiao_l  阅读(112)  评论(0编辑  收藏  举报