前端js实现图片选择后进行压缩,然后转换Base64或blob进行上传操作等。

需求描述:

手机端用户选择的照片,肯定很大,直接上传到服务器压力很大,图片压缩,本质上后台很容易实现,现在需要前端来实现。
用户选择图片后,还能立马在界面上看到预览效果

具体的实现过程。

首先是html代码,重点只需要看<input>标签

  <div class="upload-wrap">
            <!-- 图片预览 -->
            <div class="xl-uploader__preview">
              <div class="xl-uploader__preview-image">
                <van-image height="100%" width="100%" :src="imgSrc" />
              </div>
              <van-icon
                class="xl-uploader__clear"
                color="#13b7f6"
                name="close"
              />
            </div>
            <!-- 本地选择图片 -->
            <div class="xl-uploader__upload">
              <van-icon name="photo" size="0.64rem" color="#dcdee0" />
              <input ref="myFileInput" class="xl-uploader__input" type="file" accept="image/jpg, image/jpeg, image/png" @change="uploadImg"></input>
            </div>
            <!-- 手机拍照 -->
            <div class="xl-uploader__upload">
              <van-icon name="photograph" size="0.64rem" color="#dcdee0" />
            </div>
          </div>

其次是css内容:
重点是input标签的opacity: 0;,以及宽高都是父元素的高度。实现结果是表面上点击的是外面的div,实际上会触发input的点击事件。

.upload-wrap {
  display: flex;
}
.xl-uploader__upload {
  position: relative;
  width: 80px;
  height: 80px;
  background-color: #f7f8fa;
  border-radius: 8px;
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-right: 10px;
}
.xl-uploader__input {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  cursor: pointer;
  opacity: 0;
}
.xl-uploader__preview {
  margin-right: 10px;
  position: relative;
}
.xl-uploader__preview-image {
  width: 80px;
  height: 80px;
  border-radius: 8px;
  overflow: hidden;
}
.xl-uploader__clear {
  position: absolute;
  top: -8px;
  right: -8px;
  font-size: 18px;
}

最后是js实现过程:

 async uploadImg() {
      try {
        var that = this
        const inputFiles = await this.$refs.myFileInput.files
         if (inputFiles.length > 1) {
          // 最多只能上传1张图片
          return false
        }
        const img = await this.readImg(inputFiles[0])
        const imgSrc = await this.compressImg(img, 1000, 1000)
        console.log(imgSrc)
        // 拿到转换的base64格式的图片内容了,接下去就可以去实现其他的操作。譬如作为字段内容传递给后台等,还可以拿这个imgSrc来赋值给图片的src来实现图片查看预览操作。
      } catch (error) {
        console.log(error)
      }
    },
    /**
     * 将图片file转换为img对象
     */
    readImg(file) {
      return new Promise((resolve, reject) => {
        const img = new Image()
        const reader = new FileReader()
        reader.onload = function(e) {
          img.src = e.target.result
        }
        reader.onerror = function(e) {
          reject(e)
        }
        reader.readAsDataURL(file)
        img.onload = function() {
          resolve(img)
        }
        img.onerror = function(e) {
          reject(e)
        }
      })
    },
 /**
    * 压缩图片
    * @param img 被压缩的img对象
    * @param mx 触发压缩的图片最大宽度限制
    * @param mh 触发压缩的图片最大高度限制
    */
    compressImg(img, mx, mh) {
      return new Promise((resolve, reject) => {
        const canvas = document.createElement('canvas')
        const context = canvas.getContext('2d')
        const { width: originWidth, height: originHeight } = img
        let dataURL = ''
        // 最大尺寸限制
        const maxWidth = mx
        const maxHeight = mh
        // 目标尺寸
        let targetWidth = originWidth
        let targetHeight = originHeight
        if (originWidth > maxWidth || originHeight > maxHeight) {
          if (originWidth / originHeight > 1) {
            // 宽图片
            targetWidth = maxWidth
            targetHeight = Math.round(maxWidth * (originHeight / originWidth))
          } else {
            // 高图片
            targetHeight = maxHeight
            targetWidth = Math.round(maxHeight * (originWidth / originHeight))
          }
        }
        canvas.width = targetWidth
        canvas.height = targetHeight
        context.clearRect(0, 0, targetWidth, targetHeight)
        // 图片绘制
        context.drawImage(img, 0, 0, targetWidth, targetHeight)
        dataURL = canvas.toDataURL('image/jpeg') // 转换图片为dataURL
        resolve(dataURL)
        // 转换为bolb对象
        // canvas.toBlob(function(blob) {
        //   resolve(blob)
        // }, type || 'image/png')
      })
    },

我这里去掉了图片格式传参,也将转换为bolb修改为base64了。因为实际项目需求。

参考链接地址:https://www.jb51.net/article/182078.htm

猜你喜欢

转载自blog.csdn.net/qq_42991509/article/details/106098263