Jquery插件-Html5图片上传并裁剪

/**
 * 图片裁剪
 * @author yanglizhe
 * 2015/11/16
 */
(function($){

    /**
     * Drag
     */
    var Drag={obj:null,init:function(elementHeader,element){elementHeader.onmousedown=Drag.start;elementHeader.obj=element;if(isNaN(parseInt(element.style.left))){element.style.left="0px"}if(isNaN(parseInt(element.style.top))){element.style.top="0px"}element.onDragStart=new Function();element.onDragEnd=new Function();element.onDrag=new Function()},start:function(event){var element=Drag.obj=this.obj;event=Drag.fixE(event);if(event.which!=1){return true}element.onDragStart();element.lastMouseX=event.clientX;element.lastMouseY=event.clientY;document.onmouseup=Drag.end;document.onmousemove=Drag.drag;return false},drag:function(event){event=Drag.fixE(event);if(event.which==0){return Drag.end()}var element=Drag.obj;var _clientX=event.clientY;var _clientY=event.clientX;if(element.lastMouseX==_clientY&&element.lastMouseY==_clientX){return false}var _lastX=parseInt(element.style.top);var _lastY=parseInt(element.style.left);var newX,newY;newX=_lastY+_clientY-element.lastMouseX;newY=_lastX+_clientX-element.lastMouseY;element.style.left=newX+"px";element.style.top=newY+"px";element.lastMouseX=_clientY;element.lastMouseY=_clientX;element.onDrag(newX,newY);return false},end:function(event){event=Drag.fixE(event);document.onmousemove=null;document.onmouseup=null;var _onDragEndFuc=Drag.obj.onDragEnd();Drag.obj=null;return _onDragEndFuc},fixE:function(ig_){if(typeof ig_=="undefined"){ig_=window.event}if(typeof ig_.layerX=="undefined"){ig_.layerX=ig_.offsetX}if(typeof ig_.layerY=="undefined"){ig_.layerY=ig_.offsetY}if(typeof ig_.which=="undefined"){ig_.which=ig_.button}return ig_}};

    /**
     * 创建样式表
     * @param String cssStr
     */
    function createStyle(cssStr){
        if( document.createStyleSheet){
            var style = document.createStyleSheet();
            style.cssText = cssStr;
        }
        else{
            var style = document.createElement("style");
            style.type = "text/css";
            style.textContent = cssStr;
            document.getElementsByTagName("head").item(0).appendChild(style);
        }
    }


    var MAX_SIZE = 200;

    function ImageCrop(config){
        this.zoomMin = 0.1; //最小比例
        this.zoomMax = 10; //最大比例
        this.wrapWidth = 280;
        this.wrapHeight = 260;
        this.gripMinX = 0;
        this.gripMaxX = 189;
        this.originalWidth = 0;
        this.originalHeight = 0;
        this.originalLeft = 0;
        this.origianlTop = 0;
        this._construct(config);
    }

    ImageCrop.prototype = {
        /**
         * 构建方法
         * @param config
         * @private
         */
        _construct:function(config){
            this.eventTarget = config.target;
            this.cropWidth = config.width || 140;
            this.cropHeight = config.height || 140;
            this.ratio = 1;
            if(this.cropWidth > MAX_SIZE || this.cropHeight > MAX_SIZE){
                if(this.cropWidth > this.cropHeight){
                    this.ratio = MAX_SIZE/this.cropWidth;
                    this.cropWidth = MAX_SIZE;
                    this.cropHeight *= this.ratio;
                }
                else{
                    this.ratio = MAX_SIZE / this.cropHeight;
                    this.cropHeight = MAX_SIZE;
                    this.cropWidth *= this.ratio;
                }
            }
            this.offsetX = (this.wrapWidth - this.cropWidth ) / 2;
            this.offsetY = (this.wrapHeight - this.cropHeight) / 2;
            this.destWidth = config.destWidth || this.cropWidth;
            this.destHeight = config.destHeight || this.cropHeight;
            this.onConfirm = config.onConfirm || function(){};
            var parent = config.container || $(document.body);
            this.initHTML(parent);
            this.bindEvent();

        },
        initHTML:function(parent){
            var html = '<div class="crop-container" style="display:block;">'+
                '    <div class="left-box">'+
                '        <div class="crop-wrapper">'+
                '            <div class="crop-preview"><div class="crop-preview-box"></div></div>'+
                '            <img class="crop-target" style="position:relative;" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />'+
                '        </div>'+
                '        <div class="crop-tool-bar">'+
                '            <span><a href="javascript:;" class="zoom-tool btn-zoom zoom-out" alt="图片缩小"></a></span>'+
                '            <span class="bar-zoom-box">'+
                '                <span class="zoom-tool bar-zoom"></span>'+
                '                <a href="javascript:;" class= "zoom-tool crop-grip"></a>'+
                '            </span>'+
                '            <span><a href="javascript:;" class="zoom-tool btn-zoom zoom-in"   alt="图片放大"></a></span>'+
                '        </div>'+
                '    </div>'+
                '    <div class="right-box">'+
                '        <div class="image-preview"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>'+
                '        <div class="btn-box"><a class="btn-upload-image" href="javascript:;">图片上传</a></div>'+
                '        <div class="btn-box"><a class="btn-confirm-crop" href="javascript:;">确认裁剪</a></div>'+
                '    </div>'+
                '</div>';
            this.container = $(html);

            this.find(".crop-preview").css({
                width : (this.cropWidth + 4) +"px",
                height: (this.cropHeight + 4) + "px",
                "border-width": (this.offsetY -2) +"px " + (this.offsetX - 2) +"px"
            });

            this.find(".crop-preview-box").css({
                width : (this.cropWidth) +"px",
                height: (this.cropHeight) + "px"
            });

            parent.append(this.container);
        },
        bindEvent:function(){
            this.cropTarget = this.find(".crop-target");
            this.cropGrip = this.find(".crop-grip");
            this.wrapper = this.find(".crop-wrapper");
            var _this = this;
            this.eventTarget.bind("click", function(){
                _this.show();
            });


            this.bindCropGrip();
            this.bindUpload();
            this.find(".btn-zoom").bind("click", function(){
               if($(this).hasClass("zoom-out")){
                    _this.scale(false);
               }
               else if($(this).hasClass("zoom-in")){
                   _this.scale(true);
               }
            });

            var canvas = document.createElement("canvas");
            canvas.width = this.destWidth;
            canvas.height = this.destHeight;

            var context = canvas.getContext("2d");
            this.find(".btn-confirm-crop").bind("click", function(){
                var target = _this.cropTarget.get(0);
                var top = parseInt(target.style.top);
                var left = parseInt(target.style.left);
                var offsetLeft = left - _this.originalLeft;
                var offsetTop = top - _this.origianlTop;
                var scale =  _this.zoom;
                var _left = (_this.zoom * _this.originalWidth - _this.cropWidth) / 2;
                var _top = (_this.zoom * _this.originalHeight - _this.cropHeight) / 2;
                var x = (-_left + offsetLeft) / scale;
                var y = (-_top + offsetTop) /scale;
                context.clearRect(0, 0, canvas.width, canvas.height);
                context.save();
                context.scale(scale, scale);
                context.drawImage(_this.cropTarget.get(0), x, y);
                context.restore();
                var base64Url = canvas.toDataURL("image/png");
                _this.find(".image-preview").find("img").attr("src", base64Url);
                _this.onConfirm(base64Url)
            });

        },
        bindUpload:function(){
            var _this = this;

            this.fileInput = $('<input type="file" accept="image/*" style="position: absolute;left: -999999px;" />');
            this.fileInput.bind("change", function(e){
                if($.trim($(this).val())==""){
                    return ;
                }
                var files = e.target.files || e.dataTransfer.files;
                var file = files[0];

                if(!/^image//.test(file.type)){
                    alert("请上传图片文件");
                    _this.fileInput.val("");
                    return false;
                }

                //对路径进行压缩
                var reader = new FileReader();
                reader.onload = function(e) {
                    var image = new Image();
                    image.onload = function(){
                        _this.cropTarget.attr("src", this.src);
                        _this.initImage(this.width, this.height);

                    };
                    image.src = e.target.result;
                }
                reader.readAsDataURL(file);
            });

            var _this = this;
            this.find(".btn-upload-image").bind("click", function(){
                _this.fileInput.trigger("click");
            });
        },
        initImage:function(width, height){

            var _this = this;
            var top = -(height - this.wrapHeight) / 2;
            var left =  -(width - this.wrapWidth) / 2;
            this.originalLeft = left;
            this.origianlTop = top;
            this.originalWidth = width;
            this.originalHeight = height;
            this.cropTarget.get(0).style.transform = "";
            this.cropTarget.css({
                top:top,
                left:left
            });
            this.zoomMin = 1;
            this.gripPos = 5;
            this.zoom = 1;
            if (width > this.cropWidth) {
                this.zoomMin = this.cropWidth / width;
            }
            this.zoomMax = this.zoomMin > 0.25 ? 8.0 : 4.0 / Math.sqrt(this.zoomMin);
            this.cropGrip.css({
                "left":(this.gripMinX + (this.gripPos / 10 * (this.gripMaxX - this.gripMinX))) + "px"
            });

            var target = this.cropTarget.get(0);
            Drag.init(this.wrapper.get(0), target);
            target.onDrag = function(){
                _this.rePosition();
            };
        },
        rePosition:function(){
            var target = this.cropTarget.get(0);
            var width = this.originalWidth;
            var height = this.originalHeight;
            var offsetLeft = parseInt(this.cropTarget.css("left"));
            var offsetTop = parseInt(this.cropTarget.css("top"));
            var _width = width * this.zoom;
            var _height = height * this.zoom;
            var _x = (_width - width ) / 2;
            var _y = (_height - height) / 2;

            var maxX = Math.max(this.offsetX, this.offsetX + this.cropWidth - _width) + _x;
            var minX = Math.min(this.offsetX + this.cropWidth - _width, this.offsetX) + _x;

            if (offsetLeft > maxX) target.style.left = maxX + 'px';
            else if (offsetLeft < minX) target.style.left = minX + 'px';

            var maxY = Math.max(this.offsetY, this.offsetY + this.cropHeight - _height) + _y;
            var minY = Math.min(this.offsetY + this.cropHeight - _height, this.offsetY) + _y;

            if (offsetTop > maxY) target.style.top = maxY + 'px';
            else if (offsetTop < minY) target.style.top = minY + 'px';
        },
        scale:function(flag){
            if (flag) {
                this.zoom = this.zoom * 1.5;
            } else {
                this.zoom = this.zoom / 1.5;
            }
            if (this.zoom < this.zoomMin) this.zoom = this.zoomMin;
            if (this.zoom > this.zoomMax) this.zoom = this.zoomMax;
            this.imageResize(this.zoom);
            this.gripPos = 5 * (Math.log(this.zoom * this.zoomMax) / Math.log(this.zoomMax));
            this.cropGrip.css({
                left:(this.gripMinX + (this.gripPos / 10 * (this.gripMaxX - this.gripMinX))) + "px"
            });
            this.rePosition();
        },
        bindCropGrip:function(){
            var _this = this;

            var cropGrip = this.cropGrip.get(0);
            Drag.init(cropGrip, cropGrip);
            cropGrip.onDrag = function (clientX, clientY) {
                var offsetX = clientX;
                if (clientX < _this.gripMinX) {
                    cropGrip.style.left = _this.gripMinX + "px";
                    offsetX = _this.gripMinX;
                }
                if (clientX > _this.gripMaxX) {
                    cropGrip.style.left = _this.gripMaxX + "px";
                    offsetX = _this.gripMaxX;
                }
                cropGrip.style.top = 0;
                var x = (offsetX - _this.gripMinX) * 10 / (_this.gripMaxX - _this.gripMinX);
                var zoom = Math.pow(_this.zoomMax, x / 5) / _this.zoomMax;
                if (zoom < _this.zoomMin) zoom = _this.zoomMin;
                if (zoom > _this.zoomMax) zoom = _this.zoomMax;
                _this.imageResize(zoom);
                _this.rePosition();
            }
        },
        imageResize:function(zoom){
            this.zoom = zoom;
            this.cropTarget.get(0).style.transform = "scale("+zoom+")";
        },
        show:function(){
            this.container.show();
        },
        hide:function(){
            this.container.hide();
        },
        find:function(selector){
            return $(selector, this.container);
        }
    };

    $.fn.imageCrop = function(config){
        return this.each(function(){
            new ImageCrop($.extend({
                target:$(this)
            },config||{}));
        });
    };


    createStyle('.crop-container{480px;height:300px;overflow:hidden;margin:10px auto;border:1px solid #e0e0e0;border-radius:5px;padding:10px}.zoom-tool{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAASCAYAAAGWfdOKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjIzMDY1QUQ4QzEzMTFFNUJGQTk5MTg5Q0Q5RjA1NjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjIzMDY1QUU4QzEzMTFFNUJGQTk5MTg5Q0Q5RjA1NjkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MjMwNjVBQjhDMTMxMUU1QkZBOTkxODlDRDlGMDU2OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo2MjMwNjVBQzhDMTMxMUU1QkZBOTkxODlDRDlGMDU2OSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiaUw1sAAAjASURBVHjaYvwPBAy0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);background-repeat:no-repeat}.left-box{float:left;height:320px;292px;overflow:hidden}.crop-wrapper{border:2px solid #888;280px;height:260px;overflow:hidden;position:relative;margin:4px;cursor:pointer;float:left}.crop-preview{144px;height:144px;border-color:#ccc;border-style:solid;border-58px 68px;position:absolute;z-index:1;opacity:.75}.crop-preview-box{140px;height:140px;border:2px solid #e0e0e0}.crop-tool-bar{252px;padding:4px 20px;height:20px;position:relative;overflow:hidden}.bar-zoom-box{position:relative;200px;display:inline-block}.crop-grip{position:absolute;z-index:100;left:100%;top:0;cursor:pointer;11px;height:18px;display:inline-block;background-position:-287px 0}.right-box{float:right;144px;padding:8px;height:280px}.right-box .image-preview{height:166px;144px;margin:8px auto;overflow:hidden;text-align:center;}.image-preview img{border:2px #eee solid;max-height:100%;max-140px;}.right-box .btn-box{height:50px;text-align:center}.right-box .btn-box a{display:inline-block;100px;padding:8px;text-align:center;border-radius:8px;text-decoration:none;border:1px solid #efefef;color:#FFF;font-size:14px;background:#80b6e7}.right-box .btn-box a:hover{background:#5498db}.btn-zoom{18px;height:18px;display:inline-block}.bar-zoom{200px;height:18px;display:inline-block}.zoom-out{background-position:-224px 0}.zoom-out:hover{background-position:-203px 0}.zoom-in{background-position:-266px 0}.zoom-in:hover{background-position:-245px 0}');




})(jQuery);

原文地址:https://www.cnblogs.com/rubekid/p/4970417.html