html5,js插件實現手機端頭像剪切上傳

思路:先打開相冊,選取圖片,在剪切圖片,轉化爲base64格式,而後上傳到七牛存儲,返回url,再傳給後端,整個流程就是這樣。用的是angular框架,圖像插件用到imagecropper.js,廢話很少說,直接上代碼。javascript

效果:css

 

 

用到的插件html

<!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>	

 

頁面java

<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="width: 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="width: 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="width: 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="">

 

cssjquery

.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-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;
    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; }

jsios

/**
 * 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。web

 

這是我頭像上傳頁面的路由。chrome

 

 

 

 

若有什麼問題,歡迎指正。json

相關文章
相關標籤/搜索