master
This commit is contained in:
parent
f46a01daf2
commit
57811df6e2
|
|
@ -0,0 +1,22 @@
|
||||||
|
.block {
|
||||||
|
height: 300px;
|
||||||
|
border: 3px solid #ccc;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: white;
|
||||||
|
padding: 24px;
|
||||||
|
line-height: 32px;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lazyloadImg{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
&>li{
|
||||||
|
width: 400px;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
img{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
import styles from "../../index.less";
|
||||||
|
|
||||||
|
interface OwnProps {}
|
||||||
|
|
||||||
|
type Props = OwnProps;
|
||||||
|
|
||||||
|
const Index: React.FC<Props> = (props) => {
|
||||||
|
const itemRef = useRef<HTMLElement[]>([]);
|
||||||
|
const ob = new IntersectionObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
const img: any = entry.target;
|
||||||
|
img.src = img.dataset.src;
|
||||||
|
ob.unobserve(entry.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
useEffect(() => {
|
||||||
|
if (itemRef.current) {
|
||||||
|
_.forEach(itemRef.current, (item) => {
|
||||||
|
ob.observe(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (itemRef.current) {
|
||||||
|
_.forEach(itemRef.current, (item) => {
|
||||||
|
ob.unobserve(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [itemRef.current]);
|
||||||
|
return (
|
||||||
|
<ul className={styles.lazyloadImg}>
|
||||||
|
{_.map(
|
||||||
|
Array.from({ length: 200 }, () => Math.floor(Math.random() * 100)),
|
||||||
|
(item, index) => (
|
||||||
|
<li key={index}>
|
||||||
|
<img data-src={`https://picsum.photos/300/300?random=${index}`} alt="" src={require("../default.jpeg")} ref={(el) => (itemRef.current[index] = el as HTMLElement)} />
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Index;
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 8.0 KiB |
|
|
@ -0,0 +1,43 @@
|
||||||
|
import React from "react";
|
||||||
|
import SlideInItem from "./slideInItem";
|
||||||
|
|
||||||
|
interface OwnProps {}
|
||||||
|
|
||||||
|
type Props = OwnProps;
|
||||||
|
|
||||||
|
const list = [
|
||||||
|
{ id: 1, bg: "red" },
|
||||||
|
{ id: 2, bg: "blue" },
|
||||||
|
{ id: 3, bg: "green" },
|
||||||
|
{ id: 4, bg: "yellowgreen" },
|
||||||
|
{ id: 5, bg: "orange" },
|
||||||
|
{ id: 6, bg: "pink" },
|
||||||
|
{ id: 7, bg: "antiquewhite" },
|
||||||
|
{ id: 8, bg: "darkseagreen" },
|
||||||
|
{ id: 9, bg: "purple" },
|
||||||
|
{ id: 10, bg: "red" },
|
||||||
|
{ id: 11, bg: "black" }
|
||||||
|
];
|
||||||
|
const Index: React.FC<Props> = (props) => {
|
||||||
|
const map = new WeakMap();
|
||||||
|
const ob = new IntersectionObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
const animation = map.get(entry.target);
|
||||||
|
if (animation) {
|
||||||
|
animation.play();
|
||||||
|
ob.unobserve(entry.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{list.map((item, index) => {
|
||||||
|
return <SlideInItem key={index} item={item} ob={ob} map={map}></SlideInItem>;
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Index;
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
import styles from "../index.less";
|
||||||
|
|
||||||
|
interface OwnProps {
|
||||||
|
item: any;
|
||||||
|
ob: any;
|
||||||
|
map: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = OwnProps;
|
||||||
|
const SLIDE_FADE_DISTANCE = 50;
|
||||||
|
const SLIDE_FADE_DURATION = 1000;
|
||||||
|
|
||||||
|
const isBelowViewport = (el: HTMLDivElement) => {
|
||||||
|
const rect = el.getBoundingClientRect();
|
||||||
|
return rect.top - SLIDE_FADE_DISTANCE > window.innerHeight;
|
||||||
|
};
|
||||||
|
const slideInItem: React.FC<Props> = (props) => {
|
||||||
|
const { item, ob, map } = props;
|
||||||
|
const itemRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (itemRef.current && ob) {
|
||||||
|
if (!isBelowViewport(itemRef.current)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const animation = itemRef.current.animate(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
transform: `translateY(${SLIDE_FADE_DISTANCE}px)`,
|
||||||
|
opacity: 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
transform: `translateY(0)`,
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
{
|
||||||
|
duration: SLIDE_FADE_DURATION,
|
||||||
|
easing: "ease-in-out",
|
||||||
|
fill: "forwards" // 当动画完成后,保留最后一个关键帧的样式
|
||||||
|
}
|
||||||
|
);
|
||||||
|
animation.pause();
|
||||||
|
map.set(itemRef.current, animation);
|
||||||
|
ob.observe(itemRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
ob.unobserve(itemRef.current);
|
||||||
|
};
|
||||||
|
}, [itemRef.current]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.block} ref={itemRef} style={{ backgroundColor: item.bg }}>
|
||||||
|
<h3>The most popular component library</h3>
|
||||||
|
|
||||||
|
<h5>for Tailwind CSS</h5>
|
||||||
|
<p>daisyUI adds component class names to Tailwind CSS so you can make beautiful websites faster than ever.</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default slideInItem;
|
||||||
Loading…
Reference in New Issue