zoukankan      html  css  js  c++  java
  • html5,js插件实现手机端头像剪切上传

    思路:先打开相册,选取图片,在剪切图片,转化为base64格式,然后上传到七牛存储,返回url,再传给后端,整个流程就是这样。用的是angular框架,图像插件用到imagecropper.js,废话不多说,直接上代码。

    效果:

    用到的插件

    <!DOCTYPE html>
    <html lang="en" ng-app="">
    <head>
        <meta name="viewport"
            content="initial-scale=1,maximum-scale=1,user-scalable=no,width=device-width,height=device-height"/>
    	<meta charset="UTF-8">
    	<title></title>
        
    	<script type="text/javascript" src="app/lib/jquery.js"></script>
    	
    	<script type="text/javascript" src="app/lib/ionic/js/ionic.bundle.min.js"></script>
    
    	<!-- 上传头像插件 -->
    	
    	<script src="app/lib/headimg/imagecropper.js"></script>
    	
    	<base href='/'/>
    
    </head>
    <body>
    <ion-nav-view>
    </ion-nav-view>
    
    
     <script type="text/javascript" src="app/dist/js/main-396e1d7cdb.js"></script>
    
    </body>
    </html>	
    

     

    页面

    <ion-header-bar align-title="center" class="bar-light">
      <button ui-sref="home.my" class="button button-clear"><i class="icon ion-ios-arrow-left"></i></button>
      <h1 class="title">个人资料</h1>
    </ion-header-bar>
    <ion-content class="my">
      <ion-list>
        <ion-item class="item-input" style="height:1.1rem;" >
          <form id="form0" class="item-icon-right"  href="javascript:void(0);" style=" 100%">
            <span class="input-label  f26" style="margin-top:0.4rem; ">头像</span>
              <i class="icon "><img ng-src="{{info.headimgurl||'app/dist/img/my/me_img.png'}}"  style=" 0.8rem;position: absolute;top: 0.1rem;right:0.7rem;border-radius:50%;border:3px solid rgba(0,0,0,0.3)" /></i>
              <!-- <form name="form0" id="form0" style=" 100%"> -->
                  <input type="file" name="file0" id="file0" multiple="multiple"><br>
             <!--  </form> -->
              <i class="icon "><img src="app/dist/img/my/arrow_icon.png" class="arrow_icon"></i>
            </form>
        </ion-item>
    
      </ion-list>
      
     
    
    </ion-content> 
    <div class="img-container">  
            <img id="img0" src="">  
            <div class="close"><button class="button button-large button-light">取消</button></div>
            <div class="saveBtn" on-tap="save()"><button class="button button-large  button-light" >选取</button></div>
      </div>
      <img class="newImg" src="">

    css

    .albumsbox {
      width: 18.9375rem;
      position: absolute;
      bottom: 0;
      left: 0.53125rem;
      display: none;
      z-index: 999; }
      .albumsbox .albums, .albumsbox .cancel {
        width: 100%;
        height: 6.1875rem;
        background: #fff;
        border-radius: 0.625rem;
        color: #333333;
        font-size: 0.8125rem;
        line-height: 3.0625rem;
        text-align: center; }
        .albumsbox .albums .line, .albumsbox .cancel .line {
          border-bottom: 1px solid #d1d1d4; }
      .albumsbox .cancel {
        height: 3.0625rem;
        margin: 0.34375rem 0rem 0.5625rem 0rem; }
    
    .container {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      display: none;
      background: #000; }
      .container #wrapper {
        width: 100%;
        height: 12.5rem;
        position: absolute;
        top: 40%;
        margin-top: -6.25rem;
        left: 0; }
        .container #wrapper #cropper {
          width: 100%; }
        .container #wrapper #previewContainer {
          display: none; }
    
    /*img prev*/
    .img-container {
      width: 100%;
      height: 100%;
      position: absolute;
      top: 0;
      left: 0;
      display: none;
      background: #000; }
    
    .newImg {
      display: none; }
    
    .close {
      height: 1.1875rem;
      width: 30%;
      text-align: center;
      color: #fff;
      font-size: 0.8125rem;
      line-height: 1.1875rem;
      position: absolute;
      bottom: 1.5625rem;
      left: 0; }
    
    .saveBtn {
      height: 1.1875rem;
      width: 30%;
      text-align: center;
      color: #fff;
      font-size: 0.8125rem;
      line-height: 1.1875rem;
      position: absolute;
      bottom: 1.5625rem;
      right: 0; }
    
    .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 !important;
      -ms-touch-action: none;
      touch-action: none;
      -webkit-tap-highlight-color: transparent;
      -webkit-touch-callout: none; }
    
    .cropper-container img {
      display: block;
      width: 100%;
      min-width: 0 !important;
      max-width: none !important;
      height: 100%;
      min-height: 0 !important;
      max-height: none !important;
      image-orientation: 0deg !important; }
    
    .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;
      filter: alpha(opacity=0); }
    
    .cropper-modal {
      opacity: .5;
      background-color: #000;
      filter: alpha(opacity=50); }
    
    .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;
      filter: alpha(opacity=50); }
    
    .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;
      filter: alpha(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;
      filter: alpha(opacity=10); }
    
    .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;
      filter: alpha(opacity=75); }
    
    .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;
      filter: alpha(opacity=100); }
    
    .cropper-point.point-se:before {
      position: absolute;
      right: -50%;
      bottom: -50%;
      display: block;
      width: 200%;
      height: 200%;
      content: ' ';
      opacity: 0;
      background-color: #39f;
      filter: alpha(opacity=0); }
    
    @media (min- 768px) {
      .cropper-point.point-se {
        width: 15px;
        height: 15px; } }
    @media (min- 992px) {
      .cropper-point.point-se {
        width: 10px;
        height: 10px; } }
    @media (min- 1200px) {
      .cropper-point.point-se {
        width: 5px;
        height: 5px;
        opacity: .75;
        filter: alpha(opacity=75); } }
    .cropper-invisible {
      opacity: 0;
      filter: alpha(opacity=0); }
    
    .cropper-hide {
      position: absolute;
      display: block;
      width: 0;
      height: 0; }
    
    .cropper-hidden {
      display: none !important; }
    
    .cropper-move {
      cursor: move; }

    js

    /**
     * laoyou Module
     *
     * Description
     */
    angular.module('app').controller('myEditCtrl', ['$scope', 'api', '$rootScope', '$http', '$state', '$stateParams','$ionicModal','qiniuConfig', function($scope, api, $rootScope, $http, $state, $stateParams,$ionicModal,qiniuConfig) {
        var showLoad = $rootScope.showLoad;
    
        $http.post("member/info",{test:1}).success(function(data){
            $scope.info=data.data;
            if(!$scope.info.birthday){
                $scope.info.birthday=new Date("1951-01-01");
            }else{
                $scope.info.birthday=new Date($scope.info.birthday);
            }
        }).error(function(){
            $rootScope.loadFn.hide();
        });
        
    
        var config=angular.copy(qiniuConfig);
        // console.log(config)
        if(config){
            var token=config.UpToken;
        }
        
                
                
    
               /*picBase是base64图片带头部的完整编码*/
        function putb64(picBase){
    
                /*picUrl用来存储返回来的url*/
                var picUrl;
    
                /*把头部的data:image/png;base64,去掉。(注意:base64后面的逗号也去掉)*/
                picBase=picBase.substring(22);
    
                /*通过base64编码字符流计算文件流大小函数*/
                function fileSize(str)
                {
                    var fileSize;
                    if(str.indexOf('=')>0)
                    {
                        var indexOf=str.indexOf('=');
                        str=str.substring(0,indexOf);//把末尾的’=‘号去掉
                    }
    
                    fileSize=parseInt(str.length-(str.length/8)*2);
                    return fileSize;
                }
    
                /*把字符串转换成json*/
                function strToJson(str)
                { 
                    var json = eval('(' + str + ')'); 
                    return json; 
                } 
    
    
                var url = "http://up.qiniu.com/putb64/"+fileSize(picBase); 
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange=function()
                {
                    if (xhr.readyState==4){
                        var keyText=xhr.responseText;
                        // alert(keyText)
                        /*返回的key是字符串,需要装换成json*/
                        keyText=strToJson(keyText);
                        
                        /* http://ojvh6i96g.bkt.clouddn.com/是我的七牛云空间网址,keyText.key 是返回的图片文件名*/
                        picUrl=config.recordPath+'/'+keyText.key;
                        // alert(picUrl);
                        $http.post("member/updateHead",{headimgurl:picUrl}).success(function (res) {
                            if( res.statusCode == 0) {
                                
                              window.location.reload();
                            }else{
                              alert("修改失败");
                            }
                          }).error(function(data){
                              alert("网络异常")
                          });
                    }
                }
                xhr.open("POST", url, true); 
                xhr.setRequestHeader("Content-Type", "application/octet-stream"); 
                xhr.setRequestHeader("Authorization", "UpToken "+ token); //token换成自己申请七牛的。
                xhr.send(picBase);
    
             }
         // var _czc = [];
    
        $("#file0").change(function(){
          // _czc.push(["_trackEvent", "个人资料页","头像",""]);
          // console.log($("#img0"))
          var objUrl = getObjectURL(this.files[0]) ;
          console.log("objUrl = "+objUrl) ;
          if (objUrl) {
            $("#img0").attr("src", objUrl) ;
            $('.cropper-canvas img').attr('src',objUrl);
            $('.cropper-view-box img').attr('src',objUrl);
          }
          var File=$('#img0').attr('src');
          if(File!=''||File==undefined){
              // $scope.openModal();
            $(".my").css('opacity','0');
            $('.img-container').show();
          }
        }) ;
    
        //建立一個可存取到該file的url
        function getObjectURL(file) {
            console.log(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 ;
        }
    
        $('.close').click(function(){
            $(".my").css('opacity','1');
          $('.img-container').hide();
        })
    
        function convertToData(url, canvasdata, cropdata, callback) {
          var cropw = cropdata.width; // 剪切的宽
          var croph = cropdata.height; // 剪切的宽
          var imgw = canvasdata.width; // 图片缩放或则放大后的高
          var imgh = canvasdata.height; // 图片缩放或则放大后的高
    
          var poleft = canvasdata.left - cropdata.left; // canvas定位图片的左边位置
          var potop = canvasdata.top - cropdata.top; // canvas定位图片的上边位置
    
          var canvas = document.createElement("canvas");
          var ctx = canvas.getContext('2d');
    
          canvas.width = cropw;
          canvas.height = croph;
    
          var img = new Image();
          img.src = url;
    
          img.onload = function() {
            this.width = imgw;
            this.height = imgh;
            // 这里主要是懂得canvas与图片的裁剪之间的关系位置
            ctx.drawImage(this, poleft, potop, this.width, this.height);
            var base64 = canvas.toDataURL('image/jpg', 1);  // 这里的“1”是指的是处理图片的清晰度(0-1)之间,当然越小图片越模糊,处理后的图片大小也就越小
            callback && callback(base64)      // 回调base64字符串
          }
        }
    
        $(function(){
    
          var $image = $('.img-container > img');
    
          $image.on("load", function() {        // 等待图片加载成功后,才进行图片的裁剪功能
              $image.cropper({  
                  aspectRatio: 1 / 1    // 1:1的比例进行裁剪,可以是任意比例,自己调整  
              });
          })
    
          // 点击保存
          // $(".saveBtn").on("click", function() {
          $scope.save = function(){
    
              var src = $image.eq(0).attr("src");  
              var canvasdata = $image.cropper("getCanvasData");  
              var cropBoxData = $image.cropper('getCropBoxData');  
              convertToData(src, canvasdata, cropBoxData, function(basechar) {
                  // 回调后的函数处理  
                  $(".newImg").attr("src", basechar);
                  // alert(basechar)
                  putb64(basechar);
                  
              });
          }
        })
    
    }]);

     其中qiniuConfig是自己向后台要的,这是上传图片的身份凭证,这是我的qiniuConfig。

    这是我头像上传页面的路由。

     

    如有什么问题,欢迎指正。

  • 相关阅读:
    栈及练习
    约瑟夫问题
    双向链表
    链表
    线性表
    高级排序
    建议16:比较函数调用模式
    建议15:推荐动态调用函数
    建议14:灵活使用Arguments
    建议13:禁用Function构造函数
  • 原文地址:https://www.cnblogs.com/s-quan/p/6871977.html
Copyright © 2011-2022 走看看