基于jquery的图片放大镜

261 阅读1分钟

//2017-11-09

不知道说啥,上源码吧

function ReadingGlasses(options){
    var opts = $.extend({
        node : null,
        thumbnail : [],
        callback : null
    },options);
    this.node = opts.node;
    this.thumbnail = opts.thumbnail;
    this.callback = opts.callback;
    this.editBox = this.node.find("[data-node='edit-box']");
    this.previewBox = this.node.find("[data-node='preview-box']");
};
ReadingGlasses.prototype = {
    constructor : ReadingGlasses,
    trigger : function(src){
        var _this = this;
        if(!_this.node || !_this.node.length || !src){return}
        _this.loadImage(src,function(img){
            _this.initeditBox(img);
            _this.initPreviewBox();
            //设置拖拽盒子相关
            _this.setDragBox();
        });
    },
    loadImage:function(src,fn){
		var _this = this;
        var img = new Image();
		img.src = src;
		if(img.complete){
            fn(img);
            return;
        }
        img.onload = function(){
            fn(img);
        };	
		img.onerror = function(){
            alert('图片加载失败');
		}
    },
    //获取编辑盒子尺寸
    geteditBoxSize : function(){
        var _this = this;
        _this.editBoxSize = {
            w : _this.editBox.width(),
            h : _this.editBox.height()
        }
    },
    //自适应宽度
    autoWidth : function(size){
        var _this = this;
        if(size.w > _this.editBoxSize.w){
            size.h = Math.round(_this.editBoxSize.w * size.h / size.w);
            size.w = _this.editBoxSize.w;
        }
        if(size.h > _this.editBoxSize.h){
            return _this.autoHeight(size);
        }
        return size
    },
    //自适应高度
    autoHeight : function(size){
        var _this = this;
        if(size.h > _this.editBoxSize.h){
            size.w = Math.round(_this.editBoxSize.h * size.w / size.h);
            size.h = _this.editBoxSize.h;
        }
        if(size.w > _this.editBoxSize.w){
            return _this.autoWidth(size);
        }
        return size;
    },
    //获取图片自适应尺寸
    getAutoimgSize : function(){
        var _this = this;
        //编辑盒子尺寸
        if(!_this.editBoxSize){
            _this.geteditBoxSize();
        }
        var size = {
            w : _this.imgInfo.w,
            h : _this.imgInfo.h
        };
        if(size.w > _this.editBoxSize.w || size.h > _this.editBoxSize.h){
            size = _this.autoWidth(size);
        }
        return size;
    },
    //获取图片定位
    getImgPosition : function(size){
        var _this = this;
        return {
            x : Math.round((_this.editBoxSize.w - size.w) / 2),
            y : Math.round((_this.editBoxSize.h - size.h) / 2)
        }
    },
    //插入图片
    appendImage : function(){
        var _this = this;
        //图片尺寸
        _this.imgSize = _this.getAutoimgSize();
        //图片定位
        _this.imgPosition = _this.getImgPosition(_this.imgSize);
        //style
        var style = {
            width : _this.imgSize.w + 'px',
            height : _this.imgSize.h + 'px',
            left : _this.imgPosition.x + 'px',
            top : _this.imgPosition.y + 'px'
        }
        //是否已经存在img节点
        if(_this.editBox.children('img').length){
            _this.editBox.children('img').prop('src',_this.imgInfo.src).css(style);
            return;
        } 
        _this.editBox.append($("<img src='" + _this.imgInfo.src + "'/>").css(style));
        
    },
    //插入蒙板
    appendMaskLayer : function(){
        var _this = this;
        if(_this.mask){return}
        _this.editBox.append("<div class='mask-layer vo-null'>蒙板</div>");
        _this.mask = _this.editBox.children('.mask');
    },
    //创建拖拽层
    createDragLayer : function(){
        var html = ["<div class='drag-layer'>"];
        html.push("<div class='drag-box'>");
        html.push("<div class='drag-cover'><img/></div>");
        html.push("<b class='b-top vo-null'>上边线</b>");
        html.push("<b class='b-bottom vo-null'>下边线</b>");
        html.push("<b class='b-left vo-null'>左边线</b>");
        html.push("<b class='b-right vo-null'>右边线</b>");
        html.push("<a href='javascript:;' class='drag-button vo-null'>拖拽按钮</a>");
        html.push("</div>");
        html.push("</div>");
        return html.join('');
    },
    //初始化拖拽层
    initDragLayer : function(){
        var _this = this;
        //设置拖拽层
        _this.dragLayer.css({
            width : _this.imgSize.w + 'px',
            height : _this.imgSize.h + 'px',
            left : _this.imgPosition.x + 'px',
            top : _this.imgPosition.y + 'px'
        });
        //设置拖拽图片尺寸
        _this.dragImg.prop('src',_this.imgInfo.src).css({
            width : _this.imgSize.w + 'px',
            height : _this.imgSize.h + 'px'
        });
        //初始化拖拽盒子信息
        _this.initDragBoxInfo();
    },
    //初始化拖拽盒子信息
    initDragBoxInfo : function(){
        var _this = this;
        //设置拖拽盒子信息
        var size = _this.imgSize.w > _this.imgSize.h ? _this.imgSize.h : _this.imgSize.w;
        _this.dragBoxInfo = {
            size : size,
            x : Math.round((_this.imgSize.w - size) / 2),
            y : Math.round((_this.imgSize.h - size) / 2),
            offsetX : 0,
            offsetY : 0,
            offsetSize : 0
        }
    },
    //设置拖动盒子信息
    setDragBoxInfo : function(params){
        var _this = this;
        var state = false;
        for(var key in params){
            if(typeof _this.dragBoxInfo[key] == 'undefined' || _this.dragBoxInfo[key] == params[key]){
                continue;
            }
            state = true;
            _this.dragBoxInfo[key] = params[key];
        }
        //是否设置拖动盒子
        if(state){
            _this.setDragBox();
        }
    },
    //获取真是信息
    getRealDragBoxInfo : function(){
        var _this = this;
        return {
            size : _this.dragBoxInfo.size + _this.dragBoxInfo.offsetSize,
            x : _this.dragBoxInfo.x + _this.dragBoxInfo.offsetX,
            y : _this.dragBoxInfo.y + _this.dragBoxInfo.offsetY
        }
    },
    //设置拖拽盒子
    setDragBox : function(){
        var _this = this;
        var info = _this.getRealDragBoxInfo();
        _this.dragBox.css({
            width : info.size + 'px',
            height : info.size + 'px',
            left : info.x + 'px',
            top : info.y + 'px'
        });
        _this.dragCover.scrollTop(info.y).scrollLeft(info.x);
        //设置预览盒子
        _this.setPreviewBox();
        //设置坐标
        _this.setGrid();
    },
    //插入拖拽盒子
    appendDragLayer : function(){
        var _this = this;
        if(!_this.dragLayer){
            _this.editBox.append(_this.createDragLayer());
            _this.dragLayer = _this.editBox.children('.drag-layer');
            _this.dragBox = _this.dragLayer.children('.drag-box');
            _this.dragCover = _this.dragBox.children('.drag-cover');
            _this.dragImg = _this.dragCover.find('img');
            _this.dragBtn = _this.dragBox.children('.drag-button');
            //绑定拖动事件
            _this.bindDragEve();
        }
        _this.initDragLayer();
    },
    //初始化编辑盒子
    initeditBox : function(img){
        var _this = this;
        //设置img信息
        _this.imgInfo = {
            w : img.width,
            h : img.height,
            src : img.src
        }
        //插入
        _this.appendImage();
        _this.appendMaskLayer();
        _this.appendDragLayer();

    },
    //设置预览图片
    setPreviewer : function(node){
        var _this = this;
        var $img = node.children('img');
        var size = parseInt(node.attr('data-size'));
        var info = _this.getRealDragBoxInfo();
        //设置图片尺寸
        $img.css({
            width : Math.round(size * _this.imgSize.w / info.size) + 'px'
        });
        //设置position
        var top = Math.round(size * info.y / info.size),
            left = Math.round(size * info.x / info.size);
        node.scrollTop(top).scrollLeft(left);
    },
    //设置预览盒子
    setPreviewBox : function(){
        var _this = this;
        if(!_this.previewBox.length || !_this.thumbnail.length){return}
        _this.previewBox.children().each(function(){
            _this.setPreviewer($(this));
        });
    },
    //设置坐标
    setGrid:function(){
        var _this = this;
        var info = _this.getRealDragBoxInfo();
        var start = info.x + ',' + info.y,
            end = (info.x + info.size) + ',' + (info.y + info.size);
        var grid = start + ':' + end;
        if(typeof _this.callback == 'function'){
            _this.callback.call(_this.node.get(0),grid);
        }
    },
    //创建预览
    createPreviewer : function(){
        var _this = this;
        var html = [];
       for(var i = 0,len = _this.thumbnail.length; i < len; i++){
           var style = "width:" + _this.thumbnail[i] + 'px; height:' + _this.thumbnail[i] + 'px';
            html.push("<div data-size='" + _this.thumbnail[i] + "' class='preview-cover pw-" + i + "' style='" + style + "'><img src='" + _this.imgInfo.src +"'></div>");
       }
       _this.previewBox.html(html.join(''));
    },
    //初始化预览盒子
    initPreviewBox : function(){
        var _this = this;
        if(!_this.previewBox.length || !_this.thumbnail.length){return}
        //创建预览
        _this.createPreviewer();
    },
    //移动
    handleMove : function(){
        var _this = this;
        return function(info){
            var xy = info.offsetXY;
            //极限值
            if(xy.x < 0){
                xy.x = xy.x < -_this.dragBoxInfo.x ? -_this.dragBoxInfo.x : xy.x;
            }else{
                var maxX = _this.imgSize.w - _this.dragBoxInfo.size - _this.dragBoxInfo.x;
                xy.x = xy.x > maxX ? maxX : xy.x;
            }
            if(xy.y < 0){
                xy.y = xy.y < -_this.dragBoxInfo.y ? -_this.dragBoxInfo.y : xy.y;
            }else{
                var maxY = _this.imgSize.h - _this.dragBoxInfo.size - _this.dragBoxInfo.y;
                xy.y = xy.y > maxY ? maxY : xy.y;
            }
            _this.setDragBoxInfo({
                offsetX : xy.x,
                offsetY : xy.y
            });
        }
    },
    //移动结束
    handleMoveEnd : function(){
        var _this = this;
        return function(){
            //确认
            var x = _this.dragBoxInfo.x + _this.dragBoxInfo.offsetX,
                y = _this.dragBoxInfo.y + _this.dragBoxInfo.offsetY;
                _this.setDragBoxInfo({
                    x : x,
                    y : y,
                    offsetX : 0,
                    offsetY : 0
                });
        }
    },
    //改变尺寸
    handleSize : function(){
        var _this = this;
        return function(info){
            var xy = info.offsetXY;
            if((xy.x > 0 && xy.y < 0) || (xy.x < 0 && xy.y > 0)){return}
            var offset = Math.abs(xy.x) > Math.abs(xy.y) ? xy.x : xy.y; 
            //极限值
            if(offset > 0){
                var max = (_this.imgSize.h > _this.imgSize.w ? _this.imgSize.w - _this.dragBoxInfo.x : _this.imgSize.h - _this.dragBoxInfo.y) - _this.dragBoxInfo.size;
                offset = offset > max ? max : offset;
            }else{
                var min = 1 - _this.dragBoxInfo.size;
                offset = offset < min ? min : offset;
            }
            _this.setDragBoxInfo({
                offsetSize : offset
            });
        }
    },
    handleSizeEnd : function(){
        var _this = this;
        return function(){
            //确认
            var size = _this.dragBoxInfo.size + _this.dragBoxInfo.offsetSize;
            _this.setDragBoxInfo({
                size : size,
                offsetSize : 0
            });
        }
    },
    //绑定拖动相关事件
    bindDragEve : function(){
        var _this = this;
        _this.dragImg.vo_mouseDrag({
            moveCallback:_this.handleMove(),
            endCallback:_this.handleMoveEnd()
        });
        _this.dragBtn.vo_mouseDrag({
            moveCallback:_this.handleSize(),
            endCallback:_this.handleSizeEnd()
        });
    }
};

sCss:

.vo-reading-glasses{
    //编辑盒子
    .edit-box{
        float: left;
        position: relative;
        width: 200px;
        height: 200px;
        border: 1px solid #000000;
        margin: 0 10px 0 0;
        img{
            position: absolute;
        }
        .mask-layer{
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background: #ffffff;
            opacity: 0.4;
            filter:Alpha(opacity = 40);
        }
        .drag-layer{
            position: absolute;
            .drag-box{
                position: absolute;
                .drag-cover{
                    position: absolute;
                    left: 0;
                    top: 0;
                    width: 100%;
                    height: 100%;
                    overflow: hidden;
                    img{
                        position: absolute;
                        cursor: move;
                    }
                }
                b{
                    position: absolute;
                    background: red;
                    opacity: 0.5;
                    filter:Alpha(opacity = 50);
                }
                .b-top,
                .b-bottom{
                    width: 100%;
                    height: 1px;
                    left: 0;
                }
                .b-left,
                .b-right{
                    width: 1px;
                    height: 100%;
                    top: 0;
                }
                .b-top{
                    top: 0;
                }
                .b-bottom{
                    bottom: 0;
                }
                .b-left{
                    left: 0;
                }
                .b-right{
                    right: 0;
                }
                .drag-button{
                    position: absolute;
                    bottom: -6px;
                    right: -6px;
                    width: 6px;
                    height: 6px;
                    background: red;
                    cursor: se-resize;
                }
            }
        }
    }
    //预览盒子
    .preview-box{
        .preview-cover{
            margin: 0 0 10px;
            overflow: hidden;
            border: 1px solid red;
        }
    }
    .vo_browse-image{
        margin: 10px 0 0;
    }
}

使用:

<div class="vo-reading-glasses">
    <div class="vo-clear">
        <div class="edit-box" data-node="edit-box"></div>
        <div class="preview-box" data-node="preview-box"></div>
    </div>
    <input type="hidden" name="grid"/>
</div>
var readingGlasses = new Virgo.readingGlasses({
        node : $(".vo-reading-glasses"),
        thumbnail : [50,100,150],
        callback : function(grid){
            $(this).find("[name='grid']").val(grid);
        }
    });
    readingGlasses.trigger('xxx.jpg');