Skip to content

Commit e6ab6e8

Browse files
committed
fix(zoom): fix blurred image in Safari (fix #290)
1 parent 39426d4 commit e6ab6e8

File tree

4 files changed

+23
-11
lines changed

4 files changed

+23
-11
lines changed

src/consts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const CLASS_FLEX_CENTER = "flex_center";
4040
export const CLASS_NO_SCROLL = "no_scroll";
4141
export const CLASS_NO_SCROLL_PADDING = "no_scroll_padding";
4242
export const CLASS_SLIDE_WRAPPER = "slide_wrapper";
43+
export const CLASS_SLIDE_WRAPPER_INTERACTIVE = "slide_wrapper_interactive";
4344

4445
export const ACTION_PREV = "prev";
4546
export const ACTION_NEXT = "next";

src/plugins/zoom/ResponsiveImage.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export function isResponsiveImageSlide(slide: SlideImage): slide is ResponsiveIm
2323
export type ResponsiveImageProps = Omit<ImageSlideProps, "slide" | "rect"> &
2424
Required<Pick<ImageSlideProps, "rect">> & {
2525
slide: ResponsiveImageSlide;
26+
interactive: boolean;
2627
};
2728

2829
type ResponsiveImageState = {
@@ -58,7 +59,7 @@ function reducer(
5859
export function ResponsiveImage(props: ResponsiveImageProps) {
5960
const [{ current, preload }, dispatch] = React.useReducer(reducer, {});
6061

61-
const { slide: image, rect, imageFit, render } = props;
62+
const { slide: image, rect, imageFit, render, interactive } = props;
6263

6364
const srcSet = image.srcSet.sort((a, b) => a.width - b.width);
6465
const width = image.width ?? srcSet[srcSet.length - 1].width;
@@ -84,7 +85,7 @@ export function ResponsiveImage(props: ResponsiveImageProps) {
8485

8586
const style = {
8687
// workaround occasional flickering in mobile Safari
87-
WebkitTransform: "translateZ(0)",
88+
WebkitTransform: !interactive ? "translateZ(0)" : "initial",
8889
};
8990

9091
if (!cover) {

src/plugins/zoom/ZoomWrapper.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
CLASS_FLEX_CENTER,
55
CLASS_FULLSIZE,
66
CLASS_SLIDE_WRAPPER,
7+
CLASS_SLIDE_WRAPPER_INTERACTIVE,
78
clsx,
89
ContainerRect,
910
cssClass,
@@ -27,6 +28,7 @@ export function ZoomWrapper({ render, slide, offset, rect }: ZoomWrapperProps) {
2728
const zoomWrapperRef = React.useRef<HTMLDivElement>(null);
2829

2930
const { zoom, maxZoom, offsetX, offsetY, setZoomWrapper } = useZoom();
31+
const interactive = zoom > 1;
3032

3133
const { carousel, on } = useLightboxProps();
3234
const { currentIndex } = useLightboxState();
@@ -56,6 +58,7 @@ export function ZoomWrapper({ render, slide, offset, rect }: ZoomWrapperProps) {
5658
<ResponsiveImage
5759
{...slideProps}
5860
slide={slide}
61+
interactive={interactive}
5962
rect={offset === 0 ? { width: rect.width * zoom, height: rect.height * zoom } : rect}
6063
/>
6164
) : (
@@ -71,7 +74,12 @@ export function ZoomWrapper({ render, slide, offset, rect }: ZoomWrapperProps) {
7174
return (
7275
<div
7376
ref={zoomWrapperRef}
74-
className={clsx(cssClass(CLASS_FULLSIZE), cssClass(CLASS_FLEX_CENTER), cssClass(CLASS_SLIDE_WRAPPER))}
77+
className={clsx(
78+
cssClass(CLASS_FULLSIZE),
79+
cssClass(CLASS_FLEX_CENTER),
80+
cssClass(CLASS_SLIDE_WRAPPER),
81+
interactive && cssClass(CLASS_SLIDE_WRAPPER_INTERACTIVE),
82+
)}
7583
style={
7684
offset === 0 ? { transform: `scale(${zoom}) translateX(${offsetX}px) translateY(${offsetY}px)` } : undefined
7785
}

src/styles.scss

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,6 @@
9797
-webkit-user-select: none;
9898
-webkit-touch-callout: none;
9999

100-
// workaround occasional image flickering in desktop Safari
101-
@media screen and (min-width: 800px) {
102-
// noinspection CssUnknownProperty
103-
-webkit-transform: translateZ(0);
104-
-webkit-backface-visibility: hidden;
105-
-webkit-transform-style: preserve-3d;
106-
}
107-
108100
&_cover {
109101
width: 100%;
110102
height: 100%;
@@ -116,6 +108,16 @@
116108
}
117109
}
118110

111+
// workaround occasional image flickering in desktop Safari
112+
@media screen and (min-width: 800px) {
113+
&_wrapper:not(&_wrapper_interactive) &_image {
114+
// noinspection CssUnknownProperty
115+
-webkit-transform: translateZ(0);
116+
-webkit-backface-visibility: hidden;
117+
-webkit-transform-style: preserve-3d;
118+
}
119+
}
120+
119121
&_placeholder {
120122
position: absolute;
121123
top: 50%;

0 commit comments

Comments
 (0)