JSFiddle - React, Tailwind, and code Playground
by Michael Prosser
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="debug"></div>
<div class="viewport">
<div class="vrhand">
<div class="palm"></div>
<div class="finger finger-0">
<div class="nuckle-1">
<div class="nuckle-2"></div>
</div>
</div>
<div class="finger finger-1">
<div class="nuckle-1">
<div class="nuckle-2"></div>
</div>
</div>
<div class="finger finger-2">
<div class="nuckle-1">
<div class="nuckle-2"></div>
</div>
</div>
<div class="finger finger-3">
<div class="nuckle-1">
<div class="nuckle-2"></div>
</div>
</div>
<div class="finger finger-4">
<div class="nuckle-1">
<div class="nuckle-2"></div>
</div>
</div>
</div>
</div>
CSS
html{
height:100%;
}
body{
height:100%;
margin:0px;
perspective:500px;
position:relative;
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#7d7e7d+0,0e0e0e+100;Black+3D */
background: #7d7e7d; /* Old browsers */
}
.debug{
position:fixed;
left:0px;
top:0px;
color:#fff;
font-family:helvetica;
padding:8px;
font-size:12px;
}
.viewport{
position:fixed;
top:0px;
left:0px;
right:0px;
bottom:0px;
}
.vrhand{
display:none;
transform-style:preserve-3d;
position:absolute;
left:100px;
top:120px;
width:0px;
height:0px;
transform-origin:10% 10%;
transition:all .1s;
}
.vrhand div{
transform-style:preserve-3d;
position:absolute;
transition: all .5s;
}
.vrhand div:before{
content:"";
display:block;
position:absolute;
width:100%;
height:100%;
background-image:inherit;
background-size:inherit;
background-position:inherit;
background-color:#000;
transform:translateZ(-6px);
border-radius:inherit;
}
.vrhand>.finger-0{
left:-160px;
top:80px;
margin:0px !important;
transform-origin:100% 100%;
transform:rotateX(0deg) rotateY(-30deg) translateX(-20px) translateZ(-5px) rotateZ(-10deg);
border-bottom-right-radius: 0% !important;
border-bottom-left-radius: 90% !important;
}
.vrhand .finger-1{
transform: rotateX(8deg) scaleX(1) scaleY(1) scaleZ(1);
}
.vrhand .finger-2{
transform: rotateX(5deg) scaleX(1.1) scaleY(1.1) scaleZ(1.1);
}
.vrhand .finger-3{
transform: rotateX(10deg) scaleX(1.05) scaleY(1.05) scaleZ(1.05);
}
.vrhand .finger-4{
transform: rotateX(18deg) scaleX(.7) scaleY(.7) scaleZ(.7);
}
.vrhand .finger-0 .nuckle-1{
transform: rotateX(10deg);
}
.vrhand .finger-1 .nuckle-1{
transform: rotateX(13deg);
}
.vrhand .finger-2 .nuckle-1{
transform: rotateX(15deg);
}
.vrhand .finger-3 .nuckle-1{
transform: rotateX(14deg);
}
.vrhand .finger-4 .nuckle-1{
transform: rotateX(10deg);
}
.vrhand>.finger-1{
...
JavaScript
var vrhand = {
x: 0,
y:0,
status: 'off',
side: 'right', // defaults to right hand
hand_pose: 'open',
hand_poses: Array('open', 'close', 'point'),
// selector
hand: $('.vrhand'),
viewport: $('.viewport'),
width: $('.viewport').width(),
height: $('.viewport').height(),
axis_x: 0,
axis_y: 0,
z_offset: 100,
pose: function(handpose){
for(var i=0;i<vrhand.hand_poses;i++){
vrhand.hand.removeClass(vrhand.hand_poses[i]);
}
vrhand.hand.addClass(handpose);
},
toggle: function(){
if(vrhand.status == 'on'){
vrhand.status = 'off';
vrhand.hand.hide();
vrhand.viewport.css('cursor','auto');
} else {
vrhand.status = 'on';
vrhand.hand.show();
vrhand.viewport.css('cursor','none');
}
},
update: function(){
vrhand.axis_x = vrhand.x - (vrhand.width/2);
vrhand.axis_y = vrhand.y - (vrhand.width/2);
$('.debug').text('x:' + vrhand.x + ' y:' + vrhand.y);
var z = ((Math.abs(vrhand.axis_x)/10)-(Math.abs(vrhand.axis_y)/10))+vrhand.z_offset;
if(vrhand.down){
z-=20;
}
if(vrhand.side == 'left'){
var scale = ' scaleX(-1)';
} else {
var scale = '';
}
vrhand.hand.css('transform','translateX(' + vrhand.x + 'px) translateY(' + (vrhand.y) + 'px) translateZ(' + z + 'px) rotateY(' + (vrhand.axis_x/20) + 'deg) rotateX(' + ((vrhand.axis_y/20)*-1) + 'deg)' + scale);
requestAnimationFrame(vrhand.update);
},
init: function(){
vrhand.hand = $('.vrhand');
vrhand.viewport = $('.viewport');
vrhand.width = $('.viewport').width();
vrhand.height = $('.viewport').height();
$(document).mousemove(function(e){
vrhand.x = e.clientX;
vrhand.y = e.clientY;
}).mousedown(function(e){
vrhand.down = true;
vrhand.hand.addClass('close');
...