JavaScript實現本地圖片上傳前進行裁剪預覽

本項目支持IE8+,測試環境IE8,IE9,IE10,IE11,Chrome,FireFox測試經過javascript

另:本項目並不支持Vue,React等,也不建議,引入JQuery和Vue、React自己提倡的開發方式並不一致css

注:本項目未對移動端進行測試,不保證移動端可使用,而且也不推薦移動端使用這個項目,移動端建議使用Cropper插件,功能更豐富,也更強大,使用更便捷,地址:https://github.com/fengyuanchen/cropperhtml

在工做中會有不少項目須要實現圖片上傳裁剪預覽的功能,但目前不少插件基本上在較低版本的瀏覽器上使用的是flash來實現,我則更傾向於儘可能使用js來解決,在js無能爲力的時候再借助其餘的工具(其實更多的仍是由於不會,又懶得去學╮(╯﹏╰)╭,畢竟flash已經能夠說是被淘汰了),固然,實現這些功能的插件也很多,只不過,基本上都沒有實現頁面無刷新上傳的功能,或者都是須要先上傳圖片再對已上傳的圖片進行裁剪,或者兩個問題都有,這就不是我想要的功能了,我但願的是可以在還未上傳的時候就對其進行預覽,並裁剪,,也就是實現本地預覽裁剪並上傳裁剪結果。那麼,廢話收了那麼多,動手唄!java

此項目中使用的裁剪數據採集插件是Jcrop插件,這個插件感受作的仍是挺好的,那麼下一步就是進一步封裝這個插件咯,也就是說,須要本身來實現預覽和上傳,這個最終可以支持到IE8+jquery

先來上個效果圖先git

左側大圖就是咱們要上傳並進行裁剪的原圖,而右側則是最終裁剪的結果,恩,看起來好像仍是能夠的,恩,好,繼續github

html結構很簡單,無非就是引入css,js,寫個div就夠了,來看下html結構先(樣式直接寫在了頁面上,並無進行分離,懶-_-|||)web

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>IE Image Upload</title>
    <link rel="stylesheet" href="css/jquery.Jcrop.min.css">
    <script src="js/jquery-1.8.3.min.js"></script>
    <script type="text/javascript" src="js/jquery.Jcrop.min.js"></script>
    <script type="text/javascript" src="js/imgCropUpload.js"></script>
    <style type="text/css">
        body {
            font-size: 16px;
            font-family:"Microsoft YaHei",Arial, Helvetica, sans-serif
        }
        *,
        *:before,
        *:after {
            -webkit-box-sizing: border-box;
               -moz-box-sizing: border-box;
                -ms-box-sizing: border-box;
                    box-sizing: border-box;
        }

        .crop-picker-wrap {
            position: relative;
            width: 100px;
            height: 30px;
            overflow: hidden;
        }
        .crop-picker {
            width: 100%;
            height: 100%;
            line-height: 1;

            -webkit-appearance: none;
            margin: 0;
            border: none;
            border-radius: 5px;
            padding: 9px 0;
            background-color: #1ab2ff;

            color: #fff;            
            cursor: pointer;
        }
        .crop-picker-file {
            position: absolute;
            top: 0;
            right: 0;
            height: 100%;
            opacity: 0;
            cursor: pointer;
            filter: alpha(opacity=0);
        }

        .crop-wrapper {
            display: inline-block;
            min-width: 750px;
            margin: 10px 0;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 5px;
            box-shadow: 0 0 5px 2px #ccc;
        }

        .crop-container {
            font-size: 0;
        }

        .crop-container img[src=""] {
            visibility: hidden;
        }

        .crop-area-wrapper,
        .crop-preview-wrapper {
            display: inline-block;
            vertical-align: top;
        }
        .crop-area-wrapper {
            width: 500px;
            height: 400px;
        }
        .crop-preview-wrapper {
            width: 200px;
            height: 200px;
            margin-left: 28px;
            overflow: hidden;
        }
        .crop-preview-container {
            position: relative;
            overflow: hidden;
        }
        .crop-operate {
            text-align: center;
            margin: 10px 0;
        }
        .crop-save,
        .crop-cancel {
            display: inline-block;
            vertical-align: middle;

            width: 150px;
            height: 50px;
            line-height: 50px;

            -webkit-appearance: none;
            margin: 0 5px;
            border: none;
            border-radius: 5px;
            background-color: #1ab2ff;

            color: #fff;
            cursor: pointer;
        }
        .crop-hidden {
            display: none;
        }
    </style>
</head>
<body>
    <div id="TCrop"></div>
    <script type="text/javascript">
        $(function() {
            Crop.init({
                id: 'TCrop',
                /* 上傳路徑 */
                url: '',
                /* 容許上傳的圖片的後綴 */
                allowsuf: ['jpg', 'jpeg', 'png', 'gif'],
                /* JCrop參數設置 */
                cropParam: {
                    minSize: [50, 50],          // 選框最小尺寸
                    maxSize: [300, 300],        // 選框最大尺寸
                    allowSelect: true,          // 容許新選框
                    allowMove: true,            // 容許選框移動
                    allowResize: true,          // 容許選框縮放
                    dragEdges: true,            // 容許拖動邊框
                    onChange: function(c) {},   // 選框改變時的事件,參數c={x, y, x1, y1, w, h}
                    onSelect: function(c) {}    // 選框選定時的事件,參數c={x, y, x1, y1, w, h}
                },
                /* 是否進行裁剪,不裁剪則按原圖上傳,默認進行裁剪 */
                isCrop: true,
                /* 圖片上傳完成以後的回調,不管是否成功上傳 */
                onComplete: function(data) {
                    console.log('upload complete!');
                }
            });
        });
    </script>    
</body>
</html>

接下來咱們來看看js的實現json

首先咱們來分析下流程windows

簡單點說就是:選圖片 -> 預覽 -> 裁剪 -> 上傳,就像下面這樣

詳細點:選擇文件  -> 判斷文件類型是否容許上傳 -> 判斷瀏覽器類型 -> 預覽圖片 -> 裁剪並實時更新裁剪結果圖 -> 上傳原圖及裁剪信息,就像下面這樣

注意:這裏有一點須要關注下,那就是,有些同窗可能會發如今運行我這個項目的時候,那個隱藏的input文件選擇按鈕並無被真正的隱藏起來,而是定位到了選擇圖片那個標籤上,爲何要這麼作呢?而不直接使用js來出發input的click事件?緣由在於,爲了兼容IE8!在IE8下,使用js觸發的input文件選擇按鈕,並不能進行提交,會出現拒絕訪問的錯誤,這是IE8的一個安全策略,必須是用戶手動觸發的input選擇的文件才能夠在form表單中被提交

本地圖片預覽

對於這個項目而言,最重要的就是在不一樣的瀏覽器裏面如何進行預覽,至於裁剪,則所有交由Jcrop插件來進行,那麼咱們就來看看如何實現預覽吧

對於支持HTML5的File接口的瀏覽器

對於支持的瀏覽器,則能夠直接使用FileReader獲取圖片的數據,並在頁面進行展現,js以下:

var img = document.createElement('img');
img.style.visibility = 'hidden';
cropArea.appendChild(img);

img.onload = function() {
    /* 在圖片加載完成以後即可以獲取原圖的大小,根據原圖大小和預覽區域大小獲取圖片的縮放比例以及原圖在預覽時所展示的大小 */
    var scaleOpt = _getScale(cropArea.clientWidth, cropArea.clientHeight, img.offsetWidth, img.offsetHeight);
    img.setAttribute('style', 'position: absolute;visibility: visible;width: ' + scaleOpt.w + 'px;height: ' + scaleOpt.h + 'px');

    if(!opt.isCrop) {return ;}

    var cropPreviewImg = img.cloneNode(true);
    cropPreview.appendChild(cropPreviewImg);

    _startCrop(img, jcropOpt);

    /* 記錄原始比例,上傳數據須要還原實際裁剪尺寸 */
    Crop.ratio = scaleOpt.scale;
    /* 記錄裁剪圖片及裁剪預覽圖像對象,更新預覽圖時須要使用 */
    Crop.cropPreview = {
        cropAreaImg: img,
        cropPreviewImg: cropPreviewImg
    };
};
var fr = new FileReader();
fr.onload = function(eve) {                
    img.src = eve.target.result;
}
fr.readAsDataURL(fileInp.files[0]);

對於不支持HTML5的File接口的瀏覽器

對於不支持的IE八、9瀏覽器,則必需要使用濾鏡來進行實現,js實現以下,

PS:至於不考慮其餘不支持的瀏覽器,緣由在於,如今瀏覽器除IE八、9是被綁定在windows上而且基本不會自動升級外,其他現代瀏覽器都已實現了File接口,故不去考慮

var img = document.createElement('div');
img.style.visibility = 'hidden';
img.style.width = '100%';
img.style.height = '100%';
cropArea.appendChild(img);

fileInp.select();
var src = document.selection.createRange().text;
// console.log(document.selection.createRange());

var img_filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src='" + src + "')";            
img.style.filter = img_filter;

/* 需等待濾鏡加載完畢以後才能進行下一步操做 */
window.setTimeout(function() {
    _loadFiter(cropArea, img);
}, 100);


/* 加載濾鏡,等待兩秒,超時則斷定加載失敗 */
function _loadFiter(cropArea, img) {
    var time = 0;
    if(img.offsetWidth != cropArea.clientWidth) {
        /* 濾鏡加載成功,進入裁剪流程 */
        _filterCrop(cropArea, img);
    } else {
        time ++;
        if(time < 20) {
            window.setTimeout(function() {
                _loadFiter(cropArea, img);
            }, 100);
        } else {
            alert('圖片加載失敗,請重試!');
        }
    }
};

/* 使用濾鏡的裁剪 */
function _filterCrop(cropArea, img) {
    var scaleOpt = _getScale(cropArea.clientWidth, cropArea.clientHeight, img.offsetWidth, img.offsetHeight);
    /* 更改濾鏡設置 */
    var s_filter = img.style.filter.replace(/sizingMethod='image'/g, "sizingMethod='scale'");
    var jcropOpt = _getOpt().cropParam;

    img.setAttribute('style', 'position: absolute;visibility: visible;width: ' + scaleOpt.w + 'px;height: ' + scaleOpt.h + 'px;filter: ' + s_filter);

    if(!_getOpt().isCrop) {return ;}

    var cropPreview = cropArea.nextSibling.firstChild;
    var cropPreviewImg = img.cloneNode(true);
    cropPreview.appendChild(cropPreviewImg);

    _startCrop(img, jcropOpt);

    /* 記錄原始比例,上傳數據須要還原實際裁剪尺寸 */
    Crop.ratio = scaleOpt.scale;
    /* 記錄裁剪圖片及裁剪預覽圖像對象,更新預覽圖時須要使用 */
    Crop.cropPreview = {
        cropAreaImg: img,
        cropPreviewImg: cropPreviewImg
    };
};

以上即可以實現本地預覽,如下放出全部封裝後的源碼

若是有同窗須要使用這個項目的話,能夠直接將如下代碼封裝copy,並保存爲imgCropUpload.js,再如上面那個HTML頁面那樣引入便可

;(function(global, $, Crop) {
    var defaultOpt = {
        /* 整個圖片選擇、裁剪、上傳區域的最外圍包裹元素id,默認TCrop */
        id: 'TCrop',
        /* 上傳路徑 */
        url: '',
        /* 容許上傳的圖片的後綴,暫時支持如下四種,其他格式圖片未測試 */
        allowsuf: ['jpg', 'jpeg', 'png', 'gif'],
        /* JCrop參數設置 */
        cropParam: {
            minSize: [50, 50],          // 選框最小尺寸
            maxSize: [300, 300],        // 選框最大尺寸
            allowSelect: true,          // 容許新選框
            allowMove: true,            // 容許選框移動
            allowResize: true,          // 容許選框縮放
            dragEdges: true,            // 容許拖動邊框
            onChange: function(c) {},   // 選框改變時的事件
            onSelect: function(c) {}    // 選框選定時的事件,參數c={x, y, x1, y1, w, h}
        },
        /* 是否進行裁剪,不裁剪則按原圖上傳,默認進行裁剪 */
        isCrop: true,
        /* 圖片上傳完成以後的回調,不管是否成功上傳 */
        onComplete: function(data) {
            console.log('upload complete!');
        }
    };

    /* 記錄jcrop實例 */
    var jcropApi;

    /* 建立Dom結構 */
    /* 完整DOM結構 --s-- */
    /*
    <iframe id="uploadIfr" name="uploadIfr" class="crop-upload-ifr"></iframe>
    <form action="index.html" enctype="multipart/form-data" method="post" target="uploadIfr">
        <input type="hidden" name="cropData">
        <div class="crop-picker-wrap">
            <button class="crop-picker" type="button">選擇圖片</button>
            <input type="file" id="file" class="crop-picker-file">
        </div>
        <div class="crop-wrapper">
            <div class="crop-container clearfix">
                <div class="crop-area-wrapper"><img src="" alt=""></div>
                <div class="crop-preview-wrapper"><img src="" alt=""></div>
            </div>
            <div class="crop-operate">
                <div class="crop-save">上傳原圖</div>
                <div class="crop-save">保存截圖</div>
                <div class="crop-cancel">取消</div>
            </div>
        </div>
    </form>
    */
    /* 完整DOM結構 --e-- */
    function _createDom($wrap, opt) {
        var accept = 'image/' + opt.allowsuf.join(', image/');
        var $ifr = $('<iframe id="uploadIfr" name="uploadIfr" class="crop-hidden"></iframe>');
        var $form = $('<form action="' + opt.url + '" enctype="multipart/form-data" method="post" target="uploadIfr"/>');
        var $cropDataInp = $('<input type="hidden" name="cropData">');
        var $picker = $('<div class="crop-picker-wrap"><button class="crop-picker" type="button">選擇圖片</button></div>');
        var $fileInp = $('<input type="file" id="file" accept="' + accept + '" class="crop-picker-file">');
        $picker.append($fileInp);
        $form.append($cropDataInp).append($picker);

        var $cropWrap = $('<div class="crop-wrapper crop-hidden"/>');
        var $cropArea = $('<div class="crop-area-wrapper"></div>');
        var $cropPreviewWrap = $('<div class="crop-preview-wrapper"></div>');
        var $cropPreview = $('<div class="crop-preview-container"/>');
        $cropPreviewWrap.append($cropPreview);
        var $cropContainer = $('<div class="crop-container"/>').append($cropArea).append($cropPreviewWrap);
        $cropWrap.append($cropContainer);
        // var $saveSource = $('<div class="crop-save">上傳原圖</div>');
        var $save = $('<div class="crop-save">保存</div>');
        var $cropCancel = $('<div class="crop-cancel">取消</div>');
        var $cropOpe = $('<div class="crop-operate"/>').append($save).append($cropCancel);

        if(!opt.isCrop) {
            $cropPreviewWrap.addClass('crop-hidden');
        }

        $cropWrap.append($cropOpe);
        $form.append($cropWrap);

        $wrap.append($ifr).append($form);

        return {
                $ifr: $ifr,
                $form: $form,
                $cropDataInp: $cropDataInp,
                $cropPicker: $picker,
                $fileInp: $fileInp,
                $cropWrap: $cropWrap,
                $cropArea: $cropArea,
                $cropPreview: $cropPreview,
                // $saveSource: $saveSource,
                $save: $save,
                $cancel: $cropCancel
            };
    };

    /*
     * 綁定事件
     * 
     */
    function _bind($cropObj, opt) {
        
        var $cropPicker = $cropObj.$cropPicker;
        var $fileInp = $cropObj.$fileInp;
        var $save = $cropObj.$save;
        var $cancel = $cropObj.$cancel;
        var $ifr = $cropObj.$ifr;
        
        $fileInp.change(function(eve) {
            if(!this.value) {return ;}
            var fileSuf = this.value.substring(this.value.lastIndexOf('.') + 1);
            if(!_checkSuf(fileSuf, opt.allowsuf)) {
                alert('只容許上傳後綴名爲' + opt.allowsuf.join(',') + '的圖片');
                return ;
            }
            /* 進入裁剪流程 */
            _crop($cropObj, this);
            $cropPicker.addClass('crop-hidden').next().removeClass('crop-hidden');
        });

        $save.click(function(eve) {
            eve.preventDefault();
            Crop.upload();
        });

        $cancel.click(function(eve) {
            eve.preventDefault();
            Crop.cancel();
        });

        /* iframe的load應該延遲綁定,避免首次插入文檔中加載完畢時觸發load事件 */
        window.setTimeout(function() {
            $ifr.load(function() {
                var body = this.contentWindow.document.body;
                var text = body.innerText;
                opt.onComplete(text);
            });
        }, 100);        
    };

    /* 檢查文件是否符合上傳條件 */
    function _checkSuf(fileSuf, suffixs) {
        for(var i = 0, j = suffixs.length;i < j; i ++) {
            if(fileSuf.toLowerCase() == suffixs[i].toLowerCase()) {
                return true;
            }
        }
        return false;
    };

    /* 主要裁剪流程 */
    function _crop($cropObj, fileInp) {
        var cropArea = $cropObj.$cropArea.get(0);
        var cropPreview = $cropObj.$cropPreview.get(0);
        var opt = _getOpt();
        var jcropOpt = opt.cropParam;
        cropArea.innerHTML = '';
        if(fileInp.files && fileInp.files[0]) {
            var img = document.createElement('img');
            img.style.visibility = 'hidden';
            cropArea.appendChild(img);

            img.onload = function() {
                /* 在圖片加載完成以後即可以獲取原圖的大小,根據原圖大小和預覽區域大小獲取圖片的縮放比例以及原圖在預覽時所展示的大小 */
                var scaleOpt = _getScale(cropArea.clientWidth, cropArea.clientHeight, img.offsetWidth, img.offsetHeight);
                img.setAttribute('style', 'position: absolute;visibility: visible;width: ' + scaleOpt.w + 'px;height: ' + scaleOpt.h + 'px');

                if(!opt.isCrop) {return ;}

                var cropPreviewImg = img.cloneNode(true);
                cropPreview.appendChild(cropPreviewImg);

                _startCrop(img, jcropOpt);

                /* 記錄原始比例,上傳數據須要還原實際裁剪尺寸 */
                Crop.ratio = scaleOpt.scale;
                /* 記錄裁剪圖片及裁剪預覽圖像對象,更新預覽圖時須要使用 */
                Crop.cropPreview = {
                    cropAreaImg: img,
                    cropPreviewImg: cropPreviewImg
                };
            };
            var fr = new FileReader();
            fr.onload = function(eve) {                
                img.src = eve.target.result;
            }
            fr.readAsDataURL(fileInp.files[0]);
        } else {
            var img = document.createElement('div');
            img.style.visibility = 'hidden';
            img.style.width = '100%';
            img.style.height = '100%';
            cropArea.appendChild(img);

            fileInp.select();
            var src = document.selection.createRange().text;
            // console.log(document.selection.createRange());

            var img_filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src='" + src + "')";            
            img.style.filter = img_filter;

            /* 需等待濾鏡加載完畢以後才能進行下一步操做 */
            window.setTimeout(function() {
                _loadFiter(cropArea, img);
            }, 100);
        }        
    };

    /* 加載濾鏡,等待兩秒,超時則斷定加載失敗 */
    function _loadFiter(cropArea, img) {
        var time = 0;
        if(img.offsetWidth != cropArea.clientWidth) {
            /* 濾鏡加載成功,進入裁剪流程 */
            _filterCrop(cropArea, img);
        } else {
            time ++;
            if(time < 20) {
                window.setTimeout(function() {
                    _loadFiter(cropArea, img);
                }, 100);
            } else {
                alert('圖片加載失敗,請重試!');
            }
        }
    };

    /* 使用濾鏡的裁剪 */
    function _filterCrop(cropArea, img) {
        var scaleOpt = _getScale(cropArea.clientWidth, cropArea.clientHeight, img.offsetWidth, img.offsetHeight);
        /* 更改濾鏡設置 */
        var s_filter = img.style.filter.replace(/sizingMethod='image'/g, "sizingMethod='scale'");
        var jcropOpt = _getOpt().cropParam;

        img.setAttribute('style', 'position: absolute;visibility: visible;width: ' + scaleOpt.w + 'px;height: ' + scaleOpt.h + 'px;filter: ' + s_filter);

        if(!_getOpt().isCrop) {return ;}

        var cropPreview = cropArea.nextSibling.firstChild;
        var cropPreviewImg = img.cloneNode(true);
        cropPreview.appendChild(cropPreviewImg);

        _startCrop(img, jcropOpt);

        /* 記錄原始比例,上傳數據須要還原實際裁剪尺寸 */
        Crop.ratio = scaleOpt.scale;
        /* 記錄裁剪圖片及裁剪預覽圖像對象,更新預覽圖時須要使用 */
        Crop.cropPreview = {
            cropAreaImg: img,
            cropPreviewImg: cropPreviewImg
        };
    };

    /* 開始裁剪,初始化裁剪插件 */
    function _startCrop(img, jcropOpt) {
        var imgW = img.offsetWidth;
        var imgH = img.offsetHeight;
        var minW = jcropOpt.minSize[0], minH = jcropOpt.minSize[1];
        var offsetWidth = (imgW / 2) - (minW / 2);
        var offsetHeight = (imgH / 2) - (minH / 2);
        var obj = {
            x: offsetWidth,
            y: offsetHeight,
            x2: offsetWidth + minW,
            y2: offsetHeight + minH,
            w: minW,
            h: minH
        };
        $(img).Jcrop(jcropOpt, function() {
            jcropApi = this;
            this.animateTo([obj.x, obj.y, obj.x2, obj.y2]);
        });
    };

    /* 獲取配置參數opt */
    function _getOpt() {
        var id = Crop.crop.id;
        var cropDom = document.getElementById(id);
        var opt = $.data(cropDom, 'crop').opt;
        return opt;
    };

    /* 
     * 獲取縮放比例 
     * 
     * 原始寬高vw,vh
     * 實際顯示寬高sw,sh
     * 返回:
     * {w,h,scale:max(sw/vw,sh/vh)}
     * w,h均爲縮放到sw、sh後的寬高
     */
    function _getScale(vw, vh, sw, sh) {
        vw = Number(vw);
        vh = Number(vh);
        sw = Number(sw);
        sh = Number(sh);
        if(vw <= 0 || vh <= 0) {
            console.log('參數不能爲0');
            return false;
        }
        var wScale = sw / vw;
        var hScale = sh / vh;
        var scale = 1, w, h;

        if(wScale > hScale) {
            scale = wScale;
            w = vw;
            h = sh / scale;
        } else {
            scale = hScale;
            h = vh;
            w = sw / scale;
        }

        return {
            scale: scale,
            w: w,
            h: h
        };
    };

    /* 更新裁剪預覽圖 */
    function _updatePreview(c) {
        var cropAreaImg = Crop.cropPreview.cropAreaImg;
        var cropPreviewImg = Crop.cropPreview.cropPreviewImg;
        var $cropObj = $.data(document.getElementById(Crop.crop.id), 'crop').$cropObj;
        var $cropDataInp = $cropObj.$cropDataInp;
        var $cropPreview = $cropObj.$cropPreview;
        var $previewParent = $cropPreview.parent();
        var vw = $previewParent.width(), vh = $previewParent.height();
        var scaleOpt = _getScale(vw, vh, c.w, c.h);
        $cropPreview.width(scaleOpt.w);
        $cropPreview.height(scaleOpt.h);
        var width = $(cropAreaImg).width() / scaleOpt.scale;
        var height = $(cropAreaImg).height() / scaleOpt.scale;
        var top = -(c.y / scaleOpt.scale);
        var left = -(c.x / scaleOpt.scale);
        cropPreviewImg.style.width = width + 'px';
        cropPreviewImg.style.height = height + 'px';
        cropPreviewImg.style.top = top + 'px';
        cropPreviewImg.style.left = left + 'px';
        _setCropData($cropDataInp, c);
    };

    /* 設置裁剪數據 */
    function _setCropData($cropDataInp, c) {
        var ratio = Crop.ratio;
        var data = {
            x: c.x * ratio,
            y: c.y * ratio,
            w: c.w * ratio,
            h: c.h * ratio
        };
        
        var dataJson = JSON.stringify(data);
        $cropDataInp.val(dataJson);
    };

    /* 擴展配置參數,尤爲是Jcrop裁剪參數中的onSelect,onChange參數 */
    function _extendOpt(opt) {
        opt = $.extend(true, {}, defaultOpt, opt);
        var select = opt.cropParam.onSelect;
        var change = opt.cropParam.onChange;
        if(Object.prototype.toString.call(select) == '[object Function]') {
            opt.cropParam.onSelect = function(c) {
                _updatePreview.call(jcropApi, c);
                select.call(jcropApi, c);
            };
        } else {
            opt.cropParam.onSelect = _updatePreview;
        }
        if(Object.prototype.toString.call(change) == '[object Function]') {
            opt.cropParam.onChange = function(c) {
                _updatePreview.call(jcropApi, c);
                change.call(jcropApi, c);
            }
        } else {
            opt.cropParam.onChange = _updatePreview;
        }
        return opt;
    };

    /* 初始化上傳裁剪區域 */
    function init(opt) {
        var opt = _extendOpt(opt);
        var $uploadCropWrap = $('#' + opt.id);
        var hasDom = true;
        if($uploadCropWrap.length == 0) {
            $uploadCropWrap = $('<div id="' + opt.id + '" />');
            hasDom = false;
        }

        /* 清空Dom原有內部結構 */
        $uploadCropWrap.html('');
        var $cropObj = _createDom($uploadCropWrap, opt);

        $.data($uploadCropWrap.get(0), 'crop', {opt: opt, $cropObj: $cropObj});
        hasDom || $('body').append($uploadCropWrap);

        _bind($cropObj, opt);

        Crop.crop = {id: opt.id, hasDom: hasDom};
    };

    /* 上傳 */
    function upload() {
        var id = (Crop.crop && Crop.crop.id) || '';
        var dom = document.getElementById(id);
        if(!dom) {
            return ;
        }
        var form = $.data(dom, 'crop').$cropObj.$form.get(0);
        form.submit();
    };

    /* 取消裁剪 */
    function cancel() {
        var id = (Crop.crop && Crop.crop.id) || "";
        var dom = document.getElementById(id);
        if(!dom) {
            return ;
        }
        var $cropObj = $.data(dom, 'crop').$cropObj;
        $cropObj.$cropWrap.addClass('crop-hidden');
        $cropObj.$cropPicker.removeClass('crop-hidden');
    };

    /* 銷燬上傳裁剪區域 */
    function destroy() {
        var crop = Crop.crop || {};
        var $cropWrap = $('#' + crop.id);
        if(crop.hasDom === true) {
            $cropWrap.html('');
        } else {
            $cropWrap.remove();
        }
    };

    if($.isEmptyObject(Crop)) {
        global.Crop = Crop = {
            init: init,
            upload: upload,
            cancel: cancel,
            destroy: destroy,
            crop: {}
        };
    } else {
        Crop = $.extend(Crop, {
            init: init,
            upload: upload,
            cancel: cancel,
            destroy: destroy,
            crop: {}
        });
    }
})(window, jQuery, window.Crop || {});
View Code

後臺接受到的數據將會是兩個,一、上傳的圖片的二進制文件,二、json格式的裁剪數據,例如:'{"x":366.592,"y":208.89600000000002,"w":389.12,"h":335.872}'

因爲後端代碼屬於工做上的業務代碼,這裏再也不放出,其實實現也很簡單,也沒什麼複雜的邏輯,只須要對接收到的圖片直接進行裁剪便可,由於傳給後端的裁剪數據就是根據原圖的大小進行裁剪的數據

 

恩,以上,即是我我的在工做中遇到的關於本地圖片上傳預覽裁剪遇到的問題,並將之整理實現,我知道還有不少不足,我會繼續努力的。

各位如若發現什麼問題,也能夠指出,一塊兒探討進步,謝謝!

相關文章
相關標籤/搜索