图像(头像)选择,截取,压缩,上传的分享

原文是来自于DCloud的官方论坛的,看完之后觉得非常实用,因此分享出来希望更多的童鞋可以参考下。有兴趣的可以点击下面的链接前去观看原文

----------------------图像(头像)选择,截取,压缩,上传的分享


思路:
1. 通过拍照或者选择一张照片
2. 将照片作为底,一个正方形容器作为边界。通过移动正方形容器获取所需图形的边界。
3. 截取图片,并压缩到指定大小。
4. 上传到服务器。

具体实现:
1. 获取照片资源
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里面,我们需要转换为本地路径。此处打开一张新页面来对图片进行处理

function changeToLocalUrl(path) {
  plus.io.resolveLocalFileSystemURL(path, function(entry) {
    openWindow('uploadImg.html?src='   entry.toLocalURL());
  });
}

  1. 以一个正方形容器截取图片。
    此处,自己写了一些简单的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;
  }
}

  1. 移动到正方形到合适的区域后,点击完成,就将完成截取图片和压缩图片的功能。
    主要思路是: 调用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();
      });
    }
  );
}

  1. 上传图片到服务器。上传图片用的是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。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值