精华内容
下载资源
问答
  • 此组件在电脑界面测试时,会出现时灵时不灵的情况,但在手机上使用时无此情况发生。 组件中使用了BASE64编码 后台需要BASE64解码 <template> <div id="imgUploader"> <div class="fi

    由于作者并非专业前台开发人员,是一位后端开发者,组件也是与我们前台人员查询资料合并的;由于时间过长已也没保存那些资料博客,如有不妥处请联系我;QQ:1836302994 。

    这是作者开发的时候遇到的问题,希望可以帮到你。此组件在电脑界面测试时,会出现时灵时不灵的情况,但在手机上使用时无此情况发生。

    组件中使用了BASE64编码 后台需要BASE64解码
    在这里插入图片描述

    <template>
    
        <div id="imgUploader">
    
            <div class="file-list">
    
              <!-- <section class="file-item draggable-item" v-for="(item,index) in files" :key="index"> -->
    
                <div class="thumbnails my-gallery">
    
                    <figure itemprop="associatedMedia" itemscope  class="thumbnail" v-for="(item,index) in files" :key="index">
    
                        <a :href="item.src" itemprop="contentUrl" data-size="400x400" class="img-wrapper">
    
                            <img :src="item.src" itemprop="thumbnail"  />
    
                            <!-- <div :style="{background:'url('+item.src+')  no-repeat',  backgroundPosition:'center center',backgroundSize:'cover'}" style="width:100%;height:110px;" itemprop="thumbnail"></div> -->
    
                        </a>
    
                        <span class="file-remove" @click="remove(index,$event)">×</span>
    
                    </figure>
    
                    <section class="thumbnail" v-if="this.files.length < 9">
    
                      <div class="add">
    
                        <span>+</span>
    
                        <!-- accept="image/jpeg,image/png" capture="camera" -->
    
                        <input type="file" @change="selectImgs()" multiple accept="image/*" ref="file">
    
                      </div>
    
                    </section>
    
                </div>
    
                <!-- <img :src="item.src" alt="" ondragstart="return false;">
    
                <span class="file-remove" @click="remove(index)">×</span> -->
    
              <!-- </section> -->
    
              <!-- PhotoSwipe插件需要的元素, 一定要有类名 pswp -->
    
              <div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    
                  <div class="pswp__bg"></div>
    
                  <div class="pswp__scroll-wrap">
    
                      <div class="pswp__container">
    
                          <div class="pswp__item"></div>
    
                          <div class="pswp__item"></div>
    
                          <div class="pswp__item"></div>
    
                      </div>
    
                      <!-- 预览区域顶部的默认UI,可以修改 -->
    
                      <div class="pswp__ui pswp__ui--hidden">
    
                          <div class="pswp__top-bar">
    
                              <!--  与图片相关的操作 -->
    
                              <div class="pswp__counter"></div>
    
                              <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
    
                              <!--将分享按钮去掉 -->
    
                              <!-- <button class="pswp__button pswp__button--share" title="Share"></button>
    
                              <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
    
                              <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button> -->
    
                              <div class="pswp__preloader">
    
                                  <div class="pswp__preloader__icn">
    
                                      <div class="pswp__preloader__cut">
    
                                          <div class="pswp__preloader__donut"></div>
    
                                      </div>
    
                                  </div>
    
                              </div>
    
                          </div>
    
                          <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
    
                              <div class="pswp__share-tooltip"></div>
    
                          </div>
    
                          <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"></button>
    
                          <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button>
    
                          <div class="pswp__caption">
    
                              <div class="pswp__caption__center"></div>
    
                          </div>
    
                      </div>
    
                  </div>
    
              </div>
    
            </div>
    
        </div>
    
    </template>
    
    <script>
    
    import PhotoSwipe from "photoswipe";
    
    import PhotoSwipeUI_Default from "photoswipe/dist/photoswipe-ui-default";
    
    import "photoswipe/dist/photoswipe.css";
    
    import "photoswipe/dist/default-skin/default-skin.css";
    
    import { Toast } from "mint-ui";
    
    export default {
    
      name:'upload-box',
    
      data() {
    
        return {
    
          // lang: this.$lang("dynamic"),
    
          files: [], // 文件缓存
    
          index: 0, // 序列号
    
          maxLength: 9, // 图片最大数量
    
          maxSize: 10240000 //图片限制为10M内
    
        };
    
      },
    
      methods: {
    
        //选择图片
    
        selectImgs() {
    
          let fileList = this.$refs.file.files;
    
          if (fileList.length > 9) {
    
            alert(this.lang.dynamic_upload_tips);
    
          }
    
          let tempList = []; //每次点击+号后选择的图片信息
    
          for (let i = 0, len = fileList.length; i < len; i++) {
    
            let fileItem = {
    
              Id: this.index++,
    
              name: fileList[i].name,
    
              size: fileList[i].size,
    
              file: fileList[i]
    
            };
    
            //将图片文件转成Base64
    
            let reader = new FileReader();
    
            reader.onloadend = e => {
    
              this.getBase64(e.target.result).then(url => {
    
                this.$set(fileItem, "src", url);
    
              });
    
            };
    
            if (fileItem.size > this.maxSize) {
    
              Toast(this.lang.dynamic_over_size);
    
            } else {
    
              reader.readAsDataURL(fileList[i]);
    
              tempList.push(fileItem);
    
              this.files.push(fileItem);
    
            }
    
          }
    
          setTimeout(() => {
    
            this.$emit("getFiles", tempList);
    
          }, 300);
    
          this.files.splice(9);
    
        },
    
        // 图片压缩并保存到files
    
        getBase64(url) {
    
          let self = this;
    
          let Img = new Image(),
    
            dataURL = "";
    
          Img.src = url;
    
          let p = new Promise(function(resolve, reject) {
    
            Img.onload = function() {
    
              //要先确保图片完整获取到,这是个异步事件
    
              let canvas = document.createElement("canvas"), //创建canvas元素
    
                width = Img.width, //确保canvas的尺寸和图片一样
    
                height = Img.height;
    
              // 默认将长宽设置为图片的原始长宽,这样在长宽不超过最大长度时就不需要再处理
    
              let ratio = width / height,
    
                maxLength = 1000,
    
                newHeight = height,
    
                newWidth = width;
    
              // 在长宽超过最大长度时,按图片长宽比例等比缩小
    
              if (width > maxLength || height > maxLength) {
    
                if (width > height) {
    
                  newWidth = maxLength;
    
                  newHeight = maxLength / ratio;
    
                } else {
    
                  newWidth = maxLength * ratio;
    
                  newHeight = maxLength;
    
                }
    
              }
    
              canvas.width = newWidth;
    
              canvas.height = newHeight;
    
              canvas.getContext("2d").drawImage(Img, 0, 0, newWidth, newHeight); //将图片绘制到canvas中
    
              dataURL = canvas.toDataURL("image/jpeg", 0.5); //转换图片为dataURL
    
              resolve(dataURL);
    
            };
    
          });
    
          return p;
    
        },
    
        // 移除图片
    
        remove(index, e) {
    
          e.stopPropagation(); //阻止
    
          this.files.splice(index, 1);
    
          setTimeout(() => {
    
            this.$emit("removeFiles", index);
    
          }, 300);
    
        },
    
        //引入photoSwipe(可预览、滑动)
    
        initPhotoSwipeFromDOM(gallerySelector) {
    
          var parseThumbnailElements = function(el) {
    
            var thumbElements = el.childNodes,
    
              numNodes = thumbElements.length,
    
              items = [],
    
              figureEl,
    
              linkEl,
    
              size,
    
              item;
    
            for (var i = 0; i < numNodes - 1; i++) {
    
              figureEl = thumbElements[i];
    
              if (figureEl.nodeType !== 1) {
    
                continue;
    
              }
    
              linkEl = figureEl.children[0];
    
              var img = new Image();
    
              img.src = linkEl.getAttribute("href");
    
              linkEl.setAttribute(
    
                "data-size",
    
                img.naturalWidth + "x" + img.naturalHeight
    
              );
    
              size = linkEl.getAttribute("data-size").split("x");
    
              item = {
    
                src: linkEl.getAttribute("href"),
    
                w: parseInt(size[0], 10),
    
                h: parseInt(size[1], 10)
    
              };
    
              if (figureEl.children.length > 1) {
    
                item.title = figureEl.children[1].innerHTML;
    
              }
    
              if (linkEl.children.length > 0) {
    
                item.msrc = linkEl.children[0].getAttribute("src");
    
              }
    
              item.el = figureEl;
    
              items.push(item);
    
            }
    
            return items;
    
          };
    
          var closest = function closest(el, fn) {
    
            return el && (fn(el) ? el : closest(el.parentNode, fn));
    
          };
    
          var onThumbnailsClick = function(e) {
    
            e = e || window.event;
    
            // e.preventDefault ? e.preventDefault() : (e.returnValue = false);
    
            var eTarget = e.target || e.srcElement;
    
            var clickedListItem = closest(eTarget, function(el, e) {
    
              return el.tagName && el.tagName.toUpperCase() === "FIGURE";
    
            });
    
            if (!clickedListItem) {
    
              return;
    
            }
    
            var clickedGallery = clickedListItem.parentNode,
    
              childNodes = clickedListItem.parentNode.childNodes,
    
              numChildNodes = childNodes.length,
    
              nodeIndex = 0,
    
              index;
    
            for (var i = 0; i < numChildNodes; i++) {
    
              if (childNodes[i].nodeType !== 1) {
    
                continue;
    
              }
    
              if (childNodes[i] === clickedListItem) {
    
                index = nodeIndex;
    
                break;
    
              }
    
              nodeIndex++;
    
            }
    
            if (index >= 0) {
    
              openPhotoSwipe(index, clickedGallery);
    
            }
    
            return false;
    
          };
    
          var photoswipeParseHash = function() {
    
            var hash = window.location.hash.substring(1),
    
              params = {};
    
            if (hash.length < 5) {
    
              return params;
    
            }
    
            var vars = hash.split("&");
    
            for (var i = 0; i < vars.length; i++) {
    
              if (!vars[i]) {
    
                continue;
    
              }
    
              var pair = vars[i].split("=");
    
              if (pair.length < 2) {
    
                continue;
    
              }
    
              params[pair[0]] = pair[1];
    
            }
    
            if (params.gid) {
    
              params.gid = parseInt(params.gid, 10);
    
            }
    
            return params;
    
          };
    
          var openPhotoSwipe = function(
    
            index,
    
            galleryElement,
    
            disableAnimation,
    
            fromURL
    
          ) {
    
            var pswpElement = document.querySelectorAll(".pswp")[0],
    
              gallery,
    
              options,
    
              items;
    
            items = parseThumbnailElements(galleryElement);
    
            options = {
    
              history: false,
    
              tapToClose: true,
    
              galleryUID: galleryElement.getAttribute("data-pswp-uid"),
    
              getThumbBoundsFn: function(index) {
    
                var thumbnail = items[index].el.getElementsByTagName("img")[0],
    
                  pageYScroll =
    
                    window.pageYOffset || document.documentElement.scrollTop,
    
                  rect = thumbnail.getBoundingClientRect();
    
                return { x: rect.left, y: rect.top + pageYScroll, w: rect.width };
    
              }
    
            };
    
            if (fromURL) {
    
              if (options.galleryPIDs) {
    
                for (var j = 0; j < items.length; j++) {
    
                  if (items[j].pid == index) {
    
                    options.index = j;
    
                    break;
    
                  }
    
                }
    
              } else {
    
                options.index = parseInt(index, 10) - 1;
    
              }
    
            } else {
    
              options.index = parseInt(index, 10);
    
            }
    
            if (isNaN(options.index)) {
    
              return "";
    
            }
    
            if (disableAnimation) {
    
              options.showAnimationDuration = 0;
    
            }
    
            gallery = new PhotoSwipe(
    
              pswpElement,
    
              PhotoSwipeUI_Default,
    
              items,
    
              options
    
            );
    
            gallery.init();
    
          };
    
          var galleryElements = document.querySelectorAll(gallerySelector);
    
          for (var i = 0, l = galleryElements.length; i < l; i++) {
    
            galleryElements[i].setAttribute("data-pswp-uid", i + 1);
    
            galleryElements[i].onclick = onThumbnailsClick;
    
          }
    
          var hashData = photoswipeParseHash();
    
          if (hashData.pid && hashData.gid) {
    
            openPhotoSwipe(
    
              hashData.pid,
    
              galleryElements[hashData.gid - 1],
    
              true,
    
              true
    
            );
    
          }
    
        }
    
      },
    
      mounted() {
    
        this.initPhotoSwipeFromDOM(".my-gallery");
    
      }
    
    };
    
    </script>
    
    <style lang="scss" scoped>
    
    #imgUploader {
    
      flex: 1;
    
      margin-top: auto;
    
      padding-left: 10px;
    
      .file-list {
    
        padding: 10px 0px;
    
        &::after {
    
          content: "";
    
          display: block;
    
          clear: both;
    
          visibility: hidden;
    
          line-height: 0;
    
          height: 0;
    
          font-size: 0;
    
        }
    
        .file-remove {
    
          position: absolute;
    
          font-size: 12px;
    
          right: 5px;
    
          top: 1px;
    
          width: 14px;
    
          height: 14px;
    
          color: white;
    
          cursor: pointer;
    
          line-height: 12px;
    
          background: rgba(0, 0, 0, 0.25);
    
          z-index: 1000;
    
        }
    
        &:hover .file-remove {
    
          display: inline;
    
        }
    
      }
    
    }
    
    .add {
    
      width: 100%;
    
      height: 110px;
    
      float: left;
    
      text-align: center;
    
      line-height: 110px;
    
      // font-size: 1.4rem;
    
      font-weight: 100;
    
      cursor: pointer;
    
      border: 1px dashed #ccc;
    
      color: #999;
    
      position: relative;
    
      // background: #f2f2f2;
    
      @media screen and(min-width:768px) and(max-width:1024px) {
    
        height: 180px;
    
        line-height: 180px;
    
        font-size: 56px;
    
      }
    
      .fa {
    
        font-size: 1.4em;
    
        color: #7dd2d9;
    
      }
    
    }
    
    .uploadBtn {
    
      position: relative;
    
      .empty {
    
        position: absolute;
    
        right: 0;
    
        bottom: 0;
    
        background-color: #eee;
    
        color: #fff;
    
        padding: 0.2em 1em;
    
      }
    
    }
    
    .thumbnails {
    
      width: 100%;
    
      display: -webkit-box;
    
      display: -webkit-flex;
    
      display: -ms-flexbox;
    
      display: flex;
    
      -webkit-flex-wrap: wrap;
    
      -ms-flex-wrap: wrap;
    
      flex-wrap: wrap;
    
      .thumbnail {
    
        position: relative;
    
        margin: 0 0 10px 0;
    
        padding-right: 5px;
    
        width: 33%;
    
        box-sizing: border-box;
    
        height: 110px;
    
        @media screen and(min-width:768px) and(max-width:1024px) {
    
          height: 180px;
    
        }
    
        // &:nth-child(3n){
    
        //  padding-right: 0;
    
        // }
    
        .img-wrapper {
    
          position: relative;
    
          display: flex;
    
          height: 110px;
    
          @media screen and(min-width:768px) and(max-width:1024px) {
    
            height: 180px;
    
          }
    
          img {
    
            width: auto;
    
            height: auto;
    
            width: 100%;
    
            max-width: 100%;
    
            max-height: 100%;
    
          }
    
        }
    
      }
    
    }
    
    input[type="file"] {
    
      position: absolute;
    
      left: 0;
    
      top: 0;
    
      width: 100%;
    
      height: 110px;
    
      opacity: 0;
    
    }
    
    </style>
    
    展开全文
  • vue 图片裁剪上传

    千次阅读 2018-11-08 11:48:44
    最近写的一个项目用到头像上传,需要裁剪功能,缩放功能,能具备压缩上传功能,因为手机现在的像素太好了,随便一张图片的大小都上M了,而且要求手机端和pc端都可要可以使用。通过网上找到了一个合适的插件(vue-...

    最近写的一个项目用到头像上传,需要裁剪功能,缩放功能,能具备压缩上传功能,因为手机现在的像素太好了,随便一张图片的大小都上M了,而且要求手机端和pc端都可要可以使用。通过网上找到了一个合适的插件(vue-croppa)。

    先上几张图片看一下效果:

    点击更换头像后:

    截取的大小和形状,背景颜色,base64编码,缩放级别,均可以设置更改(具体参数可以参考npm网址:https://www.npmjs.com/package/vue-croppa

    这里我加了一些按钮和样式,点击完成的时候进行图片上传到服务器。

    附上代码:

    组件内使引入插件和样式

    import Vue from 'vue'
    import Croppa from 'vue-croppa'
    import 'vue-croppa/dist/vue-croppa.css'

    放置组件(这里只放了一些我用到的参数,全部参数参考官网):

    <croppa
              v-model="croppa"
              :width="250"
              :height="250"
              :placeholder-font-size="16"
              :accept="'image/*'"
              prevent-white-space
              :initial-image=dataUrl
              @init="onInit"
            ></croppa>

    methods:

    onInit () {
          this.croppa.addClipPlugin(function (ctx, x, y, w, h) {
            ctx.beginPath()
            ctx.arc(x + w / 2, y + h / 2, w / 2, 0, 2 * Math.PI, true)
            ctx.closePath()
          })
        }

    涉及到上传的问题,因为默认转化的是base64编码,但是图片过大的话,base64会很长,存取都不是很方便。还是用blob二进制存取更为合理和方便。函数如下:

     upLoad () {
          this.croppa.generateBlob(blob => {
            var formData = new FormData()
            var self = this
            formData.append('file', blob, 'png')
            this.showProgress = true
            this.axios({
              url: api.upload,
              method: 'post',
              data: formData
            }).then(res => {
              self.progressVal = 100
              self.showProgress = false
              self.showCroppa = false
              self.dataUrl = res.data.url
            })
          }, 'image/png', 0.1)
        },

     

     

    展开全文
  • 本文实例为大家分享了vue实现图片上传预览的具体代码,供大家参考,具体内容如下 ...--点击上传按钮--> !(!item.isNew&&editBtnType[index]) click=houseUpload(index)> <span class=iconfont></span> <h5
  • vue 拍照上传

    千次阅读 2018-11-27 11:49:07
    vue 拍照上传 涉及技术点 canvas裁剪 base64 blob数据装换 forData 数据传递 ,还有hammer.js和exif-js具体代码如下 &amp;lt;template&amp;gt; &amp;lt;div class=&quot;pic&quot;&amp;...

    vue 拍照上传 涉及技术点 canvas裁剪 base64 blob数据装换 forData 数据传递 ,还有hammer.js和exif-js具体代码如下

    <template>
        <div class="pic">
            <div class="bg-box">
                <div class="img-box">
                    <img src="../../assets/img/news_bg.png" width="100%" alt="">
                </div>
                <div class="headers">
                        <van-nav-bar title="个人信息" @click-left="onClickLeft" >
                            <img class="img" src="../..//assets/img/back@2x.png" slot="left" alt="">
                        </van-nav-bar>
                </div>           
            </div>
            <form enctype="multipart/form-data" >
              <div class="uploadBox">
                  <!--主编辑器canvas-->
                  <canvas id="canvas" :width="windowWidth" :height="windowWidth"></canvas>
                  <!--蒙层canvas-->
                  <canvas id="canvasMask" :width="windowWidth" :height="windowWidth"></canvas>
                  <!--用于导出图片的canvas-->
                  <canvas id="resultImg" width="160" height="160" style="display: none"></canvas>
                  <label class="uploadBar" for="uploadInput" v-if="uploadBarShow">
                      <input type="file"
                            style="display: none"
                            id="uploadInput"
                            accept="image/*"
                            ref="file"
                            @change="upLoadChange">
                      <span>点击上传</span>
                      
                  </label>
              </div>
              <!-- <img :src="src" v-if="src"/> -->
              <div class="select-box" v-if="!uploadBarShow">
                <!-- <input type="submit"  class="sure-bt"  @click="crop" value="确定裁切"> -->
                <div class="sure-bt"  @click="crop" >确定裁切</div>
                <div class="cancel-bt"  @click="cancel">取消</div>
              </div>
            </form>
            
        </div>
    </template>
    
    <script>
    import {Toast} from "vant";
    import axios from "axios";
    import { dataURItoBlob } from "../../assets/js/blob.js"
    import { mapMutations } from "vuex";
    require("@/assets/plugin/hammer.min"); //引入hammerJS
    import qs from "qs"
    import EXIF from "exif-js";
    
    export default {
      name: "home",
      data() {
        return {
          src: "",
          orientation: null, //图片元信息
          degree: 0, //原图片旋转角度
          windowWidth: 0, //屏幕的宽度
          imgEl: null,
          imgWidth: 0, //图片的宽度
          imgHeight: 0, //图片的高度
          transWidth: 0, //改变后的图片宽度
          transHeight: 0, //改变后的图片高度
          initScale: 0,
          transformScale: 1, //初始缩放
          prevX: 0, //上一次的X轴
          prevY: 0, //上一次的Y轴
          translateX: 0, //平移X轴
          translateY: 0, //平移Y轴
          uploadBarShow: true, //上传按钮显示
          canvas: null, //canvas
          canvasMask: null, //canvas-mask
          canvasResult: null, //裁切图片canvas
          eq_types : "iOS"
        };
      },
      methods: {
        ...mapMutations([
          'header_pic_update'
        ]),
        onClickLeft() {
          this.$router.go(-1);
        },
        cancel() {
          this.$router.go(-1);
        },
        /**
         * 上传图片
         * */
        upLoadChange() {
          
          let files = this.$refs.file.files[0],
            
            self = this;
            let val = this.$refs.file.value; 
            // console.log("文件是:",files);
            // console.log("文件是:",val);
            
           
          /*控制图片上传大小不超过1MB*/
          if (files.size > 8388608) {
            alert("图片不能超过1MB大小");
            return false;
          }
    
          /*用EXIF获取图片元信息*/
          EXIF.getData(files, function() {
            self.orientation = EXIF.getTag(this, "Orientation");
          });
    
          let fr = new FileReader();
    
          // 监听reader对象的的onload事件,当图片加载完成时,把base64编码賦值给预览图片
          fr.addEventListener(
            "load",
            () => {
              if (this.orientation) {
                /*需要对ios做一下兼容*/
                this.getImgData(fr.result, this.orientation, data => {
                  this.createCanvas(data); //初始化canvas
                });
              } else {
                this.createCanvas(fr.result); //初始化canvas
              }
            },
            false
          );
          fr.readAsDataURL(files);
        },
    
        /**
         * 初始化canvas
         * */
        createCanvas(imgBase64) {
          this.imgEl = new Image();
          this.imgEl.src = imgBase64;
    
          this.imgEl.onload = () => {
            this.imgWidth = this.imgEl.width; //初始化图片的宽
            this.imgHeight = this.imgEl.height; //初始化图片的高
    
            // 画蒙层
            this.canvasMask.globalCompositeOperation = "source-out";
            this.canvasMask.fillStyle = "rgb(255,255,255)";
            this.canvasMask.arc(
              this.windowWidth / 2,
              this.windowWidth / 2,
              80,
              0,
              2 * Math.PI
            );
            this.canvasMask.fill();
            this.canvasMask.fillStyle = "rgba(0,0,0,0.7)";
            this.canvasMask.fillRect(0, 0, this.windowWidth, this.windowWidth);
    
            // 当图片比canvas小时不做任何改变
            if (
              this.imgEl.width < this.windowWidth &&
              this.imgEl.height < this.windowWidth
            ) {
              this.imgWidth = this.imgEl.width;
              this.imgHeight = this.imgEl.height;
            } else {
              //原图片宽高比例 大于 图片框宽高比例
              if (1 <= this.imgEl.width / this.imgEl.height) {
                this.imgWidth = this.windowWidth; //以框的宽度为标准
                this.imgHeight =
                  this.windowWidth * (this.imgEl.height / this.imgEl.width);
              } else {
                //原图片宽高比例 小于 图片框宽高比例
                this.imgWidth =
                  this.windowWidth * (this.imgEl.width / this.imgEl.height);
                this.imgHeight = this.windowWidth; //以框的高度为标准
              }
            }
    
            this.canvas.translate(this.windowWidth / 2, this.windowWidth / 2); //把canvas原点移动到中心位置
            this.canvas.drawImage(
              this.imgEl,
              0 - this.imgWidth / 2,
              0 - this.imgHeight / 2,
              this.imgWidth,
              this.imgHeight
            );
    
            /*初始化hammer*/
            this.initHammer();
          };
        },
    
        /**
         * @param {string} img 图片的base64
         * @param {int} dir exif获取的方向信息
         * @param {function} next 回调方法,返回校正方向后的base64
         * */
        getImgData(img, dir, next) {
          let image = new Image();
          image.src = img;
    
          image.onload = function() {
            let degree = 0,
              drawWidth,
              drawHeight,
              width,
              height;
            drawWidth = image.naturalWidth; //暂存图片的宽
            drawHeight = image.naturalHeight; //暂存图片的高
    
            //以下改变一下图片大小
            let maxSide = Math.max(drawWidth, drawHeight);
            console.log(maxSide);
            if (maxSide > 4032) {
              let minSide = Math.min(drawWidth, drawHeight);
              minSide = minSide / maxSide * 4032;
              maxSide = 4032;
              if (drawWidth > drawHeight) {
                drawWidth = maxSide;
                drawHeight = minSide;
              } else {
                drawWidth = minSide;
                drawHeight = maxSide;
              }
            }
    
            let canvas = document.createElement("canvas");
            canvas.width = width = drawWidth;
            canvas.height = height = drawHeight;
            let context = canvas.getContext("2d");
            //判断图片方向,重置canvas大小,确定旋转角度,iphone默认的是home键在右方的横屏拍摄方式
            switch (dir) {
              //iphone横屏拍摄,此时home键在左侧
              case 3:
                degree = 180;
                drawWidth = -width;
                drawHeight = -height;
                break;
    
              //iphone竖屏拍摄,此时home键在下方(正常拿手机的方向)
              case 6:
                canvas.width = height;
                canvas.height = width;
                degree = 90;
                drawWidth = width;
                drawHeight = -height;
                break;
    
              //iphone竖屏拍摄,此时home键在上方
              case 8:
                canvas.width = height;
                canvas.height = width;
                degree = 270;
                drawWidth = -width;
                drawHeight = height;
                break;
            }
    
            //使用canvas旋转校正
            context.rotate(degree * Math.PI / 180);
            context.drawImage(this, 0, 0, drawWidth, drawHeight);
    
            //返回校正图片
            next(canvas.toDataURL("image/jpeg"));
          };
        },
    
        /**
         * 初始化hammer
         * */
        initHammer() {
          //隐藏上传bar
          this.uploadBarShow = false;
    
          let hammer = new Hammer(document.querySelector("#canvasMask"));
          hammer.get("pinch").set({ enable: true });
          hammer.get("rotate").set({ enable: true });
    
          /*缩放 */
          hammer.on("pinchmove pinchstart pinchin pinchout", e => {
            if (e.type === "pinchstart") {
              this.initScale = this.transformScale || 1;
            }
            this.transformScale = this.initScale * e.scale;
            this.canvas.clearRect(
              0 - this.windowWidth / 2,
              0 - this.windowWidth / 2,
              this.windowWidth,
              this.windowWidth
            );
            this.transWidth = this.imgWidth * this.transformScale;
            this.transHeight = this.imgHeight * this.transformScale;
            this.canvas.drawImage(
              this.imgEl,
              this.translateX - this.transWidth / 2,
              this.translateY - this.transHeight / 2,
              this.transWidth,
              this.transHeight
            );
          });
    
          /*平移*/
          hammer.on("panstart panmove", e => {
            if (e.type === "panstart") {
              this.prevX = this.translateX;
              this.prevY = this.translateY;
            }
            this.translateX = this.prevX + e.deltaX;
            this.translateY = this.prevY + e.deltaY;
    
            /*擦除canvas*/
            this.canvas.clearRect(
              0 - this.windowWidth / 2,
              0 - this.windowWidth / 2,
              this.windowWidth,
              this.windowWidth
            );
            this.canvas.drawImage(
              this.imgEl,
              this.translateX - (this.transWidth || this.imgWidth) / 2,
              this.translateY - (this.transHeight || this.imgHeight) / 2,
              this.transWidth || this.imgWidth,
              this.transHeight || this.imgHeight
            );
          });
        },
    
        /**
         * 裁切
         * */
        crop() {
          let base64 = document.querySelector("#canvas").toDataURL("image/png");
          let nImg = new Image();
          nImg.src = base64;
    
          nImg.onload = () => {
            this.canvasResult.fillStyle = "white";
            this.canvasResult.fillRect(0, 0, 160, 160);
            this.canvasResult.drawImage(
              nImg,
              -(this.windowWidth / 2 - 80),
              -(this.windowWidth / 2 - 80)
            );
            /*最后导出裁切好的图片为base64码*/
            //**将base64传给后台 */
            this.src = document.querySelector("#resultImg").toDataURL("image/jpeg");
            // 将base64转成blob
            let upload_imgs = dataURItoBlob(this.src)
            console.log(upload_imgs, "base64:-->"+this.src);
            
            let formData = new FormData();
            formData.append('action', "edit_user_pic");
            formData.append('files', upload_imgs, 'image.jpeg');
            //有些苹果不支持get方法
            // console.log(formData);
            // console.log(formData.get('action'));
            // console.log(formData.get('files'));
             
            //添加请求头
            axios({
                  headers: {
                      'Content-Type':'multipart/form-data'
                  },
                  method: 'post',
                  url: '/api/fileApi',
                  data: formData
            })
            .then(res =>{
              console.log(res);
              if(res._code !== "99999"){
                Toast({
                  message : res._msg,
                  duration : 2500
                });
                return;
              };
              this.header_pic_update(res._result.userPic);
              this.$router.go(-1);
    
              
            })
    
            
          };
        }
      },
      mounted() {
        let canvas = document.querySelector("#canvas"),
          canvasMask = document.querySelector("#canvasMask"),
          canvasRsut = document.querySelector("#resultImg");
        this.canvas = canvas.getContext("2d");
        this.canvasMask = canvasMask.getContext("2d");
        this.canvasResult = canvasRsut.getContext("2d");
        this.windowWidth = window.innerWidth;
      },
      created(){
            let u = navigator.userAgent;
            if (u.indexOf("Android") > -1 || u.indexOf("Linux") > -1) {
              //安卓手机
              this.eq_types = "android";
            } else if (u.indexOf("iPhone") > -1) {
              //苹果手机
              this.eq_types = "iOS";
            } else if (u.indexOf("Windows Phone") > -1) {
              //winphone手机
            }
      }
    };
    </script>
    
    <style lang="less" scoped>
    .pic {
      position: relative;
      height: 100vh;
      .bg-box {
        position: relative;
        height: 139px;
        .img-box {
          position: absolute;
          top: 0;
          left: 0;
          z-index: -5;
          width: 100%;
        }
        .headers {
          padding-top: 57px;
          margin: 0 44px;
          /deep/ .van-hairline--bottom {
            background: transparent;
            color: #fff;
            height: 55px;
            line-height: 55px;
          }
          /deep/ .van-nav-bar__left {
            top: 0;
          }
          /deep/ .van-nav-bar__title {
            font-size: 36px;
          }
          /deep/ .van-hairline--bottom::after {
            border: none;
          }
          .img {
            width: 55px;
            height: 55px;
          }
        }
      }
    }
    
    * {
      padding: 0;
      margin: 0;
    }
    
    .uploadBox {
      position: relative;
    }
    
    #canvasMask {
      position: absolute;
      left: 0;
      top: 0;
      z-index: 5;
    }
    
    .uploadBar {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 20vw;
      height: 20vw;
      border: 1px dashed gray;
      text-align: center;
      line-height: 20vw;
      font-size: 15px;
      color: gray;
      display: block;
      z-index: 10;
    }
    .select-box {
      height: 100px;
      margin: 20px 30px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      color: #fff;
      font-size: 36px;
      .sure-bt {
        width: 200px;
        height: 80px;
        line-height: 80px;
        border-radius: 10px;
        background: #44bb00;
      }
      .cancel-bt {
        width: 200px;
        height: 80px;
        line-height: 80px;
        border-radius: 10px;
        background: #ff976a;
      }
    }
    </style>
    
    

    blob代码如下

    
    
    export const dataURItoBlob = function (base64Data) {
        var byteString;
        if (base64Data.split(',')[0].indexOf('base64') >= 0)
            byteString = atob(base64Data.split(',')[1]);
        else
            // byteString = unescape(base64Data.split(',')[1]);
            byteString = decodeURI(base64Data.split(',')[1]);
        var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
        var ia = new Uint8Array(byteString.length);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }
        return new Blob([ia], {type: mimeString});
    }
    
    

    这样就可以实现拍照上传:
    注意:
    在验证数据是否append到fordata中,用formData.get(‘action’),部分ios不兼容这个方法要注释掉
    如果是放在自己app种webView中安卓app需要对其做支持否则input可能无法触发,H5浏览器则完全适用

    展开全文
  • input 里的type=file还真能调起手机的相册功能 还比微信的接口方便,真是被恶心到了。   这里用的vue.js开发的前端   &lt;div style="margin-top: -6%; float: right;"&gt; &lt;!-- ...

    在网上搜了搜发现<input 里的type=file还真能调起手机的相册功能  还比微信的接口方便,真是被恶心到了。

     

    这里用的vue.js开发的前端

     

    <div style="margin-top: -6%; float: right;">
        <!-- 选择图片 -->
        <v-btn color="blue" depressed style="color:#FFFFFF;font-size:8px;width:15%;border-radius: 7px;position: absolute;left:72%;top:14%;float: right">点击上传</v-btn>
        <input style="position: absolute;left:76%;top:30%;opacity:0;float: right;" id="inp" type="file"
               accept="image/*"
               @change="chooseImg" />
        <!-- 预览图片 -->
        <canvas style="position: absolute;left:56%;top:12%;" ref="imgPreview"
                height="0"
                width="0"></canvas>
        <!-- 提交图片 -->
        <!--<button @click="uploadImg">提交图片</button>-->
        <!-- 通过后台返回的url向文件服务器请求图片 -->
        <img :src="imgUrlFromServer">
    </div>

    这是在网上co来的上传图片   挺好用的   选择后的预览都在里面

     

     

    chooseImg (event) {
                let file = event.target.files[0]
                //console.log(file);
                let reader = new FileReader()
                let img = new Image()
                // 读取图片
                if(file == null || file == ''){
                	console.log("gg");
                }
                reader.readAsDataURL(file)
                // 读取完毕后的操作
                reader.onloadend = (e) => {
                    img.src = e.target.result
                    // 这里的e.target就是reader
                    // console.log(reader.result)
                    // reader.result就是图片的base64字符串
                    this.base64 = reader.result
                    console.log(this.base64);
                }
                // 预览图片
                let canvas = this.$refs['imgPreview']
                let context = canvas.getContext('2d')
                img.onload = () => {
                    img.width = 100
                    img.height = 100
                    // 设置canvas大小
                    canvas.width = 100
                    canvas.height = 100
                    // 清空canvas
                    context.clearRect(0, 0, 100, 50)
                    // 画图
                    context.drawImage(img, 0, 0, 50, 50)
                }
            },
    
    

     

     

    依然是co来的js代码0.0

    这里直接把图片的base64码放到了参数里,可以直接传给后台解析。

    this.getClass().getResource("").getPath();

    这样获取到当前路径然后慢慢 getParent(); 获取到图片文件夹

    我后台就是直接拿到base64码解码成byte数组   然后用io流传到服务器的某个目录下存起来   数据库里存储的是图片名+.格式

    值得注意的是base64码前面会带一些没必要的编码

    当我们上传图片的.png的时候是base64:png什么什么的

    上传.jpg文件则会带有jpeg   上传图片不需要前面这一串字符   需要截取

    if(imgbase64.substring(11,15).equals("jpeg")) {
    			imgbase = imgbase64.substring(23, imgbase64.length());
    		}else {
    			imgbase = imgbase64.substring(22, imgbase64.length());
    		}

     

    之后调用Base64解码工具类解码完成图片上传

    附上解码工具类

     

    package addaoil.support.utils;
    
    import java.io.FileOutputStream;
    
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    import java.io.OutputStream;
    
    public class Base64 {
    	//base64字符串转化成图片  
        public static boolean GenerateImage(String imgStr,String imgurl)  
        {   //对字节数组字符串进行Base64解码并生成图片  
            if (imgStr == null) { //图像数据为空  
                return false;  
            }
            BASE64Decoder decoder = new BASE64Decoder();
            try   
            {  
                //Base64解码  
                byte[] b = decoder.decodeBuffer(imgStr);  
                for(int i=0;i<b.length;++i)  
                {  
                    if(b[i]<0)  
                    {//调整异常数据  
                        b[i]+=256;  
                    }  
                }  
                //生成jpeg图片  
                String imgFilePath = imgurl;//新生成的图片  
                OutputStream out = new FileOutputStream(imgFilePath);      
                out.write(b);  
                out.flush();  
                out.close();  
                return true;  
            }   
            catch (Exception e)   
            {  
                return false;  
            }  
        }  
    }
    

     

     

    BASE64Decoder用不了的话可以百度搜一下。

     

     

     

     

    img.onload = () => {
                	img2.width = 1000
                    //img2.height = 1000
                    let canvas2 = this.$refs['imgPreview']
                	let context2 = canvas.getContext('2d')
                    canvas2.width = 1000;
    		        canvas2.height = canvas.width * (1000 / img2.width);
    
    		        console.log(this.base64.length);
    		        //this.base64 = this.base64.split(',')[1];
    		        
                    img.width = 100
                    img.height = 100
                    // 设置canvas大小
                    canvas.width = 1000
                    canvas.height = 1000
                    
                    // 清空canvas
                    context.clearRect(0, 0, 100, 50)
                    // 画图
                    context.drawImage(img, 0, 0, 1000, 1000)
                    this.base64 = canvas.toDataURL("image/jpeg", 1.0); // 这里就拿到了压缩后的base64图片
                    canvas.width = 100
                    canvas.height = 100
                    context.drawImage(img, 0, 0, 50, 50)
                    console.log(this.base64.length);
                }

     图片太大base64码几千万长度的字符串POST都传不了   然后做了个图片压缩   目前15M以下的图上传是没问题的

     

    展开全文
  • https://blog.csdn.net/Jackson991/article/details/107344345/?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-2&spm=1001.2101.3001.4242
  • 点击上传</em></div> <div class="el-upload__tip c999" slot="tip">只能上传mp4,avi,mov,rmvb,3GP文件,且视频时长不超过 60 分钟,大小不超过 2 GB</...
  • vue文件上传文档

    万次阅读 2020-02-22 15:47:55
    点击文件后面的”X”,就调用的事件  beforeRemove ( file ,  fileList ) {   var   self  =  this ;   self . form . fileList  =  fileList ; // 删除后剩的的文件数组   self ...
  • 可以在手机上微信、支付宝、钉钉、浏览器中使用 用原生的input调起手机摄像头 <input type="file" class="upImage" accept="image/*" @change="onFileChange" /> input的 capture=“camera” 这个属性 可以...
  • VUE实现文件上传下载功能实例解析

    千次阅读 2020-05-13 15:28:15
    4GB以上超大文件上传和断点续传服务器的实现 随着视频网站和大数据应用的普及,特别是高清视频和4K视频应用的到来,超大文件上传已经成为了日常的基础应用需求。 但是在很多情况下,平台运营方并没有大文件上传和...
  • 移动端的图片上传思路 理清思路: 分析ui: 设计html结构 数据 代码 分析ui,理需求 上边一行字:提示上传 下边是上传的图片展示,最多九张。逻辑:上传张数0,只显示加号图,上传张数大于0小于9,显示图片,九宫...
  • Vue调用手机相机和相册以及上传

    万次阅读 热门讨论 2018-07-11 10:41:19
    //点击事件,弹出选择摄像头和相册的选项 showActionSheet() { let bts = [{ title: "拍照" }, { title: "从相册选择" }]; plus.nativeUI.actionSheet({ cancel: "取消", buttons: bts }, function(e) {...
  • 稍加说明一下:第一张图是user.vue,第二张图是点击头像出现的系统自带上传文件格式(安卓和IOS不一样),第三张图是cropper组件(我单独设置的),第四张图是上传完成的user.vue。 其实插件不难,只不过为了契合...
  • Vue中调用微信上传图片功能

    千次阅读 2019-07-18 14:14:32
    Vue中调用微信上传图片功能 效果 说明 后台微信参数获取(略) 上传流程 点击图片控件位置,进行选择图片 选择相机拍照或图库上传 上传完成显示到图片控件 开发流程 引入weixin插件 页面初始化时获取...
  • vue移动端上传组件 Vue图像上传和调整大小 (Vue Image Upload and Resize) A Vue.js Plugin Component for client-side image upload with optional resizing and exif-based autorotate. 一个Vue.js插件组件,用于...
  • 上传小文件没问题,运行在浏览器上,上传大文件也没有问题,用Hbulder打包后就不可以了  </p>
  • vue移动端图片裁剪上传

    千次阅读 2017-08-11 16:22:43
    1. 安装cropperjs依赖库 npm install cropperjs 2. 编写组件SimpleCropper.vue 上传图片 取消 裁剪 import Cropper from 'cropperjs' import 'cro
  • vue项目里需要做上传图片功能,但是安卓和ios两者效果不一,安卓部份机型只能选择一张图片,ios可多选,在ipad上多选图片上传会出现丢失的情况,后来想到在vue项目里调用app里的选择图片和拍照方法,但是选择出来...
  • vue+vant文件上传组件

    2021-08-03 10:36:57
    vue+vant文件上传组件功能介绍:大致功能介绍:整体思路:简单效果展示: 功能介绍: 大致功能介绍: 整体思路: 简单效果展示:
  • vue-core-image-upload实现上传图片,ios系统手机点击上传图片会显示拍照、照片图库、ICloud这3种方式,怎样可以禁止拍照这个选项?![图片说明](https://img-ask.csdn.net/upload/201706/19/1497854850_349643.jpg...
  • Vue 调用录音以及录音上传

    千次阅读 2020-08-14 10:54:28
    Vue 调用录音以及录音上传 录音调用以及录音上传调用了Recorder,这里给出github链接 https://github.com/xiangyuecn/Recorder。 试了好几个录音调用的工具包,这个是唯一能用的。要注意的一点是,录音调用必须要用...
  • <el-form-item label="上传视频" prop="videoUrl"> <el-upload class="avatar-uploader" :action="actionUrl" :show-file-list="false" ...
  • vue

    2021-01-07 19:18:56
    Vue.js 简介 1.Vue (读音 /vjuː/,类似于 view)的简单认识 (1)Vue是一个渐进式的框架,什么是渐进式的呢? 渐进式意味着你可以将Vue作为你应用的一部分嵌入其中,带来更丰富的交互体验。 或者如果你希望将更多的...
  • ueditorUploadUrl: (CONFIG.base || process.env.VUE_APP_BASE_API) + '/file/upload', // 富文本上传地址 } 2.修改单文件上传方法 打开ueditor.all.js,找到单文件上传方法。 1.先修改请求方法,大约在24572行,...
  • Vue

    千次阅读 2020-07-01 21:35:19
    Vue Vue主要解决视图层的...[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rzJf0Ij8-1593610436880)(/Users/maliangcheng/Library/Application Support/typora-user-images/截屏2020-06-20
  • 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验; 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包含层级结构。 支持...
  • # Vue 2 项目,安装 Vant 2.x 版本: npm i vant -S # Vue 3 项目,安装 Vant 3.x 版本: npm i vant@next -S 2、全局或者自己局部引用 (依据自己需求而定) 3、这里使用局部引入组件 import { Uploader } ...
  • cordova环境配置,将vue项目打包成app的详细流程: https://blog.csdn.net/qq_42720683/article/details/104006233 记录一下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,277
精华内容 1,310
关键字:

vue手机点击上传

vue 订阅