Pannellum is a lightweight, free, and open source panorama viewer for the web. Built using HTML5, CSS3, JavaScript, and WebGL, it is plug-in free. It can be deployed easily as a single file, just 15kB gzipped, and then embedded into pages as an <iframe>. A configuration utility is included to generate the required code for embedding.

For more information, see Development can be followed on GitHub.

202 Responses to Pannellum

  1. Phineas says:

    Firstly, congratulations on some really good work here.

    I have been trying to integrate this on my personal website to display all my PhotoSynth images I’ve taken on my travels, and I have stumbled across a bug.

    When running this app from an iFrame, the fullscreen mode works fine, but when you go back to regular screen, it throws a JS error and does not run the onFullScreenChange() function, so you can’t return back into fullscreen mode after this without reloading the page.

    I believe that the solution to this would be to correctly reference the “fullwindowtoggle_button_active” or “fullwindowtoggle_button” elements from within the iframe parent page. I’m taking a look to see if I can figure out how to do it, but I thought that I would mention it to you, in case you knew of a quick solution.

    If I come up with a fix in the next couple of days, I shall post it here.

    Keep up the good work – Phineas.

  2. ulothix says:

    I just found your post on the Hugin mailing list about this panorama viewer. Really easy to use. Thanks for sharing this great piece of software!

  3. Ken Stroud says:

    Great piece of work! What would it take to make a stereo viewer? Two images that the user can zoom/pan and the second iframe stays in sync.

    • Matthew Petroff says:

      One could probably modify the copy of Pannellum used on the first iframe, and for each of the zoom/pan functions add “window.parent.getElementById(‘second_iframe_id’).contentWindow.function_name(parameters);” to mirror actions on the first panorama on the second (I haven’t tried it). To make it work both ways, one could add the opposite to the second iframe, but one would also have to add a parameter and check to each function to see if it was called by the other iframe to prevent infinite recursion. The other option would be to modify Pannellum to have two canvases, with different images in each.

  4. Xbo says:

    Pannellum seems to work great, but is it possible to make it work with images from ImageShack or Flickr for example? I tried with ImageShack without success!

    • Matthew Petroff says:

      Due to browser security restrictions, using an image from a remote URL requires CORS support. Since neither Flickr nor ImageShack support CORS, using images hosted by them in Pannellum is currently impossible.

  5. Serghei GM says:

    Hi Matthew,
    Really very nice panorama viewer.
    I was trying to get the angles (yaw, pitch) for the specific pixel. Any help would be appreciated.

    • Matthew Petroff says:

      I’m not entirely sure what you’re asking. If you want to know how Pannellum maps image pixels to the screen, see this PDF. If you want to know how an equirectangular images is projected on the image sphere look at this Wikipedia article.

    • Kirby Vandivort says:

      Hi. I was wondering this to. I’ll explain what I’m wanting.

      I am looking for a way to help me create custom JSON files. I want to be able to load an image into Pannellum and have it, via text overlay/debugging/i don’t really care what.., tell me the pitch, roll, and yaw, etc for the center of the screen. As I roll around, zoom in/out etc these numbers would change. Then, I could use those numbers when creating the JSON file to accurately place jump points, and so on.

      Is there a way to do this already that I’m just not aware of? It would be crazy helpful. Right now it is a matter of putting in random numbers and reloading until it gets to where we want it.

      More explanation needed? Just ask.


      • Matthew Petroff says:

        The development version has a hotSpotDebug option that prints the pitch and yaw of the mouse pointer to the console when the mouse button is clicked. I think this is what you’re looking for.

        • Kirby Vandivort says:

          Matthew, I’ve grabbed the dev version and I love it! Only suggestion.. would it be possible to also print out the current hfov? That way we could easily determine the parameters necessary to ‘create’ a given view. Thanks much!

  6. Andreas Enz says:

    Hello Matthew!

    I’m really impressed with your HTML5 Pannellum Viewer. Is there any way to use it when the files (pannellum.htm and theimage.jpg) are stored locally on my machine? I can’t get it to work.


    • Matthew Petroff says:

      This is a result of browser security restrictions. If one has Python installed, one can run “python -m SimpleHTTPServer” from the Pannellum root directory and load the URL printed in the terminal. Otherwise, you need to find some other local web server or disable the security restrictions in your browser.

  7. Ivan says:

    I have a panorama image 10453*1177 24 PP, I use it replace the example directory img file and change the example.htm. Now it does not work. The screen is black. I compare the examplepano.jpg with my panorama file, the difference is the size, which is 5000*2500 24 pp. How to change the code to load my panorama image?
    When i resize my image file to 5000*563 , the panorama image file is loaded and it seemed stretched and have distortion, how to change parameter to fit the panorama image file?

    • Matthew Petroff says:

      Set the “vaov” parameter to the panorama’s vertical angle of view, which in this case appears to be 41 degrees. You can do this by adding “&vaov=41” to the end of the iframe URL. You were right about the size of your image. One ends up with a black screen when one’s image is too big for one’s graphics card/driver.

  8. ivanxu says:

    Can I change parameter to fit the big input image file size? Which parameter should be used to change?
    If I want to achieve the effect like Google street view, let the image see from different distance, i.e from near to far, which parameter should to be adjusted?

  9. hardegg says:

    Hi Matthew,

    So impressive Pannellum is.

    It works well for me so far except for one question. During viewing panorama with mouse grabbing, how can I know the angle I’ve moved with respect to the original pose? To know how much angle I’ve gone along axis y (as defined in your document) is enough for me. Because I hope to show something at some specific angle pose, e.g., there is a person standing at some place I hope to show his name over his head every time this person appears when viewing the panorama.

    • Matthew Petroff says:

      The config.yaw and config.pitch variables (in git master) store the current center of the panorama with regards to the image center. I would recommend looking at the current hotspot code. It currently supports an information icon that will display arbitrary text when hovered over. It shouldn’t be difficult to extend this to display text directly instead of an icon.

      • Mat says:


        Thank you for your work, that’s really a great project !
        I checked out your projet, but I’m unable to use hot spots functionnality.

        Would you be nice enough to give me an example on how to use it ?

        I can’t get what those pitch and yaw values are for. I must say that I’m completelly new to imagery domain.

        • Matthew Petroff says:

          The pitch is the hot spot’s location above the horizon, and the yaw is the hot spot’s angle of displacement from the horizontal center of the panorama. Think of it like latitude and longitude on a globe respectively, except from inside the globe. See this example. Also, make sure you are using the development version (note that the copy in the build folder in Git is last stable release and is not up-to-date).

  10. Alan says:

    Hello Matthew,

    You’ve really done a great job! Here I have a little question on the buttons ‘zoom-in’ and ‘zoom-out’. How could I toggle them between hiding and show, or keep my own buttons on the panorama viewer even if the image has been changed? Thanks very much!

    • Matthew Petroff says:

      For the first part, document.getElementById('zoomcontrols').style.display = 'none'; will hide them, and document.getElementById('zoomcontrols').style.display = 'inline'; will show them again (from within pannellum.htm). For the second question, I’m not really sure what you’re asking.

  11. Adam says:

    Hi Matthew, Google recently released a new version of Chrome, and my panorama is not working anymore with it. I am using the newest one, 1.3, that works with having panorama image on different server than the main files. Any idea why this has happened?

    • Matthew Petroff says:

      I didn’t see anything in the changelog that would have caused it. With a link to the panorama that stopped working, I could try to debug it.

      • Adam says:

        I don’t know if this is any help but, I didn’t do anything with it it just stopped working after last chrome update, it loads the pano and after it finishes just displays black. It still works fine in firefox. Also I have gallery script which in the same time started to play. When clicked on next image it used to fade in next one, there is a black dotted background image for this purpose, I didn’t write the script but again it works in firefox not in chrome, something changed…

  12. Adam says:

    I have installed firebug and when I load panorama, on the script tab of firebug there is “access to restricted URI denied”. I have a portable chrome Version 31.0.1650.57 and everything in there works fine. 100% new version has faults

    • Matthew Petroff says:

      That’s an issue caused by the same-origin policy. I guess something changed in Chrome’s same-origin policy restrictions or CORS support.

      • Adam says:

        Just a recap.
        v31.0.1650.57 – Pannellum and my HTML5 gallery script are working fine and smooth.
        v32.0.1700.76 – Both are not working, script is messed up and pannellum shows black screen. Tried panos on krpano and swf worked fine, webgl ones were very very slow so I’ve updated my gfx drivers to newest ones and it solved performance problem but some glitches remained. Pannellum still didn’t work.
        v33.0.1750.29 beta-m.exe – Pannellum is working but slow, krpano newest version multires on their website works smooth. My script is still not working right. (this version without the driver didn’t work right)

        So basically why do they have to mess up so much…

  13. Daniele says:

    Hi Matthew! The first thing that I want to say is a big thanks for your work, is awesome and compatible with almost every browser (you can add IE 11 in the compatibility list); the second thing is a question, is there a way to start pannellum at a defined coordinates of view? Maybe with the pitch and yaw variables?

  14. Christoph says:

    Hello Matthew,

    i want to view my panorama with your great tool and downloaded it. Now the problem is that the included example.htm says “loading…” but nothing happens. On the other side the panorama on this website works fine with my chrome browser. Do you have any suggestions what could cause the example panorama not to load?

    Thanks a lot and best regards

    • Matthew Petroff says:

      Due to browser security restrictions, JavaScript can’t load files from file URIs. To use Pannellum locally, one needs a local web server. With Python 2, this can be done with python -m SimpleHTTPServer, and with Python 3, this can be done with python -m http.server, but any other local web server can be used as well.

      • Gary Warr says:

        Hi Mathew

        Thank you for this program. I’m sorry to trouble you, but I don’t know what you mean by ‘local server’. I’ve uploaded an sample image and the Pannellum.htm no problem, but nothing shows. I guess because I need to do something about this ‘local server’ thing.
        The servers hosting our website run Python but that’s the limit of my knowledge in that respect. I asked my IT support man and he didn’t know either. Can you explain what I need to do please?

        Many thanks


        • Matthew Petroff says:

          The need for a local server arises from browser security restrictions. Web browsers don’t allow access to `file://` URLs via JavaScript as it would allow a website to read files off of your hard drive. Therefore, Pannellum can only load images over HTTP or HTTPS (`http://` or `https://` URLs). Since serving file over HTTP requires a web server, you need to run a web server on your local machine to be able to load images that are stored on it. I hope this clears up the local server aspect for you.

          You wrote that you uploaded pannellum.htm and an image, which suggests to me that you are using a server. To display the image, you need to access pannellum.htm?panorama=imagename.jpg (if pannellum.htm and the image are in the same directory on the server). I recommend looking at the examples.

          • Gary Warr says:

            Thank you Matthew, but I’m still struggling with this.

            I don’t want to host any images on my machine, I’ve uploaded the test one to our website, the idea is to allow anybody who wants to see them. I have uploaded pannellum.htm and panorama=(imagename).jpg to our server. When I open the page with the iframe I get the pannellum.htm, and clicking just gets ‘loading’. The image is in the same directory, and it’s an http:// address
            Maybe it’s a problem with the image? The images were merged in Photoshop. Does it need to be saved in a special form or shape?
            I’ve been trying to make this work for 3 days straight now, it’s driving me mad!

            Many thanks


          • Matthew Petroff says:

            A problem with the image would result in the panorama being distorted but should not interfere with loading. Does anything print in your browser’s console (Ctrl+Shift+K in Firefox or Ctrl+Shift+C in Chrome)? If you switch to the network tab in your browser’s developer tools (and reload the page), does the correct image URL appear?

  15. Clay Jones says:

    Hi Matthew, I had a couple of quick questions.

    1) Using chrome 34.0.1847.116 m, any time I try to set autorotate=(cw|ccw) the view goes black on load and never recovers. Without it, the image loads fine and scrolls fine.

    2) Is it possible to control the top/bottom fill color if I set a vaov value?

    3) Any possiblility of adding pinch and spread touch control recognition?

    4) Failing touch controls, could the + and – buttons be separated more. It’s tough to touch when they’re so close.

    5) Your documentation talks about just putting pannellum.htm on the website, but I found I had to include the css and js directories and contents as well. Is that correct?

    6) Awesome work on Pannellum. It’s very top notch code.

    • Matthew Petroff says:

      1. The autorotate value needs to be a number. The bigger in magnitude the number, the faster the rotation. Positive is CCW; negative is CW.
      2. One would have to change the WebGL clear color in libpannellum.js.
      3. It’s on the to-do list, but adding CSS 3D support is a higher priority as most mobile devices don’t support WebGL.
      4. See previous.
      5. The documentation refers to a copy of pannellum.htm created using the build script (utils/build/ If using pannellum.htm from the src directory, the rest of that directory’s contents are also needed. Using the former on a website is preferable as it is much smaller.
      6. Thanks!

  16. ulothix says:

    I think there is a bug in the code rendering the hotspot locations in the master in pannellum.js:459:
    if((hs.yaw -90 && z 90 || hs.yaw <= -90 && z <= 0)) {
    but instead it should be
    if((hs.yaw -90 && z 90 || hs.yaw <= -90) && z <= 0)) {
    Mind the added parentheses in the second line of the condition.
    Otherwise hotspot locations with a yaw bigger than 90 never get rendered.

    Apart from that I do really like the new features of the json markup for the tours and the hotspots! Appreciate your effort and work!

    • ulothix says:

      Sorry, the line number was off, and besides the code got a little messed up by the formatting.
      so line 513 in pannellum.js should read (hs.yaw > 90 || hs.yaw <= -90 && z <= 0)) { instead of (hs.yaw > 90 || hs.yaw <= -90 && z <= 0)) {

  17. john says:

    Hi Mathew and thanks for your great work on the Pannellum panorama viewer tool. I have a couple of question about Pannellum.
    First, I would like to ask you if is it possible to load Pannellum without using an iframe. Moreover, is there an API available (I could not find anything relevant in the documentation, but it is worth asking you directly) that I could use in order to get events such as panorama change in tour mode, panorama angle change event and change panorama angle view on the fly etc.

    Thanks in advance, best regards and keep up the good work.

    • Matthew Petroff says:

      At the moment, it only loads using an iframe and doesn’t support any events. I originally wrote it this way to avoid any style or scripting conflicts with the parent page and so something would be displayed when JavaScript is disabled. However, I’m considering moving to JavaScript loading for better integration support as you describe.

  18. Gumir J says:

    Hey Matthew, at first glance, this new panoramic viewer really has great potential!!! When I first saw three.js, there is no doubt knew that someday this script will be adapted for further development.
    Your development is very good at its start-up. BUT it can make a very wonderful one little nuance – is the presence of Inertia of Movement.
    This is an important yet for true browsing of panoramas…
    Happy Programming :)

  19. Xbo says:

    How to make Pannellum work with Google Drive?
    Images address seems to always change! It works only for few hours!?

    • Matthew Petroff says:

      I have no idea what links you’re using. The hosting links from the details panel don’t change.

      • Xbo says:

        When you want to share a file in Google Drive, the “sharing links” display the files in Google Drive.
        So, in Google Drive, I open my pano image with the link at the top right of the page in an external window, with a right clic I can copy the image URL ( etc…). I can display the image in a web browser with this URL, but only for few hours. I have a 403 error with this message : “Your client does not have permission to get URL”
        If I go back in Google Drive, the image URL have changed !!
        What link I have to use to make it work in Pannellum ?

          • Xbo says:

            Thank you so much; it works better like that!

            But now I have another big problem.
            It works locally, but on my web site it doesn’t work at all.
            Is it possible the web server prevents Pannellum working? (PHP and MySQL forbidden)


          • Matthew Petroff says:

            The web server is just serving a static file, pannellum.htm, so the lack of PHP doesn’t affect Pannellum. Do you have either an error message or a link to the broken panorama?

          • Xbo says:

            No error message, perhaps image size, but it works locally.
            Here is a link.

          • Matthew Petroff says:

            Your host is inserting tracking code into pannellum.htm. Besides being a questionable practice to begin with, they’re doing it in a syntactically incorrect manner, which is breaking Pannellum. You need to either find some way to stop your host from doing this, or find somewhere else to host pannellum.htm; one way is to host it using Google Drive, the same way you are hosting your panorama.

          • Matthew Petroff says:

            Also, I would recommend rescaling your image down to 8192px wide, if not 4096px wide, for better support. At its present resolution, less than 30% of people can view it; this goes up to 78% for 8192px wide and 99% for 4096px wide.

          • Xbo says:

            My server is writing some tracking code in my pages since few months now… but It’s free !
            I hosted Pannellum.htm in Google Drive and it works !!
            But there is some problems with IE11.
            – With equirectangular pano, spaces ( ), accents (é) etc… in title parameter don’t work, Pannellum displays some squares.
            – With cubic pano, I have the error message “Your browser does not have the necessary WebGL support to display this panorama” (Works with equi.)

            Works fine with Chrome and Firefox.

  20. jm says:


    on my ipad i can’t see panorama i created (webgl error).

    this page with your panorama is working fine on my ipad, why ? what’s difference ?

    • Matthew Petroff says:

      This page is using a multres panorama, which breaks the image into a large number of small tiles. I suspect you are using a single equirectangular image, which is wider than 4096px, the maximum texture size for iOS devices. The easiest fix would be to scale down the image to 4096px.

  21. ghenz says:

    Hello Matthew! It’s a nice work and really easy to use. I had a couple of questions.
    1. How to make cubic and equirectangular work on Apple products (Safari, iOS), since it doesn’t work WebGL in default settings.
    2. I’m planning build a web interface to add hotspots dynamically with jQuery draggable; how to convert x,y pixels equirectangular coordinate into yaw and pitch?

    • Matthew Petroff says:

      1. Cubic and equirectangular panoramas should work on iOS 8+ but not on previous versions due to their lack of WebGL support.
      2. yaw = (x - width / 2) / width * 180, pitch = (height / 2 - y) / height * 90

      • ghenz says:

        thanks for the fast response it save my day.
        yes its work on IOS 8+. and the pixel to screen formula i modified it a bit and its work well.
        yaw = (((x - width / 2) / width * 180)*2)*-1, pitch = ((height / 2 - y) / height * 90)*2
        I’ve tried generate multires image tools with 3000×1500 image dimension, it generated into 512 tile resolution. its work on almost all device. But I still have some questions, why i cant pinch to zoom in mobile and why hotspot marker not working on IOS when i touch it. do you have any idea?

        • Matthew Petroff says:

          I assume you’re using Pannellum 2.0.1. Pinch to zoom will be in the next release, which will be out soon. As for why the hotspots aren’t working, I don’t know as I don’t have an iOS device to test with.

  22. Xbo says:

    Hi Matthew,
    Could you please describe how to create a multires image.
    With I have the error message:
    “ImportError: no module named PIL”
    (Python 3.4.2, I have a ‘PIL’ folder in ‘site-packages’ folder, I have intalled PILLOW too.)
    Sorry I know nothing about Python, I don’t know how to use !
    Perhaps, there is already a documentation somewhere ?

    • Matthew Petroff says:

      There’s not really any documentation. The script needs Python 3 with Pillow installed. Based on your error, it seems that you don’t have Pillow installed properly; at least Python can’t find it. Try opening an interactive Python session and see what happens when you enter from PIL import Image. If that doesn’t work, there’s an issue with your Pillow install; if it does work, there’s an issue with my script.

      • Xbo says:

        I’ve reinstalled pillow and it seems to work but I have the error:
        “the following arguments are required: -n/–nona”
        I know Nona is part of Hugin. Do I have to install Hugin and how to tell where is nona ?
        I use OpenPano (PanoSalado) for flash panoramas and SaladoConverter is very easy to use !
        Is it possible to create the multires image for Pannellum with SaladoConverter ? It would be wonderful if we could use the same tiles for the two players.

        • Matthew Petroff says:

          It does require nona to be on the path environment variable; I really should add a note about that. I’ve never used PanoSalado or SaladoConverter, but I just looked at them. It seems that their Deep Zoom Cubic format is the same as Pannellum’s multires format; the configuration file just needs to be converted. I need to take a closer look to see exactly how to do that, though.

          • Xbo says:

            It works with SaladoConverter !!
            But we have to create manualy the “fallback” folder and rename zoom level folders (1,2,3 … instead of 8,9,10…)and it will be difficult to use the same tiles with the two players because OpenPano uses a 1px overlap.
            New questions:
            – Is there an option to change the mouse mode ?
            – I open my panos in Greybox and the fullscreen button doesn’t work.

          • Matthew Petroff says:

            From what I looked at, the overlap for SaladoPlayer is specified in its configuration file; however, I don’t know whether or not it actually works with a 0px overlap. I should note that the fallback images have the edge pixels duplicated to avoid visible seams at the cube edges in the CSS 3D renderer.

            For your new questions:
            1. There isn’t an option for changing the mouse mode.
            2. The iframe needs the allowfullscreen attribute; if it’s not working, I assume this is missing.

          • Xbo says:

            I tried with an Android divice with Chrome, pano opens in CSS 3D renderer and there is white stripes at the edges while moving !

            … and the compass is reversed.

          • Matthew Petroff says:

            Unfortunately, I don’t know of any way to prevent the stripes (otherwise I would have fixed it already). As for the compass being reversed, that seems to be a bug I’ve never noticed, and I will look into it.

  23. Xbo says:

    1. :(
    2. The allowfullscreen attribute is here. It works perfectly in a simple web page but when I open this page with Greybox no fullscreen. I never had problems with other players (video, pano…)

    • Matthew Petroff says:

      I might be misunderstanding you, but based on my brief look at the GreyBox documentation, you add a rel tag to a link, and it dynamically creates an iframe when the link is clicked. Are you linking directly to pannellum.htm or another page that has Pannellum embedded? If the latter is the case, both the iframe generated by GreyBox and the Pannellum iframe in the linked page need the allowfullscreen attribute. The easy way to tell if the attribute is missing somewhere is to use the Web Console in Firefox; a warning will be displayed when you click the fullscreen button if the attribute is missing (nothing happens in Chrome’s JavaScript Console).

      • Xbo says:

        You are totally right, the allowfullscreen attribute is missing in GreyBox, now I need to find how to add it in the code !
        Thank you very much.

  24. Xbo says:

    For the compass, I removed - before config.yaw and it seems to work but I don’t know if it creates other problem !

  25. Xbo says:

    northOffset change nothing because compass turns the wrong way ! Is there something I don’t understand in the compass parameters ?

    • Xbo says:

      Your compass on this page turns the wrong way !! (George Peabody Library)

      • Matthew Petroff says:

        Actually, it points the way I intended it to point. The black arrow always points north, just like on a real compass (although the arrow is usually red).

        • Xbo says:

          It’s not the problem ! When you look North, (Black arrow up) you move the pano to see west, (The left side) the compass turns right to show east.
          For me North is UP, South is down, West is left and east is Right ! I think it is the same thing for everybody.

          • Matthew Petroff says:

            I still don’t follow. Looking north (black arrow up) and moving to look to the west, the compass turns clockwise, and the black arrow now points to the right. West is now pointing up.

  26. Xbo says:

    Ok,I understand your point of view, I found easier to read when the arrow shows what you are looking. (You look West, arrow shows West)

  27. Tomas Holusa says:

    Thanks for a great piece of work! Yesterday I decided to replace spherical panoramas on my old webpages (using flash) with something modern. I came across your Pannellum and it worked as a charm! I think there is a tiny error in the JSON doc in vOffset. This should be useful when vaov is non-180 (not nonzero) correct?

  28. Hi Matthew

    For a while I’ve been looking to replace the QuickTime plug in VR scenes on my website with HTML5 code. Pannellum looks to be the perfect tool. I congratulate you on a fantastic job.

    I have done some basic testing with an edited JSON file, and have a single scene running nicely.

    Is it possible to use javascript to read and to control the pan/yaw, tilt/pitch , and zoom independently? I would like to be able to zoom in to a specific point, and then a second point, before loading the next location in the tour (something I managed in QuickTime and give the impression of movement along path)?

    With QuickTime I would use javascript ActalPan=document.QTVR.GetPanAngle() I’m hoping I can use something similar.

    Is it also possible to use javascript to read the Pannellum scene name?

    Many thanks in advance, and best wishes


    • Matthew Petroff says:

      Currently, there isn’t really a good way for external JavaScript to interact with Pannellum; I’m working on a proper JavaScript API, but that isn’t done yet. For the time being, something along the lines of var pano = document.getElementById('pano').contentWindow; var pitch = pano.config.pitch; var yaw = pano.config.yaw; var scene = pano.config.activeScene; will allow you to read values; after changing a value (except activeScene), run pano.animate(); to update the rendering. Essentially, what you describe probably can be done right now without modifying the Pannellum source, but its a bit difficult and should be easier once I finish the API.

      • Hi Matthew.

        I had a play with the script you suggested and it works a treat. Should be able to do everything I wanted to.

        Many thanks


        • Hi Matthew

          Following your advice, I thought you might be interested to see on-going progress with using javascript to pan, tilt, and zoom Pannellum before moving to the next location / panorama. See

          I’m really pleased with the results.

          I am having some difficulty on two separate topics.

          1) Preventing the panorama from being warped when not full 180 hfov, or from not seeing any empty black space when I’ve added height to the panorama to make it equivalent to 180 hfov. I’ve experimented with setting maxPitch, and hoav with and without padding the panorama to full equirectangular image. But I’m unable to get a happy medium.

          2) The site works well on Windows Browsers, on Android devices, but not on my iPhone IOS 8.4. on which the pannellum image is a distorted view of the upper section of the panorama.

          Are you able to offer any guidance as to how I might resolve these problems.

          Many thanks


          • Matthew Petroff says:

            1. You should be able to avoid distortion without having to add empty space to the images using a combination of the haov, vaov, and vOffset parameters. Avoiding display of empty black space is a bit more tricky since this is dependent on both window size and zoom. Currently there are the minPitch, maxPitch, minYaw, and maxYaw parameters that limit where the center of the view can be set to; obviously, if this is set such that the black space is barely cut off at a specific zoom, zooming out will make the black space visible. It might be nice to add in parameters to set the maximum extents of the view instead of the maximum extents of the center, but it would be much trickier to implement than the current center limits.

            2. This appears to be the same issue that is described in issue #77. For some reason, iOS only works properly with progressive encoded JPEGs, and your images have standard JPEG encoding. WebKit doesn’t throw any errors and silently fails to properly display the image instead, making it difficult to write a proper check that can display a helpful error message. I guess I could write a check that sees whether or not the image is progressive and combine that with browser detection.

  29. Johno says:

    Hi Matthew,

    I’ve just started playing around with spherical panos and I found Pannellum. Thanks for the work to get this running. I’m always pleased to be able to use OSS wherever possible.

    It has been a very steep learning curve for me, but (after a couple of hours) I’ve managed to get a pano displaying.

    So my question is about the documentation. Pretty well everything I’ve found so far appears to assume that the reader understands how it all works and it just covers some detail. It would be nice to see a guide on how to getting the whole thing running from scratch. Is there anything like this in the pipeline?

    • Matthew Petroff says:

      It’s something I’ve been meaning to do for a while but haven’t really worked on. I would like to create a getting started tutorial and a much more complete example set that demonstrates how to use Pannellum’s various capabilities.

      • Johno says:

        That would be wonderful. I think better doco would open it up to more people, especially people like me who have no previous experience with this branch of pano photography. There are plenty of tutorials on Hugin for example to get you a nice pano file, but turning that into an interactive display on a website is a bit of a mystery.

  30. Driss says:

    I started working on a simple app that allows to taking measurements from panoramic pictures. I found Pannellum, and it was interesting. I just have a problem with yaw and pitch and I want to know how to make YAW value with 360° because now it shows 180° from right and left.

    • Matthew Petroff says:

      Being a sphere, modular arithmetic is used. Therefore, +180 degrees and -180 degrees in yaw refer to the same location, so the same value is always returned. I’m not really sure what you’re asking.

  31. Johno says:

    Hi Matthew, it appears zoom in with the Shift key is much faster than the zoom out with the Control key. Do you see that too, or is it just my Mac?

  32. Thanks says:

    hi thanks for the good work,
    how can i convert yaw/pitch to xy coordinate (in pixels) of a panorama image?

  33. Pascal says:

    Hi Matthew. i salute you for the great work, keep up!
    i have a question. can we remove the distortion from th sides of the panormaric imges. like free from BI-AS


    • Matthew Petroff says:

      Pannellum uses an ideal pinhole camera model, so there are no “lens” distortions, just a plain rectilinear projection.

      • Pascal says:

        Can I remove the rectilinear projection and show it without distortions?

        • Matthew Petroff says:

          Rectilinear is what is normally considered “distortion free,” as distortion is normally considered to be a deviation from rectilinear projection.

      • Pascal says:

        I mean like equirectangular and not rectilinear

        • Matthew Petroff says:

          If you want to show an equirectangular images, you don’t need a viewer.

          • Pascal says:

            To make my idea clear, I want to extract the yaw and pitch on a 360 degree panoramic picture.
            Using the rectilinear viewer changes the value of yaw and pitch on the corners of the viewer even if it’s the same point.
            Example: point A at center = 180y/45p; when I move the point on the rectilinear view, this values changes continuously with 2 to 3 degrees.
            That’s why I need to use the viewer with 360/90 degree but showing an equirectangular image so the values wont change because of the distortion.

          • Matthew Petroff says:

            If you want an equirectangular projection, just use an equirectangular image, not Pannellum. I’m not sure how I can be any more clear. I’d recommend reading the Wikipedia articles on equirectangular and rectilinear projections. I consider this matter closed and will therefore not approve any more comments on the topic.

  34. Norbert says:


    is there any solution to run multires/ on windows? I have “windowserror: error 5 access denied” on line 94: subprocess.check_call([args.nona, '-o', os.path.join(args.output, 'face'), os.path.join(args.output, 'cubic.pto')]) with windows 8.1 . the output folder with cubic.pto gets generated.


    • Matthew Petroff says:

      I just tried it under Windows 7, and it works fine. Your error message suggests a permissions error, but since the output folder gets created, there must be an issue with nona. The only way I’ve been able to trigger that error message is by specifying a directory for the -n option instead of a full path to nona.exe. I would check to make sure you’re specifying the proper location for nona, e.g. python panorama.jpg -n "C:\Program Files\Hugin\bin\nona.exe".

  35. valerio says:

    Hi matt, hi eb, good job! Can I to put Pannellum on my DigitalOcean server? Is it okay a Linux Ubuntu 14.04 with LAMP or I need so? tks valerio

  36. Derek says:

    Thanks for the tip on…

    1) Removing the empty space from non full equirectangular images.

    Now that I understand that voav and voffset will not automatically hid the empty space from view, I have written short javascript function that dynamically changes the maxPitch according to the formula

    maxPitch = ((vaov+vOffset)/2)-(hfov/2)

    The javascript is in a loop and works nicely.

    2) Using progressive encoded JPEGs so that it Pannellum works on iOS devices. Problem resolved. Excellent.

  37. valerio says:

    Hi Matthew, hi everybody. Can you share examples of JSON files such as “example-cube.json”, “example-tour.json”, “example-video.json” with more configurations inside according JSON Configuration File Options? Thanks.

  38. valerio says:

    It works with my iOS app panorama. Now I try with frame by camera with Hugin or pano2vr; any suggestions or tutorial how get the frames? Thanks.

  39. Rolf Ris says:

    I just want to give Pannellum a try.
    If I understand correctly, I can locate Pannellum on my host-server and my equirect panopictures too.
    Then it is possible to load the pano with a simple URL?

    During searching around about Pannellum I have found this address:

    What do you think? Helpful?

  40. haustein says:

    Hi Matthew,

    Thanks for this tool. My problem is that I have no idea to integrate the hot spots like you have integrated in your example with the “Gallery”.

  41. Jianhua Wang says:

    Dear Matthew,

    I am trying the Pannellum; I like it very much.
    Just now I can browse my panorama page from a web server. But I want to know if I can view the panorama page by browser in local file system directly?
    If can, and how?

    • Matthew Petroff says:

      From the readme:

      Due to browser security restrictions, a web server must be used locally as well. With Python 2, one can use python -m SimpleHTTPServer, and with Python 3, one can use python -m http.server, but any other web server will work as well.

      Essentially, some sort of web server needs to be run locally; it doesn’t need to be anything fancy, so there are a plethora of options that work.

      • Jianhua Wang says:

        Dear Matthew,
        Actually, the way of using a web server is not convenient to my case. I have to browse the panorama page locally without web server.
        So, how I implement this? What part of code I need to care? Can you give some ideals or hints?

        Thank you very much.

        • Matthew Petroff says:

          Browser security restrictions prevent JavaScript from loading files from the local filesystem, which is why a web server is needed. There’s no way around it.

          • Jianhua Wang says:

            I am confusing, that I test other panorama viewer, such as KRPano, it use javascript too, found that the panorama page can be browsed in local file system. How do they work?

          • Matthew Petroff says:

            They don’t work with JavaScript. Only the Flash part of krpano can be used locally.

  42. wjhtinger says:

    What is the difference between the examples of cube and multires?
    If I just configure the “maxLevel” = 1 in example-multires.json, then the multires is equal to cube, right?

    • Matthew Petroff says:

      The effect will be the same, but different rendering code will be used. If you’re not using an image pyramid for the cube faces, you should use the regular cubemap mode. It’s more efficient as it use WebGL’s built in cubemap feature opposed to building the geometry from triangles.

      • wjhtinger says:

        How about the compare between equirectangular(example.htm) and cube(example-cube.htm), which is more efficient? Small size image should use equirectangular and big size image(>4096px) should use cube, is right?

        • Matthew Petroff says:

          There isn’t much of a difference as far as efficiency goes, but you’re right that equirectangular images should be limited to 4096px for better compatibility.

  43. json says:

    What if i want to create a hotspot on click or doubleclick?

  44. Pietro Toniolo says:

    Great work Matthew. Thank you.

    I am going to replace the flash-based panorama viewer on my site with your code. I tried to render some very large jpg files created with Hugin, with sizes like 8Mb, 11720×5860. Chrome 45 renders them correctly, but Firefox 40.0.3 crashes, usually when I try to move the cursor or when I go fullscreen.

    I have verified that with smaller files (like 1024×512) even Firefox renders the panorama correctly without crashing.

    Do you know of any limitations on file sizes or number of pixels affecting Firefox?

    • Matthew Petroff says:

      I’ve never had Firefox crash due to a large file, but crashes of this sort with WebGL tend to be graphics driver dependent (Chrome handles graphics drivers differently than Firefox). Regardless, I would not recommend using equirectangular images that big, as images larger than 8192px are only supported by ~50% of devices, while images larger than 4096px are supported by ~80%, and images smaller than 4096px are supported by virtually all WebGL capable devices. For large images, I would either use cubemaps (limit the cube faces to 4096px), or ideally Pannellum’s multires mode. The cubemap mode is easier to use, but the multires mode supports larger images and reduces load times.

  45. wangjh says:

    How do I generate the cube images? I have tested the and configuration.htm, but only generate multires images and configuration.htm only generate single image codes. Did I miss something?

    • Matthew Petroff says:

      You didn’t miss anything. Nothing in the Pannellum distribution generates cube maps as there are a plethora of existing utilities to choose from as cube maps are a standard format for both the panorama and video game development communities. Personally, I use the erect2cubic script from Panotools::Script.

  46. Do you have an elementary tutorial please?
    Step 1: Import your panorama jpg or bmp
    Step 2: …
    and so on?

    • Matthew Petroff says:

      I don’t having anything like that, sorry.

      • Bruce says:

        How about a wee bit of direction regarding the implementation of the program.
        I’ve unzipped the downloadable file. Now what?
        Do I put it all on a server? or just some files?

        • Matthew Petroff says:

          When using a release build, the only file that needs to be placed on a server is pannellum.htm (and your panorama image). In the simplest case, accessing will display yourimage.jpg in Pannellum assuming it is in the same directory on the server as pannellum.htm.

  47. Stefano says:

    Hi Matthew.
    First, really congratulations and thanks for the fantastic job you have been able to create! It’s very impressive!

    Into the website that I’m developing, I would like to create a preview of every panorama (equirectangular) loaded.
    This for lighten the load of the list of panorama available.
    I would like to automatically create an image of the initial view, can you give me some advice on how to make this using the Pannellum functions?

    Greetings and congratulations again.

    • Matthew Petroff says:

      The preview option allows for specifying a preview image that will be displayed before the panorama is loaded. As for actually creating the preview image, you’re on your own.

  48. tester says:

    Is there a way to stop the user panning 360 degrees? For example, if my panorama image is only 5000 pixels by 1000 pixels, can you limit the viewer to only pan the size of the image and not right up and down?

    appreciate your help

    • Matthew Petroff says:

      I’m assuming your panorama doesn’t extend to the zenith and nadir (giving image dimensions as an example doesn’t tell me much about the angular size). If my assumption is correct, you want to use the minPitch and maxPitch parameters to limit the angles the user can center the panorama at.

  49. Richard says:

    Hi there,
    Thanks for this great project. Actually, in internet explorer 11 and chrome 46, zooming with mouse wheel is a bit confusing and does not work very well. Is there fix available instead of just using the +/- buttons?

    Thanks in advance and good luck for your next work.

  50. valerio says:

    Hi Matthew, what is your server? Ram, transfer? I’m on digital ocean with a LAMP Ubuntu 14.04 on this gear:

    Memory 512 MB
    Processor 1 Core
    Transfer 1 TB

    It’s little for Pannellum?

    I’m thinking to switch to:

    Memory 1 GB
    Processor 1 Core
    Transfer 2 TB

    Thanks bye

  51. Hi Matthew,
    I’m having some trouble running any example that uses a .json config file. The error I get is ‘The file http://pmsdu.test/examples/example-cube.json could not be accessed.’ for the cube example. The file is in the location it is looking in.
    I have no problem running a basic equirectangular panorama locally.
    System is win7 64, using IIS manager for the local server ( and Chrome Version 46.0.2490.86 m.

    I can view everything ok on the web, but I must be missing something basic this end re. the local server.


    • Matthew Petroff says:

      Does anything print in your browser’s console (Ctrl+Shift+K in Firefox or Ctrl+Shift+C in Chrome)? If pannellum.htm is hosted in a different location, there could be a CORS issue.

      • Philip Hortin says:

        Thanks Matthew,

        Theses are the two errors I get from the console:
        GET http://pmsdu.test/examples/example-cube.json 404 (not found) standalone.js:79
        parseURLParameters @standalone.js:79
        (anonymous function) @standalone.js:97

        Uncaught SyntaxError: Unexpected token <
        request.onload @ standalone.js:58

        I uploaded the examples onto my web site and they work fine so no need to go any further, just thought I'd give you the details anyway.
        Thanks for a great program.

        • Matthew Petroff says:

          The browser returned a 404 error for the configuration JSON; I have no idea why that would happen unless the file was not actually there. The rest of the errors are due to a bug with the error handling that I just fixed (unrelated to why things didn’t work).

  52. Hi Matthew,
    I have a couple of hotspots in an basic equirectangular panorama.
    On PC the work great but looking at them on a mobile platform (iPad and Galaxy S4 mini) the hotspots float around over the image as you pan, pitch or zoom. There location on startup is incorrect as well.

    Is this just a WebGL issue, or can I do something to fix it.


  53. FabKzo says:

    Hi Matthew,

    I’m trying – with no success – to display hfov and vfov below my pano title. So far I only get static display with config.hfov, the best would be an adaptative refresh: is there a way to make it?

  54. Hi Matthew, thanks for making a great panorama viewer. Is it currently possible to do any of the following:
    Define a hotspot as static while the panorama rotates.
    Adjust the size of a hotspot.
    Insert my own hotspots.
    Load hotspot targets on top of the panorama, e.g. a graphic file or a video file, which could then be closed.
    Thank you.

  55. Anubhav jain says:

    Hi Matthew,
    How can I create barrel distortion in the panorama viewer?

  56. Hi Matthew,

    I am working on this project from quite long and I am now stuck with Drag n Drop functionality where I can use Drag n Drop to create hot spot to show images upon panorama like the Panorama of whole house where we can create a hot spot to show Kitchen.

    Can you help me prepare this Drag and Drop? Any idea, formula, or indication will be much appreciated.

    I am in urgent need of your help/suggestion.


    • Matthew Petroff says:

      I just added the mouseEventToCoords function to the API. Passing your mouseup event to this function will give you the location’s pitch and yaw, which should give you the information you need to create a hot spot in your JSON configuration file.

      • Christian says:

        I’ve tried to add the ‘mouseup’ event as string to mouseEventToCoords().

        var panm = pannellum.viewer(‘panorama’, json_data);

        I got an error: v is undefined in function ea(a) at this line: d = v.getCanvas();

        I think I forgot something, but I have no idea.

        My pannellum-version is 2.2.1.

        Thanks for help in advanced,

        • Matthew Petroff says:

          The API reference explicitly states that the argument should be a MouseEvent object, not a string.

  57. Mahi says:

    Hi Matthew,

    Great job! I really liked Panellum. It is very useful. I got my things done with the help of this. I am stuck with one thing which I am struggling from two days. I wanted a “Loading…” screen to be shown before the pano is loaded. The pano type is “multires”. I can see it for the cubemap pano but not for multires. Immediately when I click “Click to Load Panorama”, it takes some time to load the pano, which I want to avoid by showing “Loading..” Screen. Please guide me how can I achieve this.


    • Matthew Petroff says:

      It can’t be done. The first level of multires tiles are a few hundred kilobytes, tops, and are often closer to 100kB, or less. As a comparison, the average website these days is over 2MB. Except on a really slow Internet connection, loading a multires panorama should be almost instant. If you want to decrease load times, use a smaller tile size with the multires generation script, say 256 instead of the default of 512. Another option would be to manually resize the images in the 1 directory to make them smaller.

  58. Mad^Angle says:

    Hey Matthew,

    I love your work.

    I’m trying to load Pannellum on mobile with no success;
    if I open your site on mobile, Pannellum works fine.
    Is there any setting recommended for mobile use?

  59. Walter says:

    Thanks for the update and for step-by-step tutorial; Pannellum 2.2.0 is now more intuitive to use.
    In multires mode, is it possible to change the starting view of a tour, only changing the url?


    • Matthew Petroff says:

      Yes. If by “starting view” you mean where the camera is pointing, use the pitch and yaw URL parameters. If you mean which scene, use the firstScene parameter.

  60. Steve Busch says:

    Is it possible to trigger a function that opens up a modal or a pop up when you click on a hot spot?

    • Matthew Petroff says:

      Not at the moment.

    • enapupe says:

      I just did a major ‘quickfix’ for that.. It is something like that:

      $(“.pnlm-render-container”).on(“click”, function(e){
      var parentElement =;
      if(parentElement.tagName.toLowerCase() === ‘a’){
      // do some stuff with parentElement.href to check which hotSpot was clicked..

      Use at your own risk

  61. nitin kandpal says:

    Hi All,

    I am getting a random error. I am initializing the viewer with different panoramas from JS. The renderer sometimes works with the image and sometimes throws a WebGL error. I am using Mozilla browser.

    Please help.

    • Matthew Petroff says:

      If your images are different sizes, some of them are probably too big for your computer. If they’re all the same size, WebGL might be unstable on your computer.

  62. Vedran Vekić says:


    First of all – thank you for a great viewer, really simple, clear and gets the job done!

    I have a question regarding creation of Viewer:
    Is it possible to have many viewers on a page, and only have one of them loaded, and the other ones in the “preview image” state?

    I’m missing some functionality on the viewer for this. Something like .unload() or even .destroy() to eliminate the viewer entirely. Would this be possible?

    • Matthew Petroff says:

      You could set one to auto load and others to not, which would leave them in the preview image state. There’s currently no destructor function or way to unload a panorama, if that’s what you’re asking.

  63. Christian says:

    Hi Matthew,

    I have a question regarding the API. How to use the renderer methods like destroy()?

    My suggestion is to remove a pannellum viewer after updating the json parameterfile from DOM. After that I want to load a new instance of pannellum viewer with new params.

    This is my code to load pannellum viewer:
    url: url,
    data: data
    }).success(function (response) {
    // How to use destroy() method here for existing viewer?
    $.getJSON(response.jsonfile, function (json_data) {
    var panm = pannellum.viewer(‘panorama’, json_data);


  64. Rana Dakota says:

    Hi Matthew,
    Thank you for this awesome work. I was working with and I am getting error -n/-C:\Program Files\Hugin\bin\nona.exe is required on Python console.

    Below is the argument I am giving in my code.
    parser.add_argument(‘-n’ , ‘-C:\\Program Files\\Hugin\\bin\\nona.exe’ , default=’nona’, required=nona is None,
    metavar=’EXECUTABLE’,help=’location of the nona executable to use’)
    Can you please guide me through this.

    • Matthew Petroff says:

      I have no idea what you’re doing; you shouldn’t be modifying the Python code. You need to call from a terminal. This requires that either nona is on your path or it is specified as a terminal argument, e.g. python -n "C:\Program Files\Hugin\bin\nona.exe" pano.jpg.

Leave a Reply

Your email address will not be published. Required fields are marked *