如何在 React App 中流畅渲染图像?
onLoad通过使用 React 的事件和简单的 SCSS增强图像渲染来改善您的 Web 应用程序的用户体验。
本文已发布于Codebrahma和Medium
让我们开门见山。下面的 GIF 展示了我们在这篇文章结束时将要实现的目标。
这是已完成的组件- RenderSmoothImage。
| // RenderSmoothImage.jsx | |
| import React from "react"; | |
| import './styles.scss'; | |
| export default ({ src, alt = "notFound", objectFit = "contain" }) => { | |
| const [imageLoaded, setImageLoaded] = React.useState(false); | |
| const [isValidSrc, setIsValidSrc] = React.useState(!!src); | |
| return ( | |
| <div className="smooth-image-wrapper"> | |
| {isValidSrc ? ( | |
| <img | |
| className={`smooth-image img-${imageLoaded ? "visible" : "hidden"}`} | |
| style={{ objectFit }} | |
| src={src} | |
| alt={alt} | |
| onLoad={() => setImageLoaded(true)} | |
| onError={() => setIsValidSrc(false)} | |
| /> | |
| ) : ( | |
| <div className="smooth-no-image">{alt}</div> | |
| )} | |
| {isValidSrc && !imageLoaded && ( | |
| <div className="smooth-preloader"> | |
| <span className="loader" /> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| }; |
| // styles.scss | |
| .fullSize { | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .smooth-image-wrapper { | |
| @extend .fullSize; | |
| position: relative; | |
| .smooth-image { | |
| transition: opacity 1s; | |
| @extend .fullSize; | |
| } | |
| .smooth-no-image { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| @extend .fullSize; | |
| background-color: #fcfcfc; | |
| text-transform: capitalize; | |
| } | |
| .img-visible { | |
| opacity: 1; | |
| } | |
| .img-hidden { | |
| opacity: 0; | |
| } | |
| @keyframes preloader-block { | |
| from { | |
| background-position: 0%, 0; | |
| } | |
| to { | |
| background-position: 170%, 0; | |
| } | |
| } | |
| .smooth-preloader { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| @extend .fullSize; | |
| background: rgba(245, 245, 245, 0.34); | |
| .loader { | |
| background-image: linear-gradient(to right, #e6e6e6, #ffffff, #e6e6e6); | |
| @extend .fullSize; | |
| display: inline-block; | |
| background-size: 200%; | |
| animation: preloader-block 2s linear 0s infinite reverse forwards; | |
| } | |
| } | |
| } |
| // RenderSmoothImage.jsx | |
| import React from "react"; | |
| import './styles.scss'; | |
| export default ({ src, alt = "notFound", objectFit = "contain" }) => { | |
| const [imageLoaded, setImageLoaded] = React.useState(false); | |
| const [isValidSrc, setIsValidSrc] = React.useState(!!src); | |
| return ( | |
| <div className="smooth-image-wrapper"> | |
| {isValidSrc ? ( | |
| <img | |
| className={`smooth-image img-${imageLoaded ? "visible" : "hidden"}`} | |
| style={{ objectFit }} | |
| src={src} | |
| alt={alt} | |
| onLoad={() => setImageLoaded(true)} | |
| onError={() => setIsValidSrc(false)} | |
| /> | |
| ) : ( | |
| <div className="smooth-no-image">{alt}</div> | |
| )} | |
| {isValidSrc && !imageLoaded && ( | |
| <div className="smooth-preloader"> | |
| <span className="loader" /> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| }; |
| // styles.scss | |
| .fullSize { | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .smooth-image-wrapper { | |
| @extend .fullSize; | |
| position: relative; | |
| .smooth-image { | |
| transition: opacity 1s; | |
| @extend .fullSize; | |
| } | |
| .smooth-no-image { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| @extend .fullSize; | |
| background-color: #fcfcfc; | |
| text-transform: capitalize; | |
| } | |
| .img-visible { | |
| opacity: 1; | |
| } | |
| .img-hidden { | |
| opacity: 0; | |
| } | |
| @keyframes preloader-block { | |
| from { | |
| background-position: 0%, 0; | |
| } | |
| to { | |
| background-position: 170%, 0; | |
| } | |
| } | |
| .smooth-preloader { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| @extend .fullSize; | |
| background: rgba(245, 245, 245, 0.34); | |
| .loader { | |
| background-image: linear-gradient(to right, #e6e6e6, #ffffff, #e6e6e6); | |
| @extend .fullSize; | |
| display: inline-block; | |
| background-size: 200%; | |
| animation: preloader-block 2s linear 0s infinite reverse forwards; | |
| } | |
| } | |
| } |
我已将其发布为render-smooth-image-reactnpm包。源代码可在GitHub上获取。
小故事
我最近开始开发一个媒体密集型应用。一切都很顺利,直到我发现一堆图片渲染效果很差。看起来像这样。
有一会儿,我想,“我最终是不是构建了一个🖨打印机模拟器应用程序?”
如此糟糕的加载体验会严重影响整体用户满意度(即使应用的其他部分都很棒)。对于媒体内容密集型应用来说尤其如此。
好吧,让我们看看如何解决这个问题。
装填并发射🔫
让浏览器下载图像并渲染它。
渲染图片的最佳时机是下载完成后。在此之前,我们只显示加载器/占位符并隐藏图片。
我们可以通过在图像标签上使用 React 的onLoad事件来实现这一点。您可以在此处阅读有关React.js事件的更多信息。
<img onLoad={'callbackAfterImageIsDownloaded'} />
编码
我们将创建一个函数式组件,并使用 Hooks 来维护一些状态。如果你是 React Hooks 的新手,可以在这里了解更多信息。
// RenderSmoothImage.jsx
function RenderSmoothImage({src, alt}) {
const [imageLoaded, setImageLoaded]=React.useState(false);
return (
<div className="smooth-image-wrapper">
<img
src={src}
alt={alt}
className={`smooth-image image-${
imageLoaded ? 'visible' : 'hidden'
}`}
onLoad={()=> setImageLoaded(true)}}
/>
{!imageLoaded && (
<div className="smooth-preloader">
<span className="loader" />
</div>
)}
</div>
)
}
/** styles.css */
.smooth-image {
transition: opacity 1s;
}
.image-visible {opacity: 1}
.image-hidden {opacity: 0}
这里,我们维护一个imageLoaded默认为 的状态。一旦图片下载完成,false它将被设置为。我们使用事件来触发此操作。trueonLoad
然后,我们使用imageLoaded状态有条件地向img标签添加类,image-visible而不是image-hidden。我们可以添加过渡/动画来使其更流畅。请参阅顶部链接的 Gist 以获取完整的样式。
就这样!页面上不再有打印机模拟器了。
如果图像下载失败/Src无效怎么办?
通过使用该alt属性,我们可以显示图片的替代文本。但是,默认图标和样式不太好。为了解决这个问题,我们可以显示自定义alt文本。
// RenderSmoothImage.jsx
function RenderSmoothImage({src, alt}) {
.....
const [isValidSrc, setIsValidSrc] = React.useState(!!src);
return (
<div className="smooth-image-wrapper">
{isValidSrc ? (
<img
....
onError={() => setIsValidSrc(false)}
/>
) : (
<div className="smooth-no-image">{alt}</div>
)}
{isValidSrc && !imageLoaded && (
<div className="smooth-preloader">
<span className="loader" />
</div>
)}
</div>
)
}
/** styles.css */
......
.smooth-no-image {
background-image: linear-gradient(90deg,#ccc,#999,#ccc);
color: #fff;
}
就这样吧,
您可以按照自己想要的任何方式设置替代文本的样式。
我让事情变得简单,并发布了一个轻量级的 npm 包render-smooth-image-react。
感谢您阅读这篇文章,我是Sai Krishna Prasad,一位自学成才、充满热情的 Web 开发者。Bubye,就此打住……下次再见。
文章来源:https://dev.to/krrish96/how-to-smoothly-render-images-in-react-app-201j
后端开发教程 - Java、Spring Boot 实战 - msg200.com



