欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue-cli結(jié)合Element-ui基于cropper.js封裝vue實(shí)現(xiàn)圖片裁剪組件功能

 更新時(shí)間:2018年03月01日 11:37:02   作者:lizimeme  
這篇文章主要介紹了vue-cli結(jié)合Element-ui基于cropper.js封裝vue實(shí)現(xiàn)圖片裁剪組件功能,本文圖文并茂給大家介紹的非常詳細(xì),需要的朋友可以參考下

前端工作中,經(jīng)常需要圖片裁剪的場(chǎng)景,cropper.js是一款優(yōu)秀的前端插件,api十分豐富。

本文是在vue-cli項(xiàng)目下封裝圖片裁剪插件,效果圖如下:

話不多說(shuō),看步驟吧。

第一步:準(zhǔn)備開發(fā)環(huán)境

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

執(zhí)行命令:

  npm  install --save-dev jquery cropper

 為webpack配置添加jquery的映射

修改webpack.base.conf.js配置,添加標(biāo)紅的一行

第二步:新建圖片裁剪組件

index.vue內(nèi)容:

由于用了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 " style="visibility: hidden" 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" style="overflow: hidden;">
    <div style="padding-left: 10px">
     <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;
  }
  },  //旋轉(zhuǎn)事件
  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();
    //裁圖參數(shù)存起來(lái)
    _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){
    //將返回的數(shù)據(jù)傳給父組件
    _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組件,此時(shí)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();
  },
  //父組件調(diào)用子組件裁剪方法
  toCropper(){
   this.$refs.cropper.submit();
  },
  //子組件裁剪方法成功執(zhí)行后與父組件通信
  cropperSuccessHandle(data){
   //返回data
  this.showCropper = false
  this.avatarUrl2 = data.url
  }
 }
 }

本文結(jié)合element-ui,vue-cli,jquery,cropper.js,實(shí)現(xiàn)裁圖組件的封裝,先寫到這啦,如果對(duì)你有幫助,還請(qǐng)點(diǎn)個(gè)贊噢!

相關(guān)文章

  • vue?路由切換過(guò)渡動(dòng)效滑入滑出效果的實(shí)例代碼

    vue?路由切換過(guò)渡動(dòng)效滑入滑出效果的實(shí)例代碼

    在支付寶賬單頁(yè)面有這樣一個(gè)特效切換過(guò)渡動(dòng)效滑入滑出效果,非常方便實(shí)用,那么這個(gè)功能如何實(shí)現(xiàn)的呢?下面小編通過(guò)vue實(shí)現(xiàn)路由切換過(guò)渡動(dòng)效滑入滑出效果,感興趣的朋友一起看看吧
    2022-03-03
  • Vue3中使用ref與reactive創(chuàng)建響應(yīng)式數(shù)據(jù)的示例代碼

    Vue3中使用ref與reactive創(chuàng)建響應(yīng)式數(shù)據(jù)的示例代碼

    這篇文章主要介紹了Vue3中使用ref與reactive創(chuàng)建響應(yīng)式數(shù)據(jù)的方法,文中通過(guò)代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-08-08
  • vue yaml代碼編輯器組件問(wèn)題

    vue yaml代碼編輯器組件問(wèn)題

    這篇文章主要介紹了vue yaml代碼編輯器組件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Vue提供的三種調(diào)試方式你知道嗎

    Vue提供的三種調(diào)試方式你知道嗎

    這篇文章主要為大家介紹了Vue提供的三種調(diào)試方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • vue中實(shí)現(xiàn)methods一個(gè)方法調(diào)用另外一個(gè)方法

    vue中實(shí)現(xiàn)methods一個(gè)方法調(diào)用另外一個(gè)方法

    下面小編就為大家分享一篇vue中實(shí)現(xiàn)methods一個(gè)方法調(diào)用另外一個(gè)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • vue3 el-form-item如何自定義label標(biāo)簽內(nèi)容

    vue3 el-form-item如何自定義label標(biāo)簽內(nèi)容

    這篇文章主要介紹了vue3 el-form-item如何自定義label標(biāo)簽內(nèi)容問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • 淺談vue-props的default寫不寫有什么區(qū)別

    淺談vue-props的default寫不寫有什么區(qū)別

    這篇文章主要介紹了淺談vue-props的default寫不寫有什么區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • Vue中的性能優(yōu)化方案

    Vue中的性能優(yōu)化方案

    本文主要介紹了Vue中的性能優(yōu)化方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 關(guān)于element?ui中的el-scrollbar橫向滾動(dòng)問(wèn)題

    關(guān)于element?ui中的el-scrollbar橫向滾動(dòng)問(wèn)題

    這篇文章主要介紹了關(guān)于element?ui中的el-scrollbar橫向滾動(dòng)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • vue 組件使用中的一些細(xì)節(jié)點(diǎn)

    vue 組件使用中的一些細(xì)節(jié)點(diǎn)

    這篇文章主要介紹了vue 組件使用中的一些細(xì)節(jié)點(diǎn),大概有兩大細(xì)節(jié)點(diǎn),本文通過(guò)基礎(chǔ)實(shí)例給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2018-04-04

最新評(píng)論