简体   繁体   中英

How to show marker location in map when mouse over to a div item - like AirBnb

I have a page in left side div items like item's image,title,its details, address ex. And on the right side I have a map (Leaflet Map) showing markers of address which taking from all of these left side items. Now I want to display marker location on map when mouse hover to the left information with its address. Shortly you can see live example in airbnb.com

I am using React Leaflet for map and React as you see. But data doesn't fetch from db yet, it is dummy data. Address is defined with lat and lng coords

在此处输入图像描述

Bikes.js

import { BIKES, BikeTypes, BikeSize } from '../../data'
const Bikes = () => {
    return <div className="bikes-page">
        <div>
            <hr className="bike-bottom-line" />
            <BikesList items={BIKES} />
        </div>
        <div className="bikes-map">
            <MapContainer style={{ height: '50rem' }} coords={BIKES} mapZoom={9} />
        </div>
    </div>
}

export default Bikes

MapContainer.js (Component made with react-leaflet)

const MapContainer = (props) => {
    const DEFAULT_LATITUDE = 40.500;
    const DEFUALT_LANGITUDE = 49.500;
    return (
        <Map style={props.mapStyle} center={[DEFAULT_LATITUDE, DEFUALT_LANGITUDE]} zoom={props.mapZoom || 7} >
            <TileLayer
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
            />
            {
                props.coords ?
                    props.coords.map(mark => {
                        return <Marker
                            position={[mark.location.lat, mark.location.lng]}
                            icon={biker}
                            key={mark.id} >
                            <Popup className="popup">
                                <Link to={`/b/${mark.id}`} className="popup-container">
                                    <img src={mark.images[0]} alt={mark.title} />
                                    <div className="popup-container__title">
                                        <h3> {mark.title} </h3>
                                        {mark.size}" · {mark.price.first}azn/s
                                    </div>
                                </Link>
                            </Popup>
                        </Marker>
                    }) : null
            }

        </Map >
    )
}

export default MapContainer

BikesList.js (left side - List)

const BikesList = (props) => {
    if (props.items.length === 0) {
        return <h2>Elan tapılmadı</h2>
    }

    return (
        <ul className="bikes-list">
            {props.items.map((bike) => (
                <BikeItem
                    key={bike.id}
                    id={bike.id}
                    image={bike.images[0]}
                    title={bike.title}
                    city={bike.city}
                    size={bike.size}
                    price={bike.price.first}
                    creator={bike.creator}
                    maxLength={24}
                />
            ))}
        </ul>
    )
}

export default BikesList

I found a solution myself. It was easy:) Here it is:

First , in the Bikes.js file, I made an isHovered state and gives it null as a default. Then made handleHoverMarker(id) function with id which will get it from specific hovered item's id. In function I changed setIsHovered's value to this sent id. So then I shared isHovered and handleHoverMarker with props.

Bikes.js

const [isHovered, setIsHovered] = useState(null)
const handleHoverMarker = (id) => {
        setIsHovered(id)
}
<div>
   <BikesList handleHoverMarker={handleHoverMarker} items={filteredDataState} />
</div>
<div className="bikes-map">
   <MapContainer isHovered={isHovered} style={{ height: '50rem' }} coords={BIKES} mapZoom={9} />
</div>

Second , handleHoverMarker props sent to the BikeItem component which represents each of items in list.

BikesList.js

<ul className="bikes-list">
            {props.items.map((bike) => (
                <BikeItem
                    key={bike.id}
                    id={bike.id}
                    image={bike.images[0]}
                    title={bike.title}
                    city={bike.city}
                    size={bike.size}
                    price={bike.price.first}
                    creator={bike.creator}
                    maxLength={24}
                    handleHoverMarker={props.handleHoverMarker}
                />
            ))}
</ul>

In the BikeItem.js set mouseHover events and pass the id with handleHoverMarker(id) function. So we will know which item hovered with id.

Note: I didn't write all codes in BikeItem.js only took the necessary part

BikeItem.js

<li onMouseEnter={()=> props.handleHoverMarker(props.id):null} onMouseLeave={()=>props.handleHoverMarker(null):null} key={props.id}>

So here we come back to the MapContainer which will show hovered item's location

MapContainer.js

{props.coords ?
   props.coords.map(mark => {
                return <Marker
                position={[mark.location.lat, mark.location.lng]}
                icon={biker}
                opacity={props.isHovered === mark.id ? .7 :1}
                key={mark.id} >
                   <Popup className="popup">
                     <Link to={`/b/${mark.id}`} className="popup container">
                       <div className="popup-container__title">
                          <h3> {mark.title}</h3>
                       </div>
                     </Link>
                </Popup>
               </Marker>
 }) : null}

Here I changed opacity value conditionally with props.isHovered which we sent from Bikes.js file.

Note: I couldn't changed marker's style because I didn't found a way from documentaton of leaflet map. So logic is the same, you can do it with Google Maps too. Enjoy good luck:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM