Pannellum: createTooltipArgs is not updating args for each hot spot

Created on 14 Mar 2021  路  6Comments  路  Source: mpetroff/pannellum

So I've created a function to use with the createTooltipFunc as you suggested, and then I added some text for the createTooltipArgs, and the argument is getting passed, but it's always the same argument that gets passed.
Here's a sample:

"hotSpots": [ { "type": "scene", "sceneId": "hallChar", "cssClass": "extWindowMan", "pitch": -12, "yaw": -112, "createTooltipFunc": showText, "createTooltipArgs": "Symptmes de Ruine", }, { "type": "scene", "sceneId": "threeBuildingsIce", "cssClass": "extWindowBuilding", "pitch": 15, "yaw": 25, "createTooltipFunc": showText, "createTooltipArgs": "The Office", }, ]

The problem is that when I try to print out the argument it just keeps writing out the second argument, so:

function showText(hotSpotDiv, args) { document.getElementById('textBeneath').innerHTML = args; }

Always writes "The Office" even if I'm hovering over the first hotspot.

question

All 6 comments

The function is called when the hot spot is created, so when the scene is initialized. It is not called when the tooltip is shown.

Your function is displaying the argument for each hot spot in the same HTML element. Since the hot spots are all created at the same time, you just end up overwriting the content of the HTML element. If you use console.log(args) instead, you'll see that both arguments will be printed to the browser developer console.

I've deleted my previous comments because I realize this is getting longwinded...
I'm trying to find a way to do the following:

When a user's mouse hovers over a hotspot a div appears below/outside the panorama window (or just at the bottom of it but is fixed in one position ie won't pan with the panorama), and it contains the corresponding title of the hotspot. Whether that is using the tooltip text field or the custom createTooltipFunc / createTooltipArgs + additional javascript is inconsequential. No matter what I try I am unable to make this happen (all the args populate the divs simultaneously), and I don't understand why your custom hotspot tooltip code works but mine doesn't. I've tried a dozen different ways of doing this (even if I write an individual createTooltipFunc / createTooltipArgs for each hotspot and create a unique div for it the div I assign the arg to still just displays the most recent/last arg).

Your function is display the argument for each hot spot in the same HTML element.

So does your function though... they all go into a span element right? Why does it assign the individual args to the proper divs?

Since the hot spots are all created at the same time, you just end up overwriting the content of the HTML element.

But why doesn't yours do that in the span?

Your built-in tooltip functionality just seems so elegant I would like to find a way to be able to use that if possible. If not I guess I'll just have to write a bunch of hacky code for each individual hotspot. I was just thinking there'd be a way around that using the built in tooltip functionality somehow...

I think this code snippet should do what you want. It's based on what I posted in https://github.com/mpetroff/pannellum/issues/962#issuecomment-791418036.

viewer = pannellum.viewer('panorama', 锘縶
    ...
    "hotSpots": [
        {
            "pitch": 10.0,
            "yaw": 10.0,
            "type": "info",
            "createTooltipFunc": hotspot,
            "createTooltipArgs": "Your hot spot text"
        }
    ]
});

function hotspot(hotSpotDiv, args) {
    hotSpotDiv.classList.add('pnlm-tooltip');
    hotSpotDiv.appendChild(span);
    span.style.width = span.scrollWidth - 20 + 'px';
    span.style.marginLeft = -(span.scrollWidth - div.offsetWidth) / 2 + 'px';
    span.style.marginTop = -span.scrollHeight - 12 + 'px';

    hotSpotDiv.addEventListener('mouseover', function() {
        document.getElementById('textBeneath').innerHTML = args;
    }, 'false');
}

You were trying to use the hot spot creation function to trigger a mouseover event. This works for the hot spot tooltips, since they're displayed using the CSS :hover pseudoselector, but it won't work for updating an element elsewhere.

Thanks! I should have clarified that was the code snippet I was referencing. So you are saying that it is not possible to adapt the tooltip functionality in order to toggle a div outside of the panorama div correct? Or even to toggle a div inside the panorama div but at a fixed position near the bottom (ie won't pan with the panorama)? I was thinking that might be possible, but I can't figure out how to affix the div to one position, it always pans.

Here's what I ended up putting together. I'm just creating a uniquely named function for each hotspot, but it's the exact same as the one before it. Let me know if you think there's an easier, less repetitive way of doing it by building on the code that already exists.

        "hotSpots": [
            {
                "pitch": 10,
                "yaw": 0,
                "cssClass": "hotSpotStyle",
                "text": "hello",
                "createTooltipFunc": hotspot,
                "createTooltipArgs": "The Office of Memory",
            },
            {
                "pitch": 10,
                "yaw": 40,
                "cssClass": "hotSpotStyle",
                "createTooltipFunc": hotspot2,
                "createTooltipArgs": "Art Museum Drive"
            }
        ],
        "autoLoad" : true
    });

    // custom hot spot creation function
    function hotspot(hotSpotDiv, args) {        
        var span = document.createElement('span');
        span.innerHTML = args;

        var bottomDiv = document.getElementById("bottomDiv");       
        hotSpotDiv.onmouseover = function(){            
            bottomDiv.appendChild(span);
        }
        hotSpotDiv.onmouseleave = function(){            
            bottomDiv.removeChild(span);
        }
    ;}

    function hotspot2(hotSpotDiv, args) {        
        var span = document.createElement('span');
        span.innerHTML = args;

        var bottomDiv = document.getElementById("bottomDiv");       
        hotSpotDiv.onmouseover = function(){            
            bottomDiv.appendChild(span);
        }
        hotSpotDiv.onmouseleave = function(){            
            bottomDiv.removeChild(span);
        }
    ;}

And so on, creating duplicated functions for each new hotspot...

You don't need separate functions. Here's a complete tested example that displays text in an external <div> on mouse over:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>Test Example</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/build/pannellum.css"/>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/build/pannellum.js"></script>
    <style>
    #panorama {
        width: 600px;
        height: 400px;
    }
    </style>
</head>
<body>

<div id="panorama"></div>
<div id="bottomDiv"></div>

<script>
// Create viewer
viewer = pannellum.viewer('panorama', 锘縶
    "panorama": "examplepano.jpg",
    "hotSpots": [
        {
            "pitch": -12,
            "yaw": 170,
            "type": "info",
            "createTooltipFunc": hotspot,
            "createTooltipArgs": "Test text 1"
        },
        {
            "pitch": -10,
            "yaw": -50,
            "type": "info",
            "createTooltipFunc": hotspot,
            "createTooltipArgs": "Test text 2"
        }
    ]
});

function hotspot(hotSpotDiv, args) {
    var span = document.createElement('span');
    span.innerHTML = args;
    hotSpotDiv.classList.add('pnlm-tooltip');
    hotSpotDiv.appendChild(span);
    span.style.width = span.scrollWidth - 20 + 'px';
    span.style.marginLeft = -(span.scrollWidth - hotSpotDiv.offsetWidth) / 2 + 'px';
    span.style.marginTop = -span.scrollHeight - 12 + 'px';

    var bottomDiv = document.getElementById('bottomDiv');
    var span2 = document.createElement('span');
    span2.innerHTML = args;
    hotSpotDiv.addEventListener('mouseover', function() {
        bottomDiv.appendChild(span2);
    }, 'false');
    hotSpotDiv.addEventListener('mouseleave', function() {
        bottomDiv.innerHTML = '';
    }, 'false');
}
</script>

</body>
</html>

Oh wow, very interesting! Ok I will try this and report back. I was not able to get this to work at all. Thanks so much!

EDIT: It works! Thank you! When I compared this with my code I realized that I was on the right track and just got turned around and confused at some point. I have no idea when or why... It just wasn't working for me and I got mixed up. Thanks so much I'm really enjoying exploring what you've built here!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

shtrudelsupport picture shtrudelsupport  路  3Comments

FlokiTV picture FlokiTV  路  6Comments

ai-tushar picture ai-tushar  路  9Comments

arpu picture arpu  路  6Comments

littlee picture littlee  路  8Comments