nextjs中多张远程图片添加placeholder="blur"
Add placeholder="blur" to multiple remote images in nextjs
我有一个 nextjs 应用程序,它显示来自 api 的电影及其海报,我试图在所有图像完全加载显示之前为它们添加模糊效果。我找到了这个 comment on github discussion which uses plaiceholder 但我找不到一种方法让它适用于 多张 图像。这是我的一些代码
// index.js
...
return (
<>
<MovieList data={props.data.trending} title="Trending Right Now" />
<MovieList data={props.data.popular} title="Popular" />
</>
);
export async function getStaticProps() {
var promises = [];
const api_key = '...'; // don't worry about api key I can make another one
const urls = [
`https://api.themoviedb.org/3/trending/movie/week?api_key=${api_key}`,
`https://api.themoviedb.org/3/movie/popular?api_key=${api_key}&language=en-US&page=1`
];
urls.forEach(function(url) {
promises.push(
axios.get(url).then(
function(data) {
return { success: true, data: data };
},
function() {
return { success: false };
}
)
);
});
const [trendingRes, popularRes] = await Promise.all(promises);
const trending = trendingRes.success === false ? null : trendingRes.data.data;
const popular = popularRes.success === false ? null : popularRes.data.data;
return { props: { data: { trending, popular } } };
}
// MovieList.js
{props.data
? props.data.results.map((movie, index) => {
return (
<>
...
<div>
<Image
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
alt="movie poster"
width="260"
height="391"
placeholder="blur" // doesn't work
/>
</div>
</>
);
})
: 'Not found'}
你可以看到完整的代码here
我终于设法在我的 movieList
组件中使用 plaiceholder and converting images in each api to blurhash
code during api calls and use that code along with react-blurhash
// index.js
const [trendingRes, popularRes] = await Promise.all(
urls.map((url) =>
axios.get(url).then(
(data) =>
Promise.all(
data.data.results.map((one) => {
return getPlaiceholder(
`https://image.tmdb.org/t/p/w500${one.poster_path}`
)
.then(({ blurhash, img }) => {
return { img, ...one, blurhash };
})
.catch(() => ({ ...one, img: "error", blurhash: null }));
})
).then((values) => ({ success: true, data: values })),
() => ({ success: false })
)
)
).then((data) => data);
// movieList.js
{props.data
? props.data.map((movie, index) => {
return (
<>
{movie.blurhash ? (
<div className="overflow-hidden relative block w-[260px] h-[391px]">
<BlurhashCanvas
punch={1}
hash={movie.blurhash.hash}
width={movie.blurhash.height}
height={movie.blurhash.width}
className="absolute left-0 top-0 w-full h-full inset-0"
/>
<Image src={movie.img.src} width="260" height="391" />
</div>
// show image without blur effect if there is any blurhash error
) : (
<Image
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
width="260"
height="391"
className="aspect-w-260 aspect-h-391"
/>
)}
</>
);
})
: "Not found"}
如果您使用 CDN 提供图像,Next.js 还支持通过允许您提供由后端提供的自定义 blurDataURL 来模糊动态图像。
<Image
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
alt="movie poster"
width="260"
height="391"
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAIAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAhEAACAQMDBQAAAAAAAAAAAAABAgMABAUGIWEREiMxUf/EABUBAQEAAAAAAAAAAAAAAAAAAAMF/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAECEgMRkf/aAAwDAQACEQMRAD8AltJagyeH0AthI5xdrLcNM91BF5pX2HaH9bcfaSXWGaRm knyJckliyjqTzSlT54b6bk+h0R//2Q=="
/>
使用动态图片进行模糊处理时,可以提供blurDataURL
道具。
在getStaticProps
中解析从API接收到的数据时,使用plaiceholder
将图像转换为base64。
// index.js - getStaticProps
const [trendingRes, popularRes] = await Promise.all(
urls.map((url) =>
axios.get(url).then(
(data) =>
Promise.all(
data.data.results.map((one) => {
return getPlaiceholder(`https://image.tmdb.org/t/p/w500${one.poster_path}`)
.then(({ base64, img }) => {
return { ...one, img, base64 };
})
.catch(() => ({ ...one, img: null, base64: null }));
})
)
.then(
(values) => ({ success: true, data: values })),
() => ({ success: false })
)
)
).then((data) => data);
)
然后在您的 MovieList
组件中,将 blurDataURL
与 placeholder="blur"
结合使用。
// MovieList.js
{props.data &&
props.data.map((movie, index) => {
return (
<>
<div>
<Image
src={movie.img}
alt="movie poster"
width="260"
height="391"
placeholder="blur"
blurDataURL={movie.base64}
/>
</div>
</>
);
})
}
我有一个 nextjs 应用程序,它显示来自 api 的电影及其海报,我试图在所有图像完全加载显示之前为它们添加模糊效果。我找到了这个 comment on github discussion which uses plaiceholder 但我找不到一种方法让它适用于 多张 图像。这是我的一些代码
// index.js
...
return (
<>
<MovieList data={props.data.trending} title="Trending Right Now" />
<MovieList data={props.data.popular} title="Popular" />
</>
);
export async function getStaticProps() {
var promises = [];
const api_key = '...'; // don't worry about api key I can make another one
const urls = [
`https://api.themoviedb.org/3/trending/movie/week?api_key=${api_key}`,
`https://api.themoviedb.org/3/movie/popular?api_key=${api_key}&language=en-US&page=1`
];
urls.forEach(function(url) {
promises.push(
axios.get(url).then(
function(data) {
return { success: true, data: data };
},
function() {
return { success: false };
}
)
);
});
const [trendingRes, popularRes] = await Promise.all(promises);
const trending = trendingRes.success === false ? null : trendingRes.data.data;
const popular = popularRes.success === false ? null : popularRes.data.data;
return { props: { data: { trending, popular } } };
}
// MovieList.js
{props.data
? props.data.results.map((movie, index) => {
return (
<>
...
<div>
<Image
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
alt="movie poster"
width="260"
height="391"
placeholder="blur" // doesn't work
/>
</div>
</>
);
})
: 'Not found'}
你可以看到完整的代码here
我终于设法在我的 movieList
组件中使用 plaiceholder and converting images in each api to blurhash
code during api calls and use that code along with react-blurhash
// index.js
const [trendingRes, popularRes] = await Promise.all(
urls.map((url) =>
axios.get(url).then(
(data) =>
Promise.all(
data.data.results.map((one) => {
return getPlaiceholder(
`https://image.tmdb.org/t/p/w500${one.poster_path}`
)
.then(({ blurhash, img }) => {
return { img, ...one, blurhash };
})
.catch(() => ({ ...one, img: "error", blurhash: null }));
})
).then((values) => ({ success: true, data: values })),
() => ({ success: false })
)
)
).then((data) => data);
// movieList.js
{props.data
? props.data.map((movie, index) => {
return (
<>
{movie.blurhash ? (
<div className="overflow-hidden relative block w-[260px] h-[391px]">
<BlurhashCanvas
punch={1}
hash={movie.blurhash.hash}
width={movie.blurhash.height}
height={movie.blurhash.width}
className="absolute left-0 top-0 w-full h-full inset-0"
/>
<Image src={movie.img.src} width="260" height="391" />
</div>
// show image without blur effect if there is any blurhash error
) : (
<Image
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
width="260"
height="391"
className="aspect-w-260 aspect-h-391"
/>
)}
</>
);
})
: "Not found"}
如果您使用 CDN 提供图像,Next.js 还支持通过允许您提供由后端提供的自定义 blurDataURL 来模糊动态图像。
<Image
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
alt="movie poster"
width="260"
height="391"
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAIAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAhEAACAQMDBQAAAAAAAAAAAAABAgMABAUGIWEREiMxUf/EABUBAQEAAAAAAAAAAAAAAAAAAAMF/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAECEgMRkf/aAAwDAQACEQMRAD8AltJagyeH0AthI5xdrLcNM91BF5pX2HaH9bcfaSXWGaRm knyJckliyjqTzSlT54b6bk+h0R//2Q=="
/>
使用动态图片进行模糊处理时,可以提供blurDataURL
道具。
在getStaticProps
中解析从API接收到的数据时,使用plaiceholder
将图像转换为base64。
// index.js - getStaticProps
const [trendingRes, popularRes] = await Promise.all(
urls.map((url) =>
axios.get(url).then(
(data) =>
Promise.all(
data.data.results.map((one) => {
return getPlaiceholder(`https://image.tmdb.org/t/p/w500${one.poster_path}`)
.then(({ base64, img }) => {
return { ...one, img, base64 };
})
.catch(() => ({ ...one, img: null, base64: null }));
})
)
.then(
(values) => ({ success: true, data: values })),
() => ({ success: false })
)
)
).then((data) => data);
)
然后在您的 MovieList
组件中,将 blurDataURL
与 placeholder="blur"
结合使用。
// MovieList.js
{props.data &&
props.data.map((movie, index) => {
return (
<>
<div>
<Image
src={movie.img}
alt="movie poster"
width="260"
height="391"
placeholder="blur"
blurDataURL={movie.base64}
/>
</div>
</>
);
})
}