Simple Web 360 Horizontal Panorama Viewer

...is something I was looking for to embed panoramic images on this blog. Keyword being simple.

People have an odd definition of simple these days; thinking that linking 3 different libraries, full of code which is never used, in multiple languages constitutes a manageable project. After minutes of looking and being redirected to the same site repeatedly, I concluded none exist. So I made one with a combination of css and js.

Background

I literally wanted the images on screen and scrollable. Nothing fantastic, just a lightweight solution that would hopefully be compatible with the major browsers. The easiest solution seemed to be a div with the scrollable pano image as a background. The div handles click/tap events, then objects can be placed in to the div which would overlay the image (but not take input).

Turns out this doesn't work very well on a blog. At all really, which is why I haven't embedded a example. I also loathe all these demo code upload sites and especially convoluted source control tools (cough, Git). That's a rant for another day. My solution needs the full control of a website and I honestly lost interest trying to implement it in this blog. It's definately possible, but requires more effort than it's worth for someone who has only taken 3 pano images over the last 5 years.

Solution

I've split this in to two solutions; single and multiple images. You could use the multiple system with only a single image. I added both to give an idea of how the system fits together. Note: I have not tested this on mobile, the code is a guess.

The example web pages, included in the following downloads, may be loadable directly in a web browser. I've tried on IE11, Firefox and Chrome with no issues. You may need to start a local web server to run them though, depending on browser security.

Single image solution: download example


- single.html
-- single.css
-- single.js
-- image-001.png

The html is rather bare. It obviously has the external links (css, js) then an 'onload' function and a div with a child div. 'onload' is used for adding the event listeners which are needed for interaction. The image is loaded in the css since it's a background. However, being a background means we need to manually set container and scrollable div area sizes. The container requires height and width to be declared, nothing unusual there, but the scrollable area only needs height. They must match or you'll image cut-offs...

single.html
    <div style="width:400px; height:400px;">
        <div class="pano-bg-001"></div>
    </div>

single.css
    .pano-bg-001 {
        width:100%;
        height:400px;

The display width is set in the html and automatically handled in the css. The js handles image scrolling. I wanted a very specific system; drag and continually scroll with speed determined by point of origin. So the further from the initial click point you move, the faster you'll scroll. We add event listeners based on class name as specified at the top of the js, which is 'pano-bg-001' in the supplied files. The 'setInterval' var is for performance and scroll smoothing. The lower it's set the smoother scrolling will be, but it wil use more resources.

Multiple image solution: download example

- multiple.html
-- multiple.css
-- multiple.js
-- image-001.png
-- image-002.png

This is almost identical to the single image system. Each scrolling image will need to have a unique class ('pano-bg-001' and 'pano-bg-002'). It would be more intelligent to change these to ID's, but I already uploaded the files! Whereas the single system hardcodes the single class in to the js, the multiple iterates through an array of these classes and adds listeners to them...

multiple.js
    var a_MappedObjects = [document.getElementsByClassName('pano-bg-001')[0], document.getElementsByClassName('pano-bg-002')[0]];

The '[0]' is to reference the first object of that class returned. Which is why it would make more sense to use 'getElementById', but I'm not doing everything for you!

If we were to simply change the single class reference to an array of classes, the scroll wouldn't work properly. Feel free to try it. The listener would correctly detect the mouse functionality, but all the images would scroll at the same time regardless of which you clicked.

To get around this we detect which image has been clicked in the 'mousedown' listener with...

multiple.js
    o_CurrentlySelected = o_PanoObject;

With 'o_PanoObject' being the div reference such as 'document.getElementsByClassName('pano-bg-001')[0]'. This is then called in the 'mainLoop' function...

multiple.js / function mainLoop()
    o_CurrentlySelected.style.backgroundPosition = i_FinalPos.toString() + "px 0px";

....and now only a single image will scroll at a time.

For image 2, in the multiple example, I added an extra div inside the scrollable container. This is all inline styling to demonstrate how to overlay information. With this we could add in headers, additional text or possibly get some more advanced manual scrolling. It wasn't required for my needs, but with the provided code it shouldn't be much effort to figure out. It doesn't respond to inputs, so users can click through it and still scroll the panoramic.


Wrapping Up

I abandoned this since it doesn't really work in blogs. I don't ever want to deal with maintaining a proper website again, it's too much money and too much effort for something no one visits.


( I'm not a programmer )

Comments