移动端裁剪头像功能

js选择文件上传

之前传统的选择文件方式是给一个input标签点击上传,然后美化一下UI。后面出了一些新的API,可以用js方式来处理选择文件这个操作。
以下是一些相关的API:

Window.showSaveFilePicker()
Window.showOpenFilePicker()
Window.showDirectoryPicker()
Window.showModalDialog()(已删除)

使用的时候需要查询一下兼容性,比如在pc浏览器模拟器里可以上传,但是在移动端浏览器上却不会出现选择文件的弹窗,需要写一个polyfill,对于不能调用showOpenFilePickerPolyfill方法的用传统方式

async showOpenFilePickerPolyfill (options = [{}]) {
      if (!Array.isArray(options)) {
        options = [options]
      }
      return new Promise((resolve, reject) => {
        const input = document.createElement('input')
        input.type = 'file'
        const accept = [
          ...options.map((option) => option.mimeTypes || []),
          ...options.map((option) => option.extensions || [])
        ].join()
        input.multiple = options[0].multiple || false
        input.accept = accept || ''
        input.style.display = 'none'
        document.body.append(input)
        const _reject = () => cleanupListenersAndMaybeReject(reject)
        const _resolve = (value) => {
          if (typeof cleanupListenersAndMaybeReject === 'function') {
            cleanupListenersAndMaybeReject()
          }
          resolve(value)
        }
        const cleanupListenersAndMaybeReject =
          options[0].legacySetup &&
          options[0].legacySetup(_resolve, _reject, input)

        const cancelDetector = () => {
          window.removeEventListener('focus', cancelDetector)
          input.remove()
        }

        input.addEventListener('click', () => {
          window.addEventListener('focus', cancelDetector)
        })

        input.addEventListener('change', () => {
          window.removeEventListener('focus', cancelDetector)
          input.remove()
          _resolve(input.multiple ? Array.from(input.files) : input.files[0])
        })

        if ('showPicker' in HTMLInputElement.prototype) {
          input.showPicker()
        } else {
          input.click()
        }
      })
    }
  
 supported () {
      if (typeof window.self === 'undefined') {
        return false
      }
      if ('top' in window.self && window.self !== window.top) {
        try {
          // eslint-disable-next-line no-unused-expressions
          window.top.location + ''
        } catch (e) {
          return false
        }
        return false
      } else if ('showOpenFilePicker' in window.self) {
        return 'showOpenFilePicker'
      }
      return false
    }

其他API polyfill请参考:
https://github.com/GoogleChromeLabs/browser-fs-access

裁剪工具

可能通过搜索出现最多的是vue-copper,经过一通操作后,发现问题很多,并且卡顿,后面更换了vue-advanced-cropper,感觉还挺不错的,可以满足要求,移动顺畅。这后面的操作就比较简单了,就是通过使用这个插件,获取相应的blob或者base64来上传到服务器

 async handleChangeAvatar () {
      var src = ''
      if (this.supported()) {
        const arrFileHandle = await window.showOpenFilePicker(this.options)
        src = await this.handleFiletoBlob(arrFileHandle)
      } else {
        const blob = await this.showOpenFilePickerPolyfill(this.options)
        src = URL.createObjectURL(blob)
      }
      this.option.img = src
      this.showCopper = true
      this.$nextTick(() => {
        const ele = document.querySelector('#app')
        ele.appendChild(this.$refs.showCopper)
      })
      this.showAvatar = false
      this.showSheet = false
    }

获取图像

  const { canvas } = this.$refs.cropper.getResult()

你可能感兴趣的:(移动端裁剪头像功能)