An update to the original 3D cube (from July 2009 no less), I’ve added touch gesture support (iOS) and click-and-drag behaviour. Animation is incredibly smooth on the iPhone, even the 3G model. Arrow key presses will still rotate the cube, and ESC will reset it.
Experiment: 3D cube with touch gestures and click and drag
One year on and the cube still only works in Safari. Chrome, which says it supports webkit-perspective
and webkit-transform
, still renders differently. Firefox doesn’t support 3D transforms yet.
: Experiment updated for Firefox 10 which supports 3D transforms. Although the perspective appears off, probably due to a perspective-origin bug.
It works relatively simply: on click the start co-ordinates are saved and on drag the difference between current drag position and starting co-ordinates are applied to the cube as a transform, which is completed after the specified transition duration. Many thanks to Remy Sharp and his rubik’s experiment, which got me started with a lot of the basics.
Touch tweaks
Pixel values for touch positions are found in event.originalEvent.touches[0].pageX
, instead of event.pageX
. Using ‘start minus current’ pixel values led the cube to rotate more than intended on the iPhone. To correct, and for intuitive behaviour, the difference is reduced by a factor of four.
JavaScript prevents single touch default events — eg scrolling and text selection, but if it detects more than one touch (event.originalEvent.touches.length
) the cube won’t rotate, so pinch and zoom will still work. This is a compromise.
A 200ms transition duration suits the browser, but on touch devices it felt sluggish, so I’ve upped it to 50ms so the cube is always at your finger-tips.
Better CSS
The cube is created exactly as before, but I’ve simplified the markup a little — dropping the face and number class names in favour of CSS3 selectors:
#cube > div:first-child {
-webkit-transform: rotateX(90deg) translateZ(200px);
-moz-transform: rotateX(90deg) translateZ(200px);
}
#cube > div:nth-child(2) {
-webkit-transform: translateZ(200px);
-moz-transform: translateZ(200px);
}
#cube > div:nth-child(3) {
-webkit-transform: rotateY(90deg) translateZ(200px);
-moz-transform: rotateY(90deg) translateZ(200px);
text-align: center;
}
#cube > div:nth-child(4) {
-webkit-transform: rotateY(180deg) translateZ(200px);
-moz-transform: rotateY(180deg) translateZ(200px);
}
#cube > div:nth-child(5) {
-webkit-transform: rotateY(-90deg) translateZ(200px);
-moz-transform: rotateY(-90deg) translateZ(200px);
}
#cube > div:nth-child(6) {
-webkit-transform: rotateX(-90deg) rotate(180deg) translateZ(200px);
-moz-transform: rotateX(-90deg) rotate(180deg) translateZ(200px);
}
Any questions?
This is quite a speedy write-up, if anything needs explaining I’m happy to go into a bit more detail.