Skip to content

Instantly share code, notes, and snippets.

@pablocortez
Created February 16, 2016 03:28
Show Gist options
  • Save pablocortez/d1aac6cb8eb3f4622e73 to your computer and use it in GitHub Desktop.
Save pablocortez/d1aac6cb8eb3f4622e73 to your computer and use it in GitHub Desktop.
Valentine's Day Project
<div id="screen">
<div id="cube" class='cube'>
<!-- cube images -->
<img id="1" src="https://i.imgur.com/vWWMKYA.jpg" class='face' data-transform="translateZ(-400px)" style="outline:none !important">
<img id="2" src="https://i.imgur.com/hhwWSV7.jpg" class='face' data-transform="rotateY(90deg) translateZ(-400px)">
<img id="3" src="http://i.imgur.com/GS7iJ0T.jpg" class='face' data-transform="rotateY(-90deg) translateZ(-400px)">
<img id="4" src="http://i.imgur.com/6KLlprL.jpg" class='face' data-transform="rotateY(180deg) translateZ(-400px)">
<img id="5" src="http://i.imgur.com/P3pZ0pt.jpg" class='face' data-transform="rotateX(90deg) translateZ(-300px)">
<img id="6" src="http://i.imgur.com/hPPq094.jpg" class='face' data-transform="rotateX(-90deg) translateZ(-300px)">
<!-- bonus image -->
<img id="7" src="http://imgur.com/3Kk3Hus" class='face' data-transform="rotateY(180deg) translateZ(305px)" style="visibility:hidden">
<!-- buttons -->
<img src="http://i.imgur.com/li7CNlI.jpg" class='face button' alt="7" data-transform="translateY(-80px) translateZ(-340px) scale(0.5)">
<img src="http://i.imgur.com/8L2jg9I.jpg" class='face button' alt="2" data-transform="translateX(-200px) translateY(-80px) translateZ(-340px) scale(0.5)">
<img src="http://i.imgur.com/C82AOL8.jpg" class='face button' alt="3" data-transform="translateX(200px) translateY(-80px) translateZ(-340px) scale(0.5)">
<img src="http://i.imgur.com/aRjgKyT.png" class='face button' alt="4" data-transform="translateY(80px) translateZ(-340px) scale(0.5)">
<img src="http://i.imgur.com/rCos44E.jpg" class='face button' alt="5" data-transform="translateX(-200px) translateY(80px) translateZ(-340px) scale(0.5)">
<img src="https://i.imgur.com/g7OsYDp.jpg" class='face button' alt="6" data-transform="translateX(200px) translateY(80px) translateZ(-340px) scale(0.5)">
</div>
</div>
! function ()
{
"use strict";
//
// ===== pointer library =====
//
var screen = {};
(function() {
this.elem = document.getElementById("screen"),
this.width = 0;
this.height = 0;
this.resize = function () {
this.width = +this.elem.offsetWidth;
this.height = +this.elem.offsetHeight;
}
this.elem.onselectstart = function() { return false; }
this.elem.ondragstart = function() { return false; }
window.addEventListener('resize', this.resize.bind(this), false);
this.resize();
this.pointer = {
x: 0,
y: 0,
dx: 0,
dy: 0,
touchMode: false,
center: function (s) {
this.dx *= s;
this.dy *= s;
endX = endY = 0;
}
}
var started = false, startX = 0, startY = 0, endX = 0, endY = 0;
this.addEvent = function (e, fn) {
for (var i = 0, events = e.split(','); i < events.length; i++) {
this.elem.addEventListener(events[i], fn.bind(this.pointer), false );
}
}
this.addEvent("mousemove,touchmove", function (e) {
e.preventDefault();
this.touchMode = e.targetTouches;
var pointer = this.touchMode ? this.touchMode[0] : e;
this.x = pointer.clientX;
this.y = pointer.clientY;
if (started) {
this.dx = endX - (this.x - startX);
this.dy = endY - (this.y - startY);
}
});
this.addEvent("mousedown,touchstart", function (e) {
e.preventDefault();
this.touchMode = e.targetTouches;
var pointer = this.touchMode ? this.touchMode[0] : e;
startX = this.x = pointer.clientX;
startY = this.y = pointer.clientY;
started = true;
setTimeout(function () {
if (!started && Math.abs(startX - this.x) < 11 && Math.abs(startY - this.y) < 11) {
if (this.tap) this.tap(e);
}
}.bind(this), 200);
});
this.addEvent("mouseup,touchend,touchcancel", function (e) {
e.preventDefault();
endX = this.dx;
endY = this.dy;
started = false;
});
}).apply(screen);
var pointer = screen.pointer;
var transform = (typeof document.body.style.webkitTransform != "undefined") ? "-webkit-transform" : "transform";
//
// ===== tweens engine =====
//
var tweens = {};
(function() {
var tweens = [];
var proto = {
normalPI: function () {
if (Math.abs(this.target - this.value) > Math.PI) {
if (this.target < this.value) this.value -= 2 * Math.PI;
else this.value += 2 * Math.PI;
}
},
setTarget: function (target, speedMod) {
this.speedMod = (speedMod) ? speedMod : 1;
this.target = target;
if (this.isAngle) {
this.target = this.target % (2 * Math.PI);
this.normalPI();
}
if (this.running && this.oldTarget === target) return;
this.oldTarget = target;
this.running = true;
this.prog = 0;
this.from = this.value;
this.dist = -(this.target - this.from) * 0.5;
},
ease: function () {
if (!this.running) return;
var s = this.speedMod * this.steps;
if (this.prog++ < s) {
this.value = this.dist * (Math.cos(Math.PI * (this.prog / s)) - 1) + this.from;
if (this.isAngle) this.normalPI();
} else {
this.running = false;
this.value = this.target;
}
}
}
this.add = function (steps, initValue, initValueTarget, isAngle) {
var tween = Object.create(proto);
tween.target = initValueTarget || 0;
tween.value = initValue || 0;
tween.steps = steps;
tween.isAngle = isAngle || false;
tween.speedMod = 1;
tween.setTarget(tween.target);
tweens.push(tween);
return tween;
}
this.iterate = function () {
for (var i = 0, len = tweens.length; i < len; i++) {
tweens[i].ease();
}
}
}).apply(tweens);
//
// ===== css3D engine =====
//
var cube = document.getElementById("cube");
var faces = document.querySelectorAll(".face");
// ---- read computed matrix ----
var getComputedMatrix = function (elem) {
var computedStyle = getComputedStyle(elem, null);
var val = computedStyle.transform || computedStyle.webkitTransform;
return val.split(/\s*[(),]\s*/).slice(1,-1);
}
// ---- initial transformation ----
for (var i = 0, len = faces.length; i < len; i++) {
var face = faces[i];
face.style[transform] = face.getAttribute("data-transform");
}
// ---- target photo ----
pointer.tap = function (e) {
if (e.target.className.indexOf("face") >= 0) {
var t = e.target.alt == "" ? e.target : document.getElementById(e.target.alt);
camera.setTarget(t);
}
}
// ---- set camera -----
var camera = {
globalRX: 0,
globalRY: 0,
z: tweens.add(100, 0, 0),
rx: tweens.add(100, 0, 0, true),
ry: tweens.add(100, 0, 0, true),
targeted: null,
setTarget: function (elem) {
// read transformation matrix
var matrix = getComputedMatrix(elem);
// determine target angles
var rotateY = Math.asin(-matrix[2]);
var rotateX = Math.atan2(+matrix[6], +matrix[10]);
if (rotateY) rotateY -= Math.PI;
if (rotateX) rotateX -= Math.PI;
// set target
if (this.targeted) {
this.targeted.style.outline = "rgba(0,0,0,1) solid 10px";
}
if (this.targeted != elem) {
this.z.setTarget(600);
if (elem.id == "4") {
document.getElementById("7").style.visibility = "hidden";
}
if (elem.id == "7") {
this.z.setTarget(-200);
document.getElementById("7").style.visibility = "visible";
}
elem.style.outline = "rgba(255,255,255,1) solid 10px";
this.targeted = elem;
} else {
this.z.setTarget(0);
if (elem.id == "7") {
camera.setTarget(document.getElementById("1"));
return;
}
this.targeted = null;
}
// set target angles
this.rx.setTarget(rotateX);
this.ry.setTarget(rotateY);
},
move: function () {
tweens.iterate();
if (pointer.touchMode) {
// interaction on touch mobiles
var x = -pointer.dy * 0.001;
var y = pointer.dx * 0.001;
pointer.center(0.98);
} else {
// interaction with mouse
var x = -(pointer.y - screen.height * 0.5) * 0.001;
var y = +(pointer.x - screen.width * 0.5) * 0.001;
}
// ease global angles
this.globalRX += ((x - this.globalRX) * 0.1);
this.globalRY += ((y - this.globalRY) * 0.1);
// cube transformation
cube.style[transform] = "translateZ("+ (this.z.value) + "px) rotateX(" + (this.rx.value + this.globalRX) + "rad) rotateY(" + (this.ry.value + this.globalRY) + "rad)";
}
}
// main loop
var run = function () {
requestAnimationFrame(run);
camera.move();
}
run();
}();
html {
overflow: hidden;
touch-action: none;
content-zooming: none;
}
body {
position: absolute;
margin: 0px;
padding: 0px;
background: #fff;
width: 100%;
height: 100%;
}
#screen {
position: absolute;
left:0;
top:0;
width: 100%;
height: 100%;
background:#000;
perspective:500px;
-webkit-perspective:500px;
}
.cube {
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
margin: 0;
user-select: none;
transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
}
.face {
position: absolute;
margin-left:-300px;
margin-top:-200px;
width:600px;
height:400px;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
transform-origin:50% 50%;
-webkit-transform-origin:50% 50%;
transition: outline 0.5s ease-in-out 0s;
cursor: pointer;
}
.button {
position: absolute;
margin-left:-150px;
margin-top:-100px;
width:300px;
height:200px;
}
.face:hover {
outline: rgba(255,255,255,1) solid 10px !important;
}

Valentine's Day Project

How would you know the difference between the dream world and the real world?

A Pen by Pablo Cortez on CodePen.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment