使用技术:

vue.js2.0、cropperjs、canvas

<template>
  <div id="app">
    <div id="demo">
      <!-- 遮罩层 -->
      <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 style="padding:20px;">
        <div class="show">
          <div class="picture" :style="'backgroundImage:url('+headerImage+')'">
          </div>
        </div>
        <div style="margin-top:20px;">
          <input type="file" id="change" accept="image" @change="change">
          <label for="change"></label>
        </div>
 
      </div>
    </div>
  </div>
</template>
 
<script>
  import Cropper from 'cropperjs'
  export default {
    components: {
 
    },
    data () {
      return {
        headerImage:'',
        picValue:'',
        cropper:'',
        croppable:false,
        panel:false,
        url:''
      }
    },
    mounted () {
      //初始化这个裁剪框
      var self = this;
      var image = document.getElementById('image');
      this.cropper = new Cropper(image, {
        aspectRatio: 1,
        viewMode: 1,
        background:false,
        zoomable:false,
        ready: function () {
          self.croppable = true;
        }
      });
    },
    methods: {
      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 ;
      },
      change (e) {
        let files = e.target.files || e.dataTransfer.files;
        if (!files.length) return;
        this.panel = true;
        this.picValue = files[0];
 
        this.url = this.getObjectURL(this.picValue);
        //每次替换图片要重新得到新的url
        if(this.cropper){
          this.cropper.replace(this.url);
        }
        this.panel = true;
 
      },
      crop () {
        this.panel = false;
        var croppedCanvas;
        var roundedCanvas;
 
        if (!this.croppable) {
          return;
        }
        // Crop
        croppedCanvas = this.cropper.getCroppedCanvas();
        console.log(this.cropper)
        // Round
        roundedCanvas = this.getRoundedCanvas(croppedCanvas);
 
        this.headerImage = roundedCanvas.toDataURL();
        this.postImg()
 
      },
      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;
      },
      postImg () {
        //这边写图片的上传
      }
    }
  }
</script>
 
<style>
  *{
    margin: 0;
    padding: 0;
  }
  #demo #button {
    position: absolute;
    right: 10px;
    top: 10px;
    width: 80px;
    height: 40px;
    border:none;
    border-radius: 5px;
    background:white;
  }
  #demo .show {
    width: 100px;
    height: 100px;
    overflow: hidden;
    position: relative;
    border-radius: 50%;
    border: 1px solid #d5d5d5;
  }
  #demo .picture {
    width: 100%;
    height: 100%;
    overflow: hidden;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
  }
  #demo .container {
    z-index: 99;
    position: fixed;
    padding-top: 60px;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background:rgba(0,0,0,1);
  }
 
  #demo #image {
    max-width: 100%;
  }
 
  .cropper-view-box,.cropper-face {
    border-radius: 50%;
  }
  /*!
   * Cropper.js v1.0.0-rc
   *
   * 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;
    #fff;
  }
 
  .cropper-modal {
    opacity: .5;
    #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: ' ';
    #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;
 
    #fff;
  }
 
  .cropper-line {
    #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;
    #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;
    #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>

Vue实现用户自定义上传头像裁剪的更多相关文章

  1. vue 剪切图片上传头像,使用 cropperjs 实现

    我使用的是vue,移动端的项目. 官网地址:cropperjs GitHub地址:https://github.com/fengyuanchen/cropperjs/blob/master/READM ...

  2. html5 上传头像的裁剪

    本示例使用HTML5 canvas,简单的编写了上传头像的裁剪效果,移动端支持拖拽后裁剪, 虽然样式不好看,但是功能还算全: 下图为裁剪后的效果: html部分: <!DOCTYPE html& ...

  3. Jcrop+uploadify+php实现上传头像预览裁剪

    最近由于项目需要,所以做了一个上传头像预览并且可以预览裁剪的功能,大概思路是上传的图片先保存到服务器,然后通过ajax从服务器获取到图片信息,再利用Jcrop插件进行裁剪,之后通过PHP获取到的四个裁 ...

  4. 上传头像,界面无跳转,php+js

    上传头像,界面无跳转的方式很多,我用的是加个iframe那种.下面直接上代码. html: //route 为后端接口//upload/avatar 为上传的头像的保存地址//imgurl=/uplo ...

  5. Android基础之——startActivityForResult启动界面并返回数据,上传头像

    在android应用的开发过程中,常常会出现启动一个界面后填写部分内容后带着数据返回启动前的界面,最典型的应用就是登录过程.在非常多应用程序的模块中,都有"我的"这个模块,在未登录 ...

  6. day105:Mofang:设置页面初始化&更新头像/上传头像&设置页面显示用户基本信息

    目录 1.设置页面初始化 2.更新头像 1.点击头像进入更新头像界面 2.更新头像页面初始化 3.更新头像页面CSS样式 4.头像上传来源选择:相册/相机 5.调用api提供的本地接口从相册/相机提取 ...

  7. swift上传头像

    很久没有写博客了,今天特地写了这个,也是一边仿照别人写的demo,注释部分都是需要的.需要的同学可以参考一下. @IBAction func headImageBtnPage(){  //上传头像 / ...

  8. 完美实现类似QQ的自拍头像、上传头像功能!(Demo 源码)

    现在很多下载客户端程序都需要设定自己头像的功能,而设定头像一般有两种方式:使用摄像头自拍头像,或者选择一个图片的某部分区域作为自己的头像. 一.相关技术 若要实现上述的自拍头像和上传头像的功能,会碰到 ...

  9. asp.net mvc上传头像加剪裁功能介绍

    正好项目用到上传+剪裁功能,发上来便于以后使用. 我不能告诉你们其实是从博客园扒的前台代码,哈哈. 前端是jquery+fineuploader+jquery.Jcrop 后台是asp.net mvc ...

随机推荐

  1. hdu4044 依赖背包变形 好题!

    由于不是求最大的可拦截的HP值,而是要将最小值最大化,那么就需要分配每个子树用的钱数以达到最小值最大化 第一步解决如何分配钱使得结点u的子树中用了j元钱后可以拦截的HP最大,这就是变形的分组(依赖)背 ...

  2. delete web server(nginx)

    #!/bin/bash conf_dir1="/usr/local/nginx/conf/vhost.d" #conf_dir2="/usr/local/apache2/ ...

  3. Sublime Text 3 快捷键总结(拿走)

    以下是个人总结不完全的快捷键总汇,祝愿各位顺利解放自己的鼠标. 选择类 Ctrl+D 选中光标所占的文本,继续操作则会选中下一个相同的文本. Alt+F3 选中文本按下快捷键,即可一次性选择全部的相同 ...

  4. 最新版谷歌浏览器的Flash设置已经不能保存了?

    解决方法:先去chrome实验室界面chrome://flags/#enable-ephemeral-flash-permission选择取消Disabled.取消该实验室选项. 然后去chrome: ...

  5. shell 写的 jrottenberg/ffmpeg 转码

    #!/bin/bash ];then echo "The argument must be 2" exit; else echo "$1 $2" fi VIDE ...

  6. Select2 多层次赋值时异步赋值的问题

    场景: 当选择人员时加载人员,选择部门时加载部门.所以在人员下,选择人员A后,如果选择部门,会触发二级select 重新获取数据. 问题: 使用select2()方法进行绑定远程数据后,对第二个sel ...

  7. System.Data.Entity.Internal.AppConfig"的类型初始值设定项引发异常

    在学习EF code First的小案例的时候,遇见了这个异常 <configSections> <!-- For more information on Entity Framew ...

  8. Redis-Sentinel 哨兵

    为什么需要哨兵? 一旦主节点宕机,那么需要人为修改所有应用方的主节点地址(改为新的master地址),还需要命令所有从节点复制新的主节点 那么这个问题,redis-sentinel就可以解决了 什么是 ...

  9. Hankson 的趣味题

    题解: 硬是把一道傻逼题写到了200行.. 长长的模板就有70行.. 由于我没有做的时候觉得并不保证$a1|a0$ $b0|b1$ 然后就加了很多特判.. 我的做法就是暴力分解质因数 T*sqrt(n ...

  10. 【BZOJ3697】采药人的路径

    题解: 比较简单的点分治 首先暴力的话直接枚举 然后枚举另一个点的时候顺便看一下有没有零点 n^2 考虑点分治 分治之后用f[i][0/1]表示权值为i,有没有零点的方案数 我们来证明一件事情,如果两 ...