How to remove blank frame from the tooltip

Hi everyone, I’m trying to implement dash in my work by creating a map of the gas station and its prices. The only problem I’m having and not being able to solve is that there’s a blank frame around the tooltip that I don’t want to be:

And this is (part of) the code in case you need it:

markers = [
        dl.CircleMarker(
            center=[row['latitud'], row['longitud']],
            radius=0,
            color='transparent',  # Color fijo para el marcador
            children=[
                dl.Popup([
                    html.B(f"{row['empresa']}"),
                    html.Br(),
                    f"Bandera: {row['bandera']}",
                    html.Br(),
                    f"Dirección: {row['direccion']}",
                    html.Br(),
                    f"Localidad: {row['localidad']}",
                    html.Br(),
                    f"Precio: {row['precio']}",
                    html.Br(),
                    f"Vigencia: {row['fecha_vigencia']}"
                ]),
                dl.Tooltip( 
                    html.Div(
                        f"{row['precio']}",
                        style={
                            'backgroundColor': color_dict.get(row['bandera'], 'black'),
                            'padding': '2px',  # Reducir el padding
                            'borderRadius': '3px',  # Ajustar el borde redondeado
                            'color': 'white',
                            'border': 'none',  # Eliminar el borde blanco
                            'margin': '0px',  # Reducir el margen
                            'boxShadow': 'none'  # Eliminar sombras
                        }
                    ),
                    direction='top',
                    permanent=True,
                    offset=[0, 20]
                )
            ]
        ) for i, row in filtered_df.iterrows()
    ]

I tried with chatgpt but didn’t work out.
Thanks in advance!

add this to your css file:

.leaflet-tooltip {
    border: none !important;
    background: transparent !important;
    box-shadow: none !important;
}

now… if you could find a solution to my leaflet project problem I’d be much appreciative:

mostly joking… lol but you should also consider using dl.GeoJSON cluster seems kinda dense. You could set it up with:

import geopandas as gpd

gdf = gpd.GeoDataFrame(
    df, geometry=gpd.points_from_xy(df.lon, df.lat))

geojson = gdf.to_json()

geojson_dict = json.loads(geojson)

point_to_layer_js = assign("""
function(feature, latlng){
    const iconData = feature.properties.icon_data;
    const flag = L.icon({
        iconUrl: 'https://cdn-icons-png.flaticon.com/128/7015/7015198.png', 
        iconSize: [35, 35],
        tooltipAnchor: [20, 0]  // Adjusts the tooltip 10px to the right
    });
    const marker = L.marker(latlng, {icon: flag});
    marker.bindTooltip(''); // setup custom tooltip here
    return marker;
}
""")

dl.Map(

                    [
                        dl.TileLayer(
                            url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
                        ),
                        dl.GeoJSON(
                            data=geojson_dict,
                            id="locations_layer",
                            cluster=True,
                            zoomToBoundsOnClick=True,
                            superClusterOptions=dict(radius=40),
                            pointToLayer=point_to_layer_js,              
                        ), 
])

that will give you the cluster effect with a custom icon and hover price on icon if setup correctly.

Icon I chose was:

but you can look through: Search results for Gas station - Flaticon
and pick a better icon or setup a way to match brands with specific icons

1 Like

Hi pip, I tried your solution of json but my app is all grey:


I don’t know why. I tried simplifying my dataframe to only some rows but still happens.

Lets try working back and take small steps before working it into your desired solution. Revert back to your prior code and just add

.leaflet-tooltip {
    border: none !important;
    background: transparent !important;
    box-shadow: none !important;
}

Into your css file, did that work? If so then help me get a better understanding of your goal. Is that enough or would you like to also setup a cluster for the data?
If you face problems with that basic implementation then inspect the page and send me the error in console.

1 Like

It worked! The issue was resolved with .leaflet-tooltip. I initially thought that adding “marker-tooltip” as a className would be sufficient. Thanks!

For now, it’s fine. The icon is not necessary at this stage. If the application progresses, I will consider adding some icons and making formatting improvements.

The only concern I have is that adding an icon for each gas station might slow down the application, considering there are 3,000 gas stations in the country. This slowdown even occurs with just the tooltips or markers. Is this a limitation of Dash? In some cases, I can use clusters to group the gas stations, but in other instances, I need to see them all, ungrouped.

At the moment im working with ~200 data points and the icons havent been a problem with me. Believe if you also cluster than they wont all load at once. Also the svg ring i initially needed help with is resolved and i could see as being a good adition for your project if you decide to move in that direction. Basically you could have specific types of gas stations show up in the svg ring to indicate how many their are like ev charging stations, exon, shell exc. Then when you zoom in it shows the icons that represent each categorie of gas station. Regardless, cool project happy it worked and best of luck!

Oh and you could also save the icons in the assets folder and load them that way to speed up the data without needing to hit the url of the image

Thanks! yes, I have a side project already hosted: Dash (buscafes.azurewebsites.net) that I’m about to finish some details, and the problem is that the icons have a weight of 5kb, and there are at least 2000 icons in the map. I believe that is slowing down the application. They are saved in the assets folder. I believe that, as you say, it would be better to have them as .svg instead of .png, and let them appear once the user zooms in, right?

1 Like

We are similar developers my friend. We are both borderline cartographers as much as we are programmers. Thats an awesome project. Currious how you gathered all that data. Everything ive been doing is manual database entry with plans of making my map user based generated. My projects still in development but i have learned a few things along the way that could be helpful. Personally i like geopandas and the cluster as i feel like it opporates faster. Fairly easy to setup and id be currious to see the preformance difference youd see with the large datasets you work with. Outside of that i have a dedicated database for my dataset and im using ninja api which preformes exeptionally well at retrieving it from dash.

My datasets smaller but i have more fields and larger renders than you do and my app loads much faster. Im gathering an image and using that as the hover tooltip and i have a modal to give more context of the individual locations which also contains images. So in total with 200 plots im probably rending 200 icons + 750 images.

You might find some useful stuff from the components i’ve developed https://pip-install-python.com and you should check out one of the maps im working on @ https://dash.geomapindex.com

You should check out my app on mobile as well as desktop and notice the diffrence. Its been a big focus of mine and a suggestion id recomend for you. Make the app designed for mobile as the priority. The majority of trafic you recieve like 70% will be from phones maybe even higher with your desired south american audiance. Not to say your app is bad on the phone, just something to mention.

Haha, that’s a nice definition. So let’s go with the answers:

-How I gathered all the data: took me a while, but I used the API Places api from google. They provide you with 200usd credits each month. So I made the request with python to obtain all the places in google that match the name: cafe, cafetería, coffee (because if you google coffee in a certain place you would get determined places, and if you google “coffee places” you might get others, so I had to cover all the options) in ever neighbourhood of my city. A youtuber named Jie Jenn has very good videos about it.

-The clusters work great, I know. It depends on the project if you can use them or not. For example in the gas stations app I certain need to see all the prices at once to compare. Maybe I can try with geopandas to locate the places in the map, I’ll see.

-Your app looks great and works fine, also in cellphone, it didn’t take me much time to open it, congrats! Maybe I’ll add different themes to the map, but that’s a feature. You used plenty amount of images. I will try to find out what resources are the bottleneck aside the marker icons (saving in svg should improve)

-I’ve designed the app also for cellphones, I know. I was doing some editing and the panel filter looked horrible. I’ve just corrected it and I’ll ask for more opinions on the user experience. Besides that, I don’t find it bad except for the time it takes to open and function

Can I ask you how did you host your app it and if you paid a plan?

Ah! Had a feeling you where going to say google api for scrapping the data. Fantastic job all around. Smart and sharp way to get setup.

Totally understand whatcha saying about the gas stations. Don’t know if you used my search functionality on the dash app i sent you but an ag grid modal might be a good way for you to filter and search locations, types and prices of gas stations. I related my search functionality of ag grid with a flyto function which looks really clean so when you click on a location via the ag grid the map flys you over to the location on the map and zooms into it specifically.

My apps a bit more complex than meets the eye. On the backend at this current moment its built with two django applications and one dash application which you opened. The initial build of the project was a single django application that wouldn’t function as clean and ideal as i would have liked on mobile, so i rebuilt and moved to a new approach of hosting a backend container built in django and a front end in dash rather than using django-plotly-dash and having everything under the same roof this new approach keeps them separate but connected through the api. Im currently in the process of removing my old django application but the api data is getting retrieved from:

The new django backend is now setup as a blog and user authentication system which i’m working on getting setup to replace my prior infrastructure as a new home to store all locations and users on the django and postgres database associated with it.

The link for the new djano application is:

The idea i’m going for is dash hits an api endponts on the django application for logging in users via the django system. It also allows the user on dash to hit other endpoints like editing or creating locations via the api.

The new django and dash application are built in docker containers and deployed on a azure vpn with docker hub and github pipelines as the method for deployment which is an awesome setup for consistent updates. Along with this i created checks on the pipeline and deployment process to make sure on uploading new updates, everything is automated and the code has to pass a test, build and deploy before removing the currently deployed application if everything passes it will only then re-deploying with the updated changes which makes sure i have absolutely no offline time in development of the production application.

I’m currently paying ~$100-$120 a month for the hosting which i could get down in price with changing from a vps to azure app services but in constant development a vps is just a better option.

In regards to your design, I would recommend changing the filter if possible. Maybe have it initially load without it opened but available with a click of a button like you have. If possible make it smaller if possible so users can see both the map and filter at all times even on mobile. Dash is such a great framework for allowing you to see changes in real time and i think it adds a lot of user functionality if the user can see how the changes they make in the filter interact in the map in real time. Rather than having a system thats all filter, click button, close filter to see the results.

Outside of that this is the best map I’ve found in my hours of searching and scraping the web:
dl.TileLayer(url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}")

I also made this example of showing like 12 other map designs, along with current cloud cover and rain in the usa based on 4h, 12h and 24h that you might find useful in your journey:
https://usa-weather-radar-map-dca8850fd07a.herokuapp.com/

Code:

Curious, are you using the google api to retrieve the current prices of gas also? will that be sustainable? Wouldn’t expect the $200 credits last long with a daily scraping of that size.

2 Likes

Wow, you have really been working hard on that stuff. Hats off. Very good information also! Id love to see the final desing (and the process),
Ag grid is not sth that I have implemented but just because didn’t have the time, I know its useful.

Ok, so you’re paying 100 per month. That’s out of my budget, but it’s reasonable given the nature of your app. I still haven’t used Django, but I imagine it will be inevitable in the future if someone wants to scale his app. In my case, I pretend to add layouts, and have not only coffe places but ice cream, restaurants, etc.

Ok, now my app has the filter panel not visible initially, but you have a point when watching the map and the filters together and not one over the another. I’ll see how can I manage it,

Nice map desings btw, they will go to my favs.

About the credits of google api, no, I’m not using them for the gas stations because there’s already a dataframe that the government publishes everyday with the updated prices and location of every gas station of my country. Unfortunately, there’s no dataframe of the coffee places in my city :frowning: so I had to create one. I should only have to update it once or twice a month.

1 Like

Thanks for the kind words, hope all this helps. Was an interesting back and forth last bit of advice with the styling of the filter and map is to set the map with a style of'position': 'absolute' and a 'z-index': -1 then setup the filter in your style.css file. The way i did it was:

/* CSS for larger screens */
@media (min-width: 768px) {
  .ag-theme-alpine-dark {
    width: 500px !important;
    height: 30vh !important;
  }
  .map_search {
        position: absolute !important;
        width: 100% !important;
        height: 92% !important;
        left: 0 !important;
    }
}

/* CSS for smaller screens */
@media (max-width: 767px) {
    .ag-theme-alpine-dark {
        width: 100vw !important;
        height: 40vh !important;
        position: absolute !important;
        top: 52vh !important;
        z-index: 10 !important;
        right: 0px !important;
    }

    .map_search {
        position: absolute !important;
        width: 100% !important;
        height: 92% !important;
        left: 0 !important;
    }

    .map_search_fixed {
        position: absolute !important;
        width: 100% !important;
        height: 57% !important;
        left: 0px !important;
    }
}

You’d need to change the names in the style.css based on the id’s you’ve selected for your components but the main idea i’m trying to articulate is use @media (min-width: px) to tell your app to render in specific ways depending on the device size the user is using.

For your use case, a lot of people in the plotly community like https://render.com/ because it offers a free hosting service. its what I used to host pip-install-python.com and might be perfect for you while you are testing and developing out these projects. Also comes with an auto re-deploy of new updates you make via the github repo you connect with it. When you push changes render.com will see that and automatically re-deploy your app without you needing to manually do anything.

Best of luck on your Journey welcome to the forum and looking forward to seeing what you develop.

Cheers :beers:,
Pip

thanks for that css advice!
I used Render at first to deploy my app and it was very “firendly”, but it was too slow, that’s why I change to azure. My idea is to share it with the people from my city, so I expect (and hope) that more than a hundread people use it.

Best of luck for you too, I’d be glad to help and contribute to the community from what I’ve learned.