Giter VIP home page Giter VIP logo

react-img-mapper's Introduction

React Img Mapper

React Component to highlight interactive zones in images

1. Promise to be maintained this repository
2. Built in TypeScript
3. Compatible with Next.js
4. Decreased size of bundled
5. Awesome Documentation
6. Selected area will stay highlighted ( Single & Multiple ) with toggle and reset feature
7. Image Reference in Width, Height and onLoad function to access image properties
8. Responsive Image Mapper

Installation

Package: react-img-mapper

# via npm
npm install react-img-mapper --save

# via yarn
yarn add react-img-mapper

Demo & Examples

Live Demo: Demo

To run the example locally

git clone https://github.com/img-mapper/react-docs.git
npm install
npm start

Then open localhost:3000 in a browser.

If you want to change something and want to make a build file, you just need to run npm run build

Usage

Import the component as you normally do, and add it wherever you like in your JSX views as below:

import React from 'react';
import ImageMapper from 'react-img-mapper';

const Mapper = props => {
  const URL =
    'https://raw.githubusercontent.com/img-mapper/react-docs/master/src/assets/example.jpg';
  const MAP = {
    name: 'my-map',
    // GET JSON FROM BELOW URL AS AN EXAMPLE AND PUT IT HERE
    areas: 'https://raw.githubusercontent.com/img-mapper/react-docs/master/src/assets/example.json',
  };

  return <ImageMapper src={URL} map={MAP} />;
};

export default Mapper;

Properties

Props Type Description Default
src string Image source url required
map object Mapping object required
areaKeyName string unique key name of the json id
isMulti bool Enable/Disable multiple highlight areas by clicking on the specific area true
toggle bool Enable/Disable toggle selected highlighted area false
active bool Enable/Disable listeners and highlighting true
disabled bool Enable/Disable listeners, highlighting and add/remove area tag from the UI false
fillColor string Fill color of the highlighted zone rgba(255, 255, 255, 0.5)
strokeColor string Border color of the highlighted zone rgba(0, 0, 0, 0.5)
lineWidth number Border thickness of the highlighted zone 1
imgWidth number Original image width 0
width number | func => number Image width, in function you will get image reference object 0
height number | func => number Image height, in function you will get image reference object 0
natural bool Give the original dimensions ( height & width ) to canvas and image wrapper false
responsive bool responsive map in all resolution ( for enable it you need to specify parentWidth ) false
parentWidth number parent max width for responsive 0

Properties Callback

Props callbacks Called on signature
onChange Area click listener (selectedArea: MapArea, areas: MapArea[]) => void
onImageClick Click outside of a zone in image (event: ImageEvent) => void
onImageMouseMove Moving mouse on the image itself (event: ImageEvent) => void
onClick Click on a zone in image (area: MapArea, index: number, event: AreaEvent) => void
onMouseDown Clicks any button of the mouse on a zone in image (area: MapArea, index: number, event: AreaEvent) => void
onMouseUp Releases left click of the mouse on a zone in image (area: MapArea, index: number, event: AreaEvent) => void
onTouchStart Start to touch the zone in image (area: MapArea, index: number, event: TouchEvent) => void
onTouchEnd Releases touch from the zone in image (area: MapArea, index: number, event: TouchEvent) => void
onMouseMove Moving mouse on a zone in image (area: MapArea, index: number, event: AreaEvent) => void
onMouseEnter Hovering a zone in image (area: MapArea, index: number, event: AreaEvent) => void
onMouseLeave Leaving a zone in image (area: MapArea, index: number, event: AreaEvent) => void
onLoad Image loading and canvas initialization completed (event: HTMLImageElement, dimensions: WidthHeight) => void

Methods

Method Description
getRefs Get container, canvas and image refs

Map Properties

A map is an object describing highlighted areas in the image.

Its structure is similar to the HTML syntax of mapping:

  • map: (object) Object to describe highlighted zones
    • name: (string) Name of the map, used to bind to the image.
    • areas: (array) Array of area objects - area: (object) Shaped like below
Property Type Description Default
id string Uniquely identify an area. An index in an array is used if this value is not provided. You can set it with areaKeyName property based on areaKeyName
shape string Either rect, circle or poly required
coords array of number Coordinates delimiting the zone according to the specified shape:
  • rect: top-left-X,top-left-Y,bottom-right-X,bottom-right-Y
  • circle: center-X,center-Y,radius
  • poly: Every point in the polygon path as point-X,point-Y,...
required
active string Enable/Disable area listeners and highlighting true
disabled string Enable/Disable area listeners, highlighting and add/remove area tag from the UI false
href string Target link for a click in the zone (note that if you provide an onClick prop, href will be prevented) undefined
fillColor string Fill color of the highlighted zone rgba(255, 255, 255, 0.5)
strokeColor string Border color of the highlighted zone rgba(0, 0, 0, 0.5)
lineWidth string Border thickness of the highlighted zone 1
preFillColor string Pre filled color of the highlighted zone undefined

When received from an event handler, an area is extended with the following properties:

Property type Description
scaledCoords array of number Scaled coordinates
center array of number Coordinates positioning the center or centroid of the area: [X, Y]

License

Distributed with an MIT License. See LICENSE.txt for more details!

Copyright (c) 2024 Nisharg Shah

react-img-mapper's People

Contributors

kholy87 avatar moverware avatar nishargshah avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

react-img-mapper's Issues

Canvas height is 0. Fails to set the right canvas height

Sometimes canvas height is 0. There is a bug, I have seen that sometimes react-img-mapper fails to set right canvas height. I am using react-image-mapper as of now and it works fine, it always sets the height of the canvas right

I have created a code sandbox here is the link. If you open the the rendering image in new tab. It fails to load the canvas height

Desktop (please complete the following information):
Windows
Chrome

Make a map with two polygons to behave as one area

Is your feature request related to a problem? Please describe.
Is it possible to make a map with two polygons to behave as one area

Describe the solution you'd like
The ability to provide an area with array of polygon or connect two or more areas together when they have the same title.

area highlight wont work when I search it thru input field

Stackoverflow posted: https://stackoverflow.com/questions/71656564/i-want-to-highlight-image-area-when-i-search-it-thru-input-field

The current behavior is when I search the area by name, it wont highlight the area by id, and when I click any area with coordinates, all of them stays highlighted without referencing the areaSearchResultByID state.

So far I have these functions and states.

const [stayHighlight, setStayHighlight] = useState(false) //to stay highlight when search is finish.
const [areaSearchResultByID, setAreaSearchResultByID] = useState(0) //set area id state when search is finish.

Handle onKeyDown where I filter the json of searching and set the state of AREA ID

const handleOnSubmitSearchArea = () => {
    cubicleJSON
      .filter((x) => {
        if (searchTerm === x.cubicle_number) {
          console.log(x.department)
        } else if (searchTerm === x.department) {
          if (x.department === 'SPOC') {
            setAreaSearchResultByID(1)
          } else if (x.department === 'GRID') {
            setAreaSearchResultByID(2)
          } else {
            setAreaSearchResultByID(0)
          }
        }
      })
      .map((x, index) => {
        return <></>
      })
    setStayHighlight(true)
  }

and I have this ImageMapper

<ImageMapper
   src={IMG}
   map={MAP}
   natural
   width={1400}
   areaKeyName={areaSearchResultByID}
   stayHighlighted={stayHighlight}
   onImageClick={() => setStayHighlight(false)}
   onMouseEnter={(areas) => setHoverArea(areas.name)}
   onMouseLeave={(areas) => setHoverArea('7th Floor Plan')}
/>

MAP areas only activate after browser refresh

Describe the bug
I have created a react webpart utilising the react-img-mapper,

I collect the MAP data from some PropertyFieldCollectionData fields then build the MAP const based the fields values

During gulp serve testing, this works perfectly, however when I deploy to a site collection and configure the webpart part, on the first visit to the page the image displays but the MAP areas do not work.

After a refresh (F5) of the browser the MAP areas work, however if I do a hard refresh of the browser (CTRL+ F5) or close the browser and go back to the page the MAP areas are inactive again.

I know the MAP const has been created due to the console.log displayed in the render area.

This is the code I am using in the .tsx file

Webpart .tsx code

`

export interface IReactImageMapState {
mapArray: string;
}

export default class ReactImageMap extends React.Component<IReactImageMapProps, IReactImageMapState > {

constructor(props) {
    super(props);

    this.state = {
        mapArray: "",
    };

    this.getMapInfo();        
} 

private getMapInfo(): void {
    if (this.props.collectionData) {
        let mapInfoData = this.props.collectionData.map((mapinfo, i) => {
            if (mapinfo.href == null || mapinfo.href == "") {
                return `{"shape":"${mapinfo.Shape}","coords":[${mapinfo.Coords}],"fillColor":"${mapinfo.fillColor}${mapinfo.fillTransparency}","strokeColor":"rgba(0,0,0,0)"}`;
            } else {
                return `{"shape":"${mapinfo.Shape}","coords":[${mapinfo.Coords}],"fillColor":"${mapinfo.fillColor}${mapinfo.fillTransparency}","href":"${mapinfo.href}","strokeColor":"rgba(0,0,0,0)"}`;
            }
        });

        this.setState({
            mapArray: JSON.parse(`{"name":"my-map","areas":[` + String(mapInfoData) + `]}`)
        });
    }
}

public componentDidUpdate(prevProps, prevState): void {
    if (prevProps.collectionData !== this.props.collectionData) {
        this.getMapInfo();
    }   
}

public componentDidMount(): void {
    this.getMapInfo();        
}

public render(): React.ReactElement<IReactImageMapProps> {
    const URL = encodeURI(this.props.imageUrl);
    const MAP = this.state.mapArray;        
    
    console.log("URL: " + URL);
    console.log("MAP: " + MAP);
    
    if (URL == "undefined") {
        return (
            <div className={styles.reactImageMap} >
                <div className={styles.container} >                         
                    <div className={styles.row}>
                        <div className={styles.column}>
                            <span className={styles.title}>React Image Map Webpart</span>
                            <p>Open the property pane to configure this webpart</p>
                        </div>
                    </div>                        
                </div>
            </div>
        );

    } else {

        if (URL && MAP) {
            return (
                <div className={styles.reactImageMap} >
                    <div className={styles.container} >
                        <span>URL & MAP</span>
                        <div>
                            <ImageMapper
                                src={URL}
                                map={MAP}
                                responsive={true}
                                parentWidth={this.props.webPartWidth}
                            />
                        </div>
                     </div>
                </div>
            );

        } else {
            return (
                <div className={styles.reactImageMap} >
                    <div className={styles.container} >
                        <span>URL</span>
                        <div>
                            <ImageMapper
                                src={URL}
                                responsive={true}
                                parentWidth={this.props.webPartWidth}
                            />
                        </div>
                     </div>
                </div>
            );
        }
    }        
}    

}
`

Expected behavior
Expected behaviour is that on the first visit to the page the MAP areas work

Desktop (please complete the following information):

  • OS: Windows
  • Browser: Chrome
  • Version: [e.g. 22]

Additional context
Add any other context about the problem here.

[Feature] Adding labelling to areas of the image.

Is your feature request related to a problem? Please describe.
It is not a problem related feature. But it would be great to have a feature that allows you to add customized labelling to each areas.

Describe the solution you'd like
I was thinking something like the preFillColor, but instead it is called something like "label" which would show a customized text on that coordinated area. So in
const map = [id: "1", name: "1", coords: [...], label: "example"]

Keyword active (false) seems to deactivate the preFillColor option.

Describe the bug
When declaring the map coordinates, if you put active = false, it deactivates the preFillColor option.

To Reproduce
Steps to reproduce the behavior:
const map = { active = false, preFillColor = "rgba(69, 82, 94, 0.70)", id = 1, name = "1", shape = "poly", coords = [...] }

Expected behavior
A clear and concise description of what you expected to happen.
The active = false should not disable the preFillColor.

Desktop (please complete the following information):

  • Browser: [Chrome]
  • Version: [89.0.4389.90 ]

Support for defaultProps will be removed

Hi, I become all the time this warning, it looks like you use defaultProps. Could you please fix this for production? Thanks!

Warning: ImageMapper: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.

at ImageMapper (webpack-internal:///(ssr)/./node_modules/react-img-mapper/dist/ImageMapper.js:73:30)
at FloorPlan (webpack-internal:///(ssr)/./src/app/loungetool/Floorplan.tsx:23:96)
at div
at eval (webpack-internal:///(ssr)/./node_modules/@emotion/react/dist/emotion-element-6bdfffb2.esm.js:61:74)
at Container (webpack-internal:///(ssr)/./node_modules/@mui/system/esm/Container/createContainer.js:114:23)
at LoungeReservations (webpack-internal:///(ssr)/./src/app/loungetool/page.tsx:37:86)
at StaticGenerationSearchParamsBailoutProvider (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/static-generation-searchparams-bailout-provider.js:15:11)
at Lazy
at InnerLayoutRouter (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/layout-router.js:239:11)
at RedirectErrorBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/redirect-boundary.js:71:9)
at RedirectBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/redirect-boundary.js:79:11)
at NotFoundBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/not-found-boundary.js:62:11)
at LoadingBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/layout-router.js:313:11)
at ErrorBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/error-boundary.js:128:11)
at InnerScrollAndFocusHandler (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/layout-router.js:151:9)
at ScrollAndFocusHandler (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/layout-router.js:226:11)
at RenderFromTemplateContext (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/render-from-template-context.js:15:44)
at Lazy
at OuterLayoutRouter (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/layout-router.js:322:11)
at Lazy
at InnerLayoutRouter (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/layout-router.js:239:11)
at RedirectErrorBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/redirect-boundary.js:71:9)
at RedirectBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/redirect-boundary.js:79:11)
at NotFoundErrorBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/not-found-boundary.js:54:9)
at NotFoundBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/not-found-boundary.js:62:11)
at LoadingBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/layout-router.js:313:11)
at ErrorBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/error-boundary.js:128:11)
at InnerScrollAndFocusHandler (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/layout-router.js:151:9)
at ScrollAndFocusHandler (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/layout-router.js:226:11)
at RenderFromTemplateContext (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/render-from-template-context.js:15:44)
at Lazy
at OuterLayoutRouter (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/layout-router.js:322:11)
at Lazy
at body
at ThemeProvider (webpack-internal:///(ssr)/./node_modules/@mui/private-theming/ThemeProvider/ThemeProvider.js:45:13)
at ThemeProvider (webpack-internal:///(ssr)/./node_modules/@mui/system/esm/ThemeProvider/ThemeProvider.js:58:13)
at ThemeProvider (webpack-internal:///(ssr)/./node_modules/@mui/material/styles/ThemeProvider.js:26:18)
at LocalizationProvider (webpack-internal:///(ssr)/./node_modules/@mui/x-date-pickers/LocalizationProvider/LocalizationProvider.js:41:25)
at html
at RootLayout (webpack-internal:///(ssr)/./src/app/layout.tsx:21:23)
at Lazy
at RedirectErrorBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/redirect-boundary.js:71:9)
at RedirectBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/redirect-boundary.js:79:11)
at ReactDevOverlay (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/react-dev-overlay/internal/ReactDevOverlay.js:66:9)
at HotReload (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:296:11)
at Router (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/app-router.js:155:11)
at ErrorBoundaryHandler (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/error-boundary.js:99:9)
at ErrorBoundary (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/error-boundary.js:128:11)
at AppRouter (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/app-router.js:421:13)
at Lazy
at Lazy
at /Users/noahpique/Documents/GitHub/nightpilotapp/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:381577
at /Users/noahpique/Documents/GitHub/nightpilotapp/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:381577
at ServerInsertedHTMLProvider (/Users/noahpique/Documents/GitHub/nightpilotapp/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:39:17605)

[Feature] Prevent Image Drag

Is your feature request related to a problem? Please describe.
When I am trying to use the feature for onMouseDown it also allows me to drag the image behind the mapping. So if the user moves the mouse a little while holding the button it causing the image to go into dragging mode

Describe the solution you'd like
I'd like to prevent the image from being dragged at all, or have an option to enable this

Additional context
If you need to see an example of this happening I can DM you. Due to what I am working on I cannot share publicly

area based is toggle check and update is possible?

I will work on a part of computer image and using toggle feature. When user click on a part, open a modal and user choose a option for that part. Its working as well but components on image too close each others. I want to user can confirm selection. If user miss click on object, user can say oh its miss click take toggle back.

is toggle update possible?

image

Disable (True) removes the preFillColor of that disabled area if I click on other areas.

Describe the bug
This is about the new disable feature for each individual area. When I change one area dynamically with Firebase, the other areas become unclickable.

To Reproduce
Steps to reproduce the behavior:
I currently have a button <button onClick={handleClick}> Click me </button> then in my handleClick I would have

firebase
			.database()
			.ref('...')
			.orderByChild('available')
			.equalTo('soldout')
			.on('value', (snapshot) => {
				snapshot.forEach((lot) => {
					var child = firebase
						.database()
						.ref('/...')
						.child(lot.key)
						.child('mapCoords');

					child.update({
						preFillColor: 'rgba(255, 20, 20, 0.47)',
						active: false,
						disabled: true

https://user-images.githubusercontent.com/34180725/112985147-d2230b80-912d-11eb-8a75-c6824e1b12c6.mp4

, <----------
					});
				});
			});

This is supposed to disable that area clicked and leave preFillColor if I click on other area

Expected behavior
Disable area set to true while leaving the preFillColor.

Desktop (please complete the following information):

  • OS: [windows 10]
  • Browser: [chrome]
  • Version: [89.0.4389.90 ]

Please find attached video:

ezgif.com-gif-maker.2.mp4

Accessibility Improvements – Dynamic Alt Text

Map is getting flagged for accessibility issues – namely around labelling for the map and individual area elements.

https://www.w3.org/WAI/tutorials/images/imagemap/

For image maps, text alternatives are needed on both the element itself (to convey the informative context) and on each of the elements (to convey the link destination or the action that will be initiated if the link is followed).

Currently, the img element and all area elements are hardcoded with the alt text "map". I'd like to be able to pass in more descriptive alt text for each.

Is it possible to add this functionality?

Disable areas hover

Is your feature request related to a problem? Please describe.
Hello! I'm creating a game to find the differences between two images with this library.
The problem is that when I hover the mouse over an area, the hover style spoils the answer.

Describe the solution you'd like
I would like to know if there's any way to hide or delete the hover styles of the map areas and also keep the styles of the shapes after clicking on them.

Describe alternatives you've considered
I've tried using the .img-mapper-map class and targeting the area but it didn't work.

My guess was that doing something like this would disable the styles, but the only property that worked was the pointer one:

.img-mapper-map {
  area:hover {
    cursor: pointer;
    fill: rgba(255, 255, 255, 0.0);
    border-color: rgba(255, 255, 255, 0.0);
    border: none;
    border-style: none;
    background: rgba(255, 255, 255, 0.0);
    background-color: rgba(255, 255, 255, 0.0);
  }
}

Additional context
game

Tooltip for area

I suggest adding possibility to render a tooltip when hovering over specific area in the map, or adding custom classNames to area tag.

Unhighlighting on click is delayed until mouse exits current area

Describe the bug
In the demo, in cases when a mouse click should cause unhighlighting of a previously highlighted area, the unhighlighting does not render immediately. Rather, it appears to be delayed until the mouse exits the area it is currently over.

To Reproduce
In the demo for "Toggle Stay Highlighted Area": click one area, say the ceiling. The ceiling is highlighted. Now click the ceiling again to toggle its highlighting off. The ceiling remains highlighted. Move the mouse out of the ceiling, say, onto the wall. NOW the ceiling shows as unhighlighted.

In the demo for "Stay Selected Highlighted Area": click one area, say the celing The ceiling is highlighted. Then click another area, say the window. The window is highlighted, but the ceiling is NOT unhighlighted. Move the mouse out of the window, say onto the surrounding wall. NOW the ceiling shows as unighlighted.

Expected behavior
Expected the unhighlighting of the previously highlighted area to be visible immediately after the click to give immediate feedback on the effect of the mouse click on the selection state.

Desktop

  • OS: MacOS Monterey 12.5.1
  • Browser: Chrome
  • Version: 105.0.5195.125 (Official Build) (x86_64)

Type '{ name: string; areas: string; }' is not assignable to type 'Map'

Describe the bug
There's an error on the map parameter of the ImageMapper component: "Type '{ name: string; areas: string; }' is not assignable to type 'Map'. Types of property 'areas' are incompatible. Type 'string' is not assignable to type 'MapAreas[]'."

To Reproduce
Use <ImageMapper src{URL} map={MAP} /> with the example JSON from the npm page: https://raw.githubusercontent.com/img-mapper/react-docs/master/src/assets/example.json

Error Stack
Type '{ name: string; areas: string; }' is not assignable to type 'Map'. Types of property 'areas' are incompatible. Type 'string' is not assignable to type 'MapAreas[]'.

Expected behavior
Map should work

Screenshots
Screenshot 2023-02-28 at 15 51 22

Desktop (please complete the following information):

  • OS: macOS Ventura
  • Browser: Chrome
  • Version: 110

Display an array of Area ID's

Is your feature request related to a problem? Please describe.
I am trying to display an array of Area ID's on a map.

Is it possible? I read the documentation and I have no clue on how to do it.

Thank you!

Is there a way to have pointer over highlited area?

Hello,

Thanks for the library.

I want to know if it's possible to have pointer cursor over highlighted area? I'd like to have as CSS, like this:

<ImageMapper
      src={url}
      map={map}
      width={180}
      height={561}
      style={{ cursor: 'pointer' }}
    />

Programmatically set highlighted area/s.

Is your feature request related to a problem? Please describe.
I couldn't find a solution for programmatically setting selected areas.
I want to sync a map with a dropdown field. See picture.

image

Describe the solution you'd like
It would be great if the highlighted areas would be available as value and to get the current set of active areas with onChange, similar to how you would handle form inputs.
Of course, the value could be overwritten to reflect the rendered areas.

Describe alternatives you've considered
I tried working around the problem (before I read the code) assuming I could set the img-mapper-area-highlighted class on the area elements to highlight an area. Before I noticed that the canvas actually takes care of displaying the areas.

Additional context

Wrong initialisation

Describe the bug
When the component is initialised, it is not always displayed correctly. The image, the canvas, the map component and the areas are always there, but sometimes neither the div#img-mapper container nor the canvas has any height, so the areas are not displayed, it is as if they were not there. You have to refresh the page to make it work correctly.

Expected behavior
The component should initialise correctly from the beginning, without the need to refresh the page.

Screenshots
Bug
Bug 1

Additional context
As you can see in the image, the component is placed inside a container with a grey background, as the content has no height, the coloured container has no height either. Although the image is visible.

When updating the highlight colors dynamatically onClick of a button, all the areas turn to the color of the highlight.

Describe the bug
When updating the highlight colors dynamatically onClick of a button, all the areas turn to the color of the highlight. I have to hover over it for the color to update.

To Reproduce
I have populated my firebase realtime database with the data of map coordinates with the other attributes like so.

const [mapCoords, setMapCoords] = useState({
	'name': 'my-map',
});

Then used useEffect to populate it

useEffect(() => {
		async function getData() {
			await firebase
				.database()
				.ref('...')
				.once('value', (snapshot) => {
					var mapCoordObj;
					var areaArr = [];
					snapshot.forEach((lot) => {
						var mapCoordVal = lot.val().mapCoords;

						areaArr.push(mapCoordVal);

						var mapCoordChild = lot.child('mapCoords');

						console.log('mapCoordChild: ' + JSON.stringify(mapCoordChild));

						mapCoordChild.forEach((child) => {
							console.log('childdddd: ' + JSON.stringify(child));
						});

						console.log('mapCoordVal ' + JSON.stringify(mapCoordVal));

						mapCoordObj = {
							...mapCoords,
							areas: areaArr,
						};
					});

					console.log('areaa: ' + areaArr);

					setMapCoords(mapCoordObj);
				});
		}
		getData();
	}, []);

Then I have a button

<button onClick={handleChangeColor}>Change Color</button>

const handleChangeColor = () => {
          firebase
			.database()
			.ref('...')
			.orderByChild('available')
			.equalTo('pending')
			.on('value', (snapshot) => {
				snapshot.forEach((lot) => {
					var child = firebase
						.database()
						.ref('...')
						.child(lot.key)
						.child('mapCoords');

					child.update({
						preFillColor: 'rgba(255, 255, 168, 0.70)',
						name: id,
						active: true,
					});
				});
			});
}

This would handle the color change. However, when I click on the button, it will turn all areas to the color of the highlight like so:

image

To change the color, I would have to hover over any of those areas and it will change it.

Desktop (please complete the following information):

  • OS: windows 10
  • Browser: chrome
  • Version: Version 89.0.4389.82 (Official Build) (64-bit)

Support gif

**Is your feature request related to a problem? I am having a gif and planning to use this. Not sure if this image mapper can help me with my gif.

Describe the solution you'd like
Support gif format too!

Describe alternatives you've considered
If this image mapper doesn't support gif, I am thinking to create a layer of transparent image overlay on my gif and allow interaction happened there.

Cords working only on first map, if page have more the one image with map

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. git clone https://github.com/img-mapper/react-docs.git
  2. cd react-docs
  3. npm install
  4. npm start
  5. edit file src/stories/Colors.stories.js
  6. on row 25 add one more map in the storie
  7. open the storybook and open Fill Color story
  8. Observe there is 2 maps
  9. Observe the first map has cords, but the second doesn't.
  10. Repeat adding images with cords, but still first have only map.

Expected behavior
Every map should have map with cords

Desktop (please complete the following information):

  • OS: Windows
  • Browser: Chrome

Type map is incompatible.

Describe the bug
Error on parameter map on the ImageMapper component.

To Reproduce
Use the component <ImageMapper src{URL} map={MAP}

Error Stack
Type '{ name: string; areas: { id: string; title: string; shape: string; name: string; fillColor: string; strokeColor: string; coords: number[]; polygon: number[][]; }[]; }' is not assignable to type 'Map'.

Expected behavior
Draw the map.

Screenshots
image

Desktop (please complete the following information):

  • OS: [Windows 10]
  • Browser: [Chrome]
  • Version: [92.x]

Additional context
I'm using this on my app build with React and Ionic 5.

NextJS with Tailwind CSS not showing the photo

Describe the bug
When using Tailwind CSS on NextJS project the React Image Mapper not working. The image is in the source of the code, but not showing.

To Reproduce
Steps to reproduce the behavior:

  1. npx create-next-app -e with-tailwindcss my-project (or create nextjs project and then add the tailwindcss, its the same)
  2. npm install react-img-mapper --force (cause its not working without force, cause react versions)
  3. add the code from Usage section on this repo
  4. See there is no image show in the project (but when inspect you can see the code is there and in network the image is downloading)
  5. go to styles/global.css and remove first line - @tailwind base;
  6. observe everything (except tailwind stuff) is working

Error Stack
No error shown in console.

Expected behavior
The image and mappers should work with tailwindcss.

Screenshots
https://prnt.sc/Vg-DRyCv4qrY

Desktop (please complete the following information):

  • OS: Windows 11
  • Browser: Chrome
  • Version: 103

Getting Continuous Key Error after upgrading from v0.2 to v0.4

Describe the bug

I am getting continuous key uniqueness error from your module

To Reproduce

  1. passing map area causing the error

Error Stack

Encountered two children with the same key, 03. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.

Expected behavior

Not getting error

Screenshots

image

Desktop (please complete the following information):

  • OS: Ubuntu
  • Browser: Chrome
  • Version: 86

JSON

[
  {
    "id": "<AutoIncrementValue>",
    "title": "title",
    "shape": "poly",
    "name": "name",
    "fillColor": "skyblue",
    "strokeColor": "black",
    "coords": [<MyCoords>]
  },
  ....
]

NPM Version Control

Hi,

I’m using react-image-mapper in a project with React 18 and noticed that the npm versions only support up to React 14. I had to install from GitHub to get the 2.0 version compatible with React 18.

Could you update the npm package to include the latest version? This would help ensure compatibility and ease dependency management.

Thanks for the great library and looking forward to the update!

Best

using Tailwind in the react project

Describe the bug
I use a React project without Tailwind the image and hover work well
but I installed "tailwindcss": "3.3.3", after that the image does not show up, the canva and map does not work as expected nothing happens

only when I comment this line it works again
/* @tailwind base; */

UseEffect Depth Exceeded causing unintended consequences

Describe the bug
There is a Maximum Depth exceeded Error that is popping up once ImageMapper is used. This seems to related to useEffects. This is affecting my GET requests that are inside of my program causing them to infinite loop call. This error seems to pop up on a basic import of the react-img-mapper.

The error creates no visual bugs. The img mapper displays accurately but if i do any asyc function it causes unintended consequences.

To Reproduce
Steps to reproduce the behavior:

  1. Add the react-img-mapper to any project
  2. When the page is inspected the error "Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render."
    Error on chrome

Examples
Here is a codesandbox of the error in its simplest form I could reproduce showing the error in the console.

I am unable to show the get request loop without repercussions if that is something that is needed to demonstrate.

https://codesandbox.io/p/github/rebelmaniac/basicimagempapper/master?file=%2FREADME.md&workspace=%257B%2522activeFileId%2522%253A%2522clfn2wrsw000lg1h880t7hv1x%2522%252C%2522openFiles%2522%253A%255B%2522%252FREADME.md%2522%255D%252C%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522gitSidebarPanel%2522%253A%2522COMMIT%2522%252C%2522spaces%2522%253A%257B%2522clfn2wt8b00153i6kgkwyryif%2522%253A%257B%2522key%2522%253A%2522clfn2wt8b00153i6kgkwyryif%2522%252C%2522name%2522%253A%2522Default%2522%252C%2522devtools%2522%253A%255B%257B%2522type%2522%253A%2522PREVIEW%2522%252C%2522taskId%2522%253A%2522start%2522%252C%2522port%2522%253A3000%252C%2522key%2522%253A%2522clfn2xibd00a03i6kbq606qdj%2522%252C%2522isMinimized%2522%253Afalse%257D%252C%257B%2522type%2522%253A%2522TASK_LOG%2522%252C%2522taskId%2522%253A%2522start%2522%252C%2522key%2522%253A%2522clfn2xg2z00653i6k2wgztsbi%2522%252C%2522isMinimized%2522%253Afalse%257D%255D%257D%257D%252C%2522currentSpace%2522%253A%2522clfn2wt8b00153i6kgkwyryif%2522%252C%2522spacesOrder%2522%253A%255B%2522clfn2wt8b00153i6kgkwyryif%2522%255D%252C%2522hideCodeEditor%2522%253Afalse%257D

Expected behavior
The Img mapper will not setState infinitely affect other parts of program when implemented

Desktop (please complete the following information):

  • Browser: [Chrome]
  • Version: [1.5]

Additional notes
-Let me know if the codesandbox works
-It might be based on the latest release but I havent tested the 1.4.3 version if it has this issue so I will be testing this next

Cannot resize the image in ImageWrapper

I cannot Resize ImageMapper like I usually do with normal img

I have a high resolution image that needs resizing in my div.

I tried resizing parent div, tried adding width prop, tried adding imgWidth prop but still no changes.

onClick prop callback not working

Describe the bug
When the onClick property is called on the mapper, nothing happens.

To Reproduce
Steps to reproduce the behavior:

  1. In the react-docs example, add onClick callback to clearButtonTemplate like so:
  const clicked = (area,i,e) => {
    console.log(area,i,e);
  }

  return (
    <Fragment>
      <ImageMapper
          containerRef={myRef}
          src={URL}
          map={MAP}
          stayMultiHighlighted
          onClick={(area,i,e)=>this.clicked(area,i,e)}
       />
       <button onClick={handleClear}>Clear</button>
    </Fragment>
  )
}

Error Stack
None

Expected behavior
console should log area, i, and e

Smooth Borders/Highlights

Is your feature request related to a problem? Please describe.
When the image map is pinched in on mobile, the borders/highlighted regions are pixelated/blurry.

Describe the solution you'd like
Borders/Highlighted regions should be smooth when zoomed in.

Describe alternatives you've considered
Considering the alternative of going without borders;

Additional context
On Chrome/Devtools, enable the mobile viewport/debugger, inspect the image map, and replace the image used with an SVG.
Use Shift-Click on the mobile viewport in devtools tools to drag and simulate pinch to zoom as it would occur on a mobile device.
Notice that while the SVG remains sharp, the border drawn by react-img-mapper is blurry and pixelated.

image

OnClick event for areas does not work.

I'm trying to implement this package. I don't want to go to a url when I click on the area but I want a modal to open.
I tried this by implementing the standard image map with html etc and this works fine. Since i want the image map to be responsive I wanted to use this pacakage. The responsive feature works great but the onClick doesn't work. Even if I add a simple console log to the onClick nothing happens.

To reproduce, add a onClick property on the ImageMapper component. Click on the area, nothing happens.

Also I can't find a demo which uses the onClick.

defaultProps being deprecated

Describe the bug
React defaultProps is scheduled to be deprecated in the next major release, 18.3: see here

To Reproduce
Steps to reproduce the behavior:
Mounting ImageMapper with React 18.2 generates this warning.

Error Stack
Warning: ImageMapper: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead. at ImageMapper (webpack-internal:///(app-client)/./node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/react-img-mapper/dist/ImageMapper.js:60:30)

Expected behavior
Change the default props syntax to the ES6 standard to remove this warning and prevent future bugs. See an example in this thread.

Screenshots
N/A

[Feature] Disabling individual area coords.

Is your feature request related to a problem? Please describe.
It is not a big problem but I think a bool disabled function would be great as sometimes on site-plans, I want to disable certain sold-out area.

Describe the solution you'd like
Probably something like disable boolean that we can add when we declare the map const.

Describe alternatives you've considered
Currently I am updating the id to empty so that users cannot click on that certain area. But this is not the best solution because users can technically still click on it. It is just that it is not linked to that id because I removed it. A disable boolean would be a better way to do it.

[Feature] The new area active (true/false) function still allows users to click and access the data from it.

Is your feature request related to a problem? Please describe.
Yes. In the new version, the users are now able to disable highlighting in certain area of the map. However, they can still click on it which allow them to access the data.

Describe the solution you'd like
I would like to be able to completely disable that area when active is false.

Describe alternatives you've considered
Alternative would be updating name attribute to empty so that they cannot access the data from it.

Map freezing/stuck random, coords Infinity

Describe the bug
It doesnt happend on Firefox.
The problem is when you move the mouse cursor over the image map, sometimes it stills freeze, stuck.
Checking the code, it makes a math division,
return coords.map(function (coord) { return coord / (imgRef.naturalWidth / parentWidth); });
and debugging it, sometimes 'imgRef.naturalWidth ' is zero (0)

Error Stack
npm package version v1.3.0

You could see "infinity" coords on each element of map:
<area shape="poly" coords="Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Infinity" href="#" alt="map">

Expected behavior
Don't do that :)

Screenshots
image

Desktop (please complete the following information):

  • OS: Linux, Windows, MacOs
  • Browser: latest safari/chrome
  • Version: Chrome 105

react-img-mapper with zoom and pan?

Is there any example, react-img-mapper with zoom and pan library?
I want my canvas to be zoomed and panned (react zoom pan pinch library) properly, is there any example available? Thre
Thanks

Error when using responsive props

Describe the bug
null is not an object (evaluating 'imgRef.naturalWidth')

To Reproduce

<ImageMapper
  responsive
  parentWidth={100}
  areaKeyName="unique-key"
  onClick={() => {}}
  src={IMAGE} 
  map={MAP}
/>

Error Stack
Screen Shot 2021-04-12 at 7 22 17 PM

Expected behavior
I specify reponsive prop & parentWidth and the component auto-sizes

Desktop (please complete the following information):

  • React.js v16.13.1
  • react-img-mapper v1.1.5
  • OS: MAC
  • Browser: SAFARI
  • Version: 14.0.2

Additional context
Im pretty sure is something wrong with my setup. Everything else works flawlessly. Great job!

Encountered Two Children with the Same Key, index cannot be used for areaKeyName without using ts-ignore

Describe the bug
Having same id in the MapAreas[] list throws an exception with Encountered two children with the same key.

To Reproduce
Steps to reproduce the behavior:

  1. Define map areas with id's
    Example object:
{
          id: x.baseId,
          shape: 'rect',
          coords: [0, 185, 237, 240],
          preFillColor: 'rgb(255,255,255,0)',
}
  1. Use ImageMapper component
<ImageMapper
          src={area.imgSrc}
          onClick={event => openModalForStructureDetail(event)}
          map={{name: area.id, areas: area.componentMap as MapAreas[]}}
          onLoad={e => handleLoadedImage(e)}
        />
  1. See error
    Error Stack
Warning: Encountered two children with the same key, `13`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.
    at map
    at div
    at ImageMapper (http://localhost:5173/node_modules/.vite/deps/react-img-mapper.js?v=2ed9ea2e:398:32)
    at div
    at http://localhost:5173/node_modules/.vite/deps/chunk-2NS6L6TO.js?v=2ed9ea2e:4971:18
    at http://localhost:5173/node_modules/.vite/deps/chunk-2NS6L6TO.js?v=2ed9ea2e:16193:14
    at http://localhost:5173/node_modules/.vite/deps/chunk-2NS6L6TO.js?v=2ed9ea2e:16331:14
    at div
    at http://localhost:5173/node_modules/.vite/deps/chunk-2NS6L6TO.js?v=2ed9ea2e:4971:18
    at http://localhost:5173/node_modules/.vite/deps/chunk-2NS6L6TO.js?v=2ed9ea2e:20772:14
    at div

Expected behavior
Adding areaKeyName="index" solves the issue, however declaration in the types.d.ts defines that areaKeyName only accepts id areaKeyName?: 'id';. I need to add ignore //@ts-ignore for it to work.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [Windows]
  • Browser: [Electron (chromium-based)]
  • Version: [25.4]

Additional context
I can't apply the fix stated in this issue because I cannot edit areaKeyName without getting compiler errors.

Sometimes the highlight on hover does not highlight in the right area on the image.

Describe the bug
This is an intermittent bug. Sometimes when the page loads, highlight on hover does not highlight in the right area (please see image provided). It happens when I use the attribute of responsive={true} in my <ImageMapper /> tag.

To Reproduce
Steps to reproduce the behavior:
This is how I wrote my ImageMapper for responsiveness

//this is before the render function
const [imageMapperWidth, setImageMapperWidth] = useState(0);
const imageMapperRef = useRef();

useEffect(() => {
	setImageMapperWidth(imageMapperRef.current.offsetWidth);
}, []);

let movement_timer = null;

window.addEventListener('resize', () => {
	clearTimeout(movement_timer);
	movement_timer = setTimeout(() => {
		if (imageMapperRef.current?.offsetWidth) {
			setImageMapperWidth(imageMapperRef.current.offsetWidth);
		}
	}, 1000);
});

//this is in my render
<ImageMapper
	src={url}
	map={
		...
	}
	responsive={true}
	parentWidth={imageMapperWidth}
	fillColor={'rgba(71, 131, 230, 0.70)'}
	strokeColor={'rgba(71, 131, 230)'}
	onClick={(area) => {
		handleClickLot(area);
	}}
	onMouseEnter={(area) => {
		enterArea(area);
		handleMouseMove(area);
	}}
	onMouseLeave={(event) => {
		handleMouseLeave(event);
	}}
/>

Expected behavior
When the component loads, all the highlights should be in the proper designated area. This also applies when resizing the screen.

Screenshots
Video of issue:
https://share.vidyard.com/watch/PFVv2Td5TRLN7YPLGDPkhQ?

Screenshot of issue
image

Desktop (please complete the following information):

  • OS: Windows 10
  • Browser: Chrome
  • Version: Version 102.0.5005.115 (Official Build) (64-bit)

Dynamic areas

Hi, I have a questions about coords. In the examples, the areas field is always a json. I'm wondering how to add coords dynamically with this tool. I need to draw a polygon, get coords and draw it on image, is it possible with this tool?

Thank you!

Component doesn't render

Describe the bug
Just started to work with the lib and copy/pasted the example implementation but it doesn't render anything.

To Reproduce
This is my implementation (basic example):

import React from "react";
import ImageMapper from "reactjs-img-mapper";
import { Deck } from "../../../types/typeclass";

function PannelsMarker({ deck }: { deck: Deck }) {
  const URL =
    "https://raw.githubusercontent.com/img-mapper/react-docs/master/src/assets/example.jpg";

  const MAP = {
    name: "my-map",
    // GET JSON FROM BELOW URL AS AN EXAMPLE
    areas: [...the JSON file content],
  };

  if (!deck.layout_file) return <div>No file</div>;
  console.log("Should render map");
  return (
    <div className="p-2 bg-yellow-300">
      <ImageMapper src={URL} map={MAP} />
    </div>
  );
}

export default PannelsMarker;

Error Stack
Ony error is the following
Warning: ImageMapper: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.

Expected behavior
An image map should render

Screenshots
https://imgtr.ee/image/WqlTX

Desktop (please complete the following information):

  • OS: [Windows]
  • Browser: [Brave]
  • Version: [1.56.20]

Additional context

I'm building my sie with Nxt.js 13.

onClick works one time

Describe the bug A clear and concise description of what the bug is.
I want to use a function if I am clicking on an area.
The first time the function will be used. After clicking on the other area, nothing happend.

At the screenshot you can see: Postit, keyboard and desktop is marked.

in the console only one time shows the log message "Logging a message!'", It should be everytime if I am click on the different area. Do you have a solution?

To Reproduce Steps to reproduce the behavior:

  1. Go to the page, hover on all the polygons
  2. Click on a polygon
  3. Console output shows right
  4. After clicking on another polyigon the output don't show up

grafik

Desktop (please complete the following information):

  • OS: Linux, arch
  • Browser: firefox
  • Version: latest

Additional context Add any other context about the problem here.
I use for usually typescript.

const logMessage = () => {
    console.log('Logging a message!');
};

<ImageMapper src={URL} map={MAP} stayMultiHighlighted={true} onClick={logMessage}/>

preStrokeColor prop

Is your feature request related to a problem? Please describe.
I want an area to be always highlighted like the preFillColor works, but I want only the stroke to be drawn. The stroke should be white and if the mouse enter the area the stroke should turn green.

Describe the solution you'd like
I want a new prop preStrokeColor that allows to set different stroke color in highlighted and default state.

Describe alternatives you've considered
I tried using the the preFillColor with alpha 0, but that way the stroke color is always the same if the mouse moves over the are or not. I need the stroke to be always white and if the mouse enters the are the stroke should turn green.

I also tried to use the callbacks onMouseEnter and onMouseLeave to change the map areas stroke color. But the rerendering gave me flashings and unexpected results.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.