vue+cropperjs实现图片剪裁,上传七牛云

来源:互联网 发布:小米4c可以4g网络吗 编辑:程序博客网 时间:2024/06/06 00:03

通过vue element UI  的upload组件,选择图片--进行图片剪裁--上传七牛云--获取图片key和hash--获取图片七牛云存储地址--上传地址到服务器。

父组件:

<template>    <div class="upload-img">        <h2>上传封面<span class="mark">上传视频缩略图封面,建议上传16:9的图片,仅支持JPEG,BMP,PNG格式,图像小于2M</span></h2>        <div class="select-button clearfix">        <el-upload :show-file-list="false" :auto-upload="false" :data="{token:token}" action="http://up-z2.qiniu.com/" :http-request="upload"  name="file" ref="coverImg"  list-type="picture-card" class="upload-plus clearfix" :on-change="handleChange" :on-preview="handlePictureCardPreview" :before-upload="handleBefore">            <i class="el-icon-plus add-img">点击添加图片</i>        </el-upload>        <div class="file" v-if="showCover">            <div class="file-box">                <span class="tag" :style="{backgroundColor:tagObj.color}">{{tagObj.label}}</span>                <img :src="item.coverUrl" alt="">                <div class="cover-bar">                    <a href="javascript:;" class="el-icon-view" @click="handleCheckView"></a>                    <a href="javascript:;" class="el-icon-delete2" @click="handleDelete"></a>                </div>            </div>        </div>        <cropper :panel="panel" :url="url" v-if="panel" @handleShow="handleShow" @handleGetUrl="handleGetUrl" @upload="upload"></cropper>        <el-dialog v-model="dialogVisible" size="tiny">            <img width="100%" :src="dialogImageUrl" alt="">        </el-dialog>        </div>    </div></template><script>import url from '../urls/index'import EditVideo from '../api/service/videoEdit'import cropper from '@/components/common/cropper.vue'    export default {        data() {            return {                dialogImageUrl: '',//查看缩略图弹框的图片url                dialogVisible: false,//查看缩略图弹框显示                uploadUrl:'',//上传的url                fileName:"",//文件名                showCover:false,//上传缩略图成功控制是否显示                // coverUrl:"" //上传成功后的url地址                panel:false,                url:''            }        },        components: {          cropper        },        computed:{            item:{                get:function(){                    return JSON.parse(window.localStorage.getItem('item'))                },                set:function(value){                    window.localStorage.setItem('item',JSON.stringify(value))                }            },            tagObj:{                get:function(){                    return this.$store.getters.GET_TAG_OBJ                },                set:function(value){                    this.$store.commit('UPDATE_TAG_OBJ',value)                }            },            token:{                get:function(){                    return this.$store.getters.GET_TOKEN                },                set:function(value){                    return this.$store.commit('UPDATE_TOKEN',value)                }            }        },        mounted(){            this.uploadUrl = url['Upload'];            //页面加载完成  判断localStorage是否存在            try {              if(this.item.coverUrl != "" && this.item.coverUrl){                this.showCover=true              }else{                this.showCover=false              }            } catch (error) {              this.showCover = false              return this.file=[]              this.postData.token = ''            }        },        methods: {            handleChange:function (files) {              if (!files) return;              this.panel = true;              this.picValue = files.raw;              this.url = files.url;              this.panel = true;            },            //生成图片链接            getObjectURL (file) {              var url = null ;              if (window.createObjectURL!=undefined) { // basic                url = window.createObjectURL(file) ;              } else if (window.URL!=undefined) { // mozilla(firefox)                url = window.URL.createObjectURL(file) ;              } else if (window.webkitURL!=undefined) { // webkit or chrome                url = window.webkitURL.createObjectURL(file) ;              }              return url ;            },            //子组件修改弹出层显示和隐藏状态            handleShow:function (data) {              this.panel = data            },            //子组件剪裁过后的bese64图片            handleGetUrl:function (data) {              this.item.coverUrl = data            },            upload:function(e){              const self = this              var pic = this.item.coverUrl.replace('data:image/png;base64,','');              var url = "http://up-z2.qiniu.com/putb64/-1"; //非华东空间需要根据注意事项 1 修改上传域名              var xhr = new XMLHttpRequest();              xhr.onreadystatechange=function(){                if (xhr.readyState==4){                  // document.getElementById("myDiv").innerHTML=xhr.responseText;                  const fileName = xhr.responseText ? JSON.parse(xhr.responseText) : ""                  EditVideo.DownloadUrl({fileName:fileName.key,type:20}).then((data)=>{                      const item=JSON.parse(window.localStorage.getItem('item'))                      item.coverUrl = data.fileUrl                      self.item.coverUrl = data.fileUrl//返回的封面url                      self.dialogImageUrl = data.fileUrl//查看大图的url地址                      self.showCover = true //上传成功控制列表显示                      window.localStorage.setItem('item',JSON.stringify(item))                  })                }              }              xhr.open("POST", url, true);              xhr.setRequestHeader("Content-Type", "application/octet-stream");              xhr.setRequestHeader("Authorization", "UpToken "+this.token);              xhr.send(pic);            },            //上传之前 文件类型判断            handleBefore:function(file){                const extension = file.name.split('.')[1] === 'jpeg'                const extension1 = file.name.split('.')[1] === 'bmp'                const extension2 = file.name.split('.')[1] === 'png'                const extension3 = file.name.split('.')[1] === 'jpg'                const isLt2M = file.size / 1024 / 1024 < 2                if(!extension && !extension1 && !extension2 && !extension3){                    this.$notify({                        type: 'error',                        message: '上传图片格式不正确!'                    });                    return false                }                if(!isLt2M){                    this.$notify({                        type: 'error',                        message: '上传缩略图不能超过2M!'                    });                    return false                }                return extension || extension1 || extension2 ||  extension3            },            //查看图片            handlePictureCardPreview(file) {                this.dialogImageUrl = this.item.coverUrl                this.dialogVisible = true;            },            //查看大图            handleCheckView:function(){                this.dialogImageUrl = this.item.coverUrl                this.dialogVisible = true            },            //删除已上传的缩略图            handleDelete:function(){                this.file = {}                this.showCover = false                this.item.coverUrl = ""                const item=JSON.parse(window.localStorage.getItem('item'))                item.coverUrl = ""                window.localStorage.setItem('item',JSON.stringify(item))                window.localStorage.removeItem('coverFile')            }        }    }</script><style scoped>    .upload-img {        width: 1000px;        margin: 20px auto 10px;        box-shadow: 0 6px 10px 0 rgba(212, 212, 212, 0.50);        background: #ffffff;    }    .upload-img h2 {        padding: 10px;        text-align: left;        border-bottom: 1px solid #f4f4f4;        font-size: 16px;        color: #38424b;    }    .mark {        font-size: 12px;        color: #69717a;        margin-left: 20px;    }    .select-button {        text-align: left;        padding: 20px 10px;    }    .add-img{        font-size:14px;        color:#38424b;        position: relative;    }    .add-img::before{        position: absolute;        top: -25px;        left: 50%;        margin-left: -10px;        border-radius: 50%;        background: #000;        color: #fff;        padding: 3px;    }    .upload-plus{        float: left;    }    .file{        float: left;        position: relative;    }    .file-box{        position: relative;        line-height: 150px;        float: left;        margin-right: 20px;        width: 235px;        height: 132px;        background: #f4f4f4;        /* border: 1px dashed #c0ccda; */        /* border-radius: 6px; */    }    .file-box img{        width: 235px;        height: 132px;        /* border-radius: 6px; */    }    .cover-bar{        position: absolute;        top: 0;        left: 0;        width: 235px;        height: 132px;        text-align: center;        display: none;        /* border-radius: 6px; */        background: rgba(0, 0, 0, 0.50)    }    .file:hover .cover-bar{        display: block;    }    .cover-bar a{        color: #fff;        text-decoration: none;        font-size: 20px;        margin: 0 10px;    }    .tag{        position: absolute;        left: 0;        top: 0;        z-index: 99;        width: 34px;        height: 17px;        display: block;        font-size: 14px;        color: #fff;        line-height: 17px;        text-align: center;    }</style>

子组件:

<template>  <div id="cropper">    <!-- 遮罩层 -->    <div class="container" v-show="panel">      <div>        <img id="image" :src="url" alt="Picture">      </div>      <button type="button" id="button" @click="crop">确定</button>    </div>  </div></template><script>import Cropper from 'cropperjs'export default {  components: {  },  data () {    return {      headerImage:'',      cropper:'',      croppable:false,    }  },  props: {    picValue:String,    panel:Boolean,    url:String  },  mounted () {    //初始化这个裁剪框    var self = this;    var image = document.getElementById('image');    this.cropper = new Cropper(image, {      aspectRatio: 16/9,      viewMode: 1,      background:false,      zoomable:false,      ready: function () {        self.croppable = true;      }    });  },  methods: {    crop () {        var croppedCanvas;        var roundedCanvas;        this.$emit('handleShow',false)        if (!this.croppable) {          return;        }        // Crop        croppedCanvas = this.cropper.getCroppedCanvas();        // Round        roundedCanvas = this.getRoundedCanvas(croppedCanvas);        this.headerImage = roundedCanvas.toDataURL();        this.$emit('handleGetUrl',this.headerImage)        this.$emit('upload')    },    getRoundedCanvas (sourceCanvas) {      var canvas = document.createElement('canvas');      var context = canvas.getContext('2d');      var width = sourceCanvas.width;      var height = sourceCanvas.height;      canvas.width = width;      canvas.height = height;      context.imageSmoothingEnabled = true;      context.drawImage(sourceCanvas, 0, 0, width, height);      context.globalCompositeOperation = 'destination-in';      context.beginPath();      // context.arc(width / 2, height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI, true);      context.fill();      return canvas;    }  }}</script><style>*{  margin: 0;  padding: 0;}#cropper #button {  position: absolute;  right: 10px;  top: 10px;  width: 80px;  color: #fff;  height: 40px;  border: none;  border-radius: 5px;  background: #24a4ff;}#cropper .show {  width: 100px;  height: 100px;  overflow: hidden;  position: relative;  /* border-radius: 50%; */  border: 1px solid #d5d5d5;}#cropper .picture {  width: 100%;  height: 100%;  overflow: hidden;  background-position: center center;  background-repeat: no-repeat;  background-size: cover;}#cropper .container {    z-index: 99;    position: fixed;    padding-top: 60px;    left: 0;    top: 0;    right: 0;    bottom: 0;    background:rgba(0,0,0,1);}#cropper #image {  max-width: 100%;}.cropper-view-box,.cropper-face {  /* border-radius: 50%; */}/*! * Cropper.js v1.0.0-rc * https://github.com/fengyuanchen/cropperjs * * Copyright (c) 2017 Fengyuan Chen * Released under the MIT license * * Date: 2017-03-25T12:02:21.062Z */.cropper-container {  font-size: 0;  line-height: 0;  position: relative;  -webkit-user-select: none;     -moz-user-select: none;      -ms-user-select: none;          user-select: none;  direction: ltr;  -ms-touch-action: none;      touch-action: none}.cropper-container img {  /* Avoid margin top issue (Occur only when margin-top <= -height) */  display: block;  min-width: 0 !important;  max-width: none !important;  min-height: 0 !important;  max-height: none !important;  width: 100%;  height: 100%;  image-orientation: 0deg}.cropper-wrap-box,.cropper-canvas,.cropper-drag-box,.cropper-crop-box,.cropper-modal {  position: absolute;  top: 0;  right: 0;  bottom: 0;  left: 0;}.cropper-wrap-box {  overflow: hidden;}.cropper-drag-box {  opacity: 0;  background-color: #fff;}.cropper-modal {  opacity: .5;  background-color: #000;}.cropper-view-box {  display: block;  overflow: hidden;  width: 100%;  height: 100%;  outline: 1px solid #39f;  outline-color: rgba(51, 153, 255, 0.75);}.cropper-dashed {  position: absolute;  display: block;  opacity: .5;  border: 0 dashed #eee}.cropper-dashed.dashed-h {  top: 33.33333%;  left: 0;  width: 100%;  height: 33.33333%;  border-top-width: 1px;  border-bottom-width: 1px}.cropper-dashed.dashed-v {  top: 0;  left: 33.33333%;  width: 33.33333%;  height: 100%;  border-right-width: 1px;  border-left-width: 1px}.cropper-center {  position: absolute;  top: 50%;  left: 50%;  display: block;  width: 0;  height: 0;  opacity: .75}.cropper-center:before,  .cropper-center:after {  position: absolute;  display: block;  content: ' ';  background-color: #eee}.cropper-center:before {  top: 0;  left: -3px;  width: 7px;  height: 1px}.cropper-center:after {  top: -3px;  left: 0;  width: 1px;  height: 7px}.cropper-face,.cropper-line,.cropper-point {  position: absolute;  display: block;  width: 100%;  height: 100%;  opacity: .1;}.cropper-face {  top: 0;  left: 0;  background-color: #fff;}.cropper-line {  background-color: #39f}.cropper-line.line-e {  top: 0;  right: -3px;  width: 5px;  cursor: e-resize}.cropper-line.line-n {  top: -3px;  left: 0;  height: 5px;  cursor: n-resize}.cropper-line.line-w {  top: 0;  left: -3px;  width: 5px;  cursor: w-resize}.cropper-line.line-s {  bottom: -3px;  left: 0;  height: 5px;  cursor: s-resize}.cropper-point {  width: 5px;  height: 5px;  opacity: .75;  background-color: #39f}.cropper-point.point-e {  top: 50%;  right: -3px;  margin-top: -3px;  cursor: e-resize}.cropper-point.point-n {  top: -3px;  left: 50%;  margin-left: -3px;  cursor: n-resize}.cropper-point.point-w {  top: 50%;  left: -3px;  margin-top: -3px;  cursor: w-resize}.cropper-point.point-s {  bottom: -3px;  left: 50%;  margin-left: -3px;  cursor: s-resize}.cropper-point.point-ne {  top: -3px;  right: -3px;  cursor: ne-resize}.cropper-point.point-nw {  top: -3px;  left: -3px;  cursor: nw-resize}.cropper-point.point-sw {  bottom: -3px;  left: -3px;  cursor: sw-resize}.cropper-point.point-se {  right: -3px;  bottom: -3px;  width: 20px;  height: 20px;  cursor: se-resize;  opacity: 1}@media (min-width: 768px) {  .cropper-point.point-se {    width: 15px;    height: 15px  }}@media (min-width: 992px) {  .cropper-point.point-se {    width: 10px;    height: 10px  }}@media (min-width: 1200px) {  .cropper-point.point-se {    width: 5px;    height: 5px;    opacity: .75  }}.cropper-point.point-se:before {  position: absolute;  right: -50%;  bottom: -50%;  display: block;  width: 200%;  height: 200%;  content: ' ';  opacity: 0;  background-color: #39f}.cropper-invisible {  opacity: 0;}.cropper-bg {  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');}.cropper-hide {  position: absolute;  display: block;  width: 0;  height: 0;}.cropper-hidden {  display: none !important;}.cropper-move {  cursor: move;}.cropper-crop {  cursor: crosshair;}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point {  cursor: not-allowed;}</style>




原创粉丝点击