JavaScript学习笔记(十五)——事件(对象、绑定、流程)

事件对象——event

事件对象是用来记录一些事件发生时的相关信息的对象。事件对象只有事件发生时才会产生,并且只能是事件处理函数内部访问,在所有事件处理函数运行结束后,事件对象就被销毁!

     div.onclick = function(e) {
         console.log(e);
        //  e 就是事件对象 我们可以根据它获取到许多的信息
         // 在IE中,时间对象没有传递给函数,而是在window上,名字叫做event
     }

在IE浏览器中,通过window.event获取事件对象,在其他浏览器中可以通过e获取事件对象。因为在IE浏览器与其他浏览器获取事件对象存在兼容性问题,可以通过以下方式处理兼容性问题。

方式1:使用if…else

// 定义一个变量用于存放事件对象
var event = null;
// 不是IE浏览器
if(event == e){
	event = e;
}else{
	// 是IE浏览器
	event = window.event;
}

方式2:三目运算

var event = e ? e : window.event;

方式3:短路运算(常用)

var event = e || window.event;

事件对象的重要属性

鼠标事件

  • altKey 热键alt键
  • ctrlKey 热键ctrl键
  • shiftKey 热键shift键
    以上属性都是布尔值,表示是否按下,没有按下为false,按下为true
  • offsetX 事件发生时鼠标位于元素内部的left位置(从鼠标位置到左边框内)
  • offsetY 事件发生时鼠标位于元素内部的top位置(从鼠标位置到上边框内)
  • clientX 事件发生时鼠标到视口的左边距离
  • clientY 事件发生时鼠标到视口的上边距离
  • pageX 事件发生时鼠标到页面的左边距离
  • pageY 事件发生时鼠标到页面的上边距离
  • screenX 事件发生时鼠标到屏幕的左边距离
  • screenY 事件发生时鼠标到屏幕的上边距离
  • currentTarget 绑定事件的元素
  • target 触发事件的元素

键盘事件

  • key 表示当前的键对应的字符
  • keyCode 表示当前的键对应的字符的ASCII码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box{
            position: relative;
            width: 500px;
            height: 500px;
            margin: 100px auto;
            background-color: tomato;
            border: 10px solid red;
        }
        .box1{
            position: absolute;
            width: 200px;
            height: 200px;
            left: 0;
            top: 0;
            right: 0;
            bottom: 0;
            margin: auto;
            background-color: yellow;
            border: 10px solid green;
        }
    </style>
</head>
<body>
    <div id="box" class="box">
        <div id="box1" class="box1"></div>
    </div>
    <script>
        var box = document.getElementById("box");
        var box1 = document.getElementById("box1");
        box.onclick = function(e){
            // 浏览器兼容 事件对象
            // 方式1:if(){}else{}
            // var event = null;
            // if(event == e){
            //     event = e;
            // }else{
            //     event = window.event;
            // }
            // 方式2:三目运算
            // var event = e ? e : window.event;
            // 方式3:短路运算
            var event = e || window.event;

            // 获取鼠标位置
            // offsetX 事件发生时,鼠标到元素左边框内的距离。注意:会受到子元素的影响
            console.log("鼠标到元素左边框内的距离:"+event.offsetX);
            // offsetY 事件发生时,鼠标到元素上边框内的距离。注意:会受到子元素的影响
            console.log("鼠标到元素上边框内的距离:"+event.offsetY);

            // clientX 事件发生时,鼠标到视口的左边距离
            console.log("鼠标到视口的左边距离"+event.clientX);
            // clientY 事件发生时,鼠标到视口的上边距离
            console.log("鼠标到视口的上边距离:"+event.clientY);
            
            // pageX 事件发生时,鼠标到页面的左边距离
            console.log("鼠标到页面的左边距离:"+event.pageX);
            // pageY 事件发生时,鼠标到页面的上边距离
            console.log("鼠标到页面的上边距离:"+event.pageY);

            // screenX 事件发生时,鼠标到屏幕的左边距离
            console.log("鼠标到屏幕的左边距离:"+event.screenX);
            // screenY 事件发生时,鼠标到屏幕的上边距离
            console.log("鼠标到屏幕的上边距离:"+event.screenY);
        }
    </script>
</body>
</html>

在这里插入图片描述

鼠标点击黄色区域任意位置:
在这里插入图片描述
鼠标点击红色区域任意位置:
在这里插入图片描述

事件绑定方式

DOM0级

  • 绑定
    • 元素.on事件类型 = 事件函数
    • 只能绑定一个事件,因为它是对属性进行赋值
  • 移除
    • 元素.on事件类型 = null

注意: 一个对象的属性只能够保存一个值。 如果对一个对象属性进行多次赋值,后面赋值的属性会替换掉前面的属性。

DOM2级

  • 绑定

    • dom.addEventListener(type, handler, boolean);
      • type: 事件类型字符串,不带on,要带双引号或单引号
      • handler: 事件处理函数
      • boolean: 布尔值。决定绑定到捕获阶段还是冒泡阶段,默认是false,表示冒泡阶段
    • 注意: 可以通过addEventListener方法进行多个事件函数的绑定,执行时是按照代码的书写顺序执行,因为代码的书写顺序决定了绑定顺序。
  • 移除

    • document.removeEventListener(type, handler, boolean);
      • type: 事件类型字符串,不带on
      • handler: 事件处理函数,一定要保证函数地址是绑定的那个
      • boolean: 布尔值。决定移除的是捕获阶段还是冒泡阶段,默认是false,表示冒泡
    • 注意: 结论: 第二个参数是要移除的函数,函数是引用类型,引用类型的比较的是地址。 所以一定要保证 移除的函数是当初绑定的那个函数本身
  • IE中的高级绑定方式(非DOM2级)
    注意: IE中没有实现DOM2级

    • 绑定
      • dom.attachEvent(type, handler);
        • type: 事件类型字符串,带on
        • handler: 事件处理函数
        • 没有第三个参数,意味着不能够绑定到捕获阶段
      • 特点: 可以对同一个元素绑定多个同类型事件的处理函数,执行起来是倒着执行 ,先绑定的后执行,后绑定的先执行
    • 移除
      • dom.detachEvent(type, handler);
        • type: 事件类型字符串,带on
        • handler: 事件处理函数,要注意函数的地址问题
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box{
            width: 400px;
            height: 200px;
            background: red;
            margin: 0 auto;
        }
        .text{
            height: 60px;
            background: green;
            font-size: 24px;
            line-height: 30px;
        }
        .btn{
            width: 100px;
            height: 30px;
            text-align: center;
            line-height: 30px;
        }
    </style>
</head>
<body>
    <div id="box" class="box">
        <p id="text" class="text"></p>
        <button id="btn" class="btn">点我</button>
    </div>
    <script>
        // 获取元素
        var text = document.getElementById("text");
        var btn = document.getElementById("btn");

        // 为按钮绑定点击事件
        // 方式1:DOM0级
        btn.onclick = function(){
            // 点击按钮,p标签内输出文字
            text.innerHTML = "您点击了按钮,触发了事件,on事件";
        }

        // 方式2:DOM2级
        // btn.addEventListener('click', function(){
        //     text.innerHTML = "您点击了按钮,触发了事件,addEventListener";
        // });
    </script>
</body>
</html>

在这里插入图片描述
使用方式1绑定事件,点击按钮:
在这里插入图片描述
使用方式2绑定事件,点击按钮:
在这里插入图片描述

事件流程

  • 事件冒泡: 当点击时,事件从最精确的元素一层一层往上触发,直到最顶层元素,这个过程叫做事件冒泡
  • 事件捕获: 当点击时,事件从最顶层元素一层一层的往下触发,直到最精确元素,这个过程叫做事件捕获
    • 最精确元素: 鼠标点到谁,谁就是最精确元素
    • 最顶层元素:
      • 高级浏览器最顶层元素是window
      • IE浏览器最顶层元素是document

阻止冒泡

高级浏览器中 可以通过e.stopPropagation() 进行阻止事件的冒泡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box1{
            position: relative;
            width: 500px;
            height: 500px;
            margin: 100px auto;
            background-color: tomato;
            border: 10px solid red;
        }
        .box2{
            position: absolute;
            width: 200px;
            height: 200px;
            left: 0;
            top: 0;
            right: 0;
            bottom: 0;
            margin: auto;
            background-color: yellow;
            border: 10px solid green;
        }
    </style>
</head>
<body>
    <div class="box1" id="box1">
        <div class="box2" id="box2"></div>
    </div>
    <script>
    var box1 = document.querySelector(".box1");
    var box2 = document.querySelector(".box2");

    box1.onclick = function() {
        console.log("这是BOX1");
    }
    box2.onclick = function(e) {
        // 阻止冒泡
        // e.stopPropagation();
        console.log("这是BOX2");
    }
    </script>
</body>
</html>

在这里插入图片描述
没阻止冒泡前,点击box1,再点击box2,可以看到:
点击box1时,box1触发了一次。点击box2时,先触发了box2,再触发box1,这是由于事件冒泡引起的。
在这里插入图片描述
阻止冒泡后,点击box1,再点击box2,可以看到:
点击box1时,box1触发了一次。点击box2时,只触发了box2,没有触发box1,这是由于已经阻止了事件冒泡的发生。
在这里插入图片描述
IE浏览器中 可以通过e.cancelBubble = true 进行阻止事件的冒泡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box1{
            position: relative;
            width: 500px;
            height: 500px;
            margin: 100px auto;
            background-color: tomato;
            border: 10px solid red;
        }
        .box2{
            position: absolute;
            width: 200px;
            height: 200px;
            left: 0;
            top: 0;
            right: 0;
            bottom: 0;
            margin: auto;
            background-color: yellow;
            border: 10px solid green;
        }
    </style>
</head>
<body>
    <div class="box1" id="box1">
        <div class="box2" id="box2"></div>
    </div>
    <script>
    var box1 = document.querySelector(".box1");
    var box2 = document.querySelector(".box2");

    box1.onclick = function() {
        console.log("这是BOX1");
    }
    box2.onclick = function(e) {
       var e = e || window.event;
       e.cancelBubble = true;
       console.log("这是BOX2");
   }
    </script>
</body>
</html>

停止默认行为

浏览器的一些事件中,带有一些默认行为。比如a标签的点击事件中,会带有跳转页面的行为。表单的点击事件中,带有提交的默认行为。滚轮事件中,带有改变页面卷动值的默认行为。

高级浏览器中 可以通过 e.preventDefault() 阻止默认行为

    // 获取元素
    var a = document.getElementsByTagName("a")[0];
    // 设置点击事件
    a.addEventListener("click", function(e) {
        console.log("点击了a标签1111");
        e.preventDefault();
    }, false);

IE浏览器中 可以通过 e.returnValue = false;阻止默认行为

    // 获取元素
    var a = document.getElementsByTagName("a")[0];
    // 设置点击事件
    a.attachEvent("onclick", function(e) {
        console.log("点击了a标签1111");
        e.returnValue = false;
    });

DOM0级事件绑定方式中,可以通过return false进行阻止默认行为

   // 获取元素
   var a = document.getElementsByTagName("a")[0];
   // 设置点击事件
   a.onclick = function() {
       return false;
   }

事件委托(事件代理)

思想: 将原本子元素做的事情,委托给父元素去做。将事件绑定给父元素,父元素事件触发时,通过e.target判定触发事件的元素。决定执行对应代码。

    // 1 获取元素 获取不可能被移除的父元素
    var tbody = document.querySelector("tbody");
    // 2 给tbody绑定事件
    tbody.onclick = function(e) {
        // e.target 这个属性指向触发事件的元素
        console.log(e.target)
        // 判定 点击到的是什么  
        if (e.target.className === "del") {
            // 点击到的是移除按钮 
            e.target.parentNode.remove();
        }
    }

实现一个拖拽功能
一个元素在页面中可以被随意拖拽。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box{
            position: absolute;
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
</head>
<body>
    <div id="box" class="box"></div>
    <script>
        // 获取元素
        var box = document.getElementById("box");

        // 鼠标按下事件
        box.onmousedown = function(e){
            // 记录鼠标此时的位置
            var nowX = e.clientX;
            var nowY = e.clientY;
            // 记录元素此时的位置
            var left = box.offsetLeft;
            var top = box.offsetTop;
            // 鼠标移动事件
            document.onmousemove = function(e){
                // 设置元素位置
                box.style.left = left + e.clientX - nowX + "px";
                box.style.top = top + e.clientY - nowY + "px";
            }
        }
        // 鼠标弹起事件
        box.onmouseup = function(){
            // 移除事件
            document.onmousemove = null;
        }
    </script>
</body>
</html>

在这里插入图片描述
实现一个区域拖拽功能
一个元素在一个范围内可以被随意拖拽,不能超出范围。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box{
            position: relative;
            width: 600px;
            height: 400px;
            background: green;
            margin: 100px auto;
        }
        .box1{
            position: absolute;
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
</head>
<body>
    <div id="box" class="box">
        <div id="box1" class="box1"></div>
    </div>
    <script>
        // 获取元素
        var box = document.getElementById("box");
        var box1 = document.getElementById("box1");

        // 鼠标触发按下事件
        box1.onmousedown = function(e){
            // 浏览器兼容
            var event = e || window.event;
            // 记录鼠标此时的位置
            var nowX = e.clientX;
            var nowY = e.clientY;
            // 记录元素此时的位置
            var left = box1.offsetLeft;
            var top = box1.offsetTop;
            
            // 鼠标移动事件
            box.onmousemove = function(e){
                // 记录鼠标拖动到的位置
                var moveX = e.clientX;
                var moveY = e.clientY;
                // 计算此时元素距离左边的距离
                var resultX = moveX - nowX + left;
                // 记录此时元素距离上边的距离
                var resultY = moveY - nowY + top;
                // 如果元素超出左边框
                if(resultX < 0){
                    // 将其设为0,限制其超出
                    resultX = 0;
                }else if(resultX > box.offsetWidth - box1.offsetWidth){
                    // 如果元素超出右边,限制其超出
                    resultX = box.offsetWidth - box1.offsetWidth;
                }
                // 如果元素超出上边框
                if(resultY < 0){
                    // 将其设为0,限制其超出
                    resultY = 0;
                }else if(resultY > box.offsetHeight - box1.offsetHeight){
                    // 如果元素超出下边框,限制其超出
                    resultY = box.offsetHeight - box1.offsetHeight;
                }
                // 设置元素位置
                box1.style.left = resultX + "px";
                box1.style.top = resultY + "px";
            }
        }
        // 鼠标抬起,移除移动事件
        document.onmouseup = function(){
            // 移除事件
            box.onmousemove = null;
        }
    </script>
</body>
</html>

在这里插入图片描述
实现一个在页面中点击任意位置创建元素功能1
在页面中任意位置点击,创建一个元素,再点击第二次,上一个元素消失。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
    <script>
        document.onclick = function(e){
            var event = e || window.event;
            // 点击第二次,前一次的消失
            document.body.innerHTML = "";
            // 创建元素
            var box = document.createElement("div");
            box.style.position = "absolute";
            box.style.width = "100px";
            box.style.height = "100px";
            box.style.backgroundColor = "red";
            box.style.left = event.clientX - 50 + "px";
            box.style.top = event.clientY - 50 + "px";
            // 元素上树
            document.body.appendChild(box);
        }
    </script>    
</body>
</html>

在这里插入图片描述
实现一个在页面中点击任意位置创建元素功能2
在页面上任意位置点击,创建一个元素,点击几次就创建几个,当鼠标点击已经创建的元素时,该元素消失。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
    <script>
        document.onclick = function(e){
            var event = e || window.event;
            // 创建元素
            // 点击多少次就创建多少个div
            var box = document.createElement("div");
            box.style.position = "absolute";
            box.style.width = "100px";
            box.style.height = "100px";
            box.style.backgroundColor = "red";
            box.style.left = event.clientX - 50 + "px";
            box.style.top = event.clientY - 50 + "px";
            document.body.appendChild(box);
            // 点击页面上创建出来的div后将其移除
            box.onclick = function(e){
                // 移除
                box.remove();
                // 阻止冒泡
                e.stopPropagation();
            }
        }
    </script>    
</body>
</html>

在这里插入图片描述
实现一个留言板功能
在输入框输入留言内容,点击留言按钮,显示留言的内容并清空留言板,显示删除按钮和留言数量。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box{
            width: 800px;
            height: 400px;
            margin: 0 auto;
            border: 2px solid #ccc;
        }
        h1{
            height: 30px;
            font-size: 20px;
            line-height: 30px;
            text-align: center;
        }
        ul{
            height: 300px;
        }
        ul li{
            list-style: none;
            height: 20px;
            font-size: 16px;
            line-height: 20px;
            display: flex;
        }
        ul li span{
            flex: 9;
        }
        ul li i{
            flex: 1;
            cursor: pointer;
            text-align: center;
        }
        .box .operate{
            height: 70px;
            display: flex;
        }
        .box .operate textarea{
            height: 70px;
            flex: 9;
            resize: none;
        }
        .box .operate button{
            height: 70px;
            flex: 1;
        }
    </style>
</head>
<body>
    <div class="box" id="box">
        <h1>留言板<span id="num"></span></h1>
        <ul id="list">
            <!-- <li><span>人生得意须尽欢</span><i>&times;</i></li> -->
        </ul>
        <div class="operate">
            <textarea name="" id="message"></textarea>
            <button id="btn">留言</button>
        </div>
    </div>
    <script>
        // 获取元素
        var btn = document.getElementById("btn");
        var message = document.getElementById("message");
        var list = document.getElementById("list");
        var num = document.getElementById("num");
        var count = 0;

        // 绑定事件
        btn.onclick = function(){
            // 如果msg.value为空,则return
            if(message.value === ""){
                return;
            }
            // 只有当经过了信息验证的时候,说明是有效的留言信息,才累加
            count++;

            // 创建元素
            var li = document.createElement("li");
            // 使用字符串拼接代替创建元素
            li.innerHTML = "<span>" + message.value + "</span><i>&times;</i>";
            list.appendChild(li);
            num.innerHTML = "(" + count + ")";
            message.value = "";

            // 获取元素
            var dels = document.getElementsByTagName("i");
            // console.log(dels);

            // 给i绑定事件
            for (var i = 0; i < dels.length; i++){
                dels[i].onclick = function(){
                    // 移除li
                    this.parentNode.remove();
                    count--;
                    num.innerHTML = "(" + count + ")";
                } 
            }
        }

        // 现在我们面临的问题:
        // 1、未来元素没有事件
        // 2、事件数量太多
        // 3、防止内存泄漏
    </script>
</body>
</html>

在这里插入图片描述
使用事件委托的方式实现留言板功能

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box{
            width: 800px;
            height: 400px;
            margin: 0 auto;
            border: 2px solid #ccc;
        }
        h1{
            height: 30px;
            font-size: 20px;
            line-height: 30px;
            text-align: center;
        }
        ul{
            height: 300px;
        }
        ul li{
            list-style: none;
            height: 20px;
            font-size: 16px;
            line-height: 20px;
            display: flex;
        }
        ul li span{
            flex: 9;
        }
        ul li i{
            flex: 1;
            cursor: pointer;
        }
        .box .operate{
            height: 70px;
            display: flex;
        }
        .box .operate textarea{
            height: 70px;
            flex: 9;
            resize: none;
        }
        .box .operate button{
            height: 70px;
            flex: 1;
        }
    </style>
</head>
<body>
    <div class="box" id="box">
        <h1>留言板<span id="num"></span></h1>
        <ul id="list">
            <!-- <li><span>人生得意须尽欢</span><i class="dels">&times;</i></li> -->
        </ul>
        <div class="operate">
            <textarea name="" id="message"></textarea>
            <button id="btn">留言</button>
        </div>
    </div>
    <script>
        // 获取元素
        var btn = document.getElementById("btn");
        var message = document.getElementById("message");
        var list = document.getElementById("list");
        var num = document.getElementById("num");
        var count = 0;

        btn.onclick = function(){
            // 如果msg.value为空,则return
            if(message.value === ""){
                return;
            }
            // 只有当经过了信息验证的时候,说明是有效的留言信息,才累加
            count++;

            // 创建元素
            var li = document.createElement("li");
            // 使用字符串拼接代替创建元素
            li.innerHTML = "<span>" + message.value + "</span><i class='dels'>&times;</i>";
            list.appendChild(li);
            num.innerHTML = "(" + count + ")";
            message.value = "";
            }

        // 为了解决之前留下的问题,我们研究出了一种叫做委托模式(代理模式)的设计模式
        // 委托模式原理:给父元素添加事件,利用e.target做判定,只有点击的元素符合某种特征时,才执行对应的代码
        list.onclick = function(e){
            // 利用e.target判定最精确元素(判定点的是哪个元素)
            // console.log(e.target);
            if(e.target.className.toUpperCase() === "DELS"){
                // console.log("点击到的是i标签了");
                e.target.parentNode.remove();
                count--;
                num.innerHTML = "(" + count + ")";
            }
        }

    </script>
</body>
</html>

在这里插入图片描述
淘宝放大镜功能1
鼠标移动到小图片上,显示一个放大镜蒙层,页面右边显示蒙层所在区域的放大图像,放大镜蒙层只能在小图片内移动

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .small_box{
            position: relative;
            width: 400px;
            height: 300px;
            margin: 50px;
            z-index: 1;
            border: 1px solid #555;
        }
        .small_box img{
            width: 100%;
            height: 100%;
        }
        .floor_box{
            display: none;
            width: 160px;
            height: 120px;
            position: absolute;
            background: #ffffcc;
            filter: alpha(opacity = 50);
            opacity: 0.5;
        }
        .mark{
            cursor: move;
            position: absolute;
            display: block;
            width: 100%;
            height: 100%;
            z-index: 10;
            background: #fff;
            filter: alpha(opacity = 100);
            opacity: 0;
        }
        .big_box{
            display: none;
            position: absolute;
            top: 0;
            left: 460px;
            width: 600px;
            height: 400px;
            overflow: hidden;
            border: 1px solid #555;
            z-index: 1;
            margin: 50px;
        }
        .big_box img{
            position: absolute;
            z-index: 5;
        }
    </style>
</head>
<body>
    <!-- 小图片 -->
    <div id="small_box" class="small_box">
        <!-- 蒙版层 -->
        <div id="mark" class="mark"></div>
        <!-- 放大镜 -->
        <div id="floor_box" class="floor_box"></div>
        <img src="../images/多肉.png" alt="" id="smallImg">
    </div>
    <!-- 大图片 -->
    <div id="big_box" class="big_box">
        <img src="../images/多肉.png" alt="" id="bigImg">
    </div>

    <script>
        // 获取元素
        var small_box = document.getElementById("small_box");
        var floor_box = document.getElementById("floor_box");
        var big_box = document.getElementById("big_box");
        var bigImg = document.getElementById("bigImg");
        var mark = document.getElementById("mark");

        // 鼠标移入小图片
        mark.onmouseover = function(){
            floor_box.style.display = "block";
            big_box.style.display = "block";
        }
        // 鼠标移出小图片
        mark.onmouseout = function(){
            floor_box.style.display = "none";
            big_box.style.display = "none";
        }
        // 鼠标在小图片内移动
        mark.onmousemove = function(e){
            // 浏览器兼容
            var event = e || window.event;
            // 获取放大镜位置
            var left = event.clientX - mark.offsetLeft - floor_box.offsetWidth/2;
            var top = event.clientY - mark.offsetTop - floor_box.offsetHeight/2;

            // 控制放大镜在小图片范围内
            if(left < 0){
                left = 0;
            }else if(left > mark.offsetWidth - floor_box.offsetWidth){
                left = mark.offsetWidth - floor_box.offsetWidth;
            }
            if(top < 0){
                top = 0;
            }else if(top > mark.offsetHeight - floor_box.offsetHeight){
                top = mark.offsetHeight - floor_box.offsetHeight;
            }


            // 设置放大镜位置
            floor_box.style.left = left + "px";
            floor_box.style.top = top + "px";

            // 设置大图片的位置:X/(A-B) = Y/(C-D)
            var percentX = left / (mark.offsetWidth - floor_box.offsetWidth);
            var percentY = top / (mark.offsetHeight - floor_box.offsetHeight);
            bigImg.style.left = -percentX * (bigImg.offsetWidth - big_box.offsetWidth) + "px";
            bigImg.style.top = -percentY * (bigImg.offsetHeight - big_box.offsetHeight) + "px";
        }
    </script>
</body>
</html>

在这里插入图片描述
淘宝放大镜功能
页面左边有一个小图片,小图片下方有图片列表,鼠标划过任意一张图片列表内的图片,上方的小图片相应改变,鼠标移到上方的小图片内,显示一个放大镜蒙层,页面右边显示放大后的效果。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>放大镜</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .container{
            width: 980px;
            margin: 0 auto;
        }
        ul li{
            list-style: none;
        }
        .fdj{
            width: 350px;
            position: relative;
        }
        .fdj .small{
            width: 350px;
            height: 350px;
            border: 1px solid #ccc;
            margin-bottom: 20px; 
        }
        .fdj .small .glass {
            display: none;
            position: absolute;
            top: 0;
            left: 0;
            width: 240px;
            height: 240px;
            background-color: rgba(44, 55, 66, .3);
            cursor: move;
        }
        .fdj .list{
            width: 350px;
            height: 54px;
            display: flex;
            justify-content: space-around;
        }
        .fdj .list li{
            width: 50px;
            height: 50px;
            /* transparent是全透明黑色(black)的速记法,即一个类似rgba(0,0,0,0)这样的值。 */
            border: 2px solid transparent;
        }
        .fdj .list li.active{
            border-color: red;
        }
        .big{
            display: none;
            position: absolute;
            left: 110%;
            top: 0;
            width: 540px;
            height: 540px;
            overflow: hidden;
        }
        .big img {
            position: absolute;
            top: 0;
            left: 0;
        }
    </style>
    <!-- 引入封装好的js文件 -->
    <script src="../js/GETCSS.js"></script>
</head>
<body>
    <div class="content">
        <!-- 版心 -->
        <div class="container">
            <div class="fdj">
                <!-- 小图片 -->
                <div class="small">
                    <img src="../images/small01.jpg" />
                    <!-- 放大镜 -->
                    <div class="glass"></div>
                </div>
                <!-- 小图片列表 -->
                <ul class="list">
                    <!-- 为每个li设置自定义属性,默认是选中第一个li -->
                    <li data-small-img="../images/small01.jpg" data-big-img="../images/big01.jpg" class="active"><img src="../images/icon01.jpg" /></li>
                    <li data-small-img="../images/small02.jpg" data-big-img="../images/big02.jpg" class=""><img src="../images/icon02.jpg" /></li>
                    <li data-small-img="../images/small03.jpg" data-big-img="../images/big03.jpg" class=""><img src="../images/icon03.jpg" /></li>
                </ul>
                <!-- 大图片 -->
                <div class="big">
                    <img src="../images/big01.jpg" />
                </div>
            </div>
        </div>
    </div>

    <script>
        // 获取元素
        var glass = document.querySelector('.glass');
        var small = document.querySelector('.small');
        var big = document.querySelector('.big');
        var lis = document.querySelectorAll('.list li');
        var bigImg = big.querySelector('img');
        var smallImg = small.querySelector('img');

        // 放大镜元素右移的最大宽度
        var maxLeft = 0;
        // 放大镜元素下移的最大高度
        var maxTop = 0;
        // 小图片和大图片之间位移的像素比
        var r = (350 - 240) / (800 - 540);

        // 通过外部js文件获取small元素的left、top
        var obj = GETCSS.offset(small);

        // 鼠标进入事件
        small.onmouseover  = function(){
            // 显示放大镜元素
            glass.style.display = "block";
            // 显示大图片
            big.style.display = "block";
            // 放大镜元素右移的最大宽度
            maxLeft = small.clientWidth - glass.clientWidth;
            // 放大镜元素下移的最大高度
            maxTop = small.clientHeight - glass.clientHeight;
        }

        // 鼠标离开事件
        small.onmouseout = function(){
            // 隐藏放大镜元素
            glass.style.display = "none";
            // 隐藏大图片
            big.style.display = "none";
        }

        // 鼠标移动事件
        small.onmousemove = function(e){
            // 浏览器兼容处理
            var event = e || window.event;
            // 计算放大镜元素此时的位置
            var resultX = event.pageX - obj.left - glass.clientWidth / 2;
            var resultY = event.pageY - obj.top - glass.clientHeight / 2;

            // 控制放大镜在小图片区域内
            if(resultX < 0){
                resultX = 0;
            }else if(resultX > maxLeft){
                resultX = maxLeft;
            }
            if(resultY < 0){
                resultY = 0;
            }else if(resultY > maxTop){
                resultY = maxTop;
            }
            // 设置放大镜元素随鼠标移动后的位置
            glass.style.left = resultX + "px";
            glass.style.top = resultY + "px";
            // 设置大图片位置随放大镜的移动而移动,方向与放大镜移动的方向相反
            bigImg.style.left = -resultX / r + "px";
            bigImg.style.top = -resultY / r + "px";
        }

        // 鼠标弹起事件
        document.onmouseup = function(){
            document.onmousemove = null;
        }

        // 添加循环事件,用于设置点击小图片列表的图片,对应的li添加边框,小图片和大图片相应的改变
        for (var i = 0; i < lis.length; i++){
            // 设置鼠标进入事件
            lis[i].onmouseenter = function(){
                // 1、先清除其他li的acv=tive类,再给对应的li添加active类
                for(var j = 0; j < lis.length; j++){
                    lis[j].className = "";
                }
                this.className = "active";
                // 2、小图片获取自定义属性值,切换小图片的src
                smallImg.src = this.getAttribute("data-small-img");
                // 2、小图片获取自定义属性值,切换小图片的src
                bigImg.src = this.getAttribute("data-big-img");
            }
        }
    </script>
</body>
</html>

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值