layer 彈框 cropper 裁剪上傳圖片,thinkphp 3 使用 CropAvatar.class.php
阿新 • • 發佈:2018-11-15
最近要做一個上傳裁剪圖片功能,但是網上收出來的東西,知識點都是對的。但是就是沒說清楚,也無法連續起來用。
經過自己整理出來的一套程式碼,親測可用!
不用多說,直接上菜。
PS:搜尋引擎收錄的還是很垃圾......
呼叫頁面,簡單程式碼(可複用)
<img src="{$info.cover}" id="crop_img" width="150"> <input id="crop_img_value" type="hidden" name="cover" value="{$info.cover}" /> <a href="javascript:void();" class="btn btn-default" id="layer_upload">上傳封面</a>
$("#layer_upload").on("click",function(){
layer.open({
type: 2,
title: '上傳圖片',
shadeClose: true,
shade: 0.8,
area: ['95%', '95%'],
content: '/common/uploadimg'
});
});
layer 彈框頁面 uploadimg.tpl
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>上傳圖片</title> <link href="__STATIC__/cropavatar/css/bootstrap.min.css" rel="stylesheet"/> <link href="__STATIC__/cropavatar/css/cropper.min.css" rel="stylesheet"/> <link href="__STATIC__/cropavatar/css/main.css" rel="stylesheet"/> </head> <body> <div class="" id="crop-avatar"> <div id="avatar-modal" > <form class="avatar-form" id="avatar-form" enctype="multipart/form-data" method="post"> <div class="modal-header"> <h4 style="text-align: center;" class="modal-title" id="avatar-modal-label">上傳圖片</h4> </div> <div class="modal-body"> <div class="avatar-body"> <!-- Upload image and data --> <div class="avatar-upload"> <input class="options" id="options" name="options" type="hidden" value="cope"/> <input class="avatar-src" id="avatar_src" name="avatar_src" type="hidden" value=""/> <input class="avatar-data" id="avatar_data" name="avatar_data" type="hidden" value=""/> <label for="avatarInput" style="display:none;">圖片上傳</label> <input class="avatar-input" id="avatarInput" name="tmp_name" type="file"/> </div> <!-- Crop and preview --> <div class="row"> <div class="col-md-9"> <div class="avatar-wrapper"></div> </div> <div class="col-md-3"> <div class="avatar-preview preview-lg"></div> <div class="avatar-preview preview-md"></div> <div class="avatar-preview preview-sm"></div> </div> </div> <div class="row avatar-btns"> <div class="col-md-9"> <div class="btn-group"> <button class="btn btn-primary" data-method="rotate" data-option="-90" type="button" title="旋轉-90°">向左旋轉</button> <button class="btn btn-primary" data-method="rotate" data-option="-15" type="button">-15°</button> <button class="btn btn-primary" data-method="rotate" data-option="-30" type="button">-30°</button> <button class="btn btn-primary" data-method="rotate" data-option="-45" type="button">-45°</button> </div> <div class="btn-group"> <button class="btn btn-primary" data-method="rotate" data-option="90" type="button" title="旋轉90°">向右旋轉</button> <button class="btn btn-primary" data-method="rotate" data-option="15" type="button">15°</button> <button class="btn btn-primary" data-method="rotate" data-option="30" type="button">30°</button> <button class="btn btn-primary" data-method="rotate" data-option="45" type="button">45°</button> </div> <div class="btn-group" style="display:none;"> <label class="btn btn-primary" for="crop_caijian">裁剪</label> <input style="display:none;" id="crop_caijian" type="radio" name="options" value="cope" checked/> <label class="btn btn-primary" for="crop_yuantu">原圖</label> <input style="display:none;" id="crop_yuantu" type="radio" name="options" value="not_cut" /> </div> </div> <div class="col-md-3"> <button class="btn btn-primary btn-block avatar-save" type="button" onclick="sendPhoto()">確定上傳</button> </div> </div> </div> </div> </form> <img style="display:none;" id="viewpic" src="__STATIC__/cropavatar/images/picture.jpg" alt=""/> </div> </div> <script src="__STATIC__/cropavatar/js/jquery.min.js"></script> <script src="__STATIC__/cropavatar/js/bootstrap.min.js"></script> <script src="__STATIC__/cropavatar/js/cropper.min.js"></script> <script src="__STATIC__/tqkwap/layer/layer.js"></script> <script type="text/javascript"> (function (factory) { if (typeof define === 'function' && define.amd) { define(['jquery'], factory); } else if (typeof exports === 'object') { // Node / CommonJS factory(require('jquery')); } else { factory(jQuery); } })(function ($) { 'use strict'; var console = window.console || { log: function () {} }; function CropAvatar($element) { this.$container = $element; this.$avatar = this.$container.find('#viewpic'); this.$avatarModal = this.$container.find('#avatar-modal'); //this.$loading = this.$container.find('.loading'); this.$avatarForm = this.$avatarModal.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.$avatarBtns = this.$avatarForm.find('.avatar-btns'); this.$avatarWrapper = this.$avatarModal.find('.avatar-wrapper'); this.$avatarPreview = this.$avatarModal.find('.avatar-preview'); this.init(); console.log(this); } CropAvatar.prototype = { constructor: CropAvatar, support: { fileList: !!$('<input type="file">').prop('files'), blobURLs: !!window.URL && URL.createObjectURL, formData: !!window.FormData }, init: function () { this.support.datauri = this.support.fileList && this.support.blobURLs; if (!this.support.formData) { this.initIframe(); } this.initTooltip(); this.initModal(); this.addListener(); }, 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)); }, initTooltip: function () { }, initModal: function () { this.$avatarModal.modal({ show: false }); }, initPreview: function () { var url = this.$avatar.attr('src'); this.$avatarPreview.empty().html('<img src="' + url + '">'); }, initIframe: function () { var target = 'upload-iframe-' + (new Date()).getTime(), $iframe = $('<iframe>').attr({ name: target, src: '' }), _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.submitFail('Image upload failed!'); } _this.submitEnd(); }); }); this.$iframe = $iframe; this.$avatarForm.attr('target', target).after($iframe.hide()); }, click: function () { this.$avatarModal.modal('show'); this.initPreview(); }, change: function () { var files, 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({ aspectRatio: NaN, preview: this.$avatarPreview.selector, strict: false, viewMode: 2, crop: function (data) { var json = [ '{"x":' + data.x, '"y":' + data.y, '"height":' + data.height, '"width":' + data.width, '"rotate":' + data.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 = this.$avatarForm.attr('action'), data = new FormData(this.$avatarForm[0]), _this = this; $.ajax(url, { type: 'post', data: data, dataType: 'json', processData: false, contentType: false, beforeSend: function () { _this.submitStart(); }, success: function (data) { _this.submitDone(data); }, error: function (XMLHttpRequest, textStatus, errorThrown) { _this.submitFail(textStatus || errorThrown); }, complete: function () { _this.submitEnd(); } }); }, syncUpload: function () { this.$avatarSave.click(); }, submitStart: function () { //this.$loading.fadeIn(); }, submitDone: function (data) { console.log(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) { this.alert(data.message); } } else { this.alert('Failed to response'); } }, submitFail: function (msg) { this.alert(msg); }, submitEnd: function () { //this.$loading.fadeOut(); }, cropDone: function () { this.$avatarForm.get(0).reset(); this.$avatar.attr('src', this.url); this.stopCropper(); this.$avatarModal.modal('hide'); }, alert: function (msg) { var $alert = [ '<div class="alert alert-danger avater-alert">', '<button type="button" class="close" data-dismiss="alert">×</button>', msg, '</div>' ].join(''); this.$avatarUpload.after($alert); } }; $(function () { return new CropAvatar($('#crop-avatar')); }); }); var sendPhoto = function () { var data=$("#avatar_data").val(); var file=$("#avatarInput").val(); if(data=="" || file==""){ layer.msg('請選擇圖片,再提交!', { time: 5000, btn: ['確定'] }); return false; } var formData = new FormData($('#avatar-form')[0]); $.ajax({ url: '{:u('common/cropPicture')}', // 要上傳的地址 type: 'post', data: formData, dataType: 'json', cache: false, processData: false, contentType: false }).success(function (data) { if(data.state=="200" && data.result!=null){ $("#viewpic").attr("src",data.result); window.parent.$("#crop_img").attr("src",data.result); //回寫父級頁面 window.parent.$("#crop_img_value").attr("value",data.result); var index = parent.layer.getFrameIndex(window.name); parent.layer.close(index); } }).error(function(){ layer.msg("網路錯誤,稍後重試!"); }); } </script> </body> </html>
layer 彈出框 Action :commonAction.class.php
public function uploadimg(){ $this->display(); } //裁剪圖片 public function cropPicture() { if (IS_POST) { import('@.ORG.CropAvatar'); if ($_FILES['tmp_name']['error'] !== 0) { $response = array('state' => 200,'message' => '檔案過大或格式不對'); } else { $options = isset($_POST['options']) ? $_POST['options'] : 'cope'; if ($options == 'cope') { $crop = new CropAvatar( isset($_POST['avatar_src']) ? $_POST['avatar_src'] : null, isset($_POST['avatar_data']) ? $_POST['avatar_data'] : null, isset($_FILES['tmp_name']) ? $_FILES['tmp_name'] : null, '/data/upload/crop/'. date('Ymd') . '/'.'caijian/', '/data/upload/crop/'. date('Ymd') . '/'.'yuantu/' ); $response = array( 'state' => 200, 'message' => $crop -> getMsg(), 'result' => $crop -> getResult() ); } elseif ($options == 'not_cut') { if($_FILES['tmp_name']){ $file = $this->_upload($_FILES['tmp_name'], 'crop/picture/'); if ($file['error']) { $msg=$file['info']; } else { $file['info'][0]['savename'] = str_replace('.','.',$file['info'][0]['savename']); $data['tmp_name'] = "/" . C("yh_attach_path") . 'crop/picture/' . $file['info'][0]['savename']; } $response = array( 'state' => 200, 'message' => $msg, 'result' => $data['tmp_name'] ); } } } echo json_encode($response); } else { return json_encode('No data found!'); } }
如果你看到此處之後,還不能成功,說明你的裁剪類,不一致!
CropAvatar.class.php這個類我也除錯了好久,一直提示上傳成功,但是目錄始終沒有儲存到圖片!
原因:在類中儲存圖片沒有使用磁碟全路徑。我是這個問題,如果你不是請繞道!
執行截圖 此功能的全部程式碼,在此下載;不過你也可以直接敲。點選下載 https://download.csdn.net/download/ybb350680013/10522658