思路:
- 通过拍照或者选择一张照片
- 将照片作为底,一个正方形容器作为边界。通过移动正方形容器获取所需图形的边界。
- 截取图片,并压缩到指定大小。
- 上传到服务器。
具体实现:
-
获取照片资源
1.1 从相册选择function chooseImgFromAlbums() { plus.gallery.pick(function(file) { changeToLocalUrl(file); }, function(err) { console.log(JSON.stringify(err)); }, { filter: 'image', multiple: false }); }
1.2 拍照
function chooseImgFromPictures() { var cmr = plus.camera.getCamera(); cmr.captureImage(function(file) { changeToLocalUrl(file); }, function(err) { console.log(JSON.stringify(err)); }, { index: '2', }); }
1.3 相册选择和拍照选择返回的路径都是绝对路径,为了让其显示在img里面,我们需要转换为本地路径URL地址。此处打开一张新页面来对图片进行处理
function changeToLocalUrl(path) { plus.io.resolveLocalFileSystemURL(path, function(entry) { openWindow('uploadImg.html?src=' entry.toLocalURL()); }); }
-
以一个正方形容器截取图片。
此处,自己写了一些简单的js来做图像截取,这些js修改起来也很方便。
首先,看一下整个页面:
功能很简单:点击放大,缩小可以放大缩小正方形的区域。用手指移动正方形,来改变正方形所包含的内容。
实现的思路:通过监听正方形的touchstart和touchmove事件,改变它的top,left值。实现移动。
具体代码如下:
var Clip = {
size: 12, //这个表示正方形目前的边长,乘上一个基数就是当前的像素值
range: {}, //用来控制正方形left和top的极限值,以免移出边界
topCss: 0, //表示当前的top值
leftCss: 0, //表示当前的left值
touchX: 0, //当前的手指所处的X坐标
touchY: 0, //当前手指的Y坐标
timer: null, //用来做touchmove的函数节流,以免连续触发touchmove事件导致的效率问题
changeBase: function(index) { //这个函数用来改变正方形的边长,一般还需要设置最大边长和最小边长
this.size = index;
$('#clip').css({
height: this.size 'rem',
width: this.size 'rem',
lineHeight: this.size 'rem'
});
this.changeRange(); //边长改变,将引起当前top, left和range的变化,统一调changeRange的方法来修改
},
changeRange: function() { //这个方法用来计算初始top, left以及边界值。其算法收到当前页面布局影响,需要自行修改
this.topCss =($('body').height() - baseSize * extraHeight - baseSize * this.size) / 2 baseSize * headerHeight;
this.leftCss = ($('body').width() - baseSize * this.size) / 2;
this.changeClipStyle(this.leftCss, this.topCss);
//极限值,需控制不超出图片区域
var minTop = ($('body').height() - baseSize * extraHeight - $('#img').height()) / 2 baseSize * headerHeight;
var maxTop = $('body').height() - ($('body').height() - baseSize * extraHeight - $('#img').height()) / 2 -
baseSize * footerHeght - baseSize * this.size;
var minLeft = 0;
var maxLeft = $('body').width() - baseSize * this.size;
this.range = {
minTop: minTop,
maxTop: maxTop,
minLeft: minLeft,
maxLeft: maxLeft
};
},
initEvent: function() { //事件初始化
mui('body').on('tap', '#enlarge', function(e) {
Clip.changeBase(1);
});
mui('body').on('tap', '#reduce', function(e) {
Clip.changeBase(-1);
})
var clip = document.getElementById('clip');
//开始接触的时候,记录当前的手指位置
clip.addEventListener('touchstart', function(event) {
Clip.touchX = event.touches ? event.touches[0].clientX : event.screenX;
Clip.touchY = event.touches ? event.touches[0].clientY : event.screenY;
event.preventDefault();
});
//移动后,记录新的位置,设置新的top和left值
clip.addEventListener('touchmove', function(event) {
//设置20ms的事件
if(Clip.timer != null) { //函数节流
return;
}
Clip.timer = setTimeout(function() {
var x = event.touches ? event.touches[0].clientX : event.screenX;
var y = event.touches ? event.touches[0].clientY : event.screenY;
var disX = x - Clip.touchX;
var disY = y - Clip.touchY;
var nowLeft = Clip.leftCss disX;
var nowTop = Clip.topCss disY;
if(nowLeft < Clip.range.minLeft) {
nowLeft = Clip.range.minLeft;
}
if(nowLeft > Clip.range.maxLeft) {
nowLeft = Clip.range.maxLeft;
}
if(nowTop < Clip.range.minTop) {
nowTop = Clip.range.minTop;
}
if(nowTop > Clip.range.maxTop) {
nowTop = Clip.range.maxTop;
}
Clip.changeClipStyle(nowLeft, nowTop);
Clip.touchX = x;
Clip.touchY = y;
Clip.timer = null;
}, 20);
});
},
//设置新的样式,并改变当前的top和left值
changeClipStyle: function(leftCss, topCss) {
$('#clip').css({
left: leftCss 'px',
top: topCss 'px'
});
Clip.leftCss = leftCss;
Clip.topCss = topCss;
}
}
- 移动到正方形到合适的区域后,点击完成,就将完成截取图片和压缩图片的功能。
主要思路是: 调用plus.zip.compressImage函数来完成截取和压缩
3.1. 首先,需要计算出宽高的百分比和离图片左上角的top和left的百分比。同样根据布局不同,计算方式不同。
//获取width和height的百分比
var widthPix = (Clip.size * baseSize / $('#img').width()).toFixed(2) * 100;
var heightPix = (Clip.size * baseSize / $('#img').height()).toFixed(2) * 100;
//获取左上角位置百分比
var topPix = ((Clip.topCss - Clip.range.minTop) / $('#img').height()).toFixed(2) * 100;
var leftPix = (Clip.leftCss / $('#img').width()).toFixed(2) * 100;
3.2 截取
//对图片进行裁剪
plus.zip.compressImage(
{
src: search.src, //src在这里是第一步Url里的src。也就是本地路径
dst: '_doc/a.jpg',
overwrite: true,
clip: {
top: topPix '%',
left: leftPix '%',
width: widthPix '%',
height: heightPix '%'
}
},
function(e) {
resizeImage(e.target); //压缩图片
}
);
3.3 截取图片之后,我们还需要进行压缩。
//再对图片进行压缩为270*270,再上传到服务器
function resizeImage(src) {
plus.zip.compressImage(
{
src: src,
dst: '_doc/a.jpg',
overwrite: true,
width: '270px', //这里指定了宽度,同样可以修改
format: 'jpg',
quality: 100 //图片质量不再修改,以免失真
},
function(e) {
plus.nativeUI.closeWaiting();
uploadImg(e.target); //上传图片, e.target存的是本地路径!
},
function(err) {
plus.nativeUI.alert('未知错误!',function() {
mui.back();
});
}
);
}
-
上传图片到服务器。上传图片用的是plus.uploader,数据格式符合Multipart/form-data规范,也就是平时input type='file'那样一样
function uploadImg(src) { var task = plus.uploader.createUpload(ajaxUrl, { method: 'post', blocksize:204800, timeout: 10 }); task.addFile(src, {key: 'headImg'}); task.addData('type', 'uploadImg'); task.addData('userId', ); task.addEventListener('statechanged', stateChanged, false); task.start(); function stateChanged(upload, status) { if ( upload.state == 4 && status == 200 ) { plus.uploader.clear(); //清除上传 console.log(upload.responseText); //服务器返回存在这里 } } }
好了,就这么多,代码比较简单,如果有其他能用的,欢迎修改。源码就不上传了,因为是公司项目的一个子功能,主要代码实现都在这里了。直接用了jQuery和mui。当然用原生写也OK。