Skip to content
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

Merged
merged 1 commit into from
Apr 7, 2021

Conversation

mcabs3
Copy link

@mcabs3 mcabs3 commented Mar 9, 2021

  • Added public enable/disable options that remove the retina and listeners
  • added private enabled boolean to see if a FocusPicker is enabled or not
  • updated TS and tslib

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.

- 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.
@mcabs3 mcabs3 mentioned this pull request Mar 9, 2021
@mcabs3
Copy link
Author

mcabs3 commented Apr 7, 2021

@third774 any chance this could get merged in?

@third774 third774 merged commit 6bc70c6 into third774:master Apr 7, 2021
@third774
Copy link
Owner

third774 commented Apr 7, 2021

Done! Thanks for the contribution, and sorry for the delay! :)

@mcabs3
Copy link
Author

mcabs3 commented Apr 7, 2021

No problem, thanks for accepting! I appreciate what you've done so far!

@davea38
Copy link

davea38 commented Apr 21, 2021

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?!

@mcabs3
Copy link
Author

mcabs3 commented Apr 21, 2021

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;

@mcabs3
Copy link
Author

mcabs3 commented Apr 21, 2021

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
Copy link

davea38 commented Apr 22, 2021

Hey @mcabs3 - thank you for this mate, much appreciated :) @third774 , would you consider implementing this as an example in your repo?

@mcabs3
Copy link
Author

mcabs3 commented Apr 22, 2021

@davea38 i can make a PR with an updated README on this kind of example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants