1
1
import { siteConfig } from '@/lib/config'
2
2
import Head from 'next/head'
3
- import React , { useEffect , useRef , useState } from 'react'
4
-
3
+ import { useEffect , useRef , useState } from 'react'
5
4
/**
6
5
* 图片懒加载
7
6
* @param {* } param0
@@ -20,26 +19,35 @@ export default function LazyImage({
20
19
onLoad,
21
20
style
22
21
} ) {
22
+ const maxWidth = siteConfig ( 'IMAGE_COMPRESS_WIDTH' )
23
23
const imageRef = useRef ( null )
24
- const [ imageLoaded , setImageLoaded ] = useState ( false )
24
+ const [ adjustedSrc , setAdjustedSrc ] = useState (
25
+ placeholderSrc || siteConfig ( 'IMG_LAZY_LOAD_PLACEHOLDER' )
26
+ )
27
+
25
28
if ( ! placeholderSrc ) {
26
29
placeholderSrc = siteConfig ( 'IMG_LAZY_LOAD_PLACEHOLDER' )
27
30
}
28
31
32
+ /**
33
+ * 图片加载成功回调
34
+ */
29
35
const handleImageLoad = ( ) => {
30
- setImageLoaded ( true )
31
36
if ( typeof onLoad === 'function' ) {
32
37
onLoad ( ) // 触发传递的onLoad回调函数
33
38
}
34
39
}
35
40
36
41
useEffect ( ( ) => {
42
+ const adjustedImageSrc = adjustImgSize ( src , maxWidth )
43
+ setAdjustedSrc ( adjustedImageSrc )
44
+
37
45
const observer = new IntersectionObserver (
38
- ( entries ) => {
39
- entries . forEach ( ( entry ) => {
46
+ entries => {
47
+ entries . forEach ( entry => {
40
48
if ( entry . isIntersecting ) {
41
49
const lazyImage = entry . target
42
- lazyImage . src = src
50
+ lazyImage . src = adjustedImageSrc
43
51
observer . unobserve ( lazyImage )
44
52
}
45
53
} )
@@ -56,12 +64,12 @@ export default function LazyImage({
56
64
observer . unobserve ( imageRef . current )
57
65
}
58
66
}
59
- } , [ src ] )
67
+ } , [ src , maxWidth ] )
60
68
61
69
// 动态添加width、height和className属性,仅在它们为有效值时添加
62
70
const imgProps = {
63
71
ref : imageRef ,
64
- src : imageLoaded ? src : placeholderSrc ,
72
+ src : priority ? adjustedSrc : placeholderSrc ,
65
73
alt : alt ,
66
74
onLoad : handleImageLoad
67
75
}
@@ -87,12 +95,39 @@ export default function LazyImage({
87
95
if ( style ) {
88
96
imgProps . style = style
89
97
}
90
- return ( < >
91
- { /* eslint-disable-next-line @next/next/no-img-element */ }
92
- < img { ...imgProps } />
93
- { /* 预加载 */ }
94
- { priority && < Head >
95
- < link rel = 'preload' as = 'image' src = { src } />
96
- </ Head > }
97
- </ > )
98
+ return (
99
+ < >
100
+ { /* eslint-disable-next-line @next/next/no-img-element */ }
101
+ < img { ...imgProps } />
102
+ { /* 预加载 */ }
103
+ { priority && (
104
+ < Head >
105
+ < link rel = 'preload' as = 'image' href = { adjustedSrc } />
106
+ </ Head >
107
+ ) }
108
+ </ >
109
+ )
110
+ }
111
+ /**
112
+ * 根据窗口尺寸决定压缩图片宽度
113
+ * @param {* } src
114
+ * @param {* } maxWidth
115
+ * @returns
116
+ */
117
+
118
+ const adjustImgSize = ( src , maxWidth ) => {
119
+ if ( ! src ) {
120
+ return siteConfig ( 'IMG_LAZY_LOAD_PLACEHOLDER' )
121
+ }
122
+ const screenWidth = window . screen . width
123
+
124
+ // 屏幕尺寸大于默认图片尺寸,没必要再压缩
125
+ if ( screenWidth > maxWidth ) {
126
+ return src
127
+ }
128
+
129
+ // 正则表达式,用于匹配 URL 中的 width 参数
130
+ const widthRegex = / w i d t h = \d + /
131
+ // 使用正则表达式替换 width 参数
132
+ return src . replace ( widthRegex , `width=${ screenWidth } ` )
98
133
}
0 commit comments