���ִ�Web�����У��ḻ�������Ľ���Ч���������û������Ĺؼ�Ҫ��֮һ�����У���ҳ���������ض�λ��ʱ����Ӧ�ı����Զ�չ����һЧ�������ĵ���վ����Ʒ����ҳ���Լ����˲��͵ȳ��������Ź㷺��Ӧ�á����Ľ���ϸ̽��ʵ����һЧ���IJ�ͬ�����������ӻ����Ĵ�ͳʵ�ֵ����Ŀ���Ӧ�ã����ṩ�Ż����Ժͳ��������Ľ���������
һ��Ч��Ԥ��
�ڿ�ʼ����ʵ��֮ǰ����������ȷһ��Ŀ��Ч����
- ��ʼ״̬�������ĸ߶ȱ�������40px���������ֵ��������ݱ����ء�
- ����״̬����ҳ���������ض�λ�ã������ĸ߶�չ����200px��������ȫ��ʾ��
������ͳ��������
��ͳ��ʵ�ַ�ʽ��ͨ���������ڵĹ����¼����жϱ����Ƿ������ض���λ�÷�Χ��������ʵ�ִ��룺
// ������������ֹ�����¼�����Ƶ������
function debounce(func, delay) {
let timer;
return function() {
const context = this;
const args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(context, args);
}, delay);
};
}
// �����¼���������
const handleScroll = debounce(() => {
const scrollY = window.scrollY;
const titles = document.querySelectorAll('.title');
titles.forEach((title) => {
const top = title.offsetTop;
title.classList.toggle('expanded', scrollY > top - 300);
});
}, 200);
window.addEventListener('scroll', handleScroll);
�ŵ���
- ����������ֱ�ۣ�����������ʵ�֣�����С����Ŀ������ԭ�Ϳ�����˵���ܹ��ڶ�ʱ���ڿ���Ч����
- ���������ض��Ŀ��ܻ��⣬���нϺõļ����ԣ������Ͽ������κ�֧��JavaScript�Ļ��������С�
ȱ����
- ����������Ϊͻ������������ҳ������Ƶ����Ԫ�ؽ϶��������£�Ƶ���ļ�����DOM�������ܵ���ҳ�濨�٣�Ӱ���û����顣����ʹ���˷������������Ż�����������ȫ��������ƿ����
- ��������λ�õĹ������Ը��ӣ���Ҫ��ȷ����Ԫ�ص�ƫ�����������룬�����˿����͵��Ե��Ѷȡ�
- ���ƶ����豸�ϣ����ڴ������������ԺͲ�ͬ�������IJ��죬���ܻ�������Ϊ��һ�»������쳣��������
����Intersection Observer API
Intersection Observer API���������ṩ��һ�ָ�Ч����Ԫ�����ӿڻ�����Ԫ���ཻ�����Ļ��ơ�������ʹ�ø�APIʵ�ֱ����Զ�չ���Ĵ��룺
// ����IntersectionObserverʵ�������ô�������
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
entry.target.classList.toggle('expanded', entry.isIntersecting);
});
}, {
root: null, // �������ӿڽ��й۲�
rootMargin: '-100px 0px -30% 0px', // �����������ɸ���������
threshold: 0.1 // Ԫ�ؽ����ӿ�10%������
});
// ѡ��������Ҫ�۲��ı���Ԫ�ز���ʼ�۲�
const titles = document.querySelectorAll('.title');
titles.forEach((title) => {
observer.observe(title);
});
����������
- ������ԭ��֧�֣��������������Ŀ������ܣ���������Ŀ����������Դ������
- �첽�Ҹ�Ч���ܹ��ں�̨�Զ�����Ԫ�ص��ཻ�����������������̣߳��Ӷ���֤ҳ���������ԡ�
- �ṩ�˷ḻ������ѡ���
rootMargin
��threshold
����������������������������Ӧ��ͬ�Ľ���������
������
- �������ִ������������µ���Ŀ�������Ƕ����ܺ��û�����Ҫ���ϸߵ��д�����Ŀ��
- ����Ҫʵ�ָ��ӵ�Ԫ�ؿɼ��Լ����ͽ���Ч��ʱ��Intersection Observer API�ܹ��ṩ������ǿ���Ľ���������
�ġ����ڿ��ܵ�ʵ��
��ʵ����Ŀ�У�����ͨ����ʹ�ø���ǰ�˿��������߿���Ч�ʺʹ����Ŀ�ά���ԡ���������React��Vue��Svelte������ʵ�ֱ����Զ�չ����ʾ����
React�棨ʹ��Hooks��
import React, { useState, useRef, useEffect } from'react';
const SmartTitle = ({ children }) => {
const [isExpanded, setIsExpanded] = useState(false);
const titleRef = useRef(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => setIsExpanded(entry.isIntersecting),
{
root: null,
rootMargin: '-88px 0px -30% 0px',
threshold: 0.1
}
);
if (titleRef.current) {
observer.observe(titleRef.current);
}
return () => {
if (titleRef.current) {
observer.unobserve(titleRef.current);
}
};
}, []);
return (
<div
ref={titleRef}
style={{
maxHeight: isExpanded? '200px' : '40px',
overflow: 'hidden',
transition: 'all 0.3s ease'
}}
>
{children}
</div>
);
};
export default SmartTitle;
Vue�棨ʹ��Composition API��
<template>
<div
ref="titleEl"
:style="{
maxHeight: isExpanded? '200px' : '40px',
overflow: 'hidden',
transition: 'all 0.3s ease'
}"
>
<slot></slot>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const isExpanded = ref(false);
const titleEl = ref(null);
onMounted(() => {
const observer = new IntersectionObserver(([entry]) => {
isExpanded.value = entry.isIntersecting;
}, {
root: null,
rootMargin: '-88px 0px -30% 0px',
threshold: 0.1
});
if (titleEl.value) {
observer.observe(titleEl.value);
}
onUnmounted(() => {
if (titleEl.value) {
observer.unobserve(titleEl.value);
}
});
});
</script>
Svelte��
<script>
let isOpen = false;
let titleElement;
const observer = new IntersectionObserver(
([entry]) => (isOpen = entry.isIntersecting),
{
root: null,
rootMargin: '-88px 0px -30% 0px',
threshold: 0.1
}
);
$: onMount(() => {
if (titleElement) {
observer.observe(titleElement);
}
});
$: onDestroy(() => {
if (titleElement) {
observer.unobserve(titleElement);
}
});
</script>
<div bind:this={titleElement} class:isOpen style="overflow: hidden;">
<slot></slot>
</div>
��Щ����ʵ�ֵĹ�ͬ�ص��ǣ�
- ���������˿��ܵ���Ӧʽ���Ժ��������ڹ��Ӻ�������������ͼ��������Ч�ķ��룬�����˴����Ŀɶ��ԺͿ�ά���ԡ�
- ��ѭ�˿��ܵ�����ʵ���������������������ܽ��м��ɣ���Ӧ������Ŀ�Ŀ���������
�塢�Ż�����
�����۲���
Ϊ�˽�һ���������ܺ���Դ�����ʣ����ǿ��Բ��ù����۲�����ģʽ������������Ԫ�ع���ͬһ��Intersection Observerʵ����������һ����React��ʵ�ֹ����۲�����ʾ����
// ȫ�ֹ�����IntersectionObserverʵ��
const globalObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
entry.target.classList.toggle('expanded', entry.isIntersecting);
});
}, {
root: null,
rootMargin: '-100px 0px -30% 0px',
threshold: 0.1
});
// React������ʹ�ù����۲���
import React, { useRef, useEffect } from'react';
const TitleComponent = ({ children }) => {
const titleRef = useRef(null);
useEffect(() => {
if (titleRef.current) {
globalObserver.observe(titleRef.current);
}
return () => {
if (titleRef.current) {
globalObserver.unobserve(titleRef.current);
}
};
}, []);
return (
<div
ref={titleRef}
style={{
maxHeight: '40px',
overflow: 'hidden',
transition: 'all 0.3s ease'
}}
>
{children}
</div>
);
};
export default TitleComponent;
ͨ�������۲��������Լ����ڴ�ռ�ú����ܿ�����������ҳ�����д�����Ҫ�۲���Ԫ��ʱЧ����Ϊ���ԡ�
��̬��������
���ݲ�ͬ�豸����Ļ�߶ȶ�̬�����������������ṩ��һ�µ��û����顣�����Ǽ��㶯̬rootMargin
�Ĵ���ʾ����
// ������Ļ�߶ȼ���rootMargin
const getRootMargin = () => {
const vh = window.innerHeight / 100;
return `-${vh * 15}px 0px -${vh * 30}px 0px`;
};
// ʹ�ö�̬rootMargin����IntersectionObserverʵ��
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
entry.target.classList.toggle('expanded', entry.isIntersecting);
});
}, {
root: null,
rootMargin: getRootMargin(),
threshold: 0.1
});
���ַ�ʽ����ȷ���ڲ�ͬ�豸�ϣ�������չ��Ч�������ں��ʵ�λ�ô�����
�����Դ���
���ڲ�֧��Intersection Observer API���Ͼ�����������IE������������������polyfill���ṩ֧�֡����磺
<script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver"></script>
����������һ���̶��ϱ�֤Ӧ���ڸ��������������µ��������С�
�����������⼰��������
��ʵ�ֹ����У����ܻ�����һЩ���⣬�����Ǽ��������İ���������������
����һ��δ����overflow: hidden
�����ڱ���Ԫ����û������overflow: hidden
���ԣ�������չ��ʱ���������ֵ����ݲ��ᱻ���أ������Ӿ�Ч��������Ԥ�ڡ�������������CSS��Ϊ����Ԫ������overflow: hidden
��ʽ��
����������position: sticky
Ԫ����ʹ��
position: sticky
Ԫ�ص������Կ��ܵ���Intersection Observer�Ĵ����������쳣�������������£���������ֱ����position: sticky
Ԫ����Ӧ�ñ���չ��Ч�������߽��и�ϸ�µIJ��Ժ͵�������ȷ�����ܵ���ȷ�ԡ�
��������δ��ʱ�����۲���
����������ж�ػ�������Ҫ�۲�ʱ��û�м�ʱ����unobserve
��������React��Vue��Svelte����disconnect
������ԭ��Intersection Observer�����ᵼ���ڴ�й©��Ӱ��Ӧ�õ����ܡ����ˣ����ʵ����������ڹ��Ӻ����������۲����Ƿdz���Ҫ�ġ�
�ߡ��ܽ�
���Ľ�����ʵ��ҳ������ʱ�����Զ�չ���Ķ��ּ����������ӻ����Ĵ�ͳ��������������Ч��Intersection Observer API���ٵ����ڲ�ͬǰ�˿��ܵ�ʵ�֡�ÿ�ַ�����������ȱ�������ó����������߿��Ը�����Ŀ�ľ��������ͼ���ջѡ�����ʵķ�����ͬʱ�����ǻ��ṩ��һЩ�Ż����Ժͳ��������Ľ������������������߸��õ�ʵ����һ����Ч����ϣ�����ĶԴ�����Web�����е�ʵ������������
�������ڿ������������������������������������⣬���߶Ա��Ľ��ܵ�ʵ�ַ�ʽ�в�ͬ�Ŀ����ͽ��飬��ӭ�����������Է������ڴ�����������ʵ����Ŀ��ʵ�ֵľ���Ч����