h5 js调用移动端 相机 相册

 效果:

点击从手机相机获取图片或打开相机拍摄图片,  触屏缩放移动 加载的图片到合适位置

注意这里的几个坑:

1  在红米K40上 出现了  微信浏览器点击,触发change事件后只能调到相册,无法弹出“相机或相册选择框”,而且无法选中相片的问题。

    参考  前段H5开发,小米上用input File 为什么获取不到照片的数据? - 知乎

解决方法如下代码。

<!-- 写成 accept="image/png,image/jpeg,image/gif"   时  红米k40 微信浏览器无法打开相册  要写成  accept="image/*"  -->
          <!-- <input type="file" id="image_uploads" multiple=""  class="inputFile" accept="image/png,image/jpeg,image/gif"  > -->
          <!-- <input type="file" id="image_uploads" multiple=""  class="inputFile" accept="image/*"  > -->

只不过解决后因为问题2 又都注释掉了。

2  在ios系统上 出现了  第一次点击,经常无法触发change事件的情况

     具体现象:安卓手机上,微信浏览器、自带浏览器都没有问题。苹果手机上,第一次点击,有时候无法触发change事件(复现频率较高),第二次点击就好了。访问过一次,点击,好了后,刷新页面也不一定能复现问题。(坑死)
    参考  https://stackoverflow.com/questions/47664777/javascript-file-input-onchange-not-working-ios-safari-only

       解决方法:
        将initNew() 方法里下面这两行注释掉   

  // this.input = document.querySelector('#image_uploads')
        // this.input.addEventListener('change', this.updateImageDisplay)

        将 template 里的  <input> 元素注释掉  

<!-- 写成 accept="image/png,image/jpeg,image/gif"   时  红米k40 微信浏览器无法打开相册  要写成  accept="image/*"  -->
          <!-- <input type="file" id="image_uploads" multiple=""  class="inputFile" accept="image/png,image/jpeg,image/gif"  > -->
          <!-- <input type="file" id="image_uploads" multiple=""  class="inputFile" accept="image/*"  > -->

        换成initNew() 方法里

// input 元素绑定 change 事件 
        let mobileCamera = document.querySelector('#mobileCamera')
        let input =  document.createElement("input"); 
        input = document.body.appendChild(input)
        input.type = "file"
        input.id = "image_uploads"
        input.className="inputFile";
        input.multiple= true
        input.accept="image/png,image/jpeg,image/gif"
        input.style.width=  "1%"
        input.style.height = "1%"
        input.style.position =  'absolute';
        input.style.opacity = 0;
        input.addEventListener('change', this.updateImageDisplay)

注意这里   

    input = document.body.appendChild(input)  ,绑定在 document.body 上,一开始绑定在 <div id="mobileCamera" class="mobileCamera"  v-loading="loading"> 上,未解决问题,至于绑定在其他dom上可以不,还未测试。

    绑定change事件用 ,input.addEventListener('change', this.updateImageDisplay)  

用onchange 未生效。

         

   

3  功能设计里,是用img 或者div点击后,去触发 input 元素的click事件的。而这种情况下,在ios系统上 出现了 img、div  需要双击的情况才能触发click,input 支持单击。  Android手机无此问题。
    参考  tap事件_苏醒!的博客-CSDN博客_tap事件

    解决方法 

        let mobileCamera = document.querySelector('#mobileCamera')
        // 用 tab 换掉 click ,click在ios safari浏览器上有 单击失效,需要双击  的问题
        this.bindTapEvent(mobileCamera,(e)=>{
          input.click();
        })


       bindTapEvent(dom,callback){
            var startTime = 0;
            var isMove = false;
            dom.addEventListener('touchstart',function(){
              startTime = Date.now();
              console.log(startTime);
            });
            dom.addEventListener('touchmove',function(){
              isMove = true;
            });
            dom.addEventListener('touchend',function(e){
              console.log(Date.now()-startTime);
              if((Date.now()-startTime)<250&&isMove == false){
                callback&&callback.call(this,e)
              }else{
            console.log('失败');
              }
              isMove = false;
              startTime = 0;
            });
      },

直接上代码

<template>
  <div class="component">
    <div id="mobileCamera" class="mobileCamera"  v-loading="loading">
          <!-- 写成 accept="image/png,image/jpeg,image/gif"   时  红米k40 微信浏览器无法打开相册  要写成  accept="image/*"  -->
          <!-- <input type="file" id="image_uploads" multiple=""  class="inputFile" accept="image/png,image/jpeg,image/gif"  > -->
          <!-- <input type="file" id="image_uploads" multiple=""  class="inputFile" accept="image/*"  > -->
             
          <div class="imgPreviewDiv" v-show="src">
            <img  id="mobileCameraPreview" :src="src" class="imgPreview"   >
          </div>
          <img src="./assets/b.png" class="imgCamera"  v-if="show">

    </div>

  </div>
</template>
import Hammer from 'hammerjs'
import axios from 'axios'

 export default {
    name: 'conponent01',
    props: {
  
    },
    computed: {},
    data () {
      return {

        input: undefined,
        src: "",
        show1:false,
        show:true,
        loading:false,

        // 拖动缩放
        imgScale: 1,
        oldScale: 1,
        imgPos: {
          x: 0,
          y: 0
        },

      }
    },
    mounted () {
  
      // 图片操作 移动 缩放
      this.zoom()
      
      this.initNew()
    },
  
    methods: {
      // 同事写的   移动端 移动、缩放元素
      zoom(){
        var square = this.$el.querySelector('#mobileCameraPreview')
          let that = this
          // Create an instance of Hammer with the reference.
          var hammer = new Hammer(square)
          hammer.get('pinch').set({ enable: true })
          // Subscribe to a quick start event: press, tap, or doubletap.
          // For a full list of quick start events, read the documentation.
          hammer.on('panend', function (e) {
            that.imgPos.x += e.deltaX
            that.imgPos.y += e.deltaY
          })
          hammer.on('pan', function (e) {
            // console.log('pan=====', e)
            square.style.transform = `matrix(${that.imgScale},0,0,${that.imgScale},${that.imgPos.x + e.deltaX},${that.imgPos.y + e.deltaY})`
          })
          hammer.on('pinch', function (e) {
            that.imgScale = Math.max(Math.min(that.oldScale * e.scale, 10), 1)
            square.style.transform = `matrix(${that.imgScale},0,0,${that.imgScale},${that.imgPos.x},${that.imgPos.y})`
          })
          hammer.on('pinchend', function (e) {
            that.oldScale = that.imgScale
          })
      },
 
      

      initNew () {
        // input 元素绑定 change 事件 
        let mobileCamera = document.querySelector('#mobileCamera')
        let input =  document.createElement("input"); 
        input = document.body.appendChild(input)
        input.type = "file"
        input.id = "image_uploads"
        input.className="inputFile";
        input.multiple= true
        input.accept="image/png,image/jpeg,image/gif"
        input.style.width=  "1%"
        input.style.height = "1%"
        input.style.position =  'absolute';
        input.style.opacity = 0;
        input.addEventListener('change', this.updateImageDisplay)
        
         //  在ios系统上 出现了  第一次点击,经常无法触发change事件的情况
         // 参考  https://stackoverflow.com/questions/47664777/javascript-file-input-onchange-not-working-ios-safari-only
        //  将下面这两行  和  template 里的  <input> 元素注释掉  换成上面这个 createElement('input')  
        // this.input = document.querySelector('#image_uploads')
        // this.input.addEventListener('change', this.updateImageDisplay)
        // 用 tab 换掉 click ,click在ios safari浏览器上有 单击失效,需要双击  的问题
        this.bindTapEvent(mobileCamera,(e)=>{
          input.click();
        })
      },
      // 参考 https://blog.csdn.net/qq_42309685/article/details/102526869
      bindTapEvent(dom,callback){
        var startTime = 0;
        var isMove = false;
        dom.addEventListener('touchstart',function(){
          startTime = Date.now();
          console.log(startTime);
        });
        dom.addEventListener('touchmove',function(){
          isMove = true;
        });
        dom.addEventListener('touchend',function(e){
          console.log(Date.now()-startTime);
          if((Date.now()-startTime)<250&&isMove == false){
            callback&&callback.call(this,e)
          }else{
            console.log('失败');
          }
          isMove = false;
          startTime = 0;
        });
      },
      imgClick () {
        this.input.click();
      },
      updateImageDisplay () {
        let _this = this
        this.loading = true
        
        const curFiles = this.input.files
        if (curFiles.length === 0) {
          // no file
        } else {
          for (const file of curFiles) {
            // 方法1  上传后台  返回服务器端图片地址 赋值给 src
            var formData = new FormData()
            formData.append('files',file)
            axios({
                  method: 'post',
                  url: 'https://xxxxxx/api/ossupload/uploadFile',
                  data: formData
            }).then((res)=>{
              console.log(res.data.data[0].path)
              _this.show1 = true
              _this.show = false
              _this.$nextTick(()=>{
                _this.src = res.data.data[0].path
                _this.loading = false

                // 图片操作相关
                _this.imgScale = 1
                _this.oldScale = 1
                _this.imgPos = {
                  x: 0,
                  y: 0
                }
                _this.$el.querySelector('#mobileCameraPreview').style.transform = `matrix(1,0,0,1,0,0)`
              })
            })

            // 方法2  读成 base64 赋值给 src
            // var reader = new FileReader()
            // reader.readAsDataURL(file)
            // reader.onload = function () {
            //   _this.show1 = true
            //   _this.show = false
            //   _this.$nextTick(()=>{
            //     _this.src = this.result
            //     _this.imgScale = 1
            //     _this.oldScale = 1
            //     _this.imgPos = {
            //       x: 0,
            //       y: 0
            //     }
            //     _this.$el.querySelector('#mobileCameraPreview').style.transform = `matrix(1,0,0,1,0,0)`
            //   })
            // }
          }
        }
      },
  
  
    },

  }
</script>

<style scoped>
  .component {
    width: 100%;
    height: 100%;
  }
  .mobileCamera{
    width: 100%; 
    height: 100%;
    cursor: pointer;
    border-radius: 50%;
    display:flex;
    justify-content: center;   
    align-items: center;  
    flex-direction: column;
    
  }
  .imgPreviewDiv {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    box-shadow: 0 0 15px 10px #d5d1a775; 
    overflow: hidden;
    display:flex;
    justify-content: center;   
    align-items: center;  
    flex-direction: column;
  }
  .imgPreview {
    width: 100%;
    box-shadow: 0 0 15px 10px #d5d1a775; 
  }
  .imgCamera {
    width: 80px; 
    height: 80px;
  }
  .inputFile {
    width: 1%;
    height: 1%;
    position:absolute;
    opacity: 0;
  }



    
</style>


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值