今天有时间开始动手,使用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,计算中有小数等原因,使网格标识的区域,和放大区域展示的完全匹配
在下一篇将尝试,放大镜逆应用为缩小镜,实现图片裁剪的时候,标识裁剪的部分位于原图的位置和区域.