像亚马逊一样具有放大效果的 React 图片库
React image gallery with magnify effect like Amazon
我尝试将 react-image-gallery
与 react-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("https://images-na.ssl-images-amazon.com/images/G/01/apparel/rcxgs/tile._CB483369105_.gif"); 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;
zoomedImageHeight
和 zoomedImageWidth
是图像的自然尺寸。
计算 zoomedFrameWidth
和 zoomedFrameHeight
将取决于您希望预览的响应速度。我个人可以接受最大尺寸,但不能缩水。
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"
}}
/>
我尝试将 react-image-gallery
与 react-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("https://images-na.ssl-images-amazon.com/images/G/01/apparel/rcxgs/tile._CB483369105_.gif"); 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;
zoomedImageHeight
和 zoomedImageWidth
是图像的自然尺寸。
计算 zoomedFrameWidth
和 zoomedFrameHeight
将取决于您希望预览的响应速度。我个人可以接受最大尺寸,但不能缩水。
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"
}}
/>