哈哈哈哈哈

114 阅读9分钟

Scale

前置知识

transform属性

通过平移,旋转,放大/缩小改变元素位置和大小

image.png

transition

CSS 中用于实现过渡效果的属性,它允许你在 CSS 属性值发生变化时平滑地改变属性值。过渡效果可以使元素在状态改变时呈现出平滑的动画效果,而不是突然地改变。

image.png

代码讲解

我们先来看对应的 dom 布局

<div class="text_class">
        <h1>野生动物种类</h1>
        <ul class="text_class_list">
            <li><a href="class_Mammals.html"><img src="../images/哺乳类.jpg" alt=""><span>哺乳类</span></a></li>
            <li><a href="class_fish.html"><img src="../images/鱼类.jpg" alt=""><span>鱼类</span></a></li>
            <li><a href="class_Birds.html"><img src="../images/鸟类.jpg" alt=""><span>鸟类</span></a></li>
            <li><a href="class_Reptiles.html"><img src="../images/爬行类.jpg" alt=""><span>爬行类</span></a></li>
        </ul>
    </div>
    <div class="text_pictures">
        <h1>动物世界</h1>
        <ul class="text_pictures_list">
            <li><a href="pictures.html"><img src="../images/g4.jpg" alt=""></a></li>
            <li><a href="pictures.html"><img src="../images/g5.jpg" alt=""></a></li>
            <li><a href="pictures.html"><img src="../images/g1.jpg" alt=""></a></li>
            <li><a href="pictures.html"><img src="../images/g2.jpg" alt=""></a></li>
            <li><a href="pictures.html"><img src="../images/g3.jpg" alt=""></a></li>
        </ul>
    </div>

就是两行,每行有不同的图片,hover上去时放大,离开时缩小,要实现这个功能,有两种思路,代码中实现的是思路一,js方式

方式一 JS 方式

js方式主要是监听js事件,执行不同的函数来达到目的

第一步,获取我们要放大缩小的元素,

// 获取图片列表
const picturesList = document.querySelector('.text_pictures_list');

第二步,注册鼠标事件,mouseover事件就是鼠标移入事件, mouseout就是鼠标移出事件

// 添加事件监听器,实现鼠标移过时放大图片的效果
picturesList.addEventListener('mouseover', function(event) {
    // 他的这一种方式,是监听父元素,就是text_pictures_list这个元素,
    // 触发这个事件可能是不同的元素触发的(只要是他的子级就触发),
    // 所以要判断是不是 img 图片触发的,只要图片触发才放大
    // 如果目标是图片,则放大
    if (event.target.tagName === 'IMG') {
    // 这就是前置知识中的transform属性,scale属性就是把该元素放大,放大到1.2倍
        event.target.style.transform = 'scale(1.2)'; // 放大到原尺寸的 1.2 倍
       
        // 'transform 0.5s ease'意思是 transform 属性发生变化时,做一个过渡效果,持续0.5s,变化曲线是ease类型
        
        event.target.style.transition = 'transform 0.5s ease'; // 添加动画效果
    }
});

// 添加事件监听器,实现鼠标移出时恢复原始大小的效果
picturesList.addEventListener('mouseout', function(event) {
// 同上面,要判断是谁触发的这个事件,然后把 他还原,scale(1) 就是默认大小
    // 如果目标是图片,则恢复原始大小
    if (event.target.tagName === 'IMG') {
        event.target.style.transform = 'scale(1)';
        event.target.style.transition = 'transform 0.5s ease'; // 添加动画效果
    }
});

然后看他的另一种绑定方式,和上面大同小异,上面是绑定父元素,这是给每一个img元素都绑定上mouseover mouseout鼠标移入移出事件


// 获取野生动物种类列表
const animalListItems = document.querySelectorAll('.text_class_list li a');
console.log(animalListItems)

// 添加事件监听器,实现鼠标移过时放大图片的效果
// 对每一个img元素都绑定上⌚️
animalListItems.forEach(item => {
    item.addEventListener('mouseover', function(event) {
    // 原理同上
            item.style.transform = 'scale(1.2)'; // 放大到原尺寸的 1.2 倍
            item.style.transition = 'transform 0.5s ease'; // 添加动画效果
    });

    // 添加事件监听器,实现鼠标移出时恢复原始大小的效果
    item.addEventListener('mouseout', function(event) {
            item.style.transform = 'scale(1)';
            item.style.transition = 'transform 0.5s ease'; // 添加动画效果
    });
});

第二种方式 css

代码中没有,大概这么写

.text_class_list img {
    transform: scale(1);
}
.text_class_list img:hover {
    transform: scale(1.2);
    transition: transform 0.5s ease;
}

轮播图

这里也用到了上面说的 transform 属性

我们可以先想一下大概思路,

  1. 把图片放成一排,每个图片宽高一样,然后只显示当前视口的那张图片,其他的图片在屏幕外,那么是不是需要一个currentIndex变量记录一下当前的索引,是那张图片呢?
  2. 那如何把当前图片滚动到可以看见的地方呢?假设每张图片宽度都是100px,那第 i 个图片只需要向左移动 100 * index px是不是就出现了呢?
  3. 上一页、下一页的就是计算 index,移动位置就好了对嘛?自动播放就是每秒自动的 改变索引currentIndex的值对嘛?

那我们接下来具体看看怎实现的?

  • 获取轮播图元素,定义当前索引,显示第几张照片
let currentIndex = 0; // 当前幻灯片索引
 // 获取所有幻灯片元素
const slides = document.querySelectorAll('.index_banner_list li');
let totalSlides = slides.length; // 幻灯片总数
let autoSlideInterval; // 存储自动轮播的 setInterval 函数
  • 初始化我们的幻灯片

为什么有这一步?为什么要克隆第一张和最后一张

image.png

// 克隆第一张和最后一张幻灯片,并调整位置
    const firstSlideClone = slides[0].cloneNode(true);
    const lastSlideClone = slides[totalSlides - 1].cloneNode(true);
    lastSlideClone.style.marginLeft = '-100%'; // 将最后一张幻灯片移至首位
    document.querySelector('.index_banner_list').appendChild(firstSlideClone); // 在列表末尾添加第一张克隆
    document.querySelector('.index_banner_list').insertBefore(lastSlideClone, slides[0]); // 将最后一张克隆插入到列表开头
  • 实现下一页
// 向后切换幻灯片
function nextSlide() {
    // 判断当前页是不是最后一页,如果不是,那么就直接 currentIndex + 1
    // 否则,就应该切换到第一页,也就是 updateSlide(0);
    
    // 克隆第一页的作用出现了,我们到了最后一页,实际后面有我们克隆的第一页
    // 这时候 translateX(100%),就是显示了克隆的那页,表面上是第一页,实现了无缝切换
    if (currentIndex === totalSlides - 1) {
        document.querySelector('.index_banner_list').style.transform = `translateX(100%)`;
        document.querySelector('.index_banner_list').style.transition = `none`;
        document.querySelector('.index_banner_list').clientLeft;
        updateSlide(0);
    } else {
        updateSlide(currentIndex + 1);
    }
}
  • updateSlide怎么实现的呢?

无非就是根据索引计算应该移动的距离

// 更新幻灯片显示
function updateSlide(index) {
    currentIndex = index;
    // 计算移动距离,以便切换到当前幻灯片
    const distance = -index * 100;
    // 应用 CSS transform 属性以移动幻灯片
    document.querySelector('.index_banner_list').style.transform = `translateX(${distance}%)`;
    document.querySelector('.index_banner_list').style.transition = `0.5s`;
    // 这下面就是高亮小圆点,要先去掉所有的高亮,在对当前小圆点加上高亮效果
    const active = document.querySelector('.indicator span.active');
    active.classList.remove('active'); // 移除前一个激活的幻灯片指示器
    indicators[currentIndex].classList.add('active'); // 添加当前幻灯片指示器的激活状态
}
  • 实现上一页 大概原理和「下一页」一样,不同点在于这是判断是否是第一页
// 向前切换幻灯片
function prevSlide() {
// 判断是否是第一页,还要往前翻,那就是最后一页,这时候就克隆最后一页的效果了
    if (currentIndex === 0) {
        document.querySelector('.index_banner_list').style.transform = `translateX(-${totalSlides}00%)`;
        document.querySelector('.index_banner_list').style.transition = `none`;
        document.querySelector('.index_banner_list').clientLeft;
        updateSlide(totalSlides - 1);
    } else {
        updateSlide(currentIndex - 1);
    }
}
  • 自动轮播
// 启动自动轮播
function startAutoSlide() {
// 开启定时器,每隔一段时间手动触发一下 nextSlide下一页函数就好了
    autoSlideInterval = setInterval(nextSlide, 3 * 1000); // 每3秒切换一次
}

// 停止自动轮播
function stopAutoSlide() {
// 清除定时器
    clearInterval(autoSlideInterval);
}

// 初始化时启动自动轮播
startAutoSlide();
  • 小圆点 就是根据轮播图的长度,去生成小圆点,加入到 dom 元素中
// 创建幻灯片指示器
for (let i = 0; i < totalSlides; i++) {
    //生成小圆点
    let indicator = document.createElement('span');
    // 加入到 dom 元素中
    document.querySelector('.indicator').appendChild(indicator);
}
// 获取小圆点
let indicators = document.querySelectorAll('.indicator span')
 // 将当前幻灯片指示器设置为激活状态
indicators[currentIndex].classList.add('active');

然后监听每个小圆点事件,调用updateSlide方法切换轮播图

// 为每个幻灯片指示器添加鼠标移入和移出事件
indicators.forEach((item, i) => {
    // 鼠标移入事件
    item.onmouseenter = function () {
        stopAutoSlide(); // 鼠标移入时停止自动轮播
        currentIndex = i; // 更新当前幻灯片索引为指示器的索引
        updateSlide(currentIndex); // 更新幻灯片显示
    }
    // 鼠标移出事件
    item.onmouseleave = startAutoSlide; // 鼠标移出时开始自动轮播
})

文字滚动

两种方式,

第一种 css

前置知识

  1. animaiton属性
  2. 固定定位,top属性
  3. requestAnimationFrame和cancelAnimationFrame
  4. animationPlayState

利用 css 的 animaiton属性,可以自定义一个动画,不同阶段有不同的表现,这就是不停的去改变 news-list-inner 元素的 top 值,最后动画结束时滚动到最上方,这用的是固定定位,开始 top = 0,在 6s内,滚动到 top= -440的位置,就实现了滚动。

animation: scroll 6s linear infinite normal;这句话意思是,使用了动画名为 scroll的动画,6s时间内,以linear的方式滚动,infinite是无限循环,也就是一直滚动

image.png

第二种方式 js

这种方式本质上也是采用的上面的原理,不断的改变 news-list-inner 元素的 top 值,来实现滚动。他使用requestAnimationFrame这个方法,每一帧都改变一次top值,requestAnimationFrame是浏览器提供的,一般每秒执行60次,跟定时器一样

第一步,第一滚动速度,开启自动滚动

// 获取需要操作的元素
const newsListContainer = document.querySelector('.news-list-container');
const newsListInner = document.querySelector('.news-list-inner');
const allItems = document.querySelectorAll('.news-list-inner div');

// 创建克隆节点
const clonedItems = cloneItems(Array.from(allItems));

// 将克隆节点添加到容器末尾
appendClonedItems(newsListInner, clonedItems);

// 初始化滚动速度和方向
let scrollSpeed = 1; // 初始滚动速度
let scrollDirection = 'up'; // 初始滚动方向

// 启动滚动
let animationFrameId = requestAnimationFrame(scrollNews(newsListInner, scrollDirection));

然后第二步,我们看一下 scrollNews 做了什么?

// 滚动元素
function scrollNews(element, direction) {
    // element就是我们的滚动元素
    // direction就是方向,
    // 返回的函数就是每一帧都要执行的函数
    return function() {
        if (direction === 'up') {
           // 向上滚动时,先获取当前滚动元素的的 top值,将 top + scrollSpeed速度的结果
          //给到这个元素,那么 相当于将这个元素向上移动了,
          // 比如开始是 0px,原地不同,第一次就是 -1px,那么元素top=-1px,元素会被向上移动1px
          // 依次类推。。。
            element.style.top = parseInt(element.style.top) - scrollSpeed + 'px';
            if (parseInt(element.style.top) < -440) {
                element.style.top = '0px';
            }
        } else if (direction === 'down') {
        // 同理,区别在于 + 加上 - ,向上和向下移动
            element.style.top = parseInt(element.style.top) + scrollSpeed + 'px';
            if (parseInt(element.style.top) >= 0) {
                element.style.top = '-440px';
            }
        }

// 每一帧都执行这个函数,建议百度一下requestAnimationFrame函数
        animationFrameId = requestAnimationFrame(scrollNews(element, direction));
    };
}

这样我们就实现了滚动了,那么如何实现鼠标移入停止呢?接着向下看

第三步 当然是监听mouseenter移入事件了,在移入时,执行一下函数

// 鼠标移入停止滚动
newsListContainer.addEventListener('mouseenter', handleMouseEnter(newsListInner, animationFrameId));

// 处理鼠标移入事件,暂停滚动
function handleMouseEnter(element, animationId) {
// 这个函数的功能就是 cancelAnimationFrame 清除动画帧,不要他每一帧都调用了
    return function() {
        cancelAnimationFrame(animationId);
        // 通过css设置动画效果停止,建议看一下 animationPlayState 属性
        stopScrollAnimation(element);
    };
}

// 暂停滚动动画
function stopScrollAnimation(element) {
// paused是让动画继续停止
    element.style.animationPlayState = 'paused';
}

第四步,鼠标移出继续滚动,原理同第三步,但是恰恰💡

// 鼠标移出继续滚动
newsListContainer.addEventListener('mouseleave', handleMouseLeave(newsListInner));

// 处理鼠标移出事件,恢复滚动
function handleMouseLeave(element) {
    return function() {
        resumeScrollAnimation(element);
    };
}

// 恢复滚动动画
function resumeScrollAnimation(element) {
// runing是让动画继续执行
    element.style.animationPlayState = 'running';
}

第五步鼠标移动时更新滚动速度原理差不多:监听事件,计算速度

newsListContainer.addEventListener('mousemove', adjustScrollSpeed(newsListContainer));

// 根据鼠标在容器内的位置调整滚动速度
function adjustScrollSpeed(container) {
    return function(event) {
    // 获取容器高度
        const containerHeight = container.clientHeight;
        // 根据鼠标位置和滚动容器在浏览器中的位置,计算一下速度,赋值给 scrollSpeed 就好了
        const mouseY = event.clientY - container.getBoundingClientRect().top;
        scrollSpeed = (mouseY / containerHeight) * 10; // 根据鼠标在容器内的位置调整滚动速度
    };
}


以上就是它的功能了,但是我看好像没有用到