Skip to content

Instantly share code, notes, and snippets.

@linmic
Created May 29, 2013 10:05
Show Gist options
  • Save linmic/5669280 to your computer and use it in GitHub Desktop.
Save linmic/5669280 to your computer and use it in GitHub Desktop.
A CodePen by linmic. CSS Panorama Viewer - Since chrome has some weird buggy issues on css 3d transform/transition, I would suggest use safari to enjoy this.
<div id="pano_viewer">
<div id="cube_box">
<div id="cube">
<img class="front" src="http://s.cdpn.io/19243/front.JPG" width="3000" height="3000">
<img class="left" src="http://s.cdpn.io/19243/left.JPG" width="3000" height="3000">
<img class="right" src="http://s.cdpn.io/19243/right.JPG" width="3000" height="3000">
<img class="back" src="http://s.cdpn.io/19243/back.JPG" width="3000" height="3000">
<img class="top" src="http://s.cdpn.io/19243/up.JPG" width="3000" height="3000">
<img class="bottom" src="http://s.cdpn.io/19243/down.JPG" width="3000" height="3000">
</div>
</div>
</div>
<section id="control_panel">
<button id="btn_animation" class="animation">auto</button>
<button class="boundary">disable boundary</button>
</section>
(function() {
var x1,
y1,
moving = false,
$viewer = $('#pano_viewer'),
$cube = $('#cube'),
w_v = $viewer.width(), // width of viewer
h_v = $viewer.height(), // height of viewer
c_x_deg = 0, // current x
c_y_deg = 0,
perspective = 450; // current y
$viewer.on('mousedown', function(e) {
x1 = e.pageX - $(this).offset().left;
y1 = e.pageY - $(this).offset().top;
moving = true;
e.preventDefault();
});
$(document).on('mousemove', function(e) {
if( moving === true ) {
x2 = e.pageX - $viewer.offset().left;
y2 = e.pageY - $viewer.offset().top;
var dist_x = x2 - x1,
dist_y = y2 - y1,
perc_x = dist_x / w_v,
perc_y = dist_y / h_v,
deg_x = Math.atan2(dist_y, perspective) / Math.PI * 180,
deg_y = -Math.atan2(dist_x, perspective) / Math.PI * 180,
i,
vendors = ['-webkit-', '-moz-', ''];
c_x_deg += deg_x;
c_y_deg += deg_y;
c_x_deg = Math.min(90, c_x_deg);
c_x_deg = Math.max(-90, c_x_deg);
c_y_deg %= 360;
deg_x = c_x_deg;
deg_y = c_y_deg;
for(i in vendors) {
$cube.css(vendors[i] + 'transform', 'rotateX(' + deg_x + 'deg) rotateY(' + deg_y + 'deg)');
}
x1 = x2;
y1 = y2;
}
e.preventDefault();
}).on('mouseup', function(e) {
moving = false;
e.preventDefault();
});
$('#control_panel > button').on('click', function() {
$(this).toggleClass('active');
}).parent()
.find('.animation').on('click', function() {
$('#cube').toggleClass('animate');
}).parent()
.find('.boundary').on('click', function() {
$('#pano_viewer').toggleClass('no-boundary');
});
})();
@import "compass";
@import "compass/css3";
$piece_radius: 3000px;
$overlap_offset: 2px;
$z_offset: $piece_radius / 2 - $overlap_offset;
$viewer_width: 700px;
$viewer_height: 400px;
$viewer_perspective: 750px;
// keyframes {{{
@-webkit-keyframes roll {
0% {
-webkit-transform: rotateX(0) rotateY(0);
}
50% {
-webkit-transform: rotateX(0) rotateY(360deg);
}
100% {
-webkit-transform: rotateX(360deg) rotateY(360deg);
}
}
@-moz-keyframes roll {
0% {
-moz-transform: rotateX(0) rotateY(0);
}
50% {
-moz-transform: rotateX(0) rotateY(360deg);
}
100% {
-moz-transform: rotateX(360deg) rotateY(360deg);
}
}
@keyframes roll {
0% {
transform: rotateX(0) rotateY(0);
}
50% {
transform: rotateX(0) rotateY(360deg);
}
100% {
transform: rotateX(360deg) rotateY(360deg);
}
}
@-webkit-keyframes loading {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
}
}
@-moz-keyframes loading {
from {
-moz-transform: rotate(0deg);
}
to {
-moz-transform: rotate(360deg);
}
}
@keyframes loading {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
// }}}
html {
width: 100%;
height: 100%;
}
body {
min-width: $viewer_width + 40px;
font-family: Verdana, Sans-serif;
-webkit-font-smoothing: antialiased;
width: 100%;
height: 100%;
@include background-image(radial-gradient(ellipse, #666, #333 90%));
}
#control_panel {
padding: 10px;
> button {
background: #7FB2F0;
display: inline-block;
color: white;
font: normal 18px/40px Verdana, Sans-serif;
text-align: center;
left: 10px;
top: 10px;
border: none;
padding: 0 20px;
cursor: pointer;
opacity: 0.8;
&:hover,
&.active {
opacity: 1;
}
}
}
#pano_viewer {
position: absolute;
width: $viewer_width;
height: $viewer_height;
left: 50%;
top: 50%;
margin-left: -1 * $viewer_width / 2;
margin-top: -1 * $viewer_height / 2;
cursor: move;
overflow: hidden;
&.no-boundary {
overflow: visible;
}
&.show {
outline: 1px solid #FFBE00;
overflow: visible;
}
&:focus {
cursor: move;
}
}
#cube_box {
@include perspective($viewer_perspective);
@include transform-origin($piece_radius $piece_radius 0);
@include transform-style(preserve-3d);
width: $piece_radius * 2;
height: $piece_radius * 2;
margin-left: ( $viewer_width - $piece_radius * 2 ) / 2;
margin-top: ( $viewer_height - $piece_radius * 2 ) / 2;
}
#cube {
@include transform-style(preserve-3d);
@include transform(rotate3d(0, 0, 0));
cursor: move;
position: relative;
width: $piece_radius * 2;
height: $piece_radius * 2;
&.animate {
-webkit-animation: roll 30s linear infinite;
-moz-animation: roll 30s linear infinite;
animation: roll 30s linear infinite;
}
img {
position: absolute;
opacity: 1;
top: $piece_radius / 2;
left: $piece_radius / 2;
width: $piece_radius;
height: $piece_radius;
@include backface-visibility(hidden);
@include box-shadow(0px 0px 1px transparent);
}
}
img.front {
@include transform(translate3d(0, 0, -$z_offset));
}
img.left {
@include transform(rotate3d(0, 1, 0, 90deg) translate3d(0, 0, -$z_offset));
}
img.right {
@include transform(rotate3d(0, 1, 0, -90deg) translate3d(0, 0, -$z_offset));
}
img.back {
@include transform(rotate3d(0, 1, 0, 180deg) translate3d(0, 0, -$z_offset));
}
// depends on how we make the cut of panorama
img.top {
@include transform(rotateY(0deg) rotateX(-90deg) translate3d(0, 0, -$z_offset));
}
img.bottom {
@include transform(rotate3d(1, 0, 0, 90deg) translate3d(0, 0, -$z_offset));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment