Hi Matthew
I have a large number of partial 360 panoramas, i.e. they might only have a vertical field of view of 60 degrees. Typically these are of mountainous views, and I'll use a custom hotspot icon placed above a peak to identify it. I now wish to add more content to the tooltip balloon, but in some circumstances there is not enough room above the hotspot icon, so I would like to place the tooltip balloon below the the hotspot icon.
Ideally I'd like to pass the pitch of the hotspot to the custom tooltip function and add a little code in that function to decide which css to apply.
For example
function hotspot(hotSpotDiv, args, pitch)
{
if (pitch<20)
{
hotSpotDiv.classList.add('custom-tooltip-above');
}
else
{
hotSpotDiv.classList.add('custom-tooltip-below');
}
var span = document.createElement('span');
span.innerHTML = args;
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';
}
Any ideas as to how this can be achieved? Perhaps there is a better way that already exists that I cannot see.
Best wishes and kind regards
Derek
Hi Matthew
I think I've solved this one by my self.
I can place a js object into the tooltip args, like below, where the 4 is the hotspot pitch....
"createTooltipArgs": [4,"Baltimore Museum of Art"],
then in the custom tooltip function do this....
function hotspot(hotSpotDiv, args)
{
if (args[0]<20)
{
hotSpotDiv.classList.add('custom-tooltip-above');
}
else
{
hotSpotDiv.classList.add('custom-tooltip-below');
}
var span = document.createElement('span');
span.innerHTML = args[1];
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';
}
Seems to work nicely and offers flexibility for the future.
Best wishes
Derek
Wouldn't this be something for a positional engine/library like popper.js?
Hi Strarsis
I took a look at popper.js this morning and tried out a tutorial. It's certainly offers some nice features, and as you point out, would be great for my application.
However it seems to rely on id for both the hotspot and tooltip. I think these could be added, being given some sequential code number as each scene loaded and the hotspots are created , but I'm not sure how to set up popper.js to handle the same sequentially coded id's.
Have you any experience of this?
Best wishes
Derek
The best way to change the default pannellum tooltips would be a hook function in pannellum before or after tooltip initialization to assign its elements to popper.
I’ll be giving some thought as to how best to achieve this. Thank you Strarsis.
From: strarsis [mailto:[email protected]]
Sent: 04 March 2021 00:24
To: mpetroff/pannellum pannellum@noreply.github.com
Cc: Derek Stillingfleet Derek@VirtualMountains.co.uk; Author author@noreply.github.com
Subject: Re: [mpetroff/pannellum] Controlling the position of tooltip balloon when there is not enough room above. (#961)
The best way to change the default pannellum tooltips would be a hook function in pannellum before or after tooltip initialization to assign its elements to popper.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub https://github.com/mpetroff/pannellum/issues/961#issuecomment-790182921 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AC47ZDDZGINRDKOJPTXWVWDTB3HLBANCNFSM4YOXEY6Q . https://github.com/notifications/beacon/AC47ZDAO3TF3Q4JJSMAXR7LTB3HLBA5CNFSM4YOXEY62YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOF4MTYCI.gif
I've evolved the custom hotspot function so that the tooltip will be placed above the hotspot if there is sufficient space for it. If there is insufficient space, (if you working with panorama of say 60 degrees VFOV), a position lower on the screen is calculated.
For those who need to do the same, I'll outline it here.
The pitch (on this example 20 degrees) is passed to the create hotspot function thus....
"createTooltipArgs": [20,"Baltimore Museum of Art"],
The hotspot function has some additional code to Matthew's original....
function hotspot(hotSpotDiv, args)
{
hotSpotDiv.classList.add('custom-tooltip')
var span = document.createElement('span');
span.innerHTML = args[1];
hotSpotDiv.appendChild(span);
span.style.width = span.scrollWidth - 20 + 'px';
span.style.height = span.scrollHeight + 'px';
span.style.marginLeft = -(span.scrollWidth - hotSpotDiv.offsetWidth) / 2 + 'px';
span.style.marginTop = -span.scrollHeight - 12 + 'px';
var PanoHeight = document.getElementById("PannellumSection").clientHeight;
var PPD = PanoHeight/(2*(Math.min(LocationData.MaxPitch,(LocationData.MinPitch*-1))))
var HotspotCenter = Math.round((PanoHeight / 2)+(args[0]*PPD),1);
var Offset = Math.max(0,((HotspotCenter + span.scrollHeight + 35)-PanoHeight));
span.style.top = Offset+"px"
}
Where
span.innerHTML = args[1]; passes the tooltip text / html.
span.style.height = span.scrollHeight + 'px'; The height of the tooltip text is defined by the additional line
var PanoHeight = document.getElementById("PannellumSection").clientHeight; defines the height of the pano in pixels. I named the DIV containing Pannelleum "PannellumSection".
var PPD = PanoHeight/(2*(Math.min(LocationData.MaxPitch,(LocationData.MinPitch*-1)))) calculates pixels per degree based on the panorama's max and minimum pitch which I have in global variables, and takes into account the VFOV when the horizon / zero degrees is in the centre of the view.
var HotspotCenter = Math.round((PanoHeight / 2)+(args[0]*PPD),1); calculates the centre position of the hotspot in pixels. args[0] is the pitch of the hotspot.
var Offset = Math.max(0,((HotspotCenter + span.scrollHeight + 35)-PanoHeight)); calculates the offset / position of the top of the tooltip box relative to the hotspot. The 35 degrees references the height of the hotspot with some buffer space. I'm not using an arrow between the hotspot and tooltip. The offset is zero if the calculation results in a negative number.
span.style.top = Offset+"px" applies the new offset or top position to the tooltip.
It takes a fair amount of work to get Popper.js to work with Pannellum, but Tippy.js, which uses Popper.js, works well. Here's an example:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hot spots</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>
<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://unpkg.com/tippy.js@6"></script>
<style>
#panorama {
width: 600px;
height: 400px;
}
.tippy-content {
/* Match to Pannellum default */
font-family: Helvetica, "Nimbus Sans L", "Liberation Sans", Arial, sans-serif;
text-align: center;
}
</style>
</head>
<body>
<div id="panorama"></div>
<script>
pannellum.viewer('panorama', {
"type": "equirectangular",
"panorama": "examplepano.jpg",
"hotSpots": [
{
"pitch": 14.1,
"yaw": 1.5,
"type": "info",
"createTooltipFunc": hotspot,
"createTooltipArgs": "Test tooltip text"
}
]
});
// Hot spot creation function
function hotspot(hotSpotDiv, args) {
tippy(hotSpotDiv, {
content: args
});
}
</script>
</body>
</html>
I've just tried that Tippy.js example. Brilliant.
Most helpful comment
It takes a fair amount of work to get Popper.js to work with Pannellum, but Tippy.js, which uses Popper.js, works well. Here's an example: