温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

vue-cli结合Element-ui基于cropper.js封装vue实现图片裁剪组件功能的示例

发布时间:2021-04-23 14:12:12 来源:亿速云 阅读:233 作者:小新 栏目:web开发

这篇文章将为大家详细讲解有关vue-cli结合Element-ui基于cropper.js封装vue实现图片裁剪组件功能的示例,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

为什么要使用Vue

Vue是一款友好的、多用途且高性能的JavaScript框架,使用vue可以创建可维护性和可测试性更强的代码库,Vue允许可以将一个网页分割成可复用的组件,每个组件都包含属于自己的HTML、CSS、JavaScript,以用来渲染网页中相应的地方,所以越来越多的前端开发者使用vue。

在vue-cli项目下封装图片裁剪插件,效果图如下:

vue-cli结合Element-ui基于cropper.js封装vue实现图片裁剪组件功能的示例

话不多说,看步骤吧。

第一步:准备开发环境

cropper.js是基于jquery的,所以要先安装jquery

执行命令:

  npm  install --save-dev jquery cropper

 为webpack配置添加jquery的映射

修改webpack.base.conf.js配置,添加标红的一行

vue-cli结合Element-ui基于cropper.js封装vue实现图片裁剪组件功能的示例

第二步:新建图片裁剪组件

vue-cli结合Element-ui基于cropper.js封装vue实现图片裁剪组件功能的示例

index.vue内容:

由于用了element-ui,其中布局就引用了element-ui的组件

 template:

<template>  <div class="modal-dialog modal-lg" :id="id">  <div class="modal-content">   <form class="avatar-form" enctype="multipart/form-data" method="post">   <div class="modal-header">   </div>   <div class="modal-body">    <div class="avatar-body">    <!-- Upload image and data -->    <div class="avatar-upload">     <input type="hidden" class="avatar-src" name="avatar_src">     <input type="hidden" class="avatar-data" name="ci">     <label for="avatarInput" class="el-button el-button--primary">选择图片</label>     <input type="file" class="avatar-input "  id="avatarInput" name="file">    </div>    <!-- Crop and preview -->    <el-row>     <el-col :span="18">     <div class="avatar-wrapper"></div>     </el-col>     <el-col :span="6" >     <div >      <div class="avatar-preview preview-lg" ></div>      <div class="avatar-preview avatar-preview-round preview-md"></div>     <!--<div class="avatar-preview preview-sm"></div>-->     </div>     </el-col>    </el-row>    <el-row class="avatar-btns">     <el-col :span="18">     <el-button-group>      <button type="primary" class="el-button el-button--primary" data-method="rotate" data-option="-180" title="Rotate -180 degrees">-180deg</button>      <button type="primary" class="el-button el-button--primary" data-method="rotate" data-option="-90" title="Rotate -90 degrees">-90deg</button>      <button type="primary" class="el-button el-button--primary" data-method="rotate" data-option="-45" title="Rotate -45 degrees">-45deg</button>      <button type="primary" class="el-button el-button--primary" data-method="rotate" data-option="45" title="Rotate 45 degrees">45deg</button>      <button type="primary" class="el-button el-button--primary" data-method="rotate" data-option="90" title="Rotate 90 degrees">90deg</button>      <button type="primary" class="el-button el-button--primary" data-method="rotate" data-option="180" title="Rotate 180 degrees">180deg</button>     </el-button-group>     </el-col>     <el-col :span="6"></el-col>    </el-row>    <el-row>     <!--<button type="submit" class="btn btn-primary btn-block avatar-save">裁取</button>-->    </el-row>    </div>   </div>   </form>  </div>  </div> </template>

style:

<style rel="stylesheet/scss" lang='scss' scoped>  /*@import "cropper/dist/cropper.css";*/  /*!  * Cropper v3.1.3  * https://github.com/fengyuanchen/cropper  *  * Copyright (c) 2014-2017 Chen Fengyuan  * Released under the MIT license  *  * Date: 2017-10-21T10:03:37.133Z  */  .avatar-wrapper{  width: 100%;  height: 100%;  overflow: hidden;  }  .cropper-container {  direction: ltr;  font-size: 0;  line-height: 0;  position: relative;  -ms-touch-action: none;  touch-action: none;  -webkit-user-select: none;  -moz-user-select: none;  -ms-user-select: none;  user-select: none;  }  .cropper-container img {/*Avoid margin top issue (Occur only when margin-top <= -height)  */  display: block;  height: 100%;  image-orientation: 0deg;  max-height: none !important;  max-width: none !important;  min-height: 0 !important;  min-width: 0 !important;  width: 100%;  }  .cropper-wrap-box,  .cropper-canvas,  .cropper-drag-box,  .cropper-crop-box,  .cropper-modal {  bottom: 0;  left: 0;  position: absolute;  right: 0;  top: 0;  }  .cropper-wrap-box,  .cropper-canvas {  overflow: hidden;  }  .cropper-drag-box {  background-color: #fff;  opacity: 0;  }  .cropper-modal {  background-color: #000;  opacity: .5;  }  .cropper-view-box {  display: block;  height: 100%;  outline-color: rgba(51, 153, 255, 0.75);  outline: 1px solid #39f;  overflow: hidden;  width: 100%;  }  .cropper-dashed {  border: 0 dashed #eee;  display: block;  opacity: .5;  position: absolute;  }  .cropper-dashed.dashed-h {  border-bottom-width: 1px;  border-top-width: 1px;  height: 33.33333%;  left: 0;  top: 33.33333%;  width: 100%;  }  .cropper-dashed.dashed-v {  border-left-width: 1px;  border-right-width: 1px;  height: 100%;  left: 33.33333%;  top: 0;  width: 33.33333%;  }  .cropper-center {  display: block;  height: 0;  left: 50%;  opacity: .75;  position: absolute;  top: 50%;  width: 0;  }  .cropper-center:before,  .cropper-center:after {  background-color: #eee;  content: ' ';  display: block;  position: absolute;  }  .cropper-center:before {  height: 1px;  left: -3px;  top: 0;  width: 7px;  }  .cropper-center:after {  height: 7px;  left: 0;  top: -3px;  width: 1px;  }  .cropper-face,  .cropper-line,  .cropper-point {  display: block;  height: 100%;  opacity: .1;  position: absolute;  width: 100%;  }  .cropper-face {  background-color: #fff;  left: 0;  top: 0;  }  .cropper-line {  background-color: #39f;  }  .cropper-line.line-e {  cursor: e-resize;  right: -3px;  top: 0;  width: 5px;  }  .cropper-line.line-n {  cursor: n-resize;  height: 5px;  left: 0;  top: -3px;  }  .cropper-line.line-w {  cursor: w-resize;  left: -3px;  top: 0;  width: 5px;  }  .cropper-line.line-s {  bottom: -3px;  cursor: s-resize;  height: 5px;  left: 0;  }  .cropper-point {  background-color: #39f;  height: 5px;  opacity: .75;  width: 5px;  }  .cropper-point.point-e {  cursor: e-resize;  margin-top: -3px;  right: -3px;  top: 50%;  }  .cropper-point.point-n {  cursor: n-resize;  left: 50%;  margin-left: -3px;  top: -3px;  }  .cropper-point.point-w {  cursor: w-resize;  left: -3px;  margin-top: -3px;  top: 50%;  }  .cropper-point.point-s {  bottom: -3px;  cursor: s-resize;  left: 50%;  margin-left: -3px;  }  .cropper-point.point-ne {  cursor: ne-resize;  right: -3px;  top: -3px;  }  .cropper-point.point-nw {  cursor: nw-resize;  left: -3px;  top: -3px;  }  .cropper-point.point-sw {  bottom: -3px;  cursor: sw-resize;  left: -3px;  }  .cropper-point.point-se {  bottom: -3px;  cursor: se-resize;  height: 20px;  opacity: 1;  right: -3px;  width: 20px;  }  @media (min-width: 768px) {  .cropper-point.point-se {   height: 15px;   width: 15px;  }  }  @media (min-width: 992px) {  .cropper-point.point-se {   height: 10px;   width: 10px;  }  }  @media (min-width: 1200px) {  .cropper-point.point-se {   height: 5px;   opacity: .75;   width: 5px;  }  }  .cropper-point.point-se:before {  background-color: #39f;  bottom: -50%;  content: ' ';  display: block;  height: 200%;  opacity: 0;  position: absolute;  right: -50%;  width: 200%;  }  .cropper-invisible {  opacity: 0;  }  .cropper-bg {  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');  }  .cropper-hide {  display: block;  height: 0;  position: absolute;  width: 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;  }  .avatar-view {  display: block;  margin: 15% auto 5%;  height: 220px;  width: 220px;  border: 3px solid #fff;  border-radius: 5px;  box-shadow: 0 0 5px rgba(0,0,0,.15);  cursor: pointer;  overflow: hidden;  }  .avatar-view img {  width: 100%;  }  .avatar-body {  padding-right: 15px;  padding-left: 15px;  }  .avatar-upload {  overflow: hidden;  }  .avatar-upload label {  display: block;  float: left;  clear: left;  width: 100px;  }  .avatar-upload input {  display: block;  margin-left: 110px;  }  .avatar-alert {  margin-top: 10px;  margin-bottom: 10px;  }  .avatar-wrapper {  height: 364px;  width: 100%;  margin-top: 15px;  box-shadow: inset 0 0 5px rgba(0,0,0,.25);  background-color: #fcfcfc;  overflow: hidden;  }  .avatar-wrapper img {  display: block;  height: auto;  max-width: 100%;  }  .avatar-preview {  float: left;  margin-top: 15px;  margin-right: 15px;  border: 1px solid #eee;  border-radius: 4px;  background-color: #fff;  overflow: hidden;  }  .avatar-preview:hover {  border-color: #ccf;  box-shadow: 0 0 5px rgba(0,0,0,.15);  }  .avatar-preview img {  width: 100%;  }  .avatar-preview-round{  border-radius: 50%;  }  .preview-lg {  height: 184px;  width: 184px;  margin-top: 15px;  }  .preview-md {  height: 100px;  width: 100px;  }  .preview-sm {  height: 50px;  width: 50px;  }  @media (min-width: 992px) {  .avatar-preview {   float: none;  }  }  .avatar-btns {  margin-top: 30px;  margin-bottom: 15px;  }  .avatar-btns .btn-group {  margin-right: 5px;  } </style>

script:

<script>  import $ from 'jquery'  import 'cropper/dist/cropper.js'  export default {  props:{   id:String  },  data(){   return {   $container:null,   $avatarView:null,   $avatarModal : null,   $loading : null,   $avatarForm : null,   $avatarUpload : null,   $avatarSrc : null,   $avatarData : null,   $avatarInput : null,   $avatarSave: null,   $avatarBtns : null,   $avatarWrapper : null,   $avatarPreview: null,   support: {   fileList: !!$('<input type="file">').prop('files'),    blobURLs: !!window.URL && URL.createObjectURL,    formData: !!window.FormData   }   }  },  created(){},  mounted(){   this.$container = $('#'+this.id);   this.$avatarForm = this.$container.find('.avatar-form');   this.$avatarUpload = this.$avatarForm.find('.avatar-upload');   this.$avatarSrc = this.$avatarForm.find('.avatar-src');   this.$avatarData = this.$avatarForm.find('.avatar-data');   this.$avatarInput = this.$avatarForm.find('.avatar-input');   this.$avatarSave = this.$avatarForm.find('.avatar-save');   this.$avatarWrapper = this.$container.find('.avatar-wrapper');   this.$avatarPreview = this.$container.find('.avatar-preview');   this.$avatarBtns = this.$container.find('.avatar-btns');   this.$nextTick(function () {    this.init();   })  },  methods:{   init: function () {   this.support.datauri = this.support.fileList && this.support.blobURLs;   this.addListener(); //  this.startCropper();   },   addListener: function () {   this.$avatarInput.on('change', $.proxy(this.change, this));   this.$avatarForm.on('submit', $.proxy(this.submit, this));   this.$avatarBtns.on('click', $.proxy(this.rotate, this));   },   initPreview: function () {   var url = this.$avatar.attr('src');   this.$avatarPreview.html('<img src="' + url + '">');   },   initIframe: function () {   var target = 'upload-iframe-' + (new Date()).getTime();   var $iframe = $('<iframe>').attr({    name: target,    src: ''   });   var _this = this;   // Ready ifrmae   $iframe.one('load', function () {    // respond response    $iframe.on('load', function () {    var data;    try {     data = $(this).contents().find('body').text();    } catch (e) {     console.log(e.message);    }    if (data) {     try {     data = $.parseJSON(data);     } catch (e) {     console.log(e.message);     }     _this.submitDone(data);    } else {    }    _this.submitEnd();    });   });   this.$iframe = $iframe;   this.$avatarForm.attr('target', target).after($iframe.hide());   },   click:function () {   this.initPreview();   },   change: function () {   var files;   var file;   if (this.support.datauri) {    files = this.$avatarInput.prop('files');    if (files.length > 0) {    file = files[0];    if (this.isImageFile(file)) {     if (this.url) {     URL.revokeObjectURL(this.url); // Revoke the old one     }     this.url = URL.createObjectURL(file);     this.startCropper();    }    }   } else {    file = this.$avatarInput.val();    if (this.isImageFile(file)) {    this.syncUpload();    }   }   },   //裁剪提交   submit: function () {   if (!this.$avatarSrc.val() && !this.$avatarInput.val()) {    return false;   }   if (this.support.formData) {    this.ajaxUpload();    return false;   }   },  //旋转事件   rotate: function (e) {   var data;   if (this.active) {    data = $(e.target).data();    if (data.method) {    this.$img.cropper(data.method, data.option);    }   }   },   isImageFile: function (file) {   if (file.type) {    return /^image\/\w+$/.test(file.type);   } else {    return /\.(jpg|jpeg|png|gif)$/.test(file);   }   },   startCropper: function () {   var _this = this;   if (this.active) {    this.$img.cropper('replace', this.url);   } else {    this.$img = $('<img src="' + this.url + '">');    this.$avatarWrapper.empty().html(this.$img);    this.$img.cropper({    viewMode:1,    aspectRatio: 1,    preview: this.$avatarPreview,    restore:false,    crop: function (e) {     var json = [     '{"x":' + e.x,     '"y":' + e.y,     '"height":' + e.height,     '"width":' + e.width,     '"rotate":' + e.rotate + '}'     ].join();     //裁图参数存起来     _this.$avatarData.val(json);    }    });    this.active = true;   }   },   stopCropper: function () {   if (this.active) {    this.$img.cropper('destroy');    this.$img.remove();    this.active = false;   }   },   ajaxUpload: function () {   var url = '/oss/file/cropping';   var data = new FormData(this.$avatarForm[0]);   var _this = this;   $.ajax(url, {    type: 'post',    data: data,    dataType: 'json',    processData: false,    contentType: false,    success: function (data,textStatus) {    _this.submitDone(data);    if(data.success){     //将返回的数据传给父组件     _this.$emit('cropper-success',data.data);     _this.cropDone();    }    },   });   },   syncUpload: function () {   this.$avatarSave.click();   },   submitDone: function (data) {   if ($.isPlainObject(data) && data.state === 200) {    if (data.result) {    this.url = data.result;    if (this.support.datauri || this.uploaded) {     this.uploaded = false;     this.cropDone();    } else {     this.uploaded = true;     this.$avatarSrc.val(this.url);     this.startCropper();    }    this.$avatarInput.val('');    } else if (data.message) {    }   } else {   }   },   cropDone: function () { //  this.$avatarForm.get(0).reset(); //  this.$avatarSrc.prop('src', this.url);    this.stopCropper(); //  this.$container.hide();   }  }  } </script>

第三步:父组件引用子组件

用了element-ui中的 el-dialog组件,此时el-dialog组件为父组件

在父组件中引入子组件

import cropper from '@/components/Cropper/index'

template:

<template>  <div class="app-main-content" >  <el-dialog :visible.sync="showCropper" title="封面裁图" width="70%">   <cropper id="avatarCrop" ref="cropper" @cropper-success="cropperSuccessHandle"></cropper>   <span slot="footer" class="dialog-footer">   <el-button @click="cancelCropper">取 消</el-button>   <el-button type="primary" @click="toCropper">确 定</el-button>   </span>  </el-dialog>  </div>

script:

import cropper from '@/components/Cropper/index' export default {  name: 'addNews',  components:{   cropper  },  data(){   return {   avatarUrl2: null,   showCropper:false   }  },  methods:{   //隐藏裁剪框   cancelCropper(){   this.showCropper = false   this.$refs.cropper.cropDone();   },   //父组件调用子组件裁剪方法   toCropper(){    this.$refs.cropper.submit();   },   //子组件裁剪方法成功执行后与父组件通信   cropperSuccessHandle(data){    //返回data   this.showCropper = false   this.avatarUrl2 = data.url   }  }  }

关于“vue-cli结合Element-ui基于cropper.js封装vue实现图片裁剪组件功能的示例”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI