You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

宽高动态时如何使用react-blurhash生成图片占位符?

解决react-blurhash在百分比宽高容器下的占位符问题

问题场景

使用react-blurhash组件实现图片占位符时,组件要求width和height必须传入整数,但图片容器采用百分比布局(依赖父元素尺寸),无法确定具体整数值,传入字符串"100%"不生效。

原示例代码:

<div className='sm:w-[50%] w-full flex items-center justify-center'>
    <div className="relative w-full h-full">
        {isLoading && <Blurhash
            hash="L5IW7%8x3@1G2,Dz.{{}BN0g}u1I"
            width={"100%"}
            height={"100%"}
            resolutionX={32}
            resolutionY={32}
            punch={1}
            className='absolute top-0 left-0 w-full h-full transition-opacity duration-500 rounded-lg'
        />}
        <img src={Rica} alt="Rica" className='rounded-lg lg:h-[500px] relative z-10 transition-opacity duration-500' onLoad={() => { setIsLoading(false) }} />
    </div>
</div>

可行解决方案

方案1:动态获取父容器实际尺寸

通过useRef获取父容器DOM节点,结合useEffect监听容器尺寸变化,实时计算并传入整数宽高:

import { useRef, useState, useEffect } from 'react';
import Blurhash from 'react-blurhash';

// ...

const parentRef = useRef(null);
const [placeholderSize, setPlaceholderSize] = useState({ width: 300, height: 200 }); // 初始默认值

useEffect(() => {
    const updateSize = () => {
        if (parentRef.current) {
            const { width, height } = parentRef.current.getBoundingClientRect();
            setPlaceholderSize({
                width: Math.floor(width),
                height: Math.floor(height)
            });
        }
    };

    // 初始化执行一次
    updateSize();
    // 监听窗口 resize 事件
    window.addEventListener('resize', updateSize);
    return () => window.removeEventListener('resize', updateSize);
}, []);

// ...

<div className='sm:w-[50%] w-full flex items-center justify-center'>
    <div ref={parentRef} className="relative w-full h-full">
        {isLoading && <Blurhash
            hash="L5IW7%8x3@1G2,Dz.{{}BN0g}u1I"
            width={placeholderSize.width}
            height={placeholderSize.height}
            resolutionX={32}
            resolutionY={32}
            punch={1}
            className='absolute top-0 left-0 w-full h-full transition-opacity duration-500 rounded-lg'
        />}
        <img src={Rica} alt="Rica" className='rounded-lg lg:h-[500px] relative z-10 transition-opacity duration-500' onLoad={() => { setIsLoading(false) }} />
    </div>
</div>

方案2:固定基础尺寸+CSS缩放

给Blurhash传入一个足够大的固定整数尺寸(比如和图片最大可能尺寸一致),再通过CSS让组件占满父容器。由于blurhash生成的是矢量风格的占位图,缩放不会失真:

<div className='sm:w-[50%] w-full flex items-center justify-center'>
    <div className="relative w-full h-full">
        {isLoading && <Blurhash
            hash="L5IW7%8x3@1G2,Dz.{{}BN0g}u1I"
            width={1200} // 设为容器最大可能宽度的整数
            height={800} // 对应高度整数
            resolutionX={32}
            resolutionY={32}
            punch={1}
            className='absolute top-0 left-0 w-full h-full transition-opacity duration-500 rounded-lg'
        />}
        <img src={Rica} alt="Rica" className='rounded-lg lg:h-[500px] relative z-10 transition-opacity duration-500' onLoad={() => { setIsLoading(false) }} />
    </div>
</div>

方案3:使用Canvas手动渲染(进阶)

如果上述方案不满足需求,可以直接使用blurhash核心库手动渲染到Canvas,通过CSS控制Canvas尺寸:

import { decode } from 'blurhash';
import { useRef, useEffect } from 'react';

// ...

const canvasRef = useRef(null);

useEffect(() => {
    if (isLoading && canvasRef.current) {
        const canvas = canvasRef.current;
        const ctx = canvas.getContext('2d');
        const pixels = decode("L5IW7%8x3@1G2,Dz.{{}BN0g}u1I", 32, 32);
        const imageData = new ImageData(pixels, 32, 32);
        ctx.putImageData(imageData, 0, 0);
    }
}, [isLoading]);

// ...

<div className='sm:w-[50%] w-full flex items-center justify-center'>
    <div className="relative w-full h-full">
        {isLoading && <canvas 
            ref={canvasRef}
            className='absolute top-0 left-0 w-full h-full transition-opacity duration-500 rounded-lg'
        />}
        <img src={Rica} alt="Rica" className='rounded-lg lg:h-[500px] relative z-10 transition-opacity duration-500' onLoad={() => { setIsLoading(false) }} />
    </div>
</div>

内容的提问来源于stack exchange,提问作者Vedant Shah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:35:09