-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added enable/disable feature to FocusPicker #18
Conversation
- Added public enable/disable options that remove the retina and listeners - added private enabled boolean to see if a FocusPicker is enabled or not This feature allows for easy integration into React because it allows the retina to be taken off the DOM when the image isn't in view (or rendering null). Also went with enable/disable as it works for temporary or permenant use.
@third774 any chance this could get merged in? |
Done! Thanks for the contribution, and sorry for the delay! :) |
No problem, thanks for accepting! I appreciate what you've done so far! |
Hiya @mcabs3 , I don't suppose you would be kind enough to provide quick example of how to use this in React? I presume it's something like import React, { useRef, useEffect } from 'react';
import { FocusedImage } from 'image-focus';
const ImageFocusWrapper = ({ src, ...props }) {
const imgRef = useRef(null);
useEffect(() => {
if (imgRef.current) {
const focusedImg = new FocusedImage(imgRef.current, {
focus: { x: 0, y: 0 },
debounceTime: 17,
updateOnWindowResize: true,
}),
}
});
return (
<img ref={imgRef} src={src} {...props} />
);
}; Am I anywhere close?! |
Hey @davea38! here is the picker part of the library with react. there is an issue using a ref to the image since a ref can't be used in a hook to update on, so I useState instead for both the picker and the "focused image". import React, {
FC,
useMemo,
useState,
useEffect,
DetailedHTMLProps,
ImgHTMLAttributes
} from 'react';
import { FocusPicker } from 'image-focus';
import { noop, isEqual } from 'lodash/fp';
import { debounce } from 'lodash';
import { POICoordinates, DEFAULT_INTERNAL_POI } from '@common/types';
function usePOI(
src: string,
poiCoordinates: POICoordinates = DEFAULT_INTERNAL_POI,
onChange: ImagePOISelectorProps['onChange'] = noop
): [(instance: HTMLImageElement | null) => void, FocusPicker | undefined] {
const [ref, setRef] = useState<HTMLImageElement | null>(null);
const debouncedFn = useMemo(() => debounce(onChange, 150), [onChange]);
const picker = useMemo(() => {
if (ref) {
return new FocusPicker(ref, {
focus: poiCoordinates,
onChange: debouncedFn
});
}
return undefined;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ref]);
useEffect(() => {
if (picker) {
picker.disable();
picker.enable();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [src]);
useEffect(() => {
if (picker && !isEqual(picker.focus, poiCoordinates)) {
picker.setFocus(poiCoordinates);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [poiCoordinates]);
return [setRef, picker];
}
export interface ImagePOISelectorProps
extends Omit<
DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>,
'onChange'
> {
readonly src: string;
readonly poiCoordinates?: POICoordinates;
readonly onChange?: (coordinates: POICoordinates) => void;
}
const ImagePOISelector: FC<ImagePOISelectorProps> = (props) => {
const { src, onChange, poiCoordinates, ...rest } = props;
const [setRef, picker] = usePOI(src, poiCoordinates, onChange);
useEffect(() => {
return () => {
if (picker) {
picker.disable();
}
};
}, [picker]);
return (
<div>
<img ref={setRef} style={{ width: 400 }} src={src} {...rest} />
</div>
);
};
export default ImagePOISelector; |
here is my use-case for the image that focuses on the POI, still plenty of improvements to be made, but its working for my use. cheers! import React, {
FC,
useMemo,
useState,
DetailedHTMLProps,
ImgHTMLAttributes
} from 'react';
import { FocusedImage } from 'image-focus';
import { DEFAULT_INTERNAL_POI, POICoordinates } from '@common/types';
export interface ImageWithPOIProps
extends DetailedHTMLProps<
ImgHTMLAttributes<HTMLImageElement>,
HTMLImageElement
> {
readonly poiCoordinates?: POICoordinates;
}
const ImageWithPOI: FC<ImageWithPOIProps> = (props) => {
const { poiCoordinates, src, ...rest } = props;
const [image, setRef] = useState<HTMLImageElement | null>(null);
const focusedImage = useMemo(() => {
if (image) {
return new FocusedImage(image, {
updateOnContainerResize: true,
focus: poiCoordinates,
debounceTime: 17,
updateOnWindowResize: true
});
}
return undefined;
}, [poiCoordinates, image]);
return <img {...rest} ref={setRef} src={src} />;
};
ImageWithPOI.defaultProps = {
poiCoordinates: DEFAULT_INTERNAL_POI
};
export default ImageWithPOI; |
@davea38 i can make a PR with an updated README on this kind of example. |
This feature allows for easy integration into React because it allows the
retina to be taken off the DOM when the image isn't in view (or rendering null).
Also went with enable/disable as it works for temporary or permenant use.