JavaScript面向对象实现放大镜案例

本文实例为大家分享了JavaScript面向对象实现放大镜的具体代码,供大家参考,具体内容如下

效果图

实现原理分析

如图所示

触发鼠标的移动事件时,根据事件对象的 clientX 和 clientY 属性得到实时的坐标点 x 和 y
值 ,减去 small_box 的 offsetLeft 值cutting_box 的宽度的一半 ,可以得到 cutting_box 的偏移量 left 值,top值同理。当 cutting_box 到达右侧和下侧时,left 和 top 取得最大值。用 实时变化的left和top值 比上 各自的最大值,可得到一个比例,再根据这个比例,算出右侧 big_img 元素的 left 和 top。具体求法是:先求出 big_img 放大后的宽高,由这个宽高求得big_img的 left和top 最大值。在用这个最大值乘以上述的比例值即得到相应的 big_img 的 left 和 top值。
注意点:big_img 放大后的宽高求法
small_box宽高 / cutting_box = big_img宽高 / big_box宽高。(只有big_img宽高未知)

基本页面结构

<div class="small">
 <img src="images/timg.jpg" alt="">
 <span class="grayBox"></span>
</div>
<div class="big">
 <img src="images/timg.jpg" alt="">
</div>

CSS代码

.small {
 width: 400px;
 height: 400px;
 position: relative;
 border:4px solid #ddd;
 box-shadow: 0 0 5px rgba(0,0,0,.5);
}
.small img{
 width: 100%;
 height: 100%;
}
.small .grayBox{
 display: none;
 width: 100px;
 height: 100px;
 box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
 position: absolute;
 left: 0;
 top: 0;
}
.big{
 width: 400px;
 height: 400px;
 position: absolute;
 left: 700px;
 top: 100px;
 border:1px solid #f10;
 display: none;
 overflow: hidden;
}
.big img{
 position: absolute;
}

面向对象实现

分析(OOA)

  • 元素选择功能
  • 绑定事件驱动
  • 元素的显示与隐藏功能
  • 小图移动,大图的放大跟随移动功能
  • 鼠标滚轮缩放功能

设计(OOD)

构造函数

function Magnifier(){}

初始化各个功能模块

function init(){}

事件绑定功能

function bindEvent(){}

元素的显示与隐藏功能

function eleToggle(){}

小图移动,大图放大跟随功能

function eleMove(){}

编写(OOP)

  • 首先明确应该把所有功能都放到放大镜构造函数的原型上。
  • 其次实例化一个对象时应该传入的是对象类型的参数,如下所示:
new Magnifier({
 small_box : ".small",
 cutting_box : ".grayBox",
 big_box : ".big",
 big_img : ".big img"
});

构造函数此时需要接收实例化时传入的参数:

function Magnifier( options ) {
 // 调用初始化函数,处理接收到的参数对象
 this.init( options );
}

初始化功能完成初始化元素、获取small_box、cutting_box、big_box的offset系列的值:

Magnifier.prototype.init = function( options ){
 // 初始化元素;
 for(var attr in options){
  this[attr+"_ele"] = this.$(options[attr]);
 }
 // 为了节省性能,所以只获取一次offsetLeft;
 this.small_box_offset = {
  left : this.small_box_ele.offsetLeft,
  top  : this.small_box_ele.offsetTop,
  width : parseInt( getComputedStyle(this.small_box_ele).width ),
  height : parseInt( getComputedStyle(this.small_box_ele).width )
 }
 this.cutting_box_offset = {
  width  : parseInt( getComputedStyle(this.cutting_box_ele).width ),
  height : parseInt( getComputedStyle(this.cutting_box_ele).height ),
 }
 this.big_box_offset = {
  width : parseInt( getComputedStyle(this.big_box_ele).width ),
  height : parseInt( getComputedStyle(this.big_box_ele).height ),
 }
 // 标志变量 ,鼠标是否移入放大镜
 this.magnifier_start = false;
 this.bindEvent();
 // 图片缩放功能
 this.scaleBigImg();
}

选择元素功能:

Magnifier.prototype.$ = function(selector){
 return document.querySelector(selector);
}

事件绑定功能:

Magnifier.prototype.bindEvent = function(){
 // 鼠标移入左侧small_box
 this.small_box_ele.addEventListener( "mouseover" , function(){
  // cutting_box big_box元素显示;
  this.eleToggle("show");
  // 修改标志变量为true
  this.magnifier_start = true;
  // 修改事件函数里面的this指向为当前实例对象
 }.bind(this));
 // 鼠标移出左侧small_box
 this.small_box_ele.addEventListener( "mouseout" , function(){
  // cutting_box big_box元素隐藏;
  this.eleToggle("hide");
  this.magnifier_start = false;
 }.bind(this));
 // 鼠标移动,元素运动;
 this.small_box_ele.addEventListener("mousemove" , function( evt ){
  var e = evt || event;
  // 获取鼠标点距离浏览器可视区的 x y 值
  var x = e.clientX ;
  var y = e.clientY ;
  // 调用factoryPosition处理得到的坐标值
  this.res = this.factoryPosition( x , y );
  // 把处理好后的坐标值传入eleMove方法,改变相应的left、top值
  this.eleMove( this.res );
 }.bind(this));
 // 滚轮事件;
 document.addEventListener("mousewheel" , function( evt ){
  // 如果鼠标未移入放大镜,则不执行滚轮事件函数
  if(!this.magnifier_start){ return false }
  var e = evt || event;
  // 判定滚轮向上(缩小)还是向下(放大);
  this.changeCutBoxScale( e.wheelDelta > 0 ? "narrow" : "large" );
 }.bind(this));
} 

元素显示隐藏功能:

Magnifier.prototype.eleToggle = function( type ){
 // 根据type类型,判定元素的display的属性值 block | none
 this.cutting_box_ele.style.display = type === "show" ? "block" : "none";
 this.big_box_ele.style.display = type === "show" ? "block" : "none";
}

处理鼠标移动时得到的坐标点 x 和 y 值:

Magnifier.prototype.factoryPosition = function( x , y ){
 // 根据接收到的 x 和 y 计算得到 cutting_box 的 left 和 top 偏移量
 var _left =  x - this.small_box_offset.left - this.cutting_box_offset.width / 2;
 var _top  = y - this.small_box_offset.top - this.cutting_box_offset.height / 2
 // cutting_box 的 left 和 top 的最大值
 var _left_max = this.small_box_offset.width - this.cutting_box_offset.width;
 var _top_max = this.small_box_offset.height - this.cutting_box_offset.height;
 // 最小值边界监测;
 _left = _left <= 0 ? 0  : _left;
 _top  = _top  <= 0 ? 0  : _top
 // 最大值检测
 _left = _left >= _left_max ? _left_max : _left;
 _top = _top >= _top_max ? _top_max : _top;
 // 返回处理好的坐标点值 以及 移动的距离与最大值的比例系数
 return {
  x : _left,
  y : _top,
  xp: _left / _left_max,
  yp:_top / _top_max
 }
}

小图移动,大图放大跟随功能:

Magnifier.prototype.eleMove =  function( position_obj ){
 // 左侧cutting_box移动范围
 this.cutting_box_ele.style.left = position_obj.x + "px";
 this.cutting_box_ele.style.top  = position_obj.y + "px";
 // 大图big_img的移动范围。cutting_box和big_img的移动方向时相反的
 this.big_img_ele.style.left = -position_obj.xp * this.big_img_boundary.left_max + "px";
 this.big_img_ele.style.top  = -position_obj.yp * this.big_img_boundary.top_max + "px";
}

放大图片功能:

Magnifier.prototype.scaleBigImg = function(){
 // 放大的比例 ;
 var width_p  = this.big_box_offset.width / this.cutting_box_offset.width;
 var height_p = this.big_box_offset.height / this.cutting_box_offset.height;
 // 获得了big_img放大之后的宽高;
 this.big_img_offset = {
  width  : width_p * this.small_box_offset.width,
  height : height_p * this.small_box_offset.height,
 }
 // 计算出big_img运动的边界;
 this.big_img_boundary = {
  left_max : this.big_img_offset.width  - this.big_box_offset.width,
  top_max  : this.big_img_offset.height - this.big_box_offset.height
 }
 // 给图片设置等比例宽高;
 this.big_img_ele.style.width  = this.big_img_offset.width + "px";
 this.big_img_ele.style.height = this.big_img_offset.height + "px";
}

鼠标滚轮滚动时同时需要改变左侧 cutting_box 的大小:

Magnifier.prototype.changeCutBoxScale = function( type ){
 switch ( type ) {
  // 放大
  case "large":
   this.cutting_box_offset.width += 2;
   this.cutting_box_offset.height += 2;
   // 让cutting_box 向左 向上移动 让鼠标始终保持在中心位置
   this.res.x --;
   this.res.y --;
   break;
  // 缩小
  case "narrow":
   this.cutting_box_offset.width  -= 2;
   this.cutting_box_offset.height -= 2;
   this.res.x ++;
   this.res.y ++;
   break;
  default:
   break;
 }
 this.cutting_box_ele.style.width = this.cutting_box_offset.width + "px";
 this.cutting_box_ele.style.height = this.cutting_box_offset.height + "px";
 // 位置改变之后,调用相应的比例计算工具;
 this.scaleBigImg();
 // 重新进行大图运动的计算;
 this.eleMove(this.res);
}

功能补充:多图片切换,可以放大相应的图片。
添加标签:data-src自定义属性存放不同的图片路径

<button class="btn" data-src=""><img src="" alt=""></button>
<button class="btn" data-src=""><img src="" alt=""></button>

最后只需在实例化放大镜对象后,分别给每个按钮绑定点击或者移入事件,再替换 small 和 big 容器中的 img 的 src 的属性值为相应的 data-src 的属性值即可,如下所示:

// 选中所有代表不同图片的button按钮
var btns = document.querySelectorAll(".btn");
// 选中small 和 big 容器中的 img 标签
var imgs = document.querySelectorAll(".big img,.small img");
for(var i = 0 ; i < btns.length ; i ++){
 btns[i].onclick = function(){
  // 获取每个按钮上的不同的 data-src 属性
  var src = this.getAttribute("data-src");
  for(var k = 0 ; k < imgs.length ; k ++){
   // 替换相应的 src 属性的属性值
   imgs[k].src = src;
  }
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解js的作用域、预解析机制

    虽然,ES6在我们工作中应用得越来越广泛,但是还是很多项目保留着ES5的写法,所以,今天,带着大家重新巩固下ES5下的作用域及预解析机制. 概念: 作用域:域,指的是一个空间.范围.区域,作用指的是在域内可进行读写操作.一个变量的作用域是程序源代码中定义的这个变量的区域. 在ES5中,只存在全局和函数级作用域,在ES6中,引入了块级作用域,js的预解析机制大概分为两个过程:预解析和自上而下逐行解读 预解析:js解析器会先把var定义的变量.function.参数等一些东西存储进仓库里面(内存).

  • JavaScript中5个常用的对象

    目录 1.JavaScript对象 1).Array对象 2).Boolean对象 3).Date对象 4).Math对象 5).Number对象 6).String对象 前言: 相信做网站对JavaScript再熟悉不过了,它是一门脚本语言,不同于Python的是,它是一门浏览器脚本语言,而Python则是服务器脚本语言,我们不光要会Python,还要会JavaScript,因为它对做网页方面是有很大作用的. 1.JavaScript对象 在JavaScript中有许多有用的对象,它们可以用来

  • JavaScript预解析,对象详解

    目录 一.预解析 1.变量预解析和函数预解析 1.变量预解析 2.函数预解析 2.预解析案例 二.对象 1.创建对象的三种方式 1.利用字面量创建对象 2.利用new Object创建对象 3.利用构造函数创建对象 4.构造函数和对象 2.new关键字 3.遍历对象属性 总结 一.预解析 1.变量预解析和函数预解析 JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的.JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行. 预解

  • js作用域和作用域链及预解析

    变量---->局部变量和全局变量, 作用域:在某个空间范围内,可以对数据进行读写操作 局部作用域和全局作用域 js中没有块级作用域-一对括号中定义的变量,这个变量可以在大括号外面使用 函数中定义的变量是局部变量 作用域链:变量的使用,从里向外,层层的搜索,搜索到了就可以直接使用了 层层搜索,搜索到0级作用域的时候,如果还是没有找到这个变量,结果就是报错 在 JavaScript 中, 对象和函数同样也是变量. 在 JavaScript 中, 作用域为可访问变量,对象,函数的集合. JavaScr

  • JavaScript 预解析的4种实现方法解析

    预解析:在当前作用域下,js运行之前,会把带有var和function关键字声明的变量先声明,并在内存中安排好.然后从上至下解析js语句.而且function的声明优先于var声明. 不多说,,直接上代码 正规写法: var num=10; fun(); function fun(){ console.log(num);//undefined var num=20; } 预解析里:先将变量和函数提前,如下: var num; function fun(){ var num; console.lo

  • js对象的读取速度实例详解

    1.访问字面量和局部变量最快,而访问数组元素和对象成员相对较慢.访问对象成员时,就像作用域链一样,在原型链上搜索. 2.如果找到的成员在原型链中的位置太深,访问速度就会变慢. 所以要尽量减少对象成员的搜索次数和嵌套深度. 实例 // 进行两次对象成员查找 function hasEitherClass(element, className1, className2) { return element.className === className1 || element.className ==

  • JavaScript面向对象实现放大镜案例

    本文实例为大家分享了JavaScript面向对象实现放大镜的具体代码,供大家参考,具体内容如下 效果图 实现原理分析 如图所示 触发鼠标的移动事件时,根据事件对象的 clientX 和 clientY 属性得到实时的坐标点 x 和 y 值 ,减去 small_box 的 offsetLeft 值 和 cutting_box 的宽度的一半 ,可以得到 cutting_box 的偏移量 left 值,top值同理.当 cutting_box 到达右侧和下侧时,left 和 top 取得最大值.用 实

  • JavaScript面向对象之class继承类案例讲解

    1. 面向对象class继承 在上面的章节中我们看到了JavaScript的对象模型是基于原型实现的,特点是简单,缺点是理解起来比传统的类-实例模型要困难,最大的缺点是继承的实现需要编写大量代码,并且需要正确实现原型链. 有没有更简单的写法?有! 我们先回顾用函数实现 Student 的方法: function Student(name) { this.name = name; } // 现在要给这个Student新增一个方法 Student.prototype.hello = function

  • javascript面向对象快速入门实例

    本文深入浅出的讲述了javascript面向对象快速入门实例.分享给大家供大家参考.具体如下: javascript面向对象入门案例: 复制代码 代码如下: <script language="javascript" type="text/javascript"> function Cat(){//js中对象的定义与函数一样,不同点在于怎么样调用. } var cat1 = new Cat();//创建类实例 //js中类属性可以动态添加,并不需要写在原

  • JavaScript面向对象分层思维全面解析

    js本身不是面向对象语言,在我们实际开发中其实很少用到面向对象思想,以前一直以为当要复用的时候才封装成对象,然而随着现在做的项目都后期测试阶段发现面向对象的作用不仅仅只是复用,可能你们会说面向对象还有继承,多态的概念,但在javascript里面多态的概念是不存在,而继承由于web页面的必须先下载js在运行导致js的继承不能像后台那么灵活而且js没有重载以及重写不方便(而且js中重写的意义不是很大),所以在js中很少用到面向对象,可能在一些插件中会看到对象的写法,写js的都会有同样的感觉在写一个

  • JavaScript面向对象之七大基本原则实例详解

    本文实例讲述了JavaScript面向对象之七大基本原则.分享给大家供大家参考,具体如下: 面向对象编程有自己的特性与原则,如果对于面向对象有一些了解的话,面向对象三大特征,封装.继承.多态,如果对面向对这三个概念不太了解,请参考面向对象之三个基本特征(javaScript) 单一职责 如果我们在编写程序的时候,一类或者一个方法里面包含了太多方法,对于代码的可读性来说,无非是一场灾难,对于我们来说.所以为了解决这个问题,出现了单一职责. 什么是单一职责 单一职责:又称单一功能原则,面向对象五个基

  • Javascript实例项目放大镜特效的实现流程

    目录 前言 案例:仿京东放大镜效果 offset系列 client系列 scroll系列 三大系列总结 前言 本票博客主要是放大镜案例,里面涉及到的知识点会提出来,可放心食用~后有源代码. 案例:仿京东放大镜效果 效果见下图: 功能要求: 当鼠标移动到小图片上时,遮罩层出现,同时旁边大图片也出现,鼠标移出,遮罩层消失,大图片也消失. 遮罩层只能在小盒内子移动,不能超出. 遮罩层在小盒子内移动,大图片显示对应的板块. 案例分析: 元素的隐层和显示 遮罩层的移动范围用offset计算 计算出大盒子内

  • JavaScript仿京东放大镜效果

    本文实例为大家分享了JavaScript实现京东放大镜效果的具体代码,供大家参考,具体内容如下 案例分析 整个案例可以分为三个功能模块 鼠标经过小图片盒子, 黄色的遮挡层 和 大图片盒子显示,离开隐藏2个盒子功能 黄色的遮挡层跟随鼠标功能. 移动黄色遮挡层,大图片跟随移动功能. 鼠标经过小图片盒子, 黄色的遮挡层 和 大图片盒子显示,离开隐藏2个盒子功能 就是显示与隐藏 移动黄色遮挡层,大图片跟随移动功能,大图片的移动距离要跟黄色遮挡层的比例相等. 求大图片的移动距离公式 代码 <!DOCTYP

  • Javascript面向对象扩展库代码分享

    lang.js库提供了包和类的定义.类的继承与混合(mixin).函数重载等功能,基本可满足大多数面向对象设计的需求.同时支持基于链式的定义方式,让库在使用时更加规范和便捷.下面首先通过简单的例子演示了lang.js的基本功能,之后给出了lang.js的源码及注释. 一.功能介绍 "lang"作为框架的全局定义,其中包括了四个方法: lang.Package(string name) //用于定义包(默认会暴露到全局) lang.Class(string name[, object c

  • 再谈javascript面向对象编程

    另外这篇文章是一篇入门文章,我也是才开始学习Javascript,有一点心得,才想写一篇这样文章,文章中难免有错误的地方,还请各位不吝吐槽指正 吐槽Javascript 初次接触Javascript,这门语言的确会让很多正规军感到诸多的不适,这种不适来自于Javascript的语法的简练和不严谨,这种不适也来自Javascript这个悲催的名称,我在想网景公司的Javascript设计者在给他起名称那天一定是脑壳进水了,让Javascript这么多年来受了这么多不白之冤,人们都认为他是Java的

  • Javascript 面向对象编程(coolshell)

    这两天有个前同事总在问我Javascript面向对象的东西,所以,索性写篇文章让他看去吧,这里这篇文章主要想从一个整体的角度来说明一下Javascript的面向对象的编程.(成文比较仓促,应该有不准确或是有误的地方,请大家批评指正) 另,这篇文章主要基于 ECMAScript 5, 旨在介绍新技术.关于兼容性的东西,请看最后一节. 初探 我们知道Javascript中的变量定义基本如下: 复制代码 代码如下: var name = 'Chen Hao';; var email = 'haoel(

随机推荐