今天有时间开始动手,使用css+jquery实现了图片局部放大的组件,首先看看效果图:

          界面设计思路如下: 

   1.两个div,左边放图片的缩略图
2.在左边缩略图鼠标移动的时候,区域(效果图中的网格)
3.右边放大图div,背景为缩略图的大图,在鼠标移入缩略图中,通过获取鼠标的坐标,将右侧背景图片移动到跟鼠标坐标对应的位置
4.设计时尽量,获取原大图的尺寸,和缩略图视窗计算比例,更大精度的做到左侧缩略图上表示的区域,和右侧放大部分匹配

         本示例大部分编码在javascript脚本,以下列出各部分的源码: 

<div class="all-region">
    <div class="image-wrap">
<!--缩略图div-->
<div class="little-img"> <img src="./images/show-window/timg.jpg"> </div>
<!--图片放大div-->
<div class="large-img"> </div>
<!--缩略图上展示被放大的区域,网格区域-->
<div class="relative-region"></div> </div> </div>

        css:

    .all-region {
        width: 100%;
        height: auto;
    }

    .all-region .image-wrap {
        width: 1300px;
        margin: 0px auto;
        height: 300px;
        line-height: 300px;
        overflow: hidden;
        vertical-align: center;
        background: #FBFBFB;
        border-left: 1px solid #ebebeb;
        position: relative;
    }

    .image-wrap .little-img img {
        width: 600px;
        height: 300px;
    }

    .image-wrap .large-img {
        width: 600px;
        height: 300px;
        background-image: url("./images/show-window/timg.jpg");
        border: 1px solid transparent;
        background-size: inherit;
        background-repeat: no-repeat;
        background-position-x: 0px;
        background-position-y: 0px;
        position: relative;
        top: -301px;
        left: 605px;
        float: left;
        z-index: 10;
        opacity: 0;
        display: none;
        transition: opacity 2s linear;
        overflow: hidden;
    }
    .relative-region {
        background: linear-gradient(45deg, rgba(46, 46, 46, 0.5) 50%, transparent 0),
        linear-gradient(135deg, rgba(200, 200, 200, .5) 70%, transparent 0);
        display: none;
        position: relative;
        z-index: 99;
        background-size: 5px 5px;
    }

          Javascript:

class Elements {
        constructor() {
            //缩略图区域
            this.sourceImage = $(".little-img");
            //放大区域
            this.aimImage = $(".large-img");
            //视图图片,与图片实际尺寸比例
            this.sourceToAimRate = 0.01;
            //原图高度
            this.sourceHeight = 0;
            //原图宽度
            this.sourceWidth = 0;
            //视图高度,div的高度,本例是300px
            this.containerHeight = this.sourceImage.children().height();
            this.containerWidth = this.sourceImage.children().width();
            //鼠标在缩略图上的坐标 offsetX
            this.cursor_x = 0;
            this.cursor_y = 0;
            //标志被放大的区域
            this.region = $(".relative-region");

            this.mouseMove = this.mouseMove.bind(this);
            this.regionPosition = this.regionPosition.bind(this);
            this.regionMove = this.regionMove.bind(this);
            this.caculatorRate = this.caculatorRate.bind(this);
        }
        //计算原图尺寸,思路是内存加载原图,获得尺寸,并计算容器视图和原图的比例
        caculatorRate() {
            console.log(this.sourceImage.children().attr("src"));
            $("<img/>").attr("src", this.sourceImage.children().attr("src")).load((e) => {
                //let sourceImageWidth=e.target.width;
                this.sourceWidth = e.target.width;
                this.sourceHeight = e.target.height;
                //计算图片和容器的像素比例
                this.sourceToAimRate = this.sourceWidth / this.containerWidth;
            });
        }
        //鼠标在缩略图上移动时计算,放大图的背景位置,并且定位标识被放大的区域
        mouseMove(e) {
            //console.log(`x:${e.offsetX},y:${e.offsetY}`);
            //偏离region的位置
            //由于鼠标实际上是在标识被放大区域(网格区域)的div里面,所以通过e获取的实际上是缩略图内,网格标识的offsetX 要用网格区域的offsetX+offsetLeft-缩略图的offsetleft才是鼠标对应到缩略图上的位置
            let r_x = e.offsetX;
            let r_y = e.offsetY;

            let s_t = this.sourceImage.offset().top;
            let s_l = this.sourceImage.offset().left;

            let r_t = this.region.offset().top;
            let r_l = this.region.offset().left;

            let x = r_l - s_l + r_x;
            let y = r_t - s_t + r_y;

            //在原图上显示,被放大的区域
            let w = this.region.width();
            let h = this.region.height();

             //由于鼠标在网格区域的中心,所以在计算放大图的top和left的时候,实际是从网格的左上角位置
            this.cursor_x = (x - w / 2) * this.sourceToAimRate;
            this.cursor_y = (y - h / 2) * this.sourceToAimRate;
            if (this.cursor_x + this.containerWidth > this.sourceWidth) {
                this.cursor_x = this.sourceWidth - this.containerWidth;
            }
            if (this.cursor_y + this.containerHeight > this.sourceHeight) {
                this.cursor_y = this.sourceHeight - this.containerHeight;
            }
            if (this.cursor_y < 0) {
                this.cursor_y = 0;
            }
            if (this.cursor_x < 0) {
                this.cursor_x = 0;
            }
            this.aimImage.css({
                "background-position-x": -this.cursor_x + "px",
                "background-position-y": -this.cursor_y + "px"
            }); 
            this.regionMove(w, h, x, y); 
}
        regionPosition(r_w, r_h, e) {
            let left = e.offsetX - r_w / 2;
            let top = e.offsetY - r_h / 2; 
            if (left < 0) {
                left = 0;
            }
            if (left + r_w > this.containerWidth) {
                left = this.containerWidth - r_w;
            }
            if (top < 0) {
                top = 0;
            }
            if (top + r_h > this.containerHeight) {
                top = this.containerHeight - r_h;
            }
            this.region.css({
                "top": (top - this.containerHeight) + "px",
                "left": left+ "px",
                "cursor": "crosshair"
            });
        } 
        regionMove(r_w, r_h, x, y) {
            let left = x - r_w / 2;
            let top = y - r_h / 2;

            if (left < 0) {
                left = 0;
            }
            if (left + r_w > this.containerWidth) {
                left = this.containerWidth - r_w;
            }
            if (top < 0) {
                top = 0;
            }
            if (top + r_h > this.containerHeight) {
                top = this.containerHeight - r_h;
            }
            this.region.css({"top": (top - this.containerHeight) + "px", "left": left + "px"});
        }

        init() {
            this.caculatorRate();
            //鼠标移入缩略图区域,由缩略图区域的hover事件初始化,将鼠标放入网格区域的中心
            this.sourceImage.children().mouseover((e) => {
                this.aimImage.css({"display": "block", "opacity": "1"});
                let r_w = this.containerWidth / this.sourceToAimRate;
                let r_h = this.containerHeight / this.sourceToAimRate;
                let x = e.offsetX;
                let y = e.offsetY;
                this.regionPosition(r_w, r_h, e);
                this.region.css({"display": "block", "height": r_h + "px", "width": r_w + "px"});
            });
            //修复鼠标在region上,右侧放大区域闪动
            this.region.mousemove(this.mouseMove);
            this.region.mouseleave(() => {
                this.aimImage.css({"display": "none", "opacity": "0"});
                this.region.css({"display": "none"});
            });
        }
    } 
    $(function () {
        var e = new Elements();
        e.init();
    })

         由于原图是1920*1080不是缩略视窗严格的2:1,计算中有小数等原因,使网格标识的区域,和放大区域展示的完全匹配

         在下一篇将尝试,放大镜逆应用为缩小镜,实现图片裁剪的时候,标识裁剪的部分位于原图的位置和区域.