我想在加载最终头像时加载不同的图像(假化身)。想法是检测何时加载道具图像并改变状态。可能吗?一些想法?谢谢!
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;
答案 0 :(得分:12)
有几种方法可以做到这一点,但最简单的方法是隐藏最终图像,然后在加载后将其翻转为可见。
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>
);
}
}
答案 1 :(得分:1)
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>
);
}
}```
答案 2 :(得分:1)
通过在更改图像时添加淡入过渡,可以使操作更进一步。下面的代码是我的CrossFadeImage
组件。只需复制并使用它即可代替普通的img
组件。
CrossFadeImage
有2张图像,top
和bottom
。 bottom
堆叠在 top
上,用于显示需要动画处理的图像,在这种情况下,切换时将褪色的旧图像,
在空闲状态下,top
显示当前图像,而bottom
是前一个图像,但显示为透明
CrossFadeImage
在检测到props.src
更改时将执行以下操作
top
的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"
/>
答案 3 :(得分:0)
答案与Brigand接受的答案相同,但带有挂钩:
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>
);
};
答案 4 :(得分:0)
检测何时加载图像的更好方法是创建对该元素的引用,然后向该引用添加事件侦听器。您可以避免在元素中添加事件处理程序代码,并使代码更易于阅读,例如:
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>
);
}
}
答案 5 :(得分:0)
这是一个最小的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>
)
}
答案 6 :(得分:-1)
我的解决方案:
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