mpetroff / pannellum

Pannellum is a lightweight, free, and open source panorama viewer for the web.
https://pannellum.org/
MIT License
4.21k stars 717 forks source link

Possible to add navigation button to move images? #121

Closed video-internal closed 8 years ago

video-internal commented 8 years ago

I have seen examples but I was just wondering in place of mouse to move the image in directions, is it ok to use buttons to do the same? kind of navigational buttons ? -> , <-

rferreiroa commented 8 years ago

You can develop in a easy way using functions in pannellum like onmousemove, onmouseclick and other similiar included in this library. Would be the same with zooming in or out

video-internal commented 8 years ago

@selko - I have seen krpano examples and they are having arrow keys,+,-,fullscreen button for all the browsers and devices, was just wondering if those can be added in this library also

Plus, One button to toggle 2 different type of image - dark/shine example.. I meant, normal image can be loaded at first and on click of a button, darker image of that particular image will be shown and that toggling can enable to see how same image can look in dark/light..

rferreiroa commented 8 years ago

it´s possible of course. im developing these kind of caracteristics but i don´t know really if @mpetroff is interested in implement these ones to this lib.

Kind regards

video-internal commented 8 years ago

@selko - are you developing these characteristic using pannellum? If yes, is it possible to share that with me? I'll be very thankful to you.

@mpetroff - can you please throw some light on this if possible?

mpetroff commented 8 years ago

@video-internal At some point in the next few days I'll write an actual response, but the fact that you impatiently sent me an email a few hours after opening this issue asking me to look at it makes me want to take my time.

mpetroff commented 8 years ago

I believe both of these requests are best served by the API. I always found direction buttons somewhat pointless, so I don't want to build them in (Google seems to agree, having removed them from Google Maps a while back). A toggle between two images is a bit specific. What if you want to be able to switch between three images?

Implementing direction buttons was already possible with the API. Set the button's click handler to something along the lines of viewer.setPitch(viewer.getPitch() + 5) for a pitch up button, where viewer is the Pannellum instance created via something like viewer = pannellum.viewer('containerId', {your config here});.

I just added loadScene and getScene methods to the API to support something like the image toggle. Here you would set the click handler to something like:

if (viewer.getScene() == 'day') {
    viewer.loadScene('night')
} else {
    viewer.loadScene('day')
}
video-internal commented 8 years ago

@mpetroff - I'm extremely sorry for being impatient. Thank you so much for detailed help and adding extra feature also. I will try to use the methods suggested by you and get back to you if you don't mind in case of any query.

saidmoya12 commented 8 years ago

@mpetroff the set and getScene methods work in npm instalation??

mpetroff commented 8 years ago

While Pannellum can be installed via NPM, it isn't CommonJS, so it doesn't work in Node.

video-internal commented 8 years ago

@mpetroff - sorry for disturbing you again. I was trying to use suggestion made by you above.

I have created one fiddle for up arrow and also getting scene so that I can change based on above snippet.

fiddle - https://jsfiddle.net/akaw4wq7/

I failed to do so both.

  1. For up arrow, value is getting updated but it doesn't get reflected directly on the image but if click on the image then that value is getting applied. May I know where am I making mistake?
  2. For getScene, I think cdn version of js is getting error. But on my local system, I'm getting it's value as undefined. So how can I toggle between 2 images? Should I have to load 2 images initially and then toggle? Any detail help would be very helpful to me.

----- I read js file and that created one more question in my mind. Is it possible to bind keyevents which are getting fired on press of left,right,up and down arrow key of keyboard? If so, can you please explain how?

That would be very easy and those displayed arrow buttons are having similar behavior to arrow keys only

mpetroff commented 8 years ago

The issue with the view not being updated was a bug, which I just fixed in 3de0cbefe55b87a972b6494acbacf2106ed6d946.

The issue with getScene is due to your configuration not having any scenes set up. Take a look at the tour example; you need to set the scenes in the tour but can use the API to switch between them instead of (or in addition to) hot spots.

You can bind keyboard events the same way you would normally bind such events; just add an event listener to the container element.

video-internal commented 8 years ago

Thanks for the quick fix and also solving the query.

For switching between the scene, after getting the scene by using getScene, instead of setScene, one has to use loadScene. I have made some changes in scene config and uploaded on fiddle also and it worked perfectly by using loadScene.

For navigation button, I'm directly using values. But you told me that I can also use functions which are called when someone presses keyboard arrow keys by binding those functions on custom navigation arrows as well. I didn't get that. Could you please explain that in the updated fiddle?

Updated fiddle - https://jsfiddle.net/akaw4wq7/3/

PS - In Updated fiddle, I have used original version of js and css so it's not working there but I ahev checked on my local system and all the things are working perfectly. Thanks for your help. Just throw some light on keyboard arrows and custom arrow thing if possible using fiddle.

mpetroff commented 8 years ago

Here's how you would do stuff when the arrow keys are pressed:

document.getElementById('panorama').addEventListener('keydown', function(event) {
    // Record key pressed
    var keynumber = event.keycode;
    if (event.which) {
        keynumber = event.which;
    }

    // If an arrow key is pressed
    if (keynumber == 37) {
        console.log('Left arrow pressed')
    } else if (keynumber == 38) {
        console.log('Up arrow pressed')
    } else if (keynumber == 39) {
        console.log('Right arrow pressed')
    } else if (keynumber == 40) {
        console.log('Down arrow pressed')
    }
});
video-internal commented 8 years ago

Thanks again for clarifying so quickly. But I think I wasn't clear in my question or query.

What I was trying to ask is as follows:

  1. If you can see, I have divs titled as up,down,right and left. I have updated the scene position by +5 or -5 either vertically or horizontally from the last position. But it doesn't appear as smooth as the case when we use actual arrow keys of keyboard.So is there any way that I can bind those keyboard key events functions to the custom arrow icons (div with titles) ?
  2. After making some changes to use tour to navigate between images and also custom swap button to swap between day and night mode, if I click to change the image and at same time, I click to swap image then next image isn't drag-able but hotspots become drag-able. Is there anyway to hide the buttons till the image is loaded? Initially, I have used load event for hiding them, but in case of change of scene, is there anyway to do it? or any suggestion from you to solve the issue?

Solution of 2nd - I have used scenechange event for above issue - hiding controls till the load event is being fired so this sequence solves the issue :-)

mpetroff commented 8 years ago

I created a new issue, #162, to address part one; there's currently no way to animate the API movements. Part two was a bug, which I just fixed in e2a4e6f2b505ac8876cedf026d0f9c65af609dbe.

video-internal commented 8 years ago

Thank you for updates. I'm now reading data from xml and passing it to .viewer call. For example, for "scenes": object. But I'm getting entire object which is having different index and I check scenes have one entire object. So there's issue.

inv_viewer = pannellum.viewer('panorama', {
                      "default": {
                          "firstScene": "circle",
                          "sceneFadeDuration": 1000
                      },

                      "scenes": inv_sceneData[0]
});

here, I have put all the scene related data in inv_sceneData so this is working fine.

But if I create such array by reading xml, it is having 2 issues:

  1. scene name - for example, circle or house isn't updated. It is getting the string which I have written.
  2. the array is a collection of objects so whenever I use that array, there is indexing issue

These issues may not be associated with pannellum but may be the way of data is used

Can you please elaborate on this issue?

mpetroff commented 8 years ago

I can't really say anything definitive without seeing how you're creating the array from XML. My best guess is that there's some sort of referencing between objects that's causing the issue.

video-internal commented 8 years ago

XML FILE---

<?xml version="1.0" encoding="UTF-8" ?>
<root>
    <panorama>
        <scenes>
            <scene id="circle" imgType="equirectangular" imgPath="./images/bma-1.jpg">
                <hotspots>
                    <hotspot pitch="-2.1" yaw="132.9" type="scene" sceneId="tree">
                        <![CDATA[ Mason Circle ]]>
                    </hotspot>
                    <hotspot pitch="14.1" yaw="1.5" type="info" url="https://artbma.org/">
                        <![CDATA[ Baltimore Museum of Art ]]>
                    </hotspot>
                    <hotspot pitch="-9.4" yaw="222.6" type="info">
                        <![CDATA[ Art Museum Drive ]]>
                    </hotspot>
                </hotspots>
            </scene>
            <scene id="circle_night" imgType="equirectangular" imgPath="./images/bma-1_night.jpg">
                <hotspots>
                    <hotspot pitch="-2.1" yaw="132.9" type="scene" sceneId="tree">
                        <![CDATA[ Mason Circle ]]>
                    </hotspot>
                    <hotspot pitch="14.1" yaw="1.5" type="info" url="https://artbma.org/">
                        <![CDATA[ Baltimore Museum of Art ]]>
                    </hotspot>
                    <hotspot pitch="-9.4" yaw="222.6" type="info">
                        <![CDATA[ Art Museum Drive ]]>
                    </hotspot>
                </hotspots>
            </scene>
        </scenes>
    </panorama>
</root> 

Logic for reading xml file-----

inv_sceneTempData = [];

                $(op.panoramaData).find('scene').each(function() {
                     inv_tempScene = $(this).attr('id');

                     inv_hotSpotData = [];
                     $(this).find('hotspots').find('hotspot').each(function() {
                        if($(this).attr('sceneId')!=undefined)
                        {
                            inv_hotSpotData.push({
                                "pitch": $(this).attr('pitch'),
                                "yaw": $(this).attr('yaw'),
                                "type":$(this).attr('type'),
                                "text": $(this).text(),
                                "sceneId": $(this).attr('sceneId')
                            });    
                        }
                        else
                        {
                            if($(this).attr('url')!=undefined)
                            {
                                inv_hotSpotData.push({
                                    "pitch": $(this).attr('pitch'),
                                    "yaw": $(this).attr('yaw'),
                                    "type":$(this).attr('type'),
                                    "text": $(this).text(),
                                    "URL": $(this).attr('url')
                                }); 
                            }
                            else
                            {
                                inv_hotSpotData.push({
                                    "pitch": $(this).attr('pitch'),
                                    "yaw": $(this).attr('yaw'),
                                    "type":$(this).attr('type'),
                                    "text": $(this).text()
                                }); 
                            }
                        }
                     });

                     inv_sceneTempData.push({
                        inv_tempScene : {
                            "type": $(this).attr('imgType'),
                            "panorama":$(this).attr('imgPath'),
                            "hotSpots":inv_hotSpotData
                        }    
                     });
                });

console.log(inv_sceneTempData); - this is not having similar structure as the object we pass for .viewer method for scenes attribute and also scene ids - like circle or house can't be there in json object -it is having name like inv_tempScene only...

mpetroff commented 8 years ago

The problem arises from how you create the final object and that you use and array (inv_sceneTempData = [];):

inv_sceneTempData.push({
  inv_tempScene : {
    "type": $(this).attr('imgType'),
    "panorama":$(this).attr('imgPath'),
    "hotSpots":inv_hotSpotData
  }    
});

First, inv_sceneTempData should be an object:

inv_sceneTempData = {};

Since you're using JavaScript object literal notation, inv_tempScene is interpreted as a string, not a variable. You need to use array notation:

inv_sceneTempData[inv_tempScene] = {
  "type": $(this).attr('imgType'),
  "panorama":$(this).attr('imgPath'),
  "hotSpots":inv_hotSpotData
}
video-internal commented 8 years ago

Thank you so much again for quick help. I have implemented code as per your suggestion and it's working fine now.

video-internal commented 8 years ago

@mpetroff: I have images in 1984*1200 resolution. Is it possible to create equirectangular image using those images which can be used in the pannellum? If yes, can you please tell me how to do it?

I have few queries about it:

  1. Is there any restriction in terms of max number of images to create single equirectangular image?
  2. Dimension of each image and dimension of resulting equirectangular image?
  3. Any other requirement of an image?

Thanks in advance.

mpetroff commented 8 years ago
  1. I'm not sure how this is relevant. This would apply to whatever software you're using to stitch the images together, not to Pannellum.
  2. The dimension of each input image again has nothing to do with Pannellum. Pannellum's image size restrictions apply to the equirectangular image and vary from device to device as different devices have different maximum WebGL texture sizes. For maximum compatibility, I would recommend limiting the equirectangular image width to 4096px; for larger images, Pannellum's multires format can be used.
  3. The image needs to be in a format a web browser can load, e.g. JPG. No other specific restrictions come to mind.
video-internal commented 8 years ago

@mpetroff - HI. sorry for late reply. I missed your previous reply. For stitching the images, can you please suggest any software?

mpetroff commented 8 years ago

I'd recommend Hugin.

video-internal commented 8 years ago

@mpetroff -

I will check out Hugin. Thanks for recommendation. But can you answer the following:

  1. For dimension of the image, let's say there are 90 images and each image is having dimension of 1323*800. Will it be possible to create single equirectangular image using those images?

I do have few more queries if you can answer me.

  1. Is it possible to use pannellum by any way in case of IE 10 and IE 9?
  2. Is there any other framework or library which can be used to support 360 degree image panorama in IE 9 and IE 10?
  3. I can see WEB GL limitation in case of IE 9 and IE 10, and that is because of security concerns from MS, is there any other reason of not supporting web GL in those browsers?

Thank you in advance as you have been helping me a lot. Please answer whenever you are free.

video-internal commented 8 years ago

Just to add few things.

I read about iewebgl and jebGL for IE 9 and 10. iewebgl did make some changes so that it can be used with three js. Is there anyway that pannellum can be used IE 9 and 10 along with iewebgl?

Or can you suggest anyother alternative for IE 9 and 10?

video-internal commented 8 years ago

Just to add another thing.

There is a fallback in case of multires image in pannellum , can't pannellum have a fallback in case of equirectangular image as well - like using canvas renderer in place of webgl renderer for IE 9 and 10?

mpetroff commented 8 years ago

I have no interest in supporting awful, outdated Microsoft browsers that Microsoft itself no longer supports. IE 9 and 10 support is never happening.

video-internal commented 8 years ago

@mpetroff - okay, that's completely fine. I was just asking if there is another alternative as I don't want to miss on excellent library like pannellum.

  1. Just asking, there is a fallback in case of multires image in pannellum , can't pannellum have a fallback in case of equirectangular image as well - like using canvas renderer in place of webgl renderer for IE 9 and 10?
  2. For dimension of the image, let's say there are 90 images and each image is having dimension of 1323*800. Will it be possible to create single equirectangular image using those images? - I have tried to learn hugin by creating demo images.

Can you please help me with these 2 questions if possible?

Thank you. :-)

mpetroff commented 8 years ago

This would involve writing an entirely new renderer, a non-trivial undertaking, which would also be extremely slow, possibly to the extent of being unusable. If you want to use something else, there's the fallback parameter, which allows for a URL to a different viewer.

The number of images and image dimensions are irrelevant. If there is sufficient overlap for control points to be found, or you have another way of aligning the images, it should work.