programing

소품을 통해 제공되는 이미지가 로드되었을 때 감지하고 반응에서 상태를 변경하는 방법은 무엇입니까?

powerit 2023. 3. 9. 22:22
반응형

소품을 통해 제공되는 이미지가 로드되었을 때 감지하고 반응에서 상태를 변경하는 방법은 무엇입니까?

최종 아바타 이미지를 로드하는 동안 다른 이미지(짝퉁 아바타)를 로드하고 싶습니다.이 아이디어는 프로펠러 이미지가 로드된 시점을 감지하고 상태를 변경하는 것입니다.가능합니까?어떤 아이디어?감사해요!

class ImageUser extends React.Component {

constructor(props) {
    super(props);
    this.state = {userImageLoaded: false};
    let imageSrc = "";

    if (!this.props.userImage) {
        imageSrc = this.props.noUserImage;
    } else {
        imageSrc = this.props.userImage;
    }

    this.loadingImage = <img className={styles.imageUser}
                     src={this.props.loadingImage} alt="2"/>;

    this.userImage =
        <img onLoad={this.setState({userImageLoaded: true})}
             className={styles.imageUser} src={imageSrc}
             alt="1"/>;

}

render() {
    let image = "";
    if (this.state.userImageLoaded) {
        image = this.userImage;
    } else {
        image = this.loadingImage;
    }
    return (
        <div>
            {image}
        </div>
    );
}
}

export default ImageUser;

여기에는 여러 가지 방법이 있지만 가장 간단한 방법은 최종 이미지를 숨긴 상태로 표시한 다음 로드된 이미지를 볼 수 있도록 뒤집는 것입니다.

JSBin 데모

class Foo extends React.Component {
  constructor(){
    super();
    this.state = {loaded: false};
  }

  render(){
    return (
      <div>
        {this.state.loaded ? null :
          <div
            style={{
              background: 'red',
              height: '400px',
              width: '400px',
            }}
          />
        }
        <img
          style={this.state.loaded ? {} : {display: 'none'}}
          src={this.props.src}
          onLoad={() => this.setState({loaded: true})}
        />
      </div>
    );
  }
}

브리건드가 받아들인 대답과 같은 대답이지만 훅스는:

const Foo = ({ src }) => {
  const [loaded, setLoaded] = useState(false);

  return (
    <div>
      {loaded ? null : (
        <div
          style={{
            background: 'red',
            height: '400px',
            width: '400px'
          }}
        />
      )}
      <img
        style={loaded ? {} : { display: 'none' }}
        src={src}
        onLoad={() => setLoaded(true)}
      />
    </div>
  );
};

요소에 대한 참조를 사용하지만 기능 구성 요소와 활자 스크립트가 있는 후크를 사용하는 것과 동일한 아이디어:

import React from 'react';

export const Thumbnail = () => {
  const imgEl = React.useRef<HTMLImageElement>(null);
  const [loaded, setLoaded] = React.useState(false);

  const onImageLoaded = () => setLoaded(true);

  React.useEffect(() => {
    const imgElCurrent = imgEl.current;

    if (imgElCurrent) {
      imgElCurrent.addEventListener('load', onImageLoaded);
      return () => imgElCurrent.removeEventListener('load', onImageLoaded);
    }
  }, [imgEl]);

  return (
    <>
      <p style={!loaded ? { display: 'block' } : { display: 'none' }}>
        Loading...
      </p>
      <img
        ref={imgEl}
        src="https://via.placeholder.com/60"
        alt="a placeholder"
        style={loaded ? { display: 'inline-block' } : { display: 'none' }}
      />
    </>
  );
};

이미지를 변경할 때 페이드인 전환을 추가하면 한 단계 더 나아갈 수 있습니다.의 코드입니다.CrossFadeImage 요. 보통 복사해서 쓰면 돼요.img★★★★★★ 。

CrossFadeImage.top ★★★★★★★★★★★★★★★★★」bottombottom는 위에 쌓여서 애니메이션이 필요한 이미지(이 경우 전환 시 색이 바래지는 이전 이미지)를 표시하기 위해 사용됩니다.

에서는 " " " "top 현재 됩니다.bottom입니다.

CrossFadeImage는 을 검출할 때 동작을 합니다.props.src 사항

  • 현재 실행 중인 애니메이션을 취소하려면 두 src를 모두 재설정합니다.
  • ★★top로 변환하고 src를 src로 변환합니다bottom 프레임의 src에서 로 바랜다.
  • ★★bottom하게 전환의 시작을 .
import React from "react";

const usePrevious = <T extends any>(value: T) => {
  const ref = React.useRef<T>();
  React.useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
};
const useRequestAnimationFrame = (): [(cb: () => void) => void, Function] => {
  const handles = React.useRef<number[]>([]);
  const _raf = (cb: () => void) => {
    handles.current.push(requestAnimationFrame(cb));
  };
  const _resetRaf = () => {
    handles.current.forEach((id) => cancelAnimationFrame(id));
    handles.current = [];
  };

  return [_raf, _resetRaf];
};

type ImageProps = {
  src: string;
  alt?: string;
  transitionDuration?: number;
  curve?: string;
};

const CrossFadeImage = (props: ImageProps) => {
  const { src, alt, transitionDuration = 0.35, curve = "ease" } = props;
  const oldSrc = usePrevious(src);
  const [topSrc, setTopSrc] = React.useState<string>(src);
  const [bottomSrc, setBottomSrc] = React.useState<string>("");
  const [bottomOpacity, setBottomOpacity] = React.useState(0);
  const [display, setDisplay] = React.useState(false);
  const [raf, resetRaf] = useRequestAnimationFrame();

  React.useEffect(() => {
    if (src !== oldSrc) {
      resetRaf();
      setTopSrc("");
      setBottomSrc("");

      raf(() => {
        setTopSrc(src);
        setBottomSrc(oldSrc!);
        setBottomOpacity(99);

        raf(() => {
          setBottomOpacity(0);
        });
      });
    }
  });

  return (
    <div
      className="imgContainer"
      style={{
        position: "relative",
        height: "100%"
      }}
    >
      {topSrc && (
        <img
          style={{
            position: "absolute",
            opacity: display ? "100%" : 0,
            transition: `opacity ${transitionDuration}s ${curve}`
          }}
          onLoad={() => setDisplay(true)}
          src={topSrc}
          alt={alt}
        />
      )}
      {bottomSrc && (
        <img
          style={{
            position: "absolute",
            opacity: bottomOpacity + "%",
            transition: `opacity ${transitionDuration}s ${curve}`
          }}
          src={bottomSrc}
          alt={alt}
        />
      )}
    </div>
  );
};

export default CrossFadeImage;

사용.

<CrossFadeImage
  src={image}
  alt="phonee"
  transitionDuration={0.35}
  curve="ease-in-out"
/>

라이브 데모

CodeSandbox에서 데모 앱 편집

https://stackoverflow.com/a/43115422/9536897이 도움이 됩니다.감사합니다.

당신을 강하게 하고 싶어요.배경 이미지를 위해서

  constructor(){
    super();
    this.state = {loaded: false};
  }

  render(){
    return (
      <div>
        {this.state.loaded ? null :
          <div
            style={{
              background: 'red',
              height: '400px',
              width: '400px',
            }}
          />
        }
        <img
          style={{ display: 'none' }}
          src={this.props.src}
          onLoad={() => this.setState({loaded: true})}
        />
       <div 
         style={ {
                  background: `url(${this.props.src})`
                   ,display: this.state.loaded?'none':'block'
                }}
        />
      </div>
    );
  }
}```

이미지가 로드되는 시기를 감지하는 더 좋은 방법은 요소에 대한 참조를 만든 다음 참조에 이벤트 청취자를 추가하는 것입니다.요소에 이벤트 핸들러 코드를 추가하지 않고 다음과 같이 코드를 읽기 쉽게 할 수 있습니다.

    class Foo extends React.Component {
        constructor(){
            super();
            this.state = {loaded: false};
            this.imageRef = React.createRef();
        }

        componentDidMount() {
            this.imageRef.current.addEventListener('load', onImageLoad);
        }

        onImageLoad = () => { 
            this.setState({loaded: true})
        }

        render(){
            return (
              <div>
                {this.state.loaded ? null :
                  <div
                    style={{
                      background: 'red',
                      height: '400px',
                      width: '400px',
                    }}
                  />
                }
                <img
                  ref={this.imageRef}
                  style={{ display: 'none' }}
                  src={this.props.src}
                />
                <div 
                  style={{
                      background: `url(${this.props.src})`
                      ,display: this.state.loaded?'none':'block'
                  }}
                />
              </div>
            );
        }
    }

다음은 React 로고에서 시작하여 업로드된 이미지로 대체하는 최소 React 예제입니다.

import React from 'react'
import logo from './logo.svg'
import './App.css'


export default function App() {

  function loadImage(event) {
    const file = event.target.files && event.target.files[0]
    if (file) {
      const img = document.querySelector("#image")
      img.onload = () => window.URL.revokeObjectURL(img.src) // free memory
      img.src = window.URL.createObjectURL(file)
    }
  }

  return (
    <div className="App">
      <input type="file" id="inputfile" accept=".jpg" onChange={loadImage} />
      <br/><br/>
      <img src={logo} alt="upload" id="image" width={600} />
    </div>
  )
}

한 가지만 더하고 싶어요.수락된 답변은 괜찮지만, src가 소품에서 변경되면 로딩 부품이 표시되지 않습니다.소품 변경을 처리하려면 클래스 컴포넌트에 componentDidUpdate를 구현하고 기능 컴포넌트에 useEffect를 구현합니다.

class Foo extends React.Component {
  constructor(){
    super();
    this.state = {loaded: false};
  }

  componentDidUpdate(prevProps){
    if(prevProps.src!==this.props.src){
      this.setState({loaded : false})
    }
  }

  render(){
    return (
      <div>
        {this.state.loaded ? null :
          <div
            style={{
              background: 'red',
              height: '400px',
              width: '400px',
            }}
          />
        }
        <img
          style={this.state.loaded ? {} : {display: 'none'}}
          src={this.props.src}
          onLoad={() => this.setState({loaded: true})}
        />
      </div>
    );
  }
}

또는 로드 이미지 또는 오류 이미지를 표시하는 경우 npm 패키지 "simple-react-image"를 사용할 수 있습니다.를 사용하여 설치하기만 하면 됩니다.

npm i 심플한 이미지

그 다음에 사용하시면 됩니다.또, 여기서 를 확인하실 수 있습니다.

import React from 'react';
import { Image as Img } from 'simple-react-image';

class Foo extends React.Component {
  render(){
    return (
      <div>
        <Img
          errorImage="https://www.freeiconspng.com/thumbs/error-icon/error-icon-32.png" //image in case of error
          fallback="https://i.gifer.com/ZZ5H.gif"// image in case of loading
          src={this.props.src}
          onStateChange={(imageState)=>{
            this.setState({imageState});//can be loading,loaded,error
          }}
        />
      </div>
    );
  }
}

순풍을 동반한 수락된 답변

const [isImageLoaded, setIsImageLoaded] = useState(false)     

{!isImageLoaded && <img width={30} src='/images/spinner.svg' />}

        <img
          className={`mx-4 ${!isImageLoaded && 'hidden'}`}
          width={30}
          src="imageUrl"
          onLoad={() => setIsImageLoaded(true)}
        />

솔루션:

import React, {FC,useState,useEffect} from "react"

interface ILoadingImg {
    url:string,
    classOk?:string,
    classError?:string,
    classLoading?:string
}


const LoadingImg: FC<ILoadingImg> = ({
                                         url,
                                         classOk,
                                         classError,
                                         classLoading
                                      }) => {


    const [isLoad,setIsLoad] = useState<boolean>(false)

    const [error,setError] = useState<string|undefined>(undefined)




    useEffect(() =>{

        const image = new Image()

        image.onerror = () =>{
            setError(`error loading ${url}`)
            setIsLoad( false)
        };

        image.onload = function() {

         
                setIsLoad( true)
        

/*
//and you can get the image data


            imgData = {
                                src: this.src,
                                width:this.width,
                                height:this.height
                                }

 */


        }

        image.src = url




       return () =>  setIsLoad(false)

    },[url])



    if(!isLoad){
        return <div className={classLoading}>Loading...</div>
    }

    if(error){
        return <div className={classError}>{error}</div>
    }


    return <img  src={url} className={classOk}  />

}

export default LoadingImg




언급URL : https://stackoverflow.com/questions/43115246/how-to-detect-when-a-image-is-loaded-that-is-provided-via-props-and-change-sta

반응형