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 18kB gzipped, and then embedded into pages as an <iframe>. A configuration utility is included to generate the required code for embedding.


Pannellum 1.2.1:

Development can be followed on Github.

39 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.

  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.

  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)) {

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>