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

发布于 1周前 作者 htzhanglong 来自 Uni-App

uni-app图像(头像)选择,截取,压缩,上传的分享功能 思路:

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

具体实现:

  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里面,我们需要转换为本地路径URL地址。此处打开一张新页面来对图片进行处理

      function changeToLocalUrl(path) {  
        plus.io.resolveLocalFileSystemURL(path, function(entry) {  
          openWindow('uploadImg.html?src=' + entry.toLocalURL());  
        });  
      }
      
  2. 以一个正方形容器截取图片。

    功能很简单:点击放大,缩小可以放大缩小正方形的区域。用手指移动正方形,来改变正方形所包含的内容。

    实现的思路:通过监听正方形的touchstart和touchmove事件,改变它的top,left值。实现移动。

    具体代码如下:

    var Clip = {  
      size: 12, 
      range: {}, 
      topCss: 0,  
      leftCss: 0,  
      touchX: 0,  
      touchY: 0,  
      timer: null,  
      changeBase: function(index) {  
        this.size += index;  
        $('#clip').css({  
          height: this.size + 'rem',  
          width: this.size + 'rem',  
          lineHeight: this.size + 'rem'  
        });  
        this.changeRange();  
      },  
      changeRange: function() {  
        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();  
        });  
        clip.addEventListener('touchmove', function(event) {  
          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);  
        });  
      },  
      changeClipStyle: function(leftCss, topCss) {  
        $('#clip').css({  
          left: leftCss + 'px',  
          top: topCss + 'px'  
        });  
        Clip.leftCss = leftCss;  
        Clip.topCss = topCss;  
      }  
    }
    
  3. 移动到正方形到合适的区域后,点击完成,就将完成截取图片和压缩图片的功能。

    主要思路是:调用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,  
        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);  
        },  
        function(err) {  
          plus.nativeUI.alert('未知错误!',function() {  
            mui.back();  
          });  
        }  
      );  
    }
    
  4. 上传图片到服务器。上传图片用的是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);  
        }  
      }  
    }
    

1 回复

在uni-app中实现图像(头像)的选择、截取、压缩和上传功能,可以通过以下步骤实现。以下是一个简单的代码示例,展示了如何集成这些功能。

1. 选择图像

使用uni.chooseImage API来选择图像:

uni.chooseImage({
    count: 1, // 只选择一张图片
    sizeType: ['original', 'compressed'], // 可以选择原图或压缩后的图片
    sourceType: ['album', 'camera'], // 可以从相册选择或拍照
    success: (res) => {
        const tempFilePaths = res.tempFilePaths;
        this.handleImage(tempFilePaths[0]);
    }
});

2. 图像截取(可选)

如果需要截取图像,可以使用canvas进行裁剪。以下是一个简单的裁剪示例:

handleImage(filePath) {
    uni.getImageInfo({
        src: filePath,
        success: (imageInfo) => {
            const ctx = uni.createCanvasContext('myCanvas');
            const width = 100; // 裁剪后的宽度
            const height = 100; // 裁剪后的高度
            const x = (imageInfo.width - width) / 2; // 裁剪起始点的x坐标
            const y = (imageInfo.height - height) / 2; // 裁剪起始点的y坐标
            ctx.drawImage(filePath, x, y, width, height, 0, 0, width, height);
            ctx.draw(false, () => {
                uni.canvasToTempFilePath({
                    canvasId: 'myCanvas',
                    destWidth: width,
                    destHeight: height,
                    success: (res) => {
                        this.compressAndUpload(res.tempFilePath);
                    }
                });
            });
        }
    });
}

3. 图像压缩

可以使用uni.compressImage API进行压缩,但前面已经通过canvas裁剪并调整了尺寸,这一步可以省略。如果仍需额外压缩,可以如下使用:

uni.compressImage({
    src: tempFilePath,
    quality: 80, // 压缩质量
    success: (res) => {
        this.uploadImage(res.tempFilePath);
    }
});

注意:这里的tempFilePath是裁剪后的图像路径。

4. 上传图像

使用uni.uploadFile API上传图像:

compressAndUpload(filePath) {
    uni.uploadFile({
        url: 'https://your-server-upload-url', // 上传地址
        filePath: filePath,
        name: 'file',
        formData: {
            user: 'test'
        },
        success: (uploadFileRes) => {
            console.log('上传成功:', uploadFileRes.data);
        },
        fail: (err) => {
            console.error('上传失败:', err);
        }
    });
}

总结

上述代码展示了如何在uni-app中选择、截取(通过canvas)、压缩(可选)和上传图像。注意,实际应用中需要根据具体需求调整代码,例如错误处理、用户交互等。此外,为了提升用户体验,可以在上传过程中显示加载动画或进度条。

回到顶部