像亚马逊一样具有放大效果的 React 图片库

React image gallery with magnify effect like Amazon

我尝试将 react-image-galleryreact-image-magnify 结合使用以获得具有放大预览效果的图库,根据 react-image-gallery 文档,我将 MyReactImageMagnify 组件传递给 renderItem prop 在 ImageGallery 组件上,但右侧没有放大图。

下面是带放大功能的画廊的样子 https://www.amazon.com/Samsung-MicroSD-Adapter-MB-ME128GA-AM/dp/B06XWZWYVP

这是我目前拥有的代码和框 https://codesandbox.io/s/goofy-lumiere-gk1y1

class MyImageGallery extends Component {
  myRenderItem() {
    return <MyReactImageMagnify {...this.props} />;
  }

  render() {
    const properties = {
      thumbnailPosition: "left",
      useBrowserFullscreen: false,
      showPlayButton: false,
      renderItem: this.myRenderItem.bind(this),
      items: [
        {
          original: "https://placeimg.com/640/480/any/1",
          thumbnail: "https://placeimg.com/250/150/any/1"
        },
        {
          original: "https://placeimg.com/640/480/any/2",
          thumbnail: "https://placeimg.com/250/150/any/2"
        },
        {
          original: "https://placeimg.com/640/480/any/3",
          thumbnail: "https://placeimg.com/250/150/any/3"
        }
      ]
    };

    return <ImageGallery {...properties} />;
  }
}

编辑:亚马逊只是为了说明 "magnify to the right"。我制作了另一个带有 2 列网格的 codesandbox,您可以看到普通的 <MyReactImageMagnify /> 组件是如何工作的,而 <MyImageGallery /> 不是。 https://codesandbox.io/s/practical-browser-0dbyo

我检查了您提供的 link 中的图像,发现了这个元素:

<div
    id="magnifierLens"
    style="position: absolute; background-image: url(&quot;https://images-na.ssl-images-amazon.com/images/G/01/apparel/rcxgs/tile._CB483369105_.gif&quot;); cursor: pointer; width: 300px; height: 316px; left: 184px; top: 169px;">
</div>

这是用于图像上的蓝色叠加层,然后预览只是包含原始未调整大小的图像的绝对 div。预览中的图像与放大镜镜头的位置类似。

从这里,您需要获取图像叠加和图像预览的比例。

看起来亚马逊所做的是保持产品信息元素的维度:

为了保持尺寸,您需要将 resize 事件侦听器附加到 window

window.addEventListener('resize', onWindowResize); // onWindowResize function would get new component size and update child sizes

然后您将跟踪鼠标在图像上的位置:

previewImageElement.addEventListener("mousemove", onMouseMove); // onMouseMove function would update the position of the image overlay, and zoomed image

设置完所有处理程序和侦听器后,您可以计算一些大小并实施它们。

这里是一些计算尺寸的伪代码:

 // Amazons zoom frame has a max size, and it will shrink to fit the zoomed image
const imageOverlayWidth = Math.Max(zoomedFrameWidth / zoomedImageWidth, 1) * imagePreviewWidth;
const imageOverlayWidth = Math.Max(zoomedFrameHeight / zoomedImageHeight, 1) * imagePreviewHeight;

zoomedImageHeightzoomedImageWidth 是图像的自然尺寸。

计算 zoomedFrameWidthzoomedFrameHeight 将取决于您希望预览的响应速度。我个人可以接受最大尺寸,但不能缩水。

zoomedFrameWidth = productInfoContainerWidth * 0.5;
zoomedFrameHeight = productInfoContainerHeight;

这应该足以将像亚马逊那样的漂亮的图像预览缩放结合在一起。让我知道是否有任何需要澄清的地方,因为它主要只是想法和伪代码。

我认为问题在于元素溢出。图库使用 overflow: hidden 隐藏不可见的幻灯片,因此也隐藏了缩放图像。

react-image-magnify 的好处是您可以指定要渲染大图像的门户。

这是沙盒:https://codesandbox.io/s/xenodochial-rosalind-g9ve4

创建一个带有 id 的新 div,您希望在其中显示大图:

<Grid container spacing={4}>
  <Grid item xs={6}>
    <MyImageGallery />
  </Grid>
  <Grid container spacing={2} item xs={6} direction="column">
    <Grid item>
      <div id="myPortal" />
    </Grid>
  </Grid>
</Grid>

图库的每个元素都是一个 ReactImageMagnify 组件,门户 ID 为 属性:

<ReactImageMagnify
  {...{
    smallImage: {
      alt: "Wristwatch by Ted Baker London",
      isFluidWidth: true,
      src: "https://placeimg.com/640/480/any"
    },
    largeImage: {
      src: "https://placeimg.com/640/480/any",
      width: 640,
      height: 480
    },
    enlargedImagePortalId: "myPortal"
  }}
/>