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 11kB 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.

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

  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.

  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?

    • Matthew Petroff says:

      It’s not just you. I fixed it a few months ago, but the fix hasn’t made it into a release yet.

  32. Thanks says:

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

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=""> <s> <strike> <strong>