Paver

The following examples are slightly extended implementations of Paver. They rely on configuration options. Some of the exampled presented here may be edge cases, so they are here simply to document the extensibility of Paver.

Enabling meta

Title and description of the panorama can be stored in the title and alt attributes respectively. When you enable meta, by using meta: true or data-meta="true", Paver will inject and overlay metadata over the panorama. The metadata will fade away, by default, when the user interacts with the panorama. However, this effect/interaction can be further customized by the user using CSS.

We crawled out of our beds in the wee hours of the morning, braved the narrow, muddy roads leading into the depths of the tea plantation.

The possibilities of styling the meta overlay is next to infinite. However, here are three presets that you can play around with— and they are included in the plugin.

Custom start position

The panorama below uses the data-start-position="0.25" attribute to override the default setting, and the center point is placed one quarter from the left of the image:

Taking a break from a 38km bicycle ride by the scenic lake in the neighbourhood of Brabrand, Aarhus, Denmark.
At Brabrand Sø Taking a break from a 38km bicycle ride by the scenic lake in the neighbourhood of Brabrand, Aarhus, Denmark.

Destroying a Paver instance

Sometimes you might want to destroy a Paver instance when you see fit. This is possible by:

As the sunny days of summer approaches, I attended the first outdoor yoga session at the local park. We had a blast!
Spring Yoga at Risskov Forest As the sunny days of summer approaches, I attended the first outdoor yoga session at the local park. We had a blast!

The Paver instance above was initialized using the following code:

<div data-paver id="to-destroy">
    <img src="./images/p6.jpg"
         title="Spring Yoga at Risskov Forest"
         alt="As the sunny days of summer approaches, I attended the first outdoor yoga session at the local park. We had a blast!" />
</div>

There are several ways you can call a public function in Paver. Here, we want to call this.destroy(). By taking consideration that web developers have different preferences on how to access public functions, I have created three different ways in Paver to call them:

// Option 1
// Access the plugin_paver data object
$(selector).data('plugin_paver').destroy();

// Option 2
// Pass the name of the public function through the .paver() method
$(selector).paver('destroy');

// Option 3
// Trigger the custom namespaced event, destroy.paver
$(selector).trigger('destroy.paver');

I strongly recommend calling public events on Paver instances after it is ready, i.e. after the ready.paver event is fired. You can do this by listening to the custom namespaced events, and disabling user interactions (if any) until Paver is ready. With the example above, I am using a checkbox to toggle initialization and destruction of Paver:

<div data-paver id="to-toggle">
    <img src="./images/p6.jpg" title="..." alt="..." />
</div>
<form>
    <input type="checkbox" id="paver-toggle" disabled />
    <label for="paver-toggle">Paver Status</label>
</form>
$('#to-toggle').on('ready.paver', function(e) {
	// Change state
	$('#paver-toggle').prop({
		checked: true,
		disabled: false
	});
}).on('destroyed.paver', function(e) {
	// Change state
	$('#paver-toggle').prop({
		checked: false
	});
});

$('#paver-toggle').change(function() {
	if(!$(this).prop('checked')) {
		// Unchecked: destroy paver
		$('#to-toggle').paver('destroy');
	} else {
		// Checked: reinitialize paver
		$('#to-toggle').paver()
	}
});

Custom smoothing functions

Paver also allows you to declare your own smoothing function. Note that when using your custom smoothing function, it has to accept four arguments: deltaX, thresholdX, deltaY, thresholdY. The deltaX and deltaY arguments refer to the absolute change from the center/resting position of the device, in the units of pixels (when listening to mousemove events) or in the units of angle (when listening to deviceorientation events). You may of course rename these arguments into a variable name that you can understand better.

The ratios of deltaX / thresholdX and deltaY / thresholdY will fall in the range of $[-1,1]$. Your custom function should return transformed $x$ and $y$ coordinates that must fall within the range of $[0,1]$, in the format of the object: {x: mappedX; y: mappedY}. For the reasonning behind the need to map from one range to another, and the mathematical basis behind it, please refer to the documentation on smoothing functions.

function(deltaX, thresholdX, deltaY, thresholdY) {
	// Define transformations, and map them to new range
	// Convert deltaX/thresholdX and map it to mappedX
	// Convert deltaY/thresholdY and mpa it to mappedY

    // Return the transformed x and y coordinates
	return {
		x: mappedX,
		y: mappedY
	};
}

An example of a custom function would be a reverse linear function, which does the exact opposite of the default linear transformation function. Instead of specifying one of the four provided smoothing functions as a string, i.e.:

$(selector).paver({
    mouseSmoothingFunction: 'linear',
    tiltSmoothingFunction:  'gaussian'
});

…we pass them as a function (see below). For a bulletproof setup, Paver will fallback to the default smoothing function if the custom smoothing function returns an error.

$(selector).paver({
// Here I use the recommended argument names for x and y axis changes
mouseSmoothingFunction: function(deltaX, thresholdX, deltaY, thresholdY) {
	// Declare x and y
	var x, y;

	// Reverse linear transformation
	if(deltaX >= thresholdX) x = 1;     // Remember to perform sanity checks by yourself
	if(deltaX <= thresholdX) x = 0;     // Remember to perform sanity checks by yourself
	x = 0.5 * (-deltaX/thresholdX + 1); // Map from [-1,1] to [0,1]

	if(deltaY >= thresholdY) y = 1;     // Remember to perform sanity checks by yourself
	if(deltaY <= thresholdY) y = 0;     // Remember to perform sanity checks by yourself
	y = 0.5 * (-deltaY/thresholdY + 1); // Map from [-1,1] to [0,1]

	return {
		x: x,
		y: y
	};
},
// Here I use LR and FB to denote tilting along the x and y axis
tiltSmoothingFunction: function(deltaLR, thresholdLR, deltaFB, thresholdFB) {
	// Left-right and forward-backward
	var lr, fb;

	if(deltaLR >= thresholdLR) lr = 1;     // Remember to perform sanity checks by yourself
	if(deltaLR <= thresholdLR) lr = 0;     // Remember to perform sanity checks by yourself
	lr = 0.5 * (-deltaLR/thresholdLR + 1); // Map from [-1,1] to [0,1]

	if(deltaFB >= thresholdFB) fb = 1;     // Remember to perform sanity checks by yourself
	if(deltaFB <= thresholdFB) fb = 0;     // Remember to perform sanity checks by yourself
	fb = 0.5 * (-deltaFB/thresholdFB + 1); // Map from [-1,1] to [0,1]

	return {
		lr: lr,
		y: fb
	}
});

When listening to deviceorientation, the beta and gamma values are automagically mapped to deltaX and deltaY depending on the device screen orientation, so you don't have to compensate for that.

Petrichor fills the air after the brief spring rain washed down the grime and dirt of the week.
A walk in the univeristy park Petrichor fills the air after the brief spring rain washed down the grime and dirt of the week.