飞道的博客

PC 端网页特效-offset 系列及学习案例

291人阅读  评论(0)

PC 端网页特效-offset 系列及学习案例

学习地址还是在这里:JavaScript 基础语法-dom-bom-js-es6 新语法-jQuery-数据可视化 echarts 黑马 pink 老师前端入门基础视频教程(500 多集)持续

总归说学完一个是一个,不能继续下次一定了

offset 即 元素偏移量,PC 端的网页特效是一个系列:

  • offset
  • client
  • scroll
  • 动画函数封装

不过因为每周学习的进度关系,所以会将 PC 端网页特效做一个系列的笔记。

其学习案例有 3 个:

  1. 基础的 offset 应用案例,即获得鼠标在盒子中的坐标
  2. 拖曳窗口
  3. 仿京东放大镜

offset 概述

offset 即偏移量,使用 offset 系列相关属性可以 动态的 获取该元素的位置(偏移)、大小等,如:

  • 元素距离带有定位父元素的位置
  • 获取元素自身的大小(宽度高度)

注:返回的数值不带单位

offset 系列常用的属性包括:

  • element.offsetParent

    返回作为该元素带有定位的父级元素,如果父级元素没有定位,则返回 body

    注意,parentNodeoffsetParent 还是有本质上的区别的:parentNode 返回的是直接父级元素,offsetParent 返回的是带有定位的父级元素。

  • element.offsetTop

    返回元素带有定位父元素上方的偏移

  • element.offsetLeft

    返回元素带有定位父元素左边框的偏移

  • element.offsetWidth

    返回自身包括 padding, 边框, 内容区的宽度,返回数值不带单位

  • element.offsetHeight

    返回自身包括 padding, 边框, 内容区的高度,返回数值不带单位

offset 和 style 的区别

offset style
offset 可以得到任意样式表中的样式值 style 只能得到行内样式表中的样式值,无法获得内嵌样式
offset 系列获得的数值是没有单位的 style.width 获得的是带有单位的字符串
offsetWidth 包含 padding+border+width style.width 获得不包含 padding 和 border 的值
offsetWidth 等属性是只读属性,只能获取不能赋值 style 属性是可读写属性,style.width 可以获取也可以赋值
只想要获取元素大小位置的时候,用 offset 更合适 要对元素样式进行修改的话,使用 style 更合适

offset 学习案例

即获得鼠标在盒子中的坐标

效果图:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .box {
     
        width: 500px;
        height: 500px;
        background-color: #eee;
        margin-left: 50px;
      }
    </style>
  </head>
  <body>
    <div class="box"></div>
    <script>
      // 目标:
      // 在盒子中点击,想要获得鼠标距离盒子左右的距离
      // 实现:
      // 1. 获得鼠标在页面中的坐标,e.pageX, e.pageY
      // 2. 获得盒子到页面中的距离, box.offsetLeft, box.offsetTop
      // 3. 两者相减就能够获得鼠标在盒子中的坐标
      const box = document.querySelector(".box");
      box.addEventListener("mousemove", function (e) {
     
        // console.log(e.pageX, e.pageY);
        // console.log(box.offsetLeft, box.offsetTop);
        const x = e.pageX - this.offsetLeft;
        const y = e.pageY - this.offsetTop;
        box.textContent = `x: ${
       x}, y: ${
       y}`;
      });
    </script>
  </body>
</html>

拖曳窗口

这中还有一些 modal 的东西,不过效果图上没有展示出来。

效果图:

实现是部分完整的——input 里面的东西我没有加进去,主要效果还是页面上的东西。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
     
        margin: 0;
        padding: 0;
      }
      .login,
      .modal {
     
        display: none;
      }
      .login {
     
        width: 512px;
        height: 280px;
        position: fixed;
        border: #ebebeb solid 1px;
        left: 50%;
        top: 50%;
        background-color: #fff;
        box-shadow: 0 0 20px #ddd;
        z-index: 999;
        transform: translate(-50%, -50%);
        text-align: center;
      }
      .modal {
     
        position: absolute;
        top: 0;
        left: 0;
        width: 100vw;
        height: 100vh;
        background-color: rgba(0, 0, 0, 0.3);
        z-index: 998;
      }
      .login-content {
     
        margin: 100px auto;
        text-align: center;
      }
      .login-content h3:hover,
      .closeBtn:hover {
     
        cursor: pointer;
      }
      .closeBtn {
     
        position: absolute;
        right: 10px;
        top: 10px;
      }
      .login h4 {
     
        margin-top: 10px;
      }
      .login h4:hover {
     
        cursor: move;
      }
    </style>
  </head>
  <body>
    <div class="login-content">
      <h3 id="openLogin">点击弹出登录框</h3>
    </div>
    <div class="login">
      <div class="closeBtn" id="closeBtn">关闭</div>
      <h4 class="loginHeader">登录会员</h4>
    </div>
    <div class="modal"></div>
    <script>
      // 获取元素
      const login = document.querySelector(".login");
      const modal = document.querySelector(".modal");
      const closeBtn = document.querySelector("#closeBtn");
      const openLogin = document.querySelector("#openLogin");
      // 点击显示元素
      openLogin.addEventListener("click", () => {
     
        modal.style.display = "block";
        login.style.display = "block";
      });
      closeBtn.addEventListener("click", () => {
     
        modal.style.display = "none";
        login.style.display = "none";
      });
      // 实现拖拽移动功能
      // 1. 鼠标按下获得鼠标在盒子内的坐标
      const loginHeader = document.querySelector(".loginHeader");
      loginHeader.addEventListener("mousedown", function (e) {
     
        const x = e.pageX - login.offsetLeft;
        const y = e.pageY - login.offsetTop;
        const move = function (e) {
     
          login.style.left = `${
       e.pageX - x}px`;
          login.style.top = `${
       e.pageY - y}px`;
        };
        // 2. 移动鼠标
        document.addEventListener("mousemove", move);
        document.addEventListener("mouseup", function () {
     
          document.removeEventListener("mousemove", move);
        });
      });
    </script>
  </body>
</html>

仿京东放大镜

其他的部分是在品优购项目里面实现的,这个我还没做,所以没法复用页面。

无奈只好就直接用一个拉一个 div 先做案例吧。代码都是一样的,不知道为什么在自己电脑上好抖……晚点继续研究一下。另外就是代码注释还是不够,这也是个毛病。

实现代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .magnifying-glass {
     
        position: absolute;
        left: 100px;
        margin: 50px auto;
        min-height: 300px;
        border: 1px solid #ccc;
      }
      .modal {
     
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: 300px;
        height: 300px;
        background-color: #fede4f;
        opacity: 0.5;
      }
      .modal:hover {
     
        cursor: move;
      }
      .enlarge-preview-wrapper {
     
        display: block;
        position: absolute;
        left: 460px;
        top: 0;
        width: 500px;
        height: 500px;
        overflow: hidden;
        border: 1px solid #ccc;
      }
      .enlarge-preview {
     
        position: absolute;
        top: 0;
        left: 0;
        width: 150%;
        height: auto;
      }
    </style>
  </head>
  <body>
    <div class="magnifying-glass">
      <img
        src="http://img10.360buyimg.com/n1/s450x450_jfs/t1/174266/32/5661/92244/607eb66fEcb90c325/8778d62b01b2c21b.jpg"
        class="preview-img"
      />
      <div class="modal"></div>
      <div class="enlarge-preview-wrapper">
        <img
          class="enlarge-preview"
          src="http://img10.360buyimg.com/n1/s450x450_jfs/t1/174266/32/5661/92244/607eb66fEcb90c325/8778d62b01b2c21b.jpg"
          alt=""
          srcset=""
        />
      </div>
    </div>

    <script>
      const previewImg = document.querySelector(".preview-img");
      const modal = document.querySelector(".modal");
      const enlargeImgWrapper = document.querySelector(
        ".enlarge-preview-wrapper"
      );
      // 案例分析
      // 1. 模块分割
      //      a. 鼠标经过小盒子图片,黄色的遮罩层和大图片盒子要被显示
      previewImg.addEventListener("mouseover", function (e) {
     
        modal.style.display = "block";
        enlargeImgWrapper.style.display = "block";
      });
      previewImg.addEventListener("mouseout", function (e) {
     
        modal.style.display = "none";
        enlargeImgWrapper.style.display = "none";
      });
      //      b. 黄色的遮罩层更随鼠标移动
      //          - 把鼠标坐标给遮挡层不合适,因为遮挡层坐标以父元素为准
      //          - 首先获得鼠标在盒子内的坐标
      //          - 获得的值作为遮挡层的 left 和 top
      previewImg.addEventListener("mousemove", function (e) {
     
        // 1. 先计算鼠标在盒子内的坐标
        const x = e.pageX - this.parentNode.offsetLeft;
        const y = e.pageY - this.parentNode.offsetTop;
        const maxX = this.offsetWidth - modal.offsetWidth;
        const maxY = this.offsetHeight - modal.offsetHeight;
        // 2. 计算最大最小空间
        let modalX = x - modal.offsetWidth / 2;
        modalX = modalX < 0 ? 0 : modalX > maxX ? maxX : modalX;
        let modalY = y - modal.offsetHeight / 2;
        modalY = modalY < 0 ? 0 : modalY > maxY ? maxY : modalY;

        modal.style.left = modalX + "px";
        modal.style.top = modalY + "px";
        //      c. 大图片跟随黄色遮罩层移动
        // 大图片的移动距离 = 遮挡层移动距离 * 大图片最大移动距离 /遮挡层最大移动距离
        const enlargedImg = document.querySelector(".enlarge-preview");
        const modalMax =
          enlargedImg.offsetWidth - enlargeImgWrapper.offsetWidth;
        const enlargedX = (modalX * modalMax) / maxX;
        const enlargedY = (modalY * modalMax) / maxX;
        enlargedImg.style.left = -enlargedX + "px";
        enlargedImg.style.top = -enlargedY + "px";
      });
    </script>
  </body>
</html>

转载:https://blog.csdn.net/weixin_42938619/article/details/117271357
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场