Vue中使用android和ios手机打开相机并选择相册功能和图片旋转问题

<template>

  <div>

    <input type="file" id="fileElem" accept="image/*" @change="chooseImg" ref="imgFile"/>

  //使用的vant插件

  <van-action-sheet v-model="showCameraSelect" :actions="actions" :cancel-text="'取消'" @cancel="showCameraSelect=false" />

  </div>

</template>

<script>

//cnpm下载exif-js

  import EXIF from "exif-js";

  export default {

    data() {

      return {

      actions:[],

         showCameraSelect: false

      }

    },

    created() {

       this.actions = [{

          name: '相机拍摄',

          model: 'camera'

        },

        {

          name: '选择图片',

          model: 'select'

        }

      ];

    },

     mounted() {

       //判断数组中是否包含某字符串

      Array.prototype.contains = function (needle) {

        for (i in this) {

          if (this[i].indexOf(needle) > 0)

            return i;

        }

        return -1;

      }

      var device_type = navigator.userAgent; //获取userAgent信息

      var md = new MobileDetect(device_type); //初始化mobile-detect

      var os = md.os(); //获取系统

      var model = "";

      if (os == "iOS") { //ios系统的处理

        this.$refs.imgFile.removeAttribute("capture");

      }else{

        let brand = this.phoneBrand()

        if ( brand === 'xiaomi') { // 华为、小米手机:相册选择、拍摄

          this.$refs.imgFile.setAttribute("accept","image/*");

        }else{

          this.$refs.imgFile.setAttribute("capture","user");

        }

      }

    },

    methods: {

  // 获取手机品牌

  phoneBrand() {

    let sUserAgent = navigator.userAgent.toLowerCase()

    let isIphone = sUserAgent.match(/iphone/i) == "iphone";

    let isHuawei = sUserAgent.match(/huawei/i) == "huawei";

    let isHonor = sUserAgent.match(/honor/i) == "honor";

    let isOppo = sUserAgent.match(/oppo/i) == "oppo";

    let isOppoR15 = sUserAgent.match(/pacm00/i) == "pacm00";

    let isVivo = sUserAgent.match(/vivo/i) == "vivo";

    let isXiaomi = sUserAgent.match(/mi\s/i) == "mi ";

    let isXiaomi2s = sUserAgent.match(/mix\s/i) == "mix ";

    let isRedmi = sUserAgent.match(/redmi/i) == "redmi";

    let isSamsung = sUserAgent.match(/sm-/i) == "sm-";

    if (isIphone) {

      return 'iphone';

    } else if (isHuawei || isHonor) {

      return 'huawei';

    } else if (isOppo || isOppoR15) {

      return 'oppo';

    } else if (isVivo) {

      return 'vivo';

    } else if (isXiaomi || isRedmi || isXiaomi2s) {

      return 'xiaomi';

    } else if (isSamsung) {

      return 'samsung';

    } else {

      return 'default';

    }

  }

      // 触发拍摄

      shootStart() {

        setTimeout(()=>{

          let fileElem = document.getElementById("fileElem");

          let brand = this.phoneBrand()

          if ( brand === 'xiaomi' || brand === 'huawei') { // 华为、小米手机:相册选择、拍摄

          this.$dialog.confirm({

            message: '如果您的手机不支持拍摄上传照片,请从本地相册上传',

            showCancelButton: false,

            confirmButtonText:'确定'

          }).then(() => {

            // fileElem.removeAttribute('capture');

            this.$nextTick(()=>{

              //触发点击事件

              let event = document.createEvent("MouseEvents");

              event.initEvent("click", true, true);

              document.getElementById("fileElem").dispatchEvent(event);

            })

          })

          }else { // 非小米:前置摄像头拍摄

          this.$nextTick(()=>{

            let event = document.createEvent("MouseEvents");

            event.initEvent("click", true, true);

            document.getElementById("fileElem").dispatchEvent(event);

          })

          }

        }, 100)

      },

      //选择图片/拍摄照片

      chooseImg(e) {

        let files = e.target.files || e.dataTransfer.files;

        if (!files.length) return;

    this.imgPreview(files[0]);

      },

      // 预览图片

      imgPreview(file, isRepeat) {

        let that = this;

        if (file) {

          let Orientation;

          EXIF.getData(file, function() {

            EXIF.getAllTags(this);

            Orientation = EXIF.getTag(this, 'Orientation');

            let reader = new FileReader();

            reader.readAsDataURL(file);

            reader.onload = function(ev) {

              const quality = 0.95; //图像质量

              let image = new Image();

              let canvas = document.createElement('canvas'),

                  ctx = canvas.getContext('2d');

              /* 旋转绘制 */

              let rotateImage = function(img, dir, canvas, s) {

                dir = dir || 'right';

                s = s || 1;

                let MIN_STEP = 0,

                    MAX_STEP = 3,

                    width = canvas.width || img.width,

                    height = canvas.height || img.height,

                    step = 0;

                if (dir === 'right') {

                  step += s;

                  step > MAX_STEP && (step = MIN_STEP);

                } else {

                  step -= s;

                  step < MIN_STEP && (step = MAX_STEP);

                }

                let degree = step * 90 * Math.PI / 180;

                switch (step) {

                  case 1:

                    canvas.width = height;

                    canvas.height = width;

                    ctx.rotate(degree);

                    ctx.drawImage(img, 0, -height, width, height);

                    break;

                  case 2:

                    canvas.width = width;

                    canvas.height = height;

                    ctx.rotate(degree);

                    ctx.drawImage(img, -width, -height, width, height);

                    break;

                  case 3:

                    canvas.width = height;

                    canvas.height = width;

                    ctx.rotate(degree);

                    ctx.drawImage(img, -width, 0, width, height);

                    break;

                  default:

                    canvas.width = width;

                    canvas.height = height;

                    ctx.drawImage(img, 0, 0, width, height);

                    break;

                }

              };

              /* 绘制 */

              let draw = function() {

                /* 图片原始大小 */

                let width = image.width,

                    height = image.height;

                /* 图片尺寸缩放比 800 为基数 */

                if (width > 3200 || height > 3200) {

                  width = Math.floor(width / 4);

                  height = Math.floor(height / 4);

                } else if (width > 2400 || height > 2400) {

                  width = Math.floor(width / 3);

                  height = Math.floor(height / 3);

                } else if (width > 1600 || height > 1600) {

                  width = Math.floor(width / 2);

                  height = Math.floor(height / 2);

                }

                canvas.width = width;

                canvas.height = height;

                /*canvas清屏*/

                ctx.clearRect(0, 0, canvas.width, canvas.height);

                if (Orientation && Orientation !== 1) {

                  switch (Orientation) {

                    case 6:

                      /* 顺时针旋转90度 */

                      rotateImage(image, 'right', canvas);

                      break;

                    case 8:

                      /* 逆时针旋转90度 */

                      rotateImage(image, 'left', canvas);

                      break;

                    case 3:

                      /* 顺时针旋转180度 */

                      rotateImage(image, 'right', canvas, 2);

                      break;

                    default:

                      break;

                  }

                }else {

                  ctx.drawImage(image, 0, 0, width, height);

                }

                //第一个参数为图片类型,如image/jpeg, image/png, image/gif;第二个参数为图片质量(针对image/jpeg、image/webp)

                let dataURI = canvas.toDataURL("image/jpeg", quality);

                that.validSize(file.name, dataURI);

              };

              /* 图像加载完成 */

              image.onload = function() {

                draw();

              }

              image.src = ev.target.result

            }

          });

        }

      },

    }

  }

</script>

<style scoped>

  

</style>

  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现这个功能,可以借助 CSS3 的 3D 变换和 Vue 的渲染模板来实现。 首先,我们需要一个父容器来包含所有的图片,并设置为 `perspective` 模式,以便观察者可以看到所有图像的 3D 效果。然后,我们为每个子元素(即每张图片)创建一个子容器,并应用 `transform-style: preserve-3d;` 属性来使其具有 3D 效果。 接下来,我们需要使用 Vue 的渲染模板来循环遍历所有的图片,并动态地为每个子容器应用旋转变换。这可以通过计算属性或方法来实现,具体取决于你的实现方式。 例如,以下代码演示了如何使用 Vue 和 CSS3 创建一个基本的 3D 相册效果: ```html <template> <div class="album"> <div class="album__wrapper" :style="wrapperStyles"> <div class="album__item" v-for="(item, index) in items" :key="index" :style="itemStyles(index)"> <img :src="item.src" :alt="item.alt"> </div> </div> </div> </template> <script> export default { data() { return { items: [ { src: 'image1.jpg', alt: 'Image 1' }, { src: 'image2.jpg', alt: 'Image 2' }, { src: 'image3.jpg', alt: 'Image 3' }, { src: 'image4.jpg', alt: 'Image 4' }, { src: 'image5.jpg', alt: 'Image 5' } ], currentIndex: 0 } }, computed: { wrapperStyles() { return { transform: `rotateY(${this.currentIndex * -60}deg)` } } }, methods: { itemStyles(index) { const distance = 200; const angle = index * 60; const transform = `rotateY(${angle}deg) translateZ(${distance}px)`; return { transform } } } } </script> <style scoped> .album { perspective: 1000px; height: 400px; } .album__wrapper { display: flex; height: 100%; transform-style: preserve-3d; transition: transform 0.5s ease-in-out; } .album__item { position: absolute; top: 0; left: 0; width: 400px; height: 400px; margin: 0 10px; transform-origin: center center; transition: transform 0.5s ease-in-out; } .album__item img { width: 100%; height: 100%; object-fit: cover; } </style> ``` 在这个示例,我们使用 `currentIndex` 属性来跟踪当前选定的图片,根据它来计算父容器(`.album__wrapper`)的旋转角度。我们还使用 `itemStyles()` 方法来计算每个子容器(`.album__item`)的旋转和位移变换。最后,我们使用 CSS 样式来定义每个元素在 3D 空间的位置和动画效果。 你可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值