├── .editorconfig
├── .gitignore
├── Gruntfile.js
├── LICENSE
├── README.md
├── code-examples
├── cube-apply-rotation-2.js
├── cube-apply-rotation-options-2.js
├── cube-apply-rotation-options.js
├── cube-apply-rotation.js
├── cube-custom-styles.css
├── cube-focus-on-2.js
├── cube-focus-on-3.js
├── cube-focus-on-4.js
├── cube-focus-on-options.js
├── cube-focus-on.js
├── cube-init.js
├── cube-rotate-2.js
├── cube-rotate-3.js
├── cube-rotate-options.js
├── cube-rotate.js
└── cube.html
├── config.rb
├── cube-js-docco
├── cube.html
├── docco.css
└── public
│ ├── fonts
│ ├── aller-bold.eot
│ ├── aller-bold.ttf
│ ├── aller-bold.woff
│ ├── aller-light.eot
│ ├── aller-light.ttf
│ ├── aller-light.woff
│ ├── novecento-bold.eot
│ ├── novecento-bold.ttf
│ └── novecento-bold.woff
│ └── stylesheets
│ └── normalize.css
├── cube.css
├── cube.js
├── cube.min.js
├── cube.scss
├── docco-css
└── docco.css
├── images
└── cube
│ ├── cube-texture.jpg
│ ├── cube-texture.png
│ ├── cube-texture.psd
│ └── cube-texture.zip
├── index.html
└── package.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = tabs
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Numerous always-ignore extensions
2 | *.diff
3 | *.err
4 | *.orig
5 | *.log
6 | *.rej
7 | *.swo
8 | *.swp
9 | *.vi
10 | *~
11 |
12 | # OS or Editor folders
13 | .DS_Store
14 | ._*
15 | Thumbs.db
16 | .cache
17 | .project
18 | .settings
19 | .tmproj
20 | *.esproj
21 | nbproject
22 | *.sublime-project
23 | *.sublime-workspace
24 | .idea
25 |
26 | # Folders to ignore
27 | node_modules
28 | bower_components
29 |
30 | # Sass related
31 | .sass-cache
32 | .ruby-version
33 | .ruby-gemset
34 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | // Project configuration.
3 | grunt.initConfig({
4 | pkg: grunt.file.readJSON('package.json'),
5 |
6 | sass: {
7 | cube: {
8 | options: {
9 | compass: true,
10 | style: 'expanded'
11 | },
12 |
13 | files: {
14 | 'cube.css': 'cube.scss'
15 | }
16 | },
17 |
18 | page: {
19 | options: {
20 | compass: true,
21 | style: 'compressed'
22 | },
23 |
24 | files: {
25 | 'gh-pages-css/main.css': 'gh-pages-scss/main.scss'
26 | }
27 | }
28 | },
29 |
30 | jshint: {
31 | files: ['cube.js', 'gh-pages-js/generate-nav.js']
32 | },
33 |
34 | uglify: {
35 | cube: {
36 | files: {
37 | 'cube.min.js': 'cube.js'
38 | }
39 | }
40 | },
41 |
42 | docco: {
43 | cube: {
44 | src: ['cube.js'],
45 | options: {
46 | output: 'cube-js-docco',
47 | css: 'docco-css/docco.css'
48 | }
49 | }
50 | },
51 |
52 | watch: {
53 | html: {
54 | files: ['*.html'],
55 | options: { livereload: true }
56 | },
57 |
58 | css: {
59 | files: ['*.css', 'gh-pages-css/main.css'],
60 | options: { livereload: true }
61 | },
62 |
63 | cubeSass: {
64 | files: ['cube.scss'],
65 | tasks: ['sass:cube']
66 | },
67 |
68 | pageSass: {
69 | files: ['gh-pages-scss/main.scss'],
70 | tasks: ['sass:page']
71 | },
72 |
73 | cubeJs: {
74 | files: ['cube.js'],
75 | tasks: ['jshint', 'docco:cube', 'uglify:cube'],
76 | options: { livereload: true }
77 | },
78 |
79 | pagesJs: {
80 | files: ['gh-pages-js/*.js'],
81 | tasks: ['jshint'],
82 | options: { livereload: true }
83 | }
84 | }
85 | });
86 |
87 | // Load the plugin(s).
88 | grunt.loadNpmTasks('grunt-contrib-sass');
89 | grunt.loadNpmTasks('grunt-contrib-watch');
90 | grunt.loadNpmTasks('grunt-contrib-jshint');
91 | grunt.loadNpmTasks('grunt-contrib-uglify');
92 | grunt.loadNpmTasks('grunt-docco');
93 |
94 | // Task(s).
95 | grunt.registerTask('default', ['watch']);
96 | };
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 XHTMLized Pty Ltd.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cube.js
2 |
3 | cube.js is a light script which allows you to add a fancy rotating CSS3 cube to your page!
4 |
5 | Please check the cube's page for more information and examples.
6 |
7 | You can find cube.js documentation here .
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/code-examples/cube-apply-rotation-2.js:
--------------------------------------------------------------------------------
1 | var myCube = Cube('#the-cube2a');
2 |
3 | // Set the cube's postion
4 | myCube.applyRotation({ side: 'side-5' });
--------------------------------------------------------------------------------
/code-examples/cube-apply-rotation-options-2.js:
--------------------------------------------------------------------------------
1 | { side: ['side-1', 'side-2', …, or 'side-6'] }
--------------------------------------------------------------------------------
/code-examples/cube-apply-rotation-options.js:
--------------------------------------------------------------------------------
1 | {
2 | x: [number from 0 to 360],
3 | y: [number from 0 to 360],
4 | z: [number from 0 to 360]
5 | }
--------------------------------------------------------------------------------
/code-examples/cube-apply-rotation.js:
--------------------------------------------------------------------------------
1 | var myCube = Cube('#the-cube2');
2 |
3 | // Set the cube's postion
4 | myCube.applyRotation({
5 | x: 45,
6 | y: 30,
7 | z: 270
8 | });
--------------------------------------------------------------------------------
/code-examples/cube-custom-styles.css:
--------------------------------------------------------------------------------
1 | .the-cube {
2 | margin: 80px auto;
3 | }
4 |
5 | .the-cube > span {
6 | background-image: url(../images/cube/cube-texture.jpg);
7 | }
--------------------------------------------------------------------------------
/code-examples/cube-focus-on-2.js:
--------------------------------------------------------------------------------
1 | var myCube = Cube('#the-cube4a');
2 |
3 | // Cube will spin to the selected side
4 | myCube.focusOn({
5 | spinTo: 'side-5'
6 | });
--------------------------------------------------------------------------------
/code-examples/cube-focus-on-3.js:
--------------------------------------------------------------------------------
1 | var myCube = Cube('#the-cube4b');
2 |
3 | // Cube will spin to the selected side
4 | // and back to the previous position
5 | myCube.focusOn({
6 | bounceBack: true,
7 | spinToX: 33,
8 | spinToY: 88,
9 | spinToZ: 289
10 | });
--------------------------------------------------------------------------------
/code-examples/cube-focus-on-4.js:
--------------------------------------------------------------------------------
1 | var myCube = Cube('#the-cube4c');
2 |
3 | // Start rotating
4 | myCube.rotate({
5 | startSide: 'side-3',
6 | speedX: 0, // 5 seconds to rotate by 360 degrees
7 | speedY: 10000, // 20 seconds to rotate by 360 degrees
8 | speedZ: 10000, // 10 seconds to rotate by 360 degrees
9 | rotateDir: 'left'
10 | });
11 |
12 |
13 | // Cube will spin to the selected side
14 | // and back to the previous position
15 | myCube.focusOn({
16 | bounceBack: true,
17 | spinTo: 'side-1'
18 | });
--------------------------------------------------------------------------------
/code-examples/cube-focus-on-options.js:
--------------------------------------------------------------------------------
1 | {
2 | bounceBack: true,
3 | spinTo: ['side-1', 'side-2', …, or 'side-6'],
4 | spinToX: [number from 0 to 360],
5 | spinToY: [number from 0 to 360],
6 | spinToZ: [number from 0 to 360]
7 | }
--------------------------------------------------------------------------------
/code-examples/cube-focus-on.js:
--------------------------------------------------------------------------------
1 | var myCube = Cube('#the-cube4');
2 |
3 | // Cube will spin to the selected side
4 | // and back to the previous position
5 | myCube.focusOn({
6 | bounceBack: true,
7 | spinTo: 'side-5'
8 | });
--------------------------------------------------------------------------------
/code-examples/cube-init.js:
--------------------------------------------------------------------------------
1 | var myCube = new Cube('#the-cube');
2 |
3 | myCube.rotate({
4 | speedX: 10000,
5 | speedY: 10000,
6 | speedZ: 10000,
7 | startSide: 'side-1'
8 | });
--------------------------------------------------------------------------------
/code-examples/cube-rotate-2.js:
--------------------------------------------------------------------------------
1 | var myCube = Cube('#the-cube3a');
2 |
3 | // Cube will start rotating only on one axis
4 | myCube.rotate({
5 | startSide: 'side-3',
6 | speedX: 0,
7 | speedY: 20000, // 20 seconds to rotate by 360 degrees
8 | speedZ: 0
9 | });
--------------------------------------------------------------------------------
/code-examples/cube-rotate-3.js:
--------------------------------------------------------------------------------
1 | var myCube = Cube('#the-cube3b');
2 |
3 | // Cube will start rotating only on one axis
4 | // to the left
5 | myCube.rotate({
6 | startSide: 'side-3',
7 | speedX: 0,
8 | speedY: 10000, // 10 seconds to rotate by 360 degrees
9 | speedZ: 0,
10 | rotateDir: 'left'
11 | });
--------------------------------------------------------------------------------
/code-examples/cube-rotate-options.js:
--------------------------------------------------------------------------------
1 | {
2 | startSide: ['side-1', 'side-2', 'side-3', 'side-4', 'side-5', 'side-6'],
3 | speedX: [number, time in milliseconds],
4 | speedY: [number, time in milliseconds],
5 | speedZ: [number, time in milliseconds],
6 | rotateDir: ['left' or 'right']
7 | }
--------------------------------------------------------------------------------
/code-examples/cube-rotate.js:
--------------------------------------------------------------------------------
1 | var myCube = Cube('#the-cube3');
2 |
3 | // Cube will start rotating
4 | myCube.rotate({
5 | startSide: 'side-3',
6 | speedX: 5000, // 5 seconds to rotate by 360 degrees
7 | speedY: 20000, // 20 seconds to rotate by 360 degrees
8 | speedZ: 10000 // 10 seconds to rotate by 360 degrees
9 | });
--------------------------------------------------------------------------------
/code-examples/cube.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/config.rb:
--------------------------------------------------------------------------------
1 | # Require any additional compass plugins here.
2 |
3 | # Set this to the root of your project when deployed:
4 | http_path = "/"
5 | css_dir = "css"
6 | sass_dir = "sass"
7 | images_dir = "images"
8 | javascripts_dir = "js"
9 | fonts_dir = "fonts"
10 | preferred_syntax = :scss
11 |
--------------------------------------------------------------------------------
/cube-js-docco/cube.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | cube.js
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
cube.js
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
Allows to manipulate the cube created using CSS and HTML.
31 |
author: Artur Kot (artur.kot@xhtmlized.com)
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | (function () {
40 | 'use strict' ;
41 |
42 | var Test, Cube;
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
53 |
Tests
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
68 |
‘requestAnimationFrame’ test
69 |
Checks if ‘requestAnimationFrame’ is available
70 |
71 | return: boolean Returns true if ‘requestAnimationFrame’ is available.
72 |
73 |
74 |
75 |
76 | animationFrame: function () {
77 | return !!window.requestAnimationFrame;
78 | },
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
89 |
CSS 3d test
90 |
Checks if CSS 3d transforms can be used
91 |
92 | return: boolean Returns true if ‘requestAnimationFrame’ is available.
93 |
94 |
95 |
96 |
97 | css3d: function () {
98 | if (document.querySelector === undefined ) { return false ; }
99 |
100 | var EL_ID = 'temporaryCubeCSS3dElement' ,
101 | STYLE_ID = 'temporaryCubeCSS3dStyle' ,
102 | $body = document.body,
103 | $el,
104 | $style,
105 | docStyles = document.documentElement.style,
106 | prefixes = ['webkit' , 'moz' , 'ms' , '' ],
107 | testResult,
108 | i,
109 | j;
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
120 |
121 | Test for ‘preserve3d’ CSS property.
122 |
123 | return: boolean Returns true if ‘preserve3d’ is available.
124 |
125 |
126 |
127 |
128 |
129 |
130 | function testPreserve3d () {
131 | for (i = 0 , j = prefixes.length; i < j; i += 1 ) {
132 | if (prefixes[i].length > 0 ) {
133 | if (docStyles[prefixes[i] + 'TransformStyle' ] !== undefined ) {
134 | docStyles[prefixes[i] + 'TransformStyle' ] = 'preserve-3d' ;
135 | if (docStyles[prefixes[i] + 'TransformStyle' ].length > 0 ) {
136 | docStyles[prefixes[i] + 'TransformStyle' ] = '' ;
137 | return true ;
138 | }
139 | }
140 | } else {
141 | if (docStyles.transformStyle !== undefined ) {
142 | docStyles.transformStyle = 'preserve-3d' ;
143 | if (docStyles.transformStyle.length > 0 ) {
144 | docStyles.transformStyle = '' ;
145 | return true ;
146 | }
147 | }
148 | }
149 | }
150 |
151 | return false ;
152 | }
153 |
154 | testResult = testPreserve3d();
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
165 |
166 | Note:
167 | This is additional test checking if ‘transform-3d’ is really available .
168 | It may happen that although property itself is available it’s not working properly.
169 | One of possible reasons can be lack of GPU support.
170 | The additional CSS 3d transform test is borrowed from Modernizr
171 |
172 |
173 |
174 |
175 | if (testResult && docStyles.webkitPerspective !== undefined ) {
176 | $style = document.createElement('style' );
177 | $el = document.createElement('div' );
178 |
179 | $style.id = STYLE_ID;
180 | $el.id = EL_ID;
181 |
182 | $body.appendChild($style);
183 | $body.appendChild($el);
184 |
185 | $style.textContent = [
186 | '@media (transform-3d), (-webkit-transform-3d) {' ,
187 | ' #' + EL_ID + '{' ,
188 | ' left: 9px;' ,
189 | ' position: absolute;' ,
190 | ' height: 5px;' ,
191 | ' margin: 0;' ,
192 | ' padding: 0;' ,
193 | ' border: 0' ,
194 | ' }' ,
195 | '}'
196 | ].join('\n' );
197 |
198 | testResult = $el.offsetLeft === 9 && $el.offsetHeight === 5 ;
199 |
200 | $body.removeChild($style);
201 | $body.removeChild($el);
202 | }
203 |
204 | return testResult;
205 | }
206 | };
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
217 |
CSS class
218 |
Adds class at the top of the document.
219 | Useful for applying fallback if Cube cannot be fired.
220 |
221 |
222 |
223 | if (Test.animationFrame() && Test.css3d()) {
224 | document.documentElement.className += ' cube-3d-available' ;
225 | }
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
236 |
Factory function
237 |
Allows to create new Cube instance in the following fashion
238 | (note that ‘new’ is not necessary as it’s added inside
239 | the function below):
240 |
var myCube = Cube('.my .selector' );
241 |
and later use any of the available public classes, e.g.:
242 |
myCube.rotate();
243 |
The function is revealed using window
object.
244 |
245 | parameters:
246 | selector
string Any CSS selector that will work with querySelector .
247 | props
object The cube’s options passed to the constructor.
248 |
249 |
250 | return function or object If the cube can be fired Cube
will return new instance of Cube.instance
constructor else it will return object with empty methods.
251 |
252 |
253 |
254 |
255 | Cube = function (selector, props) {
256 | if (Test.animationFrame() && Test.css3d()) {
257 | return new Cube.instance(selector, props || {});
258 | }
259 |
260 | return {
261 | applyRotation: function () { return false ; },
262 | rotate: function () { return false ; },
263 | focusOn: function () { return false ; },
264 | spinTo: function () { return false ; }
265 | };
266 | };
267 |
268 | window.Cube = Cube;
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
279 |
Constructor
280 |
281 | parameters:
282 | selector
string Any CSS selector that will work with querySelector .
283 | props
object The cube’s options.
284 |
285 |
286 |
287 |
288 |
289 |
290 | Cube.instance = function (selector, props) {
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
301 |
The only option that can be currently passed to the constructor
302 | is perspective .
303 |
304 |
305 |
306 | props.perspective = props.perspective || 1100 ;
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
317 |
Public variables
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
330 |
331 | $cube
object A DOM element which is supposed to be a cube.
332 |
333 |
334 |
335 |
336 | this .$cube = document.querySelector(selector || '#the-cube' );
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
347 |
348 | props
object Options publicly available for methods.
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
364 |
365 | rotatePropsSet
boolean True if rotate properties (posX, posY, posZ, speedX, speedY, speedZ) has been set. See rotate
method below.
366 |
367 |
368 |
369 |
370 | this .rotatePropsSet = false ;
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
381 |
382 | rotateDir
string The cube’s rotation direction. Can be either ‘left’ or ‘right’.
383 |
384 |
385 |
386 |
387 | this .rotateDir = 'right' ;
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
398 |
399 | speed[axis]
number Determines how fast the cube should rotate 360 degrees. Value is in ‘iterations’, not milliseconds.
400 |
401 |
402 |
403 |
404 | this .speedX = 0 ;
405 | this .speedY = 0 ;
406 | this .speedZ = 0 ;
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
417 |
418 | pos[axis]
number The cube’s rotation value from 0 to 360 .
419 |
420 |
421 |
422 |
423 | this .posX = 0 ;
424 | this .posY = 0 ;
425 | this .posZ = 0 ;
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
436 |
437 | snapshot[axis]
number The cube’s rotation value from 0 to 360 . Used to ‘remember’ last values. See ‘focusOn’ method.
438 |
439 |
440 |
441 |
442 | this .snapshotX = 0 ;
443 | this .snapshotY = 0 ;
444 | this .snapshotZ = 0 ;
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
455 |
456 | isRotating
boolean True if cube is being rotated at the moment (rotate method is in use). See rotate
.
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
472 |
473 | isFocusing
boolean True if cube is being focused at the moment (rotates to show selected side). See rotate
, spinTo
, and focusOn
methods.
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
489 |
490 | hasFocused
boolean True if cube has rotated to the selected side. See focusOn
method.
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
506 |
507 | iterators
object Stores iterators for each axis. See spinTo
method.
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
523 |
524 | timers
object Stores timers (requestAnimationFrame).
525 |
526 |
527 |
528 |
529 | this .timers = {};
530 | };
531 |
532 | Cube.instance.prototype = {
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
543 |
544 | xyz
and XYZ
array ‘x’, ‘y’, ‘z’ prefixes.
545 |
546 |
547 |
548 |
549 | xyz: ['x' , 'y' , 'z' ],
550 | XYZ: ['X' , 'Y' , 'Z' ],
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
561 |
562 | sides
object Predefined cube’s sides coordinates.
563 |
564 |
565 |
566 |
567 | sides: {
568 | 'side-1' : [0 , 90 , 0 ],
569 | 'side-2' : [90 , 0 , 0 ],
570 | 'side-3' : [0 , 0 , 0 ],
571 | 'side-4' : [270 , 0 , 0 ],
572 | 'side-5' : [0 , 270 , 0 ],
573 | 'side-6' : [0 , 180 , 0 ]
574 | },
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
585 |
Public Methods
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
598 |
Apply rotation
599 |
Set rotation of the cube.
600 |
601 | parameters: props
object Rotation of each axis in the following format:
602 | {
603 | x: [number from 0 to 360 ],
604 | y: [number from 0 to 360 ],
605 | z: [number from 0 to 360 ]
606 | }
607 |
or predefined side string:
608 | { side: 'side-3' }
609 |
610 |
611 |
Usage examples:
612 |
var myCube = Cube('.my .selector' );
613 |
614 |
615 | myCube.applyRotation({
616 | x: 45 ,
617 | y: 30 ,
618 | z: 270
619 | });
620 |
var myCube = Cube('.my .selector' );
621 |
622 |
623 | myCube.applyRotation({ side: 'side-4' });
624 |
625 |
626 |
627 | applyRotation: function (props) {
628 | var prefix = this ._getPrefix(),
629 | styles = 'perspective(' + this .props.perspective + 'px)' ,
630 | currentDeg,
631 | axes = 0 ;
632 |
633 | props = props || {};
634 |
635 | if (props.x && props.y && props.z) {
636 | while (axes < 3 ) {
637 | currentDeg = props[this .xyz[axes]];
638 | currentDeg = isNaN (currentDeg) ? 0 : currentDeg;
639 |
640 | this ['pos' + this .XYZ[axes]] = currentDeg;
641 |
642 | axes += 1 ;
643 | }
644 | } else if (props.side) {
645 | if (!this .sides[props.side]) { throw 'You\'ve probably entered wrong string as a "side" in "applyRotation". Try "side-1", "side-2", "side-3", "side-4", "side-5", or "side-6"' ; }
646 |
647 | while (axes < 3 ) {
648 | currentDeg = this .sides[props.side][axes];
649 |
650 | this ['pos' + this .XYZ[axes]] = currentDeg;
651 |
652 | axes += 1 ;
653 | }
654 | }
655 |
656 | axes = 0 ;
657 | while (axes < 3 ) {
658 | currentDeg = this ['pos' + this .XYZ[axes]];
659 |
660 | styles += ' rotate' + this .XYZ[axes] + '(' + currentDeg + 'deg)' ;
661 |
662 | axes += 1 ;
663 | }
664 |
665 | this .$cube.style[prefix ? prefix + 'Transform' : 'transform' ] = styles;
666 | },
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
677 |
Rotate
678 |
Start infinite rotation animation.
679 |
694 |
Usage example:
695 |
var myCube = Cube('.my .selector' );
696 |
697 |
698 | myCube.rotate({
699 | startSide: 'side-1' ,
700 | speedX: 5000 ,
701 | speedY: 20000 ,
702 | speedZ: 10000
703 | rotateDir: 'left'
704 | });
705 |
706 |
707 |
708 | rotate: function (props) {
709 | var i = 0 ,
710 | dir = 0 ,
711 | XYZ = this .XYZ,
712 | self = this ,
713 | currentSpeed;
714 |
715 | props = props || {};
716 |
717 | self.rotateDir = props.rotateDir || self.rotateDir;
718 |
719 | self.isRotating = true ;
720 |
721 | if (props.startSide && self.sides[props.startSide] === undefined ) { throw 'You\'ve typed wrong value for "startSide" option.' ; }
722 |
723 | self.isFocusing = false ;
724 |
725 | if (!self.rotatePropsSet) {
726 | while (i < 3 ) {
727 | if (props.startSide) {
728 | props['start' + XYZ[i]] = self.sides[props.startSide][i];
729 | }
730 |
731 | self['pos' + XYZ[i]] = props['start' + XYZ[i]] || 0 ;
732 |
733 | currentSpeed = props['speed' + XYZ[i]];
734 | currentSpeed = currentSpeed === 0 ? 0 : (currentSpeed || 360 );
735 | self['speed' + XYZ[i]] = currentSpeed;
736 | i += 1 ;
737 | }
738 |
739 | self.rotateDir = props.rotateDir || self.rotateDir;
740 |
741 | self.rotatePropsSet = true ;
742 | }
743 |
744 | if (self.rotateDir === 'left' ) { dir = -360 ; }
745 | if (self.rotateDir === 'right' ) { dir = 360 ; }
746 |
747 | self._spinTo({
748 | spinToX: props.startX ? props.startX + dir : dir,
749 | spinToY: props.startY ? props.startY + dir : dir,
750 | spinToZ: props.startZ ? props.startZ + dir : dir,
751 | speedX: self.speedX,
752 | speedY: self.speedY,
753 | speedZ: self.speedZ,
754 | timer: 'rotate' ,
755 | repeat: true ,
756 | easing: 'linear'
757 | });
758 | },
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
769 |
Focus On
770 |
Animate to the specified side of the cube on ‘mouseover’ or ‘touchstart’ event.
771 |
772 | parameters: props
object focusOn options:
773 | bounceBack
boolean If set to true the cube will animate back to its last position (before focusOn animation), else it will stay at the focused position.
774 | spinTo
string Specify to which side should the cube animate to. Note that this option will overwrite spintTo[axis]
.
775 | spinTo[axis]
number Specify to what degree each axis should animate to.
776 |
777 |
778 |
779 |
Usage example:
780 |
var myCube = Cube('.my .selector' );
781 |
782 |
783 |
784 | myCube.focusOn({
785 | bounceBack: true ,
786 | spinTo: 'side-6'
787 | });
788 |
789 |
790 |
791 | focusOn: function (props) {
792 | var self = this ,
793 | isTouch = window.ontouchstart === null ,
794 | startEvent = isTouch ? 'touchstart' : 'mouseover' ;
795 |
796 | props = props || {};
797 |
798 | function focus () {
799 | if (props.bounceBack) {
800 | cancelAnimationFrame(self.timers.deFocus);
801 | }
802 |
803 | if (!self.isFocusing) {
804 | self.snapshotX = self.posX;
805 | self.snapshotY = self.posY;
806 | self.snapshotZ = self.posZ;
807 | }
808 |
809 | if (props.spinTo && self.sides[props.spinTo] === undefined ) { throw 'You\'ve typed wrong value for "spinTo" option.' ; }
810 |
811 | if (props.spinTo && self.sides[props.spinTo] !== undefined ) {
812 | props.spinToX = self.sides[props.spinTo][0 ];
813 | props.spinToY = self.sides[props.spinTo][1 ];
814 | props.spinToZ = self.sides[props.spinTo][2 ];
815 | }
816 |
817 | self._spinTo({
818 | spinToX: props.spinToX || 0 ,
819 | spinToY: props.spinToY || 0 ,
820 | spinToZ: props.spinToZ || 0 ,
821 | speed: props.speed || 2000 ,
822 | timer: 'spinTo' ,
823 | easing: 'out' ,
824 | callback: function () {
825 | self.$cube.className += ' focused' ;
826 | self.hasFocused = true ;
827 | }
828 | });
829 | }
830 |
831 | function deFocus () {
832 | cancelAnimationFrame(self.timers.spinTo);
833 | cancelAnimationFrame(self.timers.rotate);
834 |
835 | self._removeClass(self.$cube, 'focused' );
836 | self.hasFocused = false ;
837 |
838 | if (props.bounceBack) {
839 | self._spinTo({
840 | spinToX: self.snapshotX,
841 | spinToY: self.snapshotY,
842 | spinToZ: self.snapshotZ,
843 | speed: props.speed || 2000 ,
844 | timer: 'deFocus' ,
845 | easing: 'out' ,
846 | callback: function () {
847 | if (self.isRotating) {
848 | self.rotate({
849 | startX: self.posX,
850 | startY: self.posY,
851 | startZ: self.posZ
852 | });
853 | }
854 | }
855 | });
856 | } else if (self.isRotating) {
857 | self.rotate({
858 | startX: self.posX,
859 | startY: self.posY,
860 | startZ: self.posZ
861 | });
862 | }
863 | }
864 |
865 | self.$cube.addEventListener(startEvent, function (e) {
866 | if (self.hasFocused) { return ; }
867 | e.preventDefault();
868 | cancelAnimationFrame(self.timers.rotate);
869 | focus();
870 | });
871 |
872 | self.$cube.addEventListener('mouseout' , deFocus);
873 |
874 | if (isTouch) {
875 | document.addEventListener('touchstart' , function (e) {
876 | var $target = e.target;
877 | if (!self._hasParent($target, self.$cube)) { deFocus(); }
878 | });
879 | }
880 | },
881 |
882 |
883 |
884 |
885 |
886 |
887 |
888 |
891 |
Private Methods
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
904 |
Spin To
905 |
Animate to the specified position.
906 |
907 | parameters: props
object spinTo options:
908 | spinTo[axis]
number Specify to what degree each axis should animate to.
909 | speed
number Time (in milliseconds) that specifies how long it will take to spin to given position. Overwrites speed[axis]
.
910 | speed[axis]
number Time (in milliseconds) that specifies how long it will take to spin to given position for each axis.
911 | timer
string Timer’s ID. It can be reset if needed thus stopping spinTo loop. Timers are attached to public variable called timers
(see in constructor).
912 | easing
string Name of easing function (available functions: ‘ease’, ‘out’, ‘inOut’)
913 | callback
function Function which executes after spinTo is done.
914 |
915 |
916 |
917 |
918 |
919 |
920 | _spinTo: function (props) {
921 | var i = 0 ,
922 | self = this ,
923 | start = {},
924 | speeds = [],
925 | changeInValue = {},
926 | changeInValueA = {},
927 | changeInValueB = {},
928 | dir = {},
929 | done = {},
930 | xyz = self.xyz,
931 | XYZ = self.XYZ,
932 | currentMax,
933 | currentDeg,
934 | currentSpeed,
935 | currentIterator;
936 |
937 | props.speed = self._calculateIterations(props.speed);
938 |
939 | self.isFocusing = props.repeat ? false : true ;
940 |
941 | while (i < 3 ) {
942 | start[xyz[i]] = self['pos' + XYZ[i]];
943 |
944 | if (props['speed' + XYZ[i]]) {
945 | props['speed' + XYZ[i]] = self._calculateIterations(props['speed' + XYZ[i]]);
946 | }
947 |
948 | if (props.repeat) {
949 | changeInValue[xyz[i]] = Math .abs(start[xyz[i]] - props['spinTo' + XYZ[i]]);
950 | } else {
951 | changeInValueA[xyz[i]] = Math .abs(start[xyz[i]] - props['spinTo' + XYZ[i]]);
952 | if (start[xyz[i]] > props['spinTo' + XYZ[i]]) {
953 | changeInValueB[xyz[i]] = Math .abs(start[xyz[i]] - props['spinTo' + XYZ[i]] - 360 );
954 | } else {
955 | changeInValueB[xyz[i]] = Math .abs(start[xyz[i]] - props['spinTo' + XYZ[i]] + 360 );
956 | }
957 |
958 | if (changeInValueA[xyz[i]] < changeInValueB[xyz[i]]) {
959 | changeInValue[xyz[i]] = changeInValueA[xyz[i]];
960 | } else {
961 | if (start[xyz[i]] > props['spinTo' + XYZ[i]]) {
962 | props['spinTo' + XYZ[i]] += 360 ;
963 | } else {
964 | props['spinTo' + XYZ[i]] -= 360 ;
965 | }
966 |
967 | changeInValue[xyz[i]] = changeInValueB[xyz[i]];
968 | }
969 | }
970 |
971 | dir[xyz[i]] = start[xyz[i]] < props['spinTo' + XYZ[i]] ? 'right' : 'left' ;
972 | speeds.push(props.speed ? Math .floor(Math .abs(start[xyz[i]] - props['spinTo' + XYZ[i]]) * props.speed / 360 ) : props['speed' + XYZ[i]]);
973 |
974 | i += 1 ;
975 | }
976 |
977 | speeds.sort(function (a, b) { return b - a; });
978 | this .iterators.spinTo = { x: 0 , y: 0 , z: 0 };
979 | props.easing = props.easing || 'linear' ;
980 |
981 | function run () {
982 | i = 0 ;
983 |
984 | while (i < 3 ) {
985 | currentMax = changeInValue[xyz[i]];
986 | currentSpeed = props.speed ? speeds[0 ] : props['speed' + XYZ[i]];
987 |
988 | if (currentMax !== 0 && currentSpeed !== 0 ) {
989 | currentDeg = self['pos' + XYZ[i]];
990 | currentIterator = self.iterators.spinTo[xyz[i]];
991 |
992 | currentDeg = currentSpeed === 0 ? 0 : self._ease[props.easing](currentIterator, 0 , currentMax, currentSpeed);
993 |
994 | if (dir[xyz[i]] === 'right' ) {
995 | currentDeg += start[xyz[i]];
996 | currentMax += start[xyz[i]];
997 |
998 | if (currentDeg < currentMax) {
999 | currentIterator += 1 ;
1000 | } else {
1001 | currentDeg = currentMax;
1002 | done[xyz[i]] = true ;
1003 | }
1004 | } else {
1005 | currentDeg = start[xyz[i]] - currentDeg;
1006 | currentMax = start[xyz[i]] - currentMax;
1007 |
1008 | if (currentDeg > currentMax) {
1009 | currentIterator += 1 ;
1010 | } else {
1011 | currentDeg = currentMax;
1012 | done[xyz[i]] = true ;
1013 | }
1014 | }
1015 |
1016 | self['pos' + XYZ[i]] = currentDeg;
1017 | self.iterators.spinTo[xyz[i]] = currentIterator;
1018 | } else {
1019 | done[xyz[i]] = true ;
1020 | }
1021 |
1022 | i += 1 ;
1023 | }
1024 |
1025 | self.applyRotation();
1026 |
1027 | i = 0 ;
1028 |
1029 | while (i < 3 ) {
1030 | if (done[xyz[i]] && props.repeat) {
1031 | self['pos' + XYZ[i]] = start[xyz[i]];
1032 | self.iterators.spinTo[xyz[i]] = 0 ;
1033 | done[xyz[i]] = false ;
1034 | }
1035 |
1036 | i += 1 ;
1037 | }
1038 |
1039 | if (done.x && done.y && done.z && !props.repeat) {
1040 | self.isFocusing = false ;
1041 | if (props.callback) { props.callback(); }
1042 | return ;
1043 | }
1044 |
1045 | self.timers[props.timer] = requestAnimationFrame(run);
1046 | }
1047 |
1048 | run();
1049 | },
1050 |
1051 |
1052 |
1053 |
1054 |
1055 |
1056 |
1057 |
1060 |
Easing functions
1061 |
1062 |
1063 |
1064 |
1065 |
1066 |
1067 |
1068 |
1069 |
1070 |
1071 |
1072 |
1075 |
Linear
1076 |
1077 | parameters
(apply for all easing functions below):
1078 | currentIteration
number Current iteration.
1079 | startValue
number Start value. For example: ‘10’.
1080 | changeInValue
number Change in value. For example ‘40’ means that if value started at 10, it would go up to 50.
1081 | totalIterations
number Tells how many iterations should pass until the animation is done.
1082 |
1083 |
1084 |
1085 |
1086 |
1087 |
1088 | linear: function (currentIteration, startValue, changeInValue, totalIterations) {
1089 | return changeInValue * currentIteration / totalIterations + startValue;
1090 | },
1091 |
1092 |
1093 |
1094 |
1095 |
1096 |
1097 |
1098 |
1101 |
Out
1102 |
1103 |
1104 |
1105 | out: function (currentIteration, startValue, changeInValue, totalIterations) {
1106 | currentIteration = currentIteration / totalIterations - 1 ;
1107 | return changeInValue * Math .sqrt(1 - Math .pow(currentIteration, 2 )) + startValue;
1108 | },
1109 |
1110 |
1111 |
1112 |
1113 |
1114 |
1115 |
1116 |
1119 |
In Out
1120 |
1121 |
1122 |
1123 | inOut: function (currentIteration, startValue, changeInValue, totalIterations) {
1124 | return changeInValue / 2 * (1 - Math .cos(Math .PI * currentIteration / totalIterations)) + startValue;
1125 | }
1126 | },
1127 |
1128 |
1129 |
1130 |
1131 |
1132 |
1133 |
1134 |
1137 |
Calculate Iterations
1138 |
Calculates approximate number of iterations.
1139 | Converts milliseconds into number of animation frames for the cube.
1140 | It’s assumed here that requestAnimationFrame
will produce 60 frames per second.
1141 |
1142 | parameters: milliseconds
number Time in milliseconds.
1143 | return: number Returns number of iterations.
1144 |
1145 |
1146 |
1147 |
1148 | _calculateIterations: function (milliseconds) {
1149 | return milliseconds * 60 / 1000 ;
1150 | },
1151 |
1152 |
1153 |
1154 |
1155 |
1156 |
1157 |
1158 |
1161 |
Get Prefix
1162 |
Check if a browser prefix is necessary and, if it is, choose the right one.
1163 | Test is based on transform
property which necessary for the script to work.
1164 |
1165 | return: Numeric Returns number of iterations.
1166 |
1167 |
1168 |
1169 |
1170 | _getPrefix: function () {
1171 | var style = document.documentElement.style,
1172 | prefix;
1173 | if (style.webkitTransform !== undefined ) { prefix = 'webkit' ; }
1174 | if (style.mozTransform !== undefined ) { prefix = 'moz' ; }
1175 | if (style.msTransform !== undefined ) { prefix = 'ms' ; }
1176 | return prefix;
1177 | },
1178 |
1179 |
1180 |
1181 |
1182 |
1183 |
1184 |
1185 |
1188 |
Has Parent
1189 |
Check if one element ($parentEl
) is parent of the second one ($el
)
1190 |
1191 | parameters:
1192 | $el
object DOM element (assumed children).
1193 | $parentEl
object DOM element (assumed parent).
1194 |
1195 |
1196 | return: boolean Returns true if $parentEl
is $el
parent.
1197 |
1198 |
1199 |
1200 |
1201 | _hasParent: function ($el, $parentEl) {
1202 | var $parentNode = $el.parentNode;
1203 |
1204 | while ($parentNode !== $parentEl && $parentNode !== document) {
1205 | $parentNode = $parentNode.parentNode;
1206 | }
1207 |
1208 | return $parentNode === $parentEl ? true : false ;
1209 | },
1210 |
1211 |
1212 |
1213 |
1214 |
1215 |
1216 |
1217 |
1220 |
Remove Class
1221 |
Remove CSS class from an element.
1222 |
1223 | parameters:
1224 | $el
object DOM element
1225 | className
string class’ name, example: ‘my-class’
1226 |
1227 |
1228 |
1229 |
1230 |
1231 |
1232 | _removeClass: function ($el, className) {
1233 | var regex = new RegExp ('\\b' + className + '\\b' , 'g' );
1234 | $el.className = $el.className.replace(regex, '' );
1235 | }
1236 | };
1237 | }());
1238 |
1239 |
1240 |
1241 |
1242 |
1243 |
1244 |
1245 |
--------------------------------------------------------------------------------
/cube-js-docco/docco.css:
--------------------------------------------------------------------------------
1 | /*--------------------- Typography ----------------------------*/
2 |
3 | @font-face {
4 | font-family: 'aller-light';
5 | src: url('public/fonts/aller-light.eot');
6 | src: url('public/fonts/aller-light.eot?#iefix') format('embedded-opentype'),
7 | url('public/fonts/aller-light.woff') format('woff'),
8 | url('public/fonts/aller-light.ttf') format('truetype');
9 | font-weight: normal;
10 | font-style: normal;
11 | }
12 |
13 | @font-face {
14 | font-family: 'aller-bold';
15 | src: url('public/fonts/aller-bold.eot');
16 | src: url('public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'),
17 | url('public/fonts/aller-bold.woff') format('woff'),
18 | url('public/fonts/aller-bold.ttf') format('truetype');
19 | font-weight: normal;
20 | font-style: normal;
21 | }
22 |
23 | @font-face {
24 | font-family: 'novecento-bold';
25 | src: url('public/fonts/novecento-bold.eot');
26 | src: url('public/fonts/novecento-bold.eot?#iefix') format('embedded-opentype'),
27 | url('public/fonts/novecento-bold.woff') format('woff'),
28 | url('public/fonts/novecento-bold.ttf') format('truetype');
29 | font-weight: normal;
30 | font-style: normal;
31 | }
32 |
33 | /*--------------------- Layout ----------------------------*/
34 | html { height: 100%; }
35 | body {
36 | font-family: "aller-light";
37 | font-size: 14px;
38 | line-height: 18px;
39 | color: #30404f;
40 | margin: 0; padding: 0;
41 | height:100%;
42 | }
43 | #container { min-height: 100%; }
44 |
45 | a {
46 | color: #000;
47 | }
48 |
49 | b, strong {
50 | font-weight: normal;
51 | font-family: "aller-bold";
52 | }
53 |
54 | p {
55 | margin: 15px 0 0px;
56 | }
57 | .annotation ul, .annotation ol {
58 | margin: 25px 0;
59 | }
60 | .annotation ul li, .annotation ol li {
61 | font-size: 14px;
62 | line-height: 18px;
63 | margin: 10px 0;
64 | }
65 |
66 | h1, h2, h3, h4, h5, h6 {
67 | color: #112233;
68 | line-height: 1em;
69 | font-weight: normal;
70 | font-family: "novecento-bold";
71 | text-transform: uppercase;
72 | margin: 0 0 15px 0;
73 | }
74 |
75 | h1 {
76 | color: #F04C23;
77 | margin-top: 40px;
78 | }
79 |
80 | hr {
81 | border: 0;
82 | background: 1px #ddd;
83 | height: 1px;
84 | margin: 20px 0;
85 | }
86 |
87 | pre, tt, code {
88 | font-size: 12px; line-height: 16px;
89 | font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
90 | margin: 0; padding: 0;
91 | }
92 | .annotation pre {
93 | display: block;
94 | margin: 0;
95 | padding: 7px 10px;
96 | background: #fcfcfc;
97 | -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
98 | -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
99 | box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
100 | overflow-x: auto;
101 | }
102 | .annotation pre code {
103 | border: 0;
104 | padding: 0;
105 | background: transparent;
106 | }
107 |
108 |
109 | blockquote {
110 | border-left: 5px solid #ccc;
111 | margin: 0;
112 | padding: 1px 0 1px 1em;
113 | }
114 | .sections blockquote p {
115 | font-family: Menlo, Consolas, Monaco, monospace;
116 | font-size: 12px; line-height: 16px;
117 | color: #999;
118 | margin: 10px 0 0;
119 | white-space: pre-wrap;
120 | }
121 |
122 | ul.sections {
123 | list-style: none;
124 | padding:0 0 5px 0;;
125 | margin:0;
126 | }
127 |
128 | /*
129 | Force border-box so that % widths fit the parent
130 | container without overlap because of margin/padding.
131 |
132 | More Info : http://www.quirksmode.org/css/box.html
133 | */
134 | ul.sections > li > div {
135 | -moz-box-sizing: border-box; /* firefox */
136 | -ms-box-sizing: border-box; /* ie */
137 | -webkit-box-sizing: border-box; /* webkit */
138 | -khtml-box-sizing: border-box; /* konqueror */
139 | box-sizing: border-box; /* css3 */
140 | }
141 |
142 |
143 | /*---------------------- Jump Page -----------------------------*/
144 | #jump_to, #jump_page {
145 | margin: 0;
146 | background: white;
147 | -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
148 | -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
149 | font: 16px Arial;
150 | cursor: pointer;
151 | text-align: right;
152 | list-style: none;
153 | }
154 |
155 | #jump_to a {
156 | text-decoration: none;
157 | }
158 |
159 | #jump_to a.large {
160 | display: none;
161 | }
162 | #jump_to a.small {
163 | font-size: 22px;
164 | font-weight: bold;
165 | color: #676767;
166 | }
167 |
168 | #jump_to, #jump_wrapper {
169 | position: fixed;
170 | right: 0; top: 0;
171 | padding: 10px 15px;
172 | margin:0;
173 | }
174 |
175 | #jump_wrapper {
176 | display: none;
177 | padding:0;
178 | }
179 |
180 | #jump_to:hover #jump_wrapper {
181 | display: block;
182 | }
183 |
184 | #jump_page {
185 | padding: 5px 0 3px;
186 | margin: 0 0 25px 25px;
187 | }
188 |
189 | #jump_page .source {
190 | display: block;
191 | padding: 15px;
192 | text-decoration: none;
193 | border-top: 1px solid #eee;
194 | }
195 |
196 | #jump_page .source:hover {
197 | background: #f5f5ff;
198 | }
199 |
200 | #jump_page .source:first-child {
201 | }
202 |
203 | /*---------------------- Low resolutions (> 320px) ---------------------*/
204 | @media only screen and (min-width: 320px) {
205 | .pilwrap { display: none; }
206 |
207 | ul.sections > li > div {
208 | display: block;
209 | padding:5px 10px 0 10px;
210 | }
211 |
212 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol {
213 | padding-left: 30px;
214 | }
215 |
216 | ul.sections > li > div.content {
217 | overflow-x:auto;
218 | -webkit-box-shadow: inset 0 0 5px #e5e5ee;
219 | box-shadow: inset 0 0 5px #e5e5ee;
220 | border: 1px solid #dedede;
221 | margin:5px 10px 5px 10px;
222 | padding-bottom: 5px;
223 | }
224 |
225 | ul.sections > li > div.annotation pre {
226 | margin: 7px 0 7px;
227 | padding-left: 15px;
228 | }
229 |
230 | ul.sections > li > div.annotation p tt, .annotation code {
231 | background: #f8f8ff;
232 | border: 1px solid #dedede;
233 | font-size: 12px;
234 | padding: 0 0.2em;
235 | }
236 | }
237 |
238 | /*---------------------- (> 481px) ---------------------*/
239 | @media only screen and (min-width: 481px) {
240 | #container {
241 | position: relative;
242 | }
243 | body {
244 | background-color: #F5F5FF;
245 | font-size: 15px;
246 | line-height: 21px;
247 | }
248 | pre, tt, code {
249 | line-height: 18px;
250 | }
251 | p, ul, ol {
252 | margin: 0 0 15px;
253 | }
254 |
255 |
256 | #jump_to {
257 | padding: 5px 10px;
258 | }
259 | #jump_wrapper {
260 | padding: 0;
261 | }
262 | #jump_to, #jump_page {
263 | font: 10px Arial;
264 | text-transform: uppercase;
265 | }
266 | #jump_page .source {
267 | padding: 5px 10px;
268 | }
269 | #jump_to a.large {
270 | display: inline-block;
271 | }
272 | #jump_to a.small {
273 | display: none;
274 | }
275 |
276 |
277 |
278 | #background {
279 | position: absolute;
280 | top: 0; bottom: 0;
281 | width: 350px;
282 | background: #fff;
283 | border-right: 1px solid #e5e5ee;
284 | z-index: -1;
285 | }
286 |
287 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol {
288 | padding-left: 40px;
289 | }
290 |
291 | ul.sections > li {
292 | white-space: nowrap;
293 | margin-bottom: 30px;
294 | }
295 |
296 | ul.sections > li > div {
297 | display: inline-block;
298 | }
299 |
300 | ul.sections > li > div.annotation {
301 | max-width: 350px;
302 | min-width: 350px;
303 | min-height: 5px;
304 | padding: 13px;
305 | overflow-x: hidden;
306 | white-space: normal;
307 | vertical-align: top;
308 | text-align: left;
309 | }
310 | ul.sections > li > div.annotation pre {
311 | margin: 15px 0 15px;
312 | padding-left: 15px;
313 | }
314 |
315 | ul.sections > li > div.content {
316 | padding: 13px;
317 | vertical-align: top;
318 | border: none;
319 | -webkit-box-shadow: none;
320 | box-shadow: none;
321 | }
322 |
323 | .pilwrap {
324 | position: relative;
325 | display: inline;
326 | }
327 |
328 | .pilcrow {
329 | font: 12px Arial;
330 | text-decoration: none;
331 | color: #454545;
332 | position: absolute;
333 | top: -2px; left: -20px;
334 | padding: 1px 2px;
335 | opacity: 0;
336 | -webkit-transition: opacity 0.2s linear;
337 | }
338 | .for-h1 .pilcrow {
339 | top: 47px;
340 | }
341 | .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow {
342 | top: 35px;
343 | }
344 |
345 | ul.sections > li > div.annotation:hover .pilcrow {
346 | opacity: 1;
347 | }
348 | }
349 |
350 | /*---------------------- (> 1025px) ---------------------*/
351 | @media only screen and (min-width: 1025px) {
352 |
353 | body {
354 | font-size: 16px;
355 | line-height: 24px;
356 | }
357 |
358 | #background {
359 | width: 525px;
360 | }
361 | ul.sections > li > div.annotation {
362 | max-width: 525px;
363 | min-width: 525px;
364 | padding: 10px 25px 1px 50px;
365 | }
366 | ul.sections > li > div.content {
367 | padding: 9px 15px 16px 25px;
368 | }
369 | }
370 |
371 | /*---------------------- Syntax Highlighting -----------------------------*/
372 |
373 | td.linenos { background-color: #f0f0f0; padding-right: 10px; }
374 | span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
375 | /*
376 |
377 | github.com style (c) Vasily Polovnyov
378 |
379 | */
380 |
381 | pre code {
382 | display: block; padding: 0.5em;
383 | color: #000;
384 | background: #f8f8ff
385 | }
386 |
387 | pre .hljs-comment,
388 | pre .hljs-template_comment,
389 | pre .hljs-diff .hljs-header,
390 | pre .hljs-javadoc {
391 | color: #408080;
392 | font-style: italic
393 | }
394 |
395 | pre .hljs-keyword,
396 | pre .hljs-assignment,
397 | pre .hljs-literal,
398 | pre .hljs-css .hljs-rule .hljs-keyword,
399 | pre .hljs-winutils,
400 | pre .hljs-javascript .hljs-title,
401 | pre .hljs-lisp .hljs-title,
402 | pre .hljs-subst {
403 | color: #954121;
404 | /*font-weight: bold*/
405 | }
406 |
407 | pre .hljs-number,
408 | pre .hljs-hexcolor {
409 | color: #40a070
410 | }
411 |
412 | pre .hljs-string,
413 | pre .hljs-tag .hljs-value,
414 | pre .hljs-phpdoc,
415 | pre .hljs-tex .hljs-formula {
416 | color: #219161;
417 | }
418 |
419 | pre .hljs-title,
420 | pre .hljs-id {
421 | color: #19469D;
422 | }
423 | pre .hljs-params {
424 | color: #00F;
425 | }
426 |
427 | pre .hljs-javascript .hljs-title,
428 | pre .hljs-lisp .hljs-title,
429 | pre .hljs-subst {
430 | font-weight: normal
431 | }
432 |
433 | pre .hljs-class .hljs-title,
434 | pre .hljs-haskell .hljs-label,
435 | pre .hljs-tex .hljs-command {
436 | color: #458;
437 | font-weight: bold
438 | }
439 |
440 | pre .hljs-tag,
441 | pre .hljs-tag .hljs-title,
442 | pre .hljs-rules .hljs-property,
443 | pre .hljs-django .hljs-tag .hljs-keyword {
444 | color: #000080;
445 | font-weight: normal
446 | }
447 |
448 | pre .hljs-attribute,
449 | pre .hljs-variable,
450 | pre .hljs-instancevar,
451 | pre .hljs-lisp .hljs-body {
452 | color: #008080
453 | }
454 |
455 | pre .hljs-regexp {
456 | color: #B68
457 | }
458 |
459 | pre .hljs-class {
460 | color: #458;
461 | font-weight: bold
462 | }
463 |
464 | pre .hljs-symbol,
465 | pre .hljs-ruby .hljs-symbol .hljs-string,
466 | pre .hljs-ruby .hljs-symbol .hljs-keyword,
467 | pre .hljs-ruby .hljs-symbol .hljs-keymethods,
468 | pre .hljs-lisp .hljs-keyword,
469 | pre .hljs-tex .hljs-special,
470 | pre .hljs-input_number {
471 | color: #990073
472 | }
473 |
474 | pre .hljs-builtin,
475 | pre .hljs-constructor,
476 | pre .hljs-built_in,
477 | pre .hljs-lisp .hljs-title {
478 | color: #0086b3
479 | }
480 |
481 | pre .hljs-preprocessor,
482 | pre .hljs-pi,
483 | pre .hljs-doctype,
484 | pre .hljs-shebang,
485 | pre .hljs-cdata {
486 | color: #999;
487 | font-weight: bold
488 | }
489 |
490 | pre .hljs-deletion {
491 | background: #fdd
492 | }
493 |
494 | pre .hljs-addition {
495 | background: #dfd
496 | }
497 |
498 | pre .hljs-diff .hljs-change {
499 | background: #0086b3
500 | }
501 |
502 | pre .hljs-chunk {
503 | color: #aaa
504 | }
505 |
506 | pre .hljs-tex .hljs-formula {
507 | opacity: 0.5;
508 | }
509 |
--------------------------------------------------------------------------------
/cube-js-docco/public/fonts/aller-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-bold.eot
--------------------------------------------------------------------------------
/cube-js-docco/public/fonts/aller-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-bold.ttf
--------------------------------------------------------------------------------
/cube-js-docco/public/fonts/aller-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-bold.woff
--------------------------------------------------------------------------------
/cube-js-docco/public/fonts/aller-light.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-light.eot
--------------------------------------------------------------------------------
/cube-js-docco/public/fonts/aller-light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-light.ttf
--------------------------------------------------------------------------------
/cube-js-docco/public/fonts/aller-light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/aller-light.woff
--------------------------------------------------------------------------------
/cube-js-docco/public/fonts/novecento-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/novecento-bold.eot
--------------------------------------------------------------------------------
/cube-js-docco/public/fonts/novecento-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/novecento-bold.ttf
--------------------------------------------------------------------------------
/cube-js-docco/public/fonts/novecento-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/cube-js-docco/public/fonts/novecento-bold.woff
--------------------------------------------------------------------------------
/cube-js-docco/public/stylesheets/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v2.0.1 | MIT License | git.io/normalize */
2 |
3 | /* ==========================================================================
4 | HTML5 display definitions
5 | ========================================================================== */
6 |
7 | /*
8 | * Corrects `block` display not defined in IE 8/9.
9 | */
10 |
11 | article,
12 | aside,
13 | details,
14 | figcaption,
15 | figure,
16 | footer,
17 | header,
18 | hgroup,
19 | nav,
20 | section,
21 | summary {
22 | display: block;
23 | }
24 |
25 | /*
26 | * Corrects `inline-block` display not defined in IE 8/9.
27 | */
28 |
29 | audio,
30 | canvas,
31 | video {
32 | display: inline-block;
33 | }
34 |
35 | /*
36 | * Prevents modern browsers from displaying `audio` without controls.
37 | * Remove excess height in iOS 5 devices.
38 | */
39 |
40 | audio:not([controls]) {
41 | display: none;
42 | height: 0;
43 | }
44 |
45 | /*
46 | * Addresses styling for `hidden` attribute not present in IE 8/9.
47 | */
48 |
49 | [hidden] {
50 | display: none;
51 | }
52 |
53 | /* ==========================================================================
54 | Base
55 | ========================================================================== */
56 |
57 | /*
58 | * 1. Sets default font family to sans-serif.
59 | * 2. Prevents iOS text size adjust after orientation change, without disabling
60 | * user zoom.
61 | */
62 |
63 | html {
64 | font-family: sans-serif; /* 1 */
65 | -webkit-text-size-adjust: 100%; /* 2 */
66 | -ms-text-size-adjust: 100%; /* 2 */
67 | }
68 |
69 | /*
70 | * Removes default margin.
71 | */
72 |
73 | body {
74 | margin: 0;
75 | }
76 |
77 | /* ==========================================================================
78 | Links
79 | ========================================================================== */
80 |
81 | /*
82 | * Addresses `outline` inconsistency between Chrome and other browsers.
83 | */
84 |
85 | a:focus {
86 | outline: thin dotted;
87 | }
88 |
89 | /*
90 | * Improves readability when focused and also mouse hovered in all browsers.
91 | */
92 |
93 | a:active,
94 | a:hover {
95 | outline: 0;
96 | }
97 |
98 | /* ==========================================================================
99 | Typography
100 | ========================================================================== */
101 |
102 | /*
103 | * Addresses `h1` font sizes within `section` and `article` in Firefox 4+,
104 | * Safari 5, and Chrome.
105 | */
106 |
107 | h1 {
108 | font-size: 2em;
109 | }
110 |
111 | /*
112 | * Addresses styling not present in IE 8/9, Safari 5, and Chrome.
113 | */
114 |
115 | abbr[title] {
116 | border-bottom: 1px dotted;
117 | }
118 |
119 | /*
120 | * Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
121 | */
122 |
123 | b,
124 | strong {
125 | font-weight: bold;
126 | }
127 |
128 | /*
129 | * Addresses styling not present in Safari 5 and Chrome.
130 | */
131 |
132 | dfn {
133 | font-style: italic;
134 | }
135 |
136 | /*
137 | * Addresses styling not present in IE 8/9.
138 | */
139 |
140 | mark {
141 | background: #ff0;
142 | color: #000;
143 | }
144 |
145 |
146 | /*
147 | * Corrects font family set oddly in Safari 5 and Chrome.
148 | */
149 |
150 | code,
151 | kbd,
152 | pre,
153 | samp {
154 | font-family: monospace, serif;
155 | font-size: 1em;
156 | }
157 |
158 | /*
159 | * Improves readability of pre-formatted text in all browsers.
160 | */
161 |
162 | pre {
163 | white-space: pre;
164 | white-space: pre-wrap;
165 | word-wrap: break-word;
166 | }
167 |
168 | /*
169 | * Sets consistent quote types.
170 | */
171 |
172 | q {
173 | quotes: "\201C" "\201D" "\2018" "\2019";
174 | }
175 |
176 | /*
177 | * Addresses inconsistent and variable font size in all browsers.
178 | */
179 |
180 | small {
181 | font-size: 80%;
182 | }
183 |
184 | /*
185 | * Prevents `sub` and `sup` affecting `line-height` in all browsers.
186 | */
187 |
188 | sub,
189 | sup {
190 | font-size: 75%;
191 | line-height: 0;
192 | position: relative;
193 | vertical-align: baseline;
194 | }
195 |
196 | sup {
197 | top: -0.5em;
198 | }
199 |
200 | sub {
201 | bottom: -0.25em;
202 | }
203 |
204 | /* ==========================================================================
205 | Embedded content
206 | ========================================================================== */
207 |
208 | /*
209 | * Removes border when inside `a` element in IE 8/9.
210 | */
211 |
212 | img {
213 | border: 0;
214 | }
215 |
216 | /*
217 | * Corrects overflow displayed oddly in IE 9.
218 | */
219 |
220 | svg:not(:root) {
221 | overflow: hidden;
222 | }
223 |
224 | /* ==========================================================================
225 | Figures
226 | ========================================================================== */
227 |
228 | /*
229 | * Addresses margin not present in IE 8/9 and Safari 5.
230 | */
231 |
232 | figure {
233 | margin: 0;
234 | }
235 |
236 | /* ==========================================================================
237 | Forms
238 | ========================================================================== */
239 |
240 | /*
241 | * Define consistent border, margin, and padding.
242 | */
243 |
244 | fieldset {
245 | border: 1px solid #c0c0c0;
246 | margin: 0 2px;
247 | padding: 0.35em 0.625em 0.75em;
248 | }
249 |
250 | /*
251 | * 1. Corrects color not being inherited in IE 8/9.
252 | * 2. Remove padding so people aren't caught out if they zero out fieldsets.
253 | */
254 |
255 | legend {
256 | border: 0; /* 1 */
257 | padding: 0; /* 2 */
258 | }
259 |
260 | /*
261 | * 1. Corrects font family not being inherited in all browsers.
262 | * 2. Corrects font size not being inherited in all browsers.
263 | * 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome
264 | */
265 |
266 | button,
267 | input,
268 | select,
269 | textarea {
270 | font-family: inherit; /* 1 */
271 | font-size: 100%; /* 2 */
272 | margin: 0; /* 3 */
273 | }
274 |
275 | /*
276 | * Addresses Firefox 4+ setting `line-height` on `input` using `!important` in
277 | * the UA stylesheet.
278 | */
279 |
280 | button,
281 | input {
282 | line-height: normal;
283 | }
284 |
285 | /*
286 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
287 | * and `video` controls.
288 | * 2. Corrects inability to style clickable `input` types in iOS.
289 | * 3. Improves usability and consistency of cursor style between image-type
290 | * `input` and others.
291 | */
292 |
293 | button,
294 | html input[type="button"], /* 1 */
295 | input[type="reset"],
296 | input[type="submit"] {
297 | -webkit-appearance: button; /* 2 */
298 | cursor: pointer; /* 3 */
299 | }
300 |
301 | /*
302 | * Re-set default cursor for disabled elements.
303 | */
304 |
305 | button[disabled],
306 | input[disabled] {
307 | cursor: default;
308 | }
309 |
310 | /*
311 | * 1. Addresses box sizing set to `content-box` in IE 8/9.
312 | * 2. Removes excess padding in IE 8/9.
313 | */
314 |
315 | input[type="checkbox"],
316 | input[type="radio"] {
317 | box-sizing: border-box; /* 1 */
318 | padding: 0; /* 2 */
319 | }
320 |
321 | /*
322 | * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome.
323 | * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome
324 | * (include `-moz` to future-proof).
325 | */
326 |
327 | input[type="search"] {
328 | -webkit-appearance: textfield; /* 1 */
329 | -moz-box-sizing: content-box;
330 | -webkit-box-sizing: content-box; /* 2 */
331 | box-sizing: content-box;
332 | }
333 |
334 | /*
335 | * Removes inner padding and search cancel button in Safari 5 and Chrome
336 | * on OS X.
337 | */
338 |
339 | input[type="search"]::-webkit-search-cancel-button,
340 | input[type="search"]::-webkit-search-decoration {
341 | -webkit-appearance: none;
342 | }
343 |
344 | /*
345 | * Removes inner padding and border in Firefox 4+.
346 | */
347 |
348 | button::-moz-focus-inner,
349 | input::-moz-focus-inner {
350 | border: 0;
351 | padding: 0;
352 | }
353 |
354 | /*
355 | * 1. Removes default vertical scrollbar in IE 8/9.
356 | * 2. Improves readability and alignment in all browsers.
357 | */
358 |
359 | textarea {
360 | overflow: auto; /* 1 */
361 | vertical-align: top; /* 2 */
362 | }
363 |
364 | /* ==========================================================================
365 | Tables
366 | ========================================================================== */
367 |
368 | /*
369 | * Remove most spacing between table cells.
370 | */
371 |
372 | table {
373 | border-collapse: collapse;
374 | border-spacing: 0;
375 | }
--------------------------------------------------------------------------------
/cube.css:
--------------------------------------------------------------------------------
1 | /* Cube styles */
2 | .cube-3d-available .the-cube {
3 | position: relative;
4 | z-index: 10;
5 | display: block;
6 | width: 130px;
7 | height: 130px;
8 | -webkit-transform: perspective(1300px);
9 | -moz-transform: perspective(1300px);
10 | -ms-transform: perspective(1300px);
11 | -o-transform: perspective(1300px);
12 | transform: perspective(1300px);
13 | -webkit-transform-style: preserve-3d;
14 | -moz-transform-style: preserve-3d;
15 | -ms-transform-style: preserve-3d;
16 | -o-transform-style: preserve-3d;
17 | transform-style: preserve-3d;
18 | }
19 | .cube-3d-available .the-cube.rotate {
20 | -webkit-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
21 | -moz-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
22 | -ms-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
23 | -o-transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
24 | transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
25 | }
26 | .cube-3d-available .the-cube .side-1, .cube-3d-available .the-cube .side-2, .cube-3d-available .the-cube .side-3, .cube-3d-available .the-cube .side-4, .cube-3d-available .the-cube .side-5, .cube-3d-available .the-cube .side-6 {
27 | position: absolute;
28 | left: 0;
29 | top: 0;
30 | z-index: 1;
31 | background-size: 390px 260px;
32 | }
33 | .cube-3d-available .the-cube .side-1 {
34 | width: 100%;
35 | height: 100%;
36 | -webkit-transform: rotateY(-90deg) translateZ(65px);
37 | -moz-transform: rotateY(-90deg) translateZ(65px);
38 | -ms-transform: rotateY(-90deg) translateZ(65px);
39 | -o-transform: rotateY(-90deg) translateZ(65px);
40 | transform: rotateY(-90deg) translateZ(65px);
41 | }
42 | .cube-3d-available .the-cube .side-2 {
43 | width: 100%;
44 | height: 100%;
45 | background-position: -130px 0;
46 | -webkit-transform: rotateX(-90deg) translateZ(65px);
47 | -moz-transform: rotateX(-90deg) translateZ(65px);
48 | -ms-transform: rotateX(-90deg) translateZ(65px);
49 | -o-transform: rotateX(-90deg) translateZ(65px);
50 | transform: rotateX(-90deg) translateZ(65px);
51 | }
52 | .cube-3d-available .the-cube .side-3 {
53 | width: 100%;
54 | height: 100%;
55 | background-position: -260px 0;
56 | -webkit-transform: translateZ(65px);
57 | -moz-transform: translateZ(65px);
58 | -ms-transform: translateZ(65px);
59 | -o-transform: translateZ(65px);
60 | transform: translateZ(65px);
61 | -webkit-transform-origin: 0 0 0;
62 | -moz-transform-origin: 0 0 0;
63 | -ms-transform-origin: 0 0 0;
64 | -o-transform-origin: 0 0 0;
65 | transform-origin: 0 0 0;
66 | -webkit-transition-property: -webkit-transform, background;
67 | -moz-transition-property: -moz-transform, background;
68 | -o-transition-property: -o-transform, background;
69 | transition-property: transform, background;
70 | -webkit-transition-duration: 0.3s;
71 | -moz-transition-duration: 0.3s;
72 | -o-transition-duration: 0.3s;
73 | transition-duration: 0.3s;
74 | }
75 | .cube-3d-available .the-cube .side-4 {
76 | width: 100%;
77 | height: 100%;
78 | background-position: 0 -130px;
79 | -webkit-transform: rotateX(90deg) translateZ(65px);
80 | -moz-transform: rotateX(90deg) translateZ(65px);
81 | -ms-transform: rotateX(90deg) translateZ(65px);
82 | -o-transform: rotateX(90deg) translateZ(65px);
83 | transform: rotateX(90deg) translateZ(65px);
84 | }
85 | .cube-3d-available .the-cube .side-5 {
86 | width: 100%;
87 | height: 100%;
88 | background-position: -130px -130px;
89 | -webkit-transform: rotateY(90deg) translateZ(65px);
90 | -moz-transform: rotateY(90deg) translateZ(65px);
91 | -ms-transform: rotateY(90deg) translateZ(65px);
92 | -o-transform: rotateY(90deg) translateZ(65px);
93 | transform: rotateY(90deg) translateZ(65px);
94 | }
95 | .cube-3d-available .the-cube .side-6 {
96 | width: 100%;
97 | height: 100%;
98 | background-position: -260px -130px;
99 | -webkit-transform: rotateY(180deg) translateX(-130px) translateZ(65px);
100 | -moz-transform: rotateY(180deg) translateX(-130px) translateZ(65px);
101 | -ms-transform: rotateY(180deg) translateX(-130px) translateZ(65px);
102 | -o-transform: rotateY(180deg) translateX(-130px) translateZ(65px);
103 | transform: rotateY(180deg) translateX(-130px) translateZ(65px);
104 | -webkit-transform-origin: 0 0 0;
105 | -moz-transform-origin: 0 0 0;
106 | -ms-transform-origin: 0 0 0;
107 | -o-transform-origin: 0 0 0;
108 | transform-origin: 0 0 0;
109 | -webkit-transition-property: -webkit-transform, background;
110 | -moz-transition-property: -moz-transform, background;
111 | -o-transition-property: -o-transform, background;
112 | transition-property: transform, background;
113 | -webkit-transition-duration: 0.3s;
114 | -moz-transition-duration: 0.3s;
115 | -o-transition-duration: 0.3s;
116 | transition-duration: 0.3s;
117 | }
118 |
119 | /* Cube styles - END */
120 |
--------------------------------------------------------------------------------
/cube.js:
--------------------------------------------------------------------------------
1 | // Allows to manipulate the cube created using CSS and HTML.
2 | //
3 | // author: Artur Kot (artur.kot@xhtmlized.com)
4 |
5 | /*jshint browser: true, smarttabs: false, indent: 4, undef: true, unused: true, strict: true, trailing: true, onevar: true, white: true */
6 | /*globals requestAnimationFrame, cancelAnimationFrame*/
7 |
8 | (function () {
9 | 'use strict';
10 |
11 | var Test, Cube;
12 |
13 | // ## Tests
14 | Test = {
15 | // ### 'requestAnimationFrame' test
16 | // Checks if 'requestAnimationFrame' is available
17 | //
18 | // * return: __boolean__ Returns true if 'requestAnimationFrame' is available.
19 | animationFrame: function () {
20 | return !!window.requestAnimationFrame;
21 | },
22 |
23 | // ### CSS 3d test
24 | // Checks if CSS 3d transforms can be used
25 | //
26 | // * return: __boolean__ Returns true if 'requestAnimationFrame' is available.
27 | css3d: function () {
28 | if (document.querySelector === undefined) { return false; }
29 |
30 | var EL_ID = 'temporaryCubeCSS3dElement',
31 | STYLE_ID = 'temporaryCubeCSS3dStyle',
32 | $body = document.body,
33 | $el,
34 | $style,
35 | docStyles = document.documentElement.style,
36 | prefixes = ['webkit', 'moz', 'ms', ''],
37 | testResult,
38 | i,
39 | j;
40 |
41 | // * #### Test for 'preserve3d' CSS property.
42 | // - return: __boolean__ Returns true if 'preserve3d' is available.
43 | function testPreserve3d() {
44 | for (i = 0, j = prefixes.length; i < j; i += 1) {
45 | if (prefixes[i].length > 0) {
46 | if (docStyles[prefixes[i] + 'TransformStyle'] !== undefined) {
47 | docStyles[prefixes[i] + 'TransformStyle'] = 'preserve-3d';
48 | if (docStyles[prefixes[i] + 'TransformStyle'].length > 0) {
49 | docStyles[prefixes[i] + 'TransformStyle'] = '';
50 | return true;
51 | }
52 | }
53 | } else {
54 | if (docStyles.transformStyle !== undefined) {
55 | docStyles.transformStyle = 'preserve-3d';
56 | if (docStyles.transformStyle.length > 0) {
57 | docStyles.transformStyle = '';
58 | return true;
59 | }
60 | }
61 | }
62 | }
63 |
64 | return false;
65 | }
66 |
67 | testResult = testPreserve3d();
68 |
69 | // * **Note:**
70 | // This is additional test checking if 'transform-3d' is **really available**.
71 | // It may happen that although property itself is available it's not working properly.
72 | // One of possible reasons can be lack of GPU support.
73 | // The additional CSS 3d transform test is borrowed from [Modernizr](https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/transforms3d.js)
74 | if (testResult && docStyles.webkitPerspective !== undefined) {
75 | $style = document.createElement('style');
76 | $el = document.createElement('div');
77 |
78 | $style.id = STYLE_ID;
79 | $el.id = EL_ID;
80 |
81 | $body.appendChild($style);
82 | $body.appendChild($el);
83 |
84 | $style.textContent = [
85 | '@media (transform-3d), (-webkit-transform-3d) {',
86 | ' #' + EL_ID + '{',
87 | ' left: 9px;',
88 | ' position: absolute;',
89 | ' height: 5px;',
90 | ' margin: 0;',
91 | ' padding: 0;',
92 | ' border: 0',
93 | ' }',
94 | '}'
95 | ].join('\n');
96 |
97 | testResult = $el.offsetLeft === 9 && $el.offsetHeight === 5;
98 |
99 | $body.removeChild($style);
100 | $body.removeChild($el);
101 | }
102 |
103 | return testResult;
104 | }
105 | };
106 |
107 | // ## CSS class
108 | // Adds class at the top of the document.
109 | // Useful for applying fallback if Cube cannot be fired.
110 | if (Test.animationFrame() && Test.css3d()) {
111 | document.documentElement.className += ' cube-3d-available';
112 | }
113 |
114 | // ## Factory function
115 | // Allows to create new Cube instance in the following fashion
116 | // (note that 'new' is not necessary as it's added inside
117 | // the function below):
118 | // ```
119 | // var myCube = Cube('.my .selector');
120 | // ```
121 | // and later use any of the available public classes, e.g.:
122 | // ```
123 | // myCube.rotate();
124 | // ```
125 | // The function is revealed using `window` object.
126 | //
127 | // * parameters:
128 | // - `selector` __string__ Any CSS selector that will work with [querySelector](https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector).
129 | // - `props` __object__ The cube's options passed to the constructor.
130 | // * return __function__ or __object__ If the cube can be fired `Cube` will return new instance of `Cube.instance` constructor else it will return object with empty methods.
131 | Cube = function (selector, props) {
132 | if (Test.animationFrame() && Test.css3d()) {
133 | return new Cube.instance(selector, props || {});
134 | }
135 |
136 | return {
137 | applyRotation: function () { return false; },
138 | rotate: function () { return false; },
139 | focusOn: function () { return false; },
140 | spinTo: function () { return false; }
141 | };
142 | };
143 |
144 | window.Cube = Cube;
145 |
146 | // ## Constructor
147 | // * parameters:
148 | // - `selector` __string__ Any CSS selector that will work with [querySelector](https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector).
149 | // - `props` __object__ The cube's options.
150 | Cube.instance = function (selector, props) {
151 | // The only option that can be currently passed to the constructor
152 | // is [perspective](https://developer.mozilla.org/en-US/docs/Web/CSS/perspective).
153 | props.perspective = props.perspective || 1100;
154 |
155 | // ### Public variables
156 |
157 | // * `$cube` __object__ A DOM element which is supposed to be a cube.
158 | this.$cube = document.querySelector(selector || '#the-cube');
159 |
160 | // * `props` __object__ Options publicly available for methods.
161 | this.props = props;
162 |
163 | // * `rotatePropsSet` __boolean__ True if rotate properties (posX, posY, posZ, speedX, speedY, speedZ) has been set. See `rotate` method below.
164 | this.rotatePropsSet = false;
165 |
166 | // * `rotateDir` __string__ The cube's rotation direction. Can be either 'left' or 'right'.
167 | this.rotateDir = 'right';
168 |
169 | // * `speed[axis]` __number__ Determines how fast the cube should rotate 360 degrees. Value is in 'iterations', not milliseconds.
170 | this.speedX = 0;
171 | this.speedY = 0;
172 | this.speedZ = 0;
173 |
174 | // * `pos[axis]` __number__ The cube's rotation value from **0 to 360**.
175 | this.posX = 0;
176 | this.posY = 0;
177 | this.posZ = 0;
178 |
179 | // * `snapshot[axis]` __number__ The cube's rotation value from **0 to 360**. Used to 'remember' last values. See 'focusOn' method.
180 | this.snapshotX = 0;
181 | this.snapshotY = 0;
182 | this.snapshotZ = 0;
183 |
184 | // * `isRotating` __boolean__ True if cube is being rotated at the moment (rotate method is in use). See `rotate`.
185 | this.isRotating = false;
186 |
187 | // * `isFocusing` __boolean__ True if cube is being focused at the moment (rotates to show selected side). See `rotate`, `spinTo`, and `focusOn` methods.
188 | this.isFocusing = false;
189 |
190 | // * `hasFocused` __boolean__ True if cube has rotated to the selected side. See `focusOn` method.
191 | this.hasFocused = false;
192 |
193 | // * `iterators` __object__ Stores iterators for each axis. See `spinTo` method.
194 | this.iterators = {};
195 |
196 | // * `timers` __object__ Stores timers (requestAnimationFrame).
197 | this.timers = {};
198 | };
199 |
200 | Cube.instance.prototype = {
201 | // * `xyz` and `XYZ` __array__ 'x', 'y', 'z' prefixes.
202 | xyz: ['x', 'y', 'z'],
203 | XYZ: ['X', 'Y', 'Z'],
204 |
205 | // * `sides` __object__ Predefined cube's sides coordinates.
206 | sides: {
207 | 'side-1': [0, 90, 0],
208 | 'side-2': [90, 0, 0],
209 | 'side-3': [0, 0, 0],
210 | 'side-4': [270, 0, 0],
211 | 'side-5': [0, 270, 0],
212 | 'side-6': [0, 180, 0]
213 | },
214 |
215 | // ### Public Methods
216 |
217 | // #### Apply rotation
218 | // Set rotation of the cube.
219 | //
220 | // * parameters: `props` __object__ Rotation of each axis in the following format:
221 | // ```
222 | // {
223 | // x: [number from 0 to 360],
224 | // y: [number from 0 to 360],
225 | // z: [number from 0 to 360]
226 | // }
227 | // ```
228 | // or predefined side string:
229 | //
230 | // ```
231 | // { side: 'side-3' }
232 | // ```
233 | //
234 | // Usage examples:
235 | // ```
236 | // var myCube = Cube('.my .selector');
237 | //
238 | // // Set the cube's position
239 | // myCube.applyRotation({
240 | // x: 45,
241 | // y: 30,
242 | // z: 270
243 | // });
244 | // ```
245 | //
246 | // ```
247 | // var myCube = Cube('.my .selector');
248 | //
249 | // // Set the cube's position
250 | // myCube.applyRotation({ side: 'side-4' });
251 | // ```
252 | applyRotation: function (props) {
253 | var prefix = this._getPrefix(),
254 | styles = 'perspective(' + this.props.perspective + 'px)',
255 | currentDeg,
256 | axes = 0;
257 |
258 | props = props || {};
259 |
260 | if (props.x && props.y && props.z) {
261 | while (axes < 3) {
262 | currentDeg = props[this.xyz[axes]];
263 | currentDeg = isNaN(currentDeg) ? 0 : currentDeg;
264 |
265 | this['pos' + this.XYZ[axes]] = currentDeg;
266 |
267 | axes += 1;
268 | }
269 | } else if (props.side) {
270 | if (!this.sides[props.side]) { throw 'You\'ve probably entered wrong string as a "side" in "applyRotation". Try "side-1", "side-2", "side-3", "side-4", "side-5", or "side-6"'; }
271 |
272 | while (axes < 3) {
273 | currentDeg = this.sides[props.side][axes];
274 |
275 | this['pos' + this.XYZ[axes]] = currentDeg;
276 |
277 | axes += 1;
278 | }
279 | }
280 |
281 | axes = 0;
282 | while (axes < 3) {
283 | currentDeg = this['pos' + this.XYZ[axes]];
284 |
285 | styles += ' rotate' + this.XYZ[axes] + '(' + currentDeg + 'deg)';
286 |
287 | axes += 1;
288 | }
289 |
290 | this.$cube.style[prefix ? prefix + 'Transform' : 'transform'] = styles;
291 | },
292 |
293 | // #### Rotate
294 | // Start infinite rotation animation.
295 | //
296 | // * parameters: `props` __object__ Rotate options:
297 | // - `startSide` __string__ Specify from which side should the cube start to animate.
298 | // Possible options:
299 | // - side-1, side-2, side-3, side-4, side-5, side-6
300 | //
301 | // - `speed[axis]` __number__ Time in milliseconds in which the cube rotate around one axis (from 0 to 360 degrees).
302 | // - `rotateDir` __string__ Can be 'left' or 'right'.
303 | //
304 | // Usage example:
305 | // ```
306 | // var myCube = Cube('.my .selector');
307 | //
308 | // // Cube will start rotating
309 | // myCube.rotate({
310 | // startSide: 'side-1',
311 | // speedX: 5000, // 5 seconds
312 | // speedY: 20000, // 20 seconds
313 | // speedZ: 10000 // 10 seconds
314 | // rotateDir: 'left'
315 | // });
316 | // ```
317 | rotate: function (props) {
318 | var i = 0,
319 | dir = 0,
320 | XYZ = this.XYZ,
321 | self = this,
322 | currentSpeed;
323 |
324 | props = props || {};
325 |
326 | self.rotateDir = props.rotateDir || self.rotateDir;
327 |
328 | self.isRotating = true;
329 |
330 | if (props.startSide && self.sides[props.startSide] === undefined) { throw 'You\'ve typed wrong value for "startSide" option.'; }
331 |
332 | self.isFocusing = false;
333 |
334 | if (!self.rotatePropsSet) {
335 | while (i < 3) {
336 | if (props.startSide) {
337 | props['start' + XYZ[i]] = self.sides[props.startSide][i];
338 | }
339 |
340 | self['pos' + XYZ[i]] = props['start' + XYZ[i]] || 0;
341 |
342 | currentSpeed = props['speed' + XYZ[i]];
343 | currentSpeed = currentSpeed === 0 ? 0 : (currentSpeed || 360);
344 | self['speed' + XYZ[i]] = currentSpeed;
345 | i += 1;
346 | }
347 |
348 | self.rotateDir = props.rotateDir || self.rotateDir;
349 |
350 | self.rotatePropsSet = true;
351 | }
352 |
353 | if (self.rotateDir === 'left') { dir = -360; }
354 | if (self.rotateDir === 'right') { dir = 360; }
355 |
356 | self._spinTo({
357 | spinToX: props.startX ? props.startX + dir : dir,
358 | spinToY: props.startY ? props.startY + dir : dir,
359 | spinToZ: props.startZ ? props.startZ + dir : dir,
360 | speedX: self.speedX,
361 | speedY: self.speedY,
362 | speedZ: self.speedZ,
363 | timer: 'rotate',
364 | repeat: true,
365 | easing: 'linear'
366 | });
367 | },
368 |
369 | // #### Focus On
370 | // Animate to the specified side of the cube on 'mouseover' or 'touchstart' event.
371 | //
372 | // * parameters: `props` __object__ focusOn options:
373 | // - `bounceBack` __boolean__ If set to true the cube will animate back to its last position (before focusOn animation), else it will stay at the focused position.
374 | // - `spinTo` __string__ Specify to which side should the cube animate to. **Note** that this option will overwrite `spintTo[axis]`.
375 | // - `spinTo[axis]` __number__ Specify to what degree each axis should animate to.
376 | //
377 | // Usage example:
378 | // ```
379 | // var myCube = Cube('.my .selector');
380 | //
381 | // // Cube will rotate to selected face
382 | // // either on 'touchstart' or 'mouseover' event.
383 | // myCube.focusOn({
384 | // bounceBack: true,
385 | // spinTo: 'side-6'
386 | // });
387 | // ```
388 | focusOn: function (props) {
389 | var self = this,
390 | isTouch = window.ontouchstart === null,
391 | startEvent = isTouch ? 'touchstart' : 'mouseover';
392 |
393 | props = props || {};
394 |
395 | function focus() {
396 | if (props.bounceBack) {
397 | cancelAnimationFrame(self.timers.deFocus);
398 | }
399 |
400 | if (!self.isFocusing) {
401 | self.snapshotX = self.posX;
402 | self.snapshotY = self.posY;
403 | self.snapshotZ = self.posZ;
404 | }
405 |
406 | if (props.spinTo && self.sides[props.spinTo] === undefined) { throw 'You\'ve typed wrong value for "spinTo" option.'; }
407 |
408 | if (props.spinTo && self.sides[props.spinTo] !== undefined) {
409 | props.spinToX = self.sides[props.spinTo][0];
410 | props.spinToY = self.sides[props.spinTo][1];
411 | props.spinToZ = self.sides[props.spinTo][2];
412 | }
413 |
414 | self._spinTo({
415 | spinToX: props.spinToX || 0,
416 | spinToY: props.spinToY || 0,
417 | spinToZ: props.spinToZ || 0,
418 | speed: props.speed || 2000,
419 | timer: 'spinTo',
420 | easing: 'out',
421 | callback: function () {
422 | self.$cube.className += ' focused';
423 | self.hasFocused = true;
424 | }
425 | });
426 | }
427 |
428 | function deFocus() {
429 | cancelAnimationFrame(self.timers.spinTo);
430 | cancelAnimationFrame(self.timers.rotate);
431 |
432 | self._removeClass(self.$cube, 'focused');
433 | self.hasFocused = false;
434 |
435 | if (props.bounceBack) {
436 | self._spinTo({
437 | spinToX: self.snapshotX,
438 | spinToY: self.snapshotY,
439 | spinToZ: self.snapshotZ,
440 | speed: props.speed || 2000,
441 | timer: 'deFocus',
442 | easing: 'out',
443 | callback: function () {
444 | if (self.isRotating) {
445 | self.rotate({
446 | startX: self.posX,
447 | startY: self.posY,
448 | startZ: self.posZ
449 | });
450 | }
451 | }
452 | });
453 | } else if (self.isRotating) {
454 | self.rotate({
455 | startX: self.posX,
456 | startY: self.posY,
457 | startZ: self.posZ
458 | });
459 | }
460 | }
461 |
462 | self.$cube.addEventListener(startEvent, function (e) {
463 | if (self.hasFocused) { return; }
464 | e.preventDefault();
465 | cancelAnimationFrame(self.timers.rotate);
466 | focus();
467 | });
468 |
469 | self.$cube.addEventListener('mouseout', deFocus);
470 |
471 | if (isTouch) {
472 | document.addEventListener('touchstart', function (e) {
473 | var $target = e.target;
474 | if (!self._hasParent($target, self.$cube)) { deFocus(); }
475 | });
476 | }
477 | },
478 |
479 | // ### Private Methods
480 |
481 | // #### Spin To
482 | // Animate to the specified position.
483 | //
484 | // * parameters: `props` __object__ spinTo options:
485 | // - `spinTo[axis]` __number__ Specify to what degree each axis should animate to.
486 | // - `speed` __number__ Time (in milliseconds) that specifies how long it will take to spin to given position. Overwrites `speed[axis]`.
487 | // - `speed[axis]` __number__ Time (in milliseconds) that specifies how long it will take to spin to given position for each axis.
488 | // - `timer` __string__ Timer's ID. It can be reset if needed thus stopping spinTo loop. Timers are attached to public variable called `timers` (see in constructor).
489 | // - `easing` __string__ Name of easing function (available functions: 'ease', 'out', 'inOut')
490 | // - `callback` __function__ Function which executes after spinTo is done.
491 | _spinTo: function (props) {
492 | var i = 0,
493 | self = this,
494 | start = {},
495 | speeds = [],
496 | changeInValue = {},
497 | changeInValueA = {},
498 | changeInValueB = {},
499 | dir = {},
500 | done = {},
501 | xyz = self.xyz,
502 | XYZ = self.XYZ,
503 | currentMax,
504 | currentDeg,
505 | currentSpeed,
506 | currentIterator;
507 |
508 | props.speed = self._calculateIterations(props.speed);
509 |
510 | self.isFocusing = props.repeat ? false : true;
511 |
512 | while (i < 3) {
513 | start[xyz[i]] = self['pos' + XYZ[i]];
514 |
515 | if (props['speed' + XYZ[i]]) {
516 | props['speed' + XYZ[i]] = self._calculateIterations(props['speed' + XYZ[i]]);
517 | }
518 |
519 | if (props.repeat) {
520 | changeInValue[xyz[i]] = Math.abs(start[xyz[i]] - props['spinTo' + XYZ[i]]);
521 | } else {
522 | changeInValueA[xyz[i]] = Math.abs(start[xyz[i]] - props['spinTo' + XYZ[i]]);
523 | if (start[xyz[i]] > props['spinTo' + XYZ[i]]) {
524 | changeInValueB[xyz[i]] = Math.abs(start[xyz[i]] - props['spinTo' + XYZ[i]] - 360);
525 | } else {
526 | changeInValueB[xyz[i]] = Math.abs(start[xyz[i]] - props['spinTo' + XYZ[i]] + 360);
527 | }
528 |
529 | if (changeInValueA[xyz[i]] < changeInValueB[xyz[i]]) {
530 | changeInValue[xyz[i]] = changeInValueA[xyz[i]];
531 | } else {
532 | if (start[xyz[i]] > props['spinTo' + XYZ[i]]) {
533 | props['spinTo' + XYZ[i]] += 360;
534 | } else {
535 | props['spinTo' + XYZ[i]] -= 360;
536 | }
537 |
538 | changeInValue[xyz[i]] = changeInValueB[xyz[i]];
539 | }
540 | }
541 |
542 | dir[xyz[i]] = start[xyz[i]] < props['spinTo' + XYZ[i]] ? 'right' : 'left';
543 | speeds.push(props.speed ? Math.floor(Math.abs(start[xyz[i]] - props['spinTo' + XYZ[i]]) * props.speed / 360) : props['speed' + XYZ[i]]);
544 |
545 | i += 1;
546 | }
547 |
548 | speeds.sort(function (a, b) { return b - a; });
549 | this.iterators.spinTo = { x: 0, y: 0, z: 0 };
550 | props.easing = props.easing || 'linear';
551 |
552 | function run() {
553 | i = 0;
554 |
555 | while (i < 3) {
556 | currentMax = changeInValue[xyz[i]];
557 | currentSpeed = props.speed ? speeds[0] : props['speed' + XYZ[i]];
558 |
559 | if (currentMax !== 0 && currentSpeed !== 0) {
560 | currentDeg = self['pos' + XYZ[i]];
561 | currentIterator = self.iterators.spinTo[xyz[i]];
562 |
563 | currentDeg = currentSpeed === 0 ? 0 : self._ease[props.easing](currentIterator, 0, currentMax, currentSpeed);
564 |
565 | if (dir[xyz[i]] === 'right') {
566 | currentDeg += start[xyz[i]];
567 | currentMax += start[xyz[i]];
568 |
569 | if (currentDeg < currentMax) {
570 | currentIterator += 1;
571 | } else {
572 | currentDeg = currentMax;
573 | done[xyz[i]] = true;
574 | }
575 | } else {
576 | currentDeg = start[xyz[i]] - currentDeg;
577 | currentMax = start[xyz[i]] - currentMax;
578 |
579 | if (currentDeg > currentMax) {
580 | currentIterator += 1;
581 | } else {
582 | currentDeg = currentMax;
583 | done[xyz[i]] = true;
584 | }
585 | }
586 |
587 | self['pos' + XYZ[i]] = currentDeg;
588 | self.iterators.spinTo[xyz[i]] = currentIterator;
589 | } else {
590 | done[xyz[i]] = true;
591 | }
592 |
593 | i += 1;
594 | }
595 |
596 | self.applyRotation();
597 |
598 | i = 0;
599 |
600 | while (i < 3) {
601 | if (done[xyz[i]] && props.repeat) {
602 | self['pos' + XYZ[i]] = start[xyz[i]];
603 | self.iterators.spinTo[xyz[i]] = 0;
604 | done[xyz[i]] = false;
605 | }
606 |
607 | i += 1;
608 | }
609 |
610 | if (done.x && done.y && done.z && !props.repeat) {
611 | self.isFocusing = false;
612 | if (props.callback) { props.callback(); }
613 | return;
614 | }
615 |
616 | self.timers[props.timer] = requestAnimationFrame(run);
617 | }
618 |
619 | run();
620 | },
621 |
622 | // #### Easing functions
623 | _ease: {
624 | // ##### Linear
625 | // * `parameters` (apply for all easing functions below):
626 | // - `currentIteration` __number__ Current iteration.
627 | // - `startValue` __number__ Start value. For example: '10'.
628 | // - `changeInValue` __number__ Change in value. For example '40' means that if value started at 10, it would go up to 50.
629 | // - `totalIterations` __number__ Tells how many iterations should pass until the animation is done.
630 | linear: function (currentIteration, startValue, changeInValue, totalIterations) {
631 | return changeInValue * currentIteration / totalIterations + startValue;
632 | },
633 |
634 | // ##### Out
635 | out: function (currentIteration, startValue, changeInValue, totalIterations) { // outCirc
636 | currentIteration = currentIteration / totalIterations - 1;
637 | return changeInValue * Math.sqrt(1 - Math.pow(currentIteration, 2)) + startValue;
638 | },
639 |
640 | // ##### In Out
641 | inOut: function (currentIteration, startValue, changeInValue, totalIterations) { // inOutCirc
642 | return changeInValue / 2 * (1 - Math.cos(Math.PI * currentIteration / totalIterations)) + startValue;
643 | }
644 | },
645 |
646 | // #### Calculate Iterations
647 | // Calculates approximate number of iterations.
648 | // Converts milliseconds into number of animation frames for the cube.
649 | // It's assumed here that `requestAnimationFrame` will produce 60 frames per second.
650 | //
651 | // * parameters: `milliseconds` __number__ Time in milliseconds.
652 | // * return: __number__ Returns number of iterations.
653 | _calculateIterations: function (milliseconds) {
654 | return milliseconds * 60 / 1000;
655 | },
656 |
657 | // #### Get Prefix
658 | // Check if a browser prefix is necessary and, if it is, choose the right one.
659 | // Test is based on `transform` property which necessary for the script to work.
660 | //
661 | // * return: __Numeric__ Returns number of iterations.
662 | _getPrefix: function () {
663 | var style = document.documentElement.style,
664 | prefix;
665 | if (style.webkitTransform !== undefined) { prefix = 'webkit'; }
666 | if (style.mozTransform !== undefined) { prefix = 'moz'; }
667 | if (style.msTransform !== undefined) { prefix = 'ms'; }
668 | return prefix;
669 | },
670 |
671 | // #### Has Parent
672 | // Check if one element (`$parentEl`) is parent of the second one (`$el`)
673 | //
674 | // * parameters:
675 | // - `$el` __object__ DOM element (assumed children).
676 | // - `$parentEl` __object__ DOM element (assumed parent).
677 | // * return: __boolean__ Returns true if `$parentEl` is `$el` parent.
678 | _hasParent: function ($el, $parentEl) {
679 | var $parentNode = $el.parentNode;
680 |
681 | while ($parentNode !== $parentEl && $parentNode !== document) {
682 | $parentNode = $parentNode.parentNode;
683 | }
684 |
685 | return $parentNode === $parentEl ? true : false;
686 | },
687 |
688 | // #### Remove Class
689 | // Remove CSS class from an element.
690 | //
691 | // * parameters:
692 | // - `$el` __object__ DOM element
693 | // - `className` __string__ class' name, example: *'my-class'*
694 | _removeClass: function ($el, className) {
695 | var regex = new RegExp('\\b' + className + '\\b', 'g');
696 | $el.className = $el.className.replace(regex, '');
697 | }
698 | };
699 | }());
--------------------------------------------------------------------------------
/cube.min.js:
--------------------------------------------------------------------------------
1 | !function(){"use strict";var a,b;a={animationFrame:function(){return!!window.requestAnimationFrame},css3d:function(){function a(){for(e=0,f=k.length;f>e;e+=1)if(k[e].length>0){if(void 0!==j[k[e]+"TransformStyle"]&&(j[k[e]+"TransformStyle"]="preserve-3d",j[k[e]+"TransformStyle"].length>0))return j[k[e]+"TransformStyle"]="",!0}else if(void 0!==j.transformStyle&&(j.transformStyle="preserve-3d",j.transformStyle.length>0))return j.transformStyle="",!0;return!1}if(void 0===document.querySelector)return!1;var b,c,d,e,f,g="temporaryCubeCSS3dElement",h="temporaryCubeCSS3dStyle",i=document.body,j=document.documentElement.style,k=["webkit","moz","ms",""];return d=a(),d&&void 0!==j.webkitPerspective&&(c=document.createElement("style"),b=document.createElement("div"),c.id=h,b.id=g,i.appendChild(c),i.appendChild(b),c.textContent=["@media (transform-3d), (-webkit-transform-3d) {"," #"+g+"{"," left: 9px;"," position: absolute;"," height: 5px;"," margin: 0;"," padding: 0;"," border: 0"," }","}"].join("\n"),d=9===b.offsetLeft&&5===b.offsetHeight,i.removeChild(c),i.removeChild(b)),d}},a.animationFrame()&&a.css3d()&&(document.documentElement.className+=" cube-3d-available"),b=function(c,d){return a.animationFrame()&&a.css3d()?new b.instance(c,d||{}):{applyRotation:function(){return!1},rotate:function(){return!1},focusOn:function(){return!1},spinTo:function(){return!1}}},window.Cube=b,b.instance=function(a,b){b.perspective=b.perspective||1100,this.$cube=document.querySelector(a||"#the-cube"),this.props=b,this.rotatePropsSet=!1,this.rotateDir="right",this.speedX=0,this.speedY=0,this.speedZ=0,this.posX=0,this.posY=0,this.posZ=0,this.snapshotX=0,this.snapshotY=0,this.snapshotZ=0,this.isRotating=!1,this.isFocusing=!1,this.hasFocused=!1,this.iterators={},this.timers={}},b.instance.prototype={xyz:["x","y","z"],XYZ:["X","Y","Z"],sides:{"side-1":[0,90,0],"side-2":[90,0,0],"side-3":[0,0,0],"side-4":[270,0,0],"side-5":[0,270,0],"side-6":[0,180,0]},applyRotation:function(a){var b,c=this._getPrefix(),d="perspective("+this.props.perspective+"px)",e=0;if(a=a||{},a.x&&a.y&&a.z)for(;3>e;)b=a[this.xyz[e]],b=isNaN(b)?0:b,this["pos"+this.XYZ[e]]=b,e+=1;else if(a.side){if(!this.sides[a.side])throw'You\'ve probably entered wrong string as a "side" in "applyRotation". Try "side-1", "side-2", "side-3", "side-4", "side-5", or "side-6"';for(;3>e;)b=this.sides[a.side][e],this["pos"+this.XYZ[e]]=b,e+=1}for(e=0;3>e;)b=this["pos"+this.XYZ[e]],d+=" rotate"+this.XYZ[e]+"("+b+"deg)",e+=1;this.$cube.style[c?c+"Transform":"transform"]=d},rotate:function(a){var b,c=0,d=0,e=this.XYZ,f=this;if(a=a||{},f.rotateDir=a.rotateDir||f.rotateDir,f.isRotating=!0,a.startSide&&void 0===f.sides[a.startSide])throw'You\'ve typed wrong value for "startSide" option.';if(f.isFocusing=!1,!f.rotatePropsSet){for(;3>c;)a.startSide&&(a["start"+e[c]]=f.sides[a.startSide][c]),f["pos"+e[c]]=a["start"+e[c]]||0,b=a["speed"+e[c]],b=0===b?0:b||360,f["speed"+e[c]]=b,c+=1;f.rotateDir=a.rotateDir||f.rotateDir,f.rotatePropsSet=!0}"left"===f.rotateDir&&(d=-360),"right"===f.rotateDir&&(d=360),f._spinTo({spinToX:a.startX?a.startX+d:d,spinToY:a.startY?a.startY+d:d,spinToZ:a.startZ?a.startZ+d:d,speedX:f.speedX,speedY:f.speedY,speedZ:f.speedZ,timer:"rotate",repeat:!0,easing:"linear"})},focusOn:function(a){function b(){if(a.bounceBack&&cancelAnimationFrame(d.timers.deFocus),d.isFocusing||(d.snapshotX=d.posX,d.snapshotY=d.posY,d.snapshotZ=d.posZ),a.spinTo&&void 0===d.sides[a.spinTo])throw'You\'ve typed wrong value for "spinTo" option.';a.spinTo&&void 0!==d.sides[a.spinTo]&&(a.spinToX=d.sides[a.spinTo][0],a.spinToY=d.sides[a.spinTo][1],a.spinToZ=d.sides[a.spinTo][2]),d._spinTo({spinToX:a.spinToX||0,spinToY:a.spinToY||0,spinToZ:a.spinToZ||0,speed:a.speed||2e3,timer:"spinTo",easing:"out",callback:function(){d.$cube.className+=" focused",d.hasFocused=!0}})}function c(){cancelAnimationFrame(d.timers.spinTo),cancelAnimationFrame(d.timers.rotate),d._removeClass(d.$cube,"focused"),d.hasFocused=!1,a.bounceBack?d._spinTo({spinToX:d.snapshotX,spinToY:d.snapshotY,spinToZ:d.snapshotZ,speed:a.speed||2e3,timer:"deFocus",easing:"out",callback:function(){d.isRotating&&d.rotate({startX:d.posX,startY:d.posY,startZ:d.posZ})}}):d.isRotating&&d.rotate({startX:d.posX,startY:d.posY,startZ:d.posZ})}var d=this,e=null===window.ontouchstart,f=e?"touchstart":"mouseover";a=a||{},d.$cube.addEventListener(f,function(a){d.hasFocused||(a.preventDefault(),cancelAnimationFrame(d.timers.rotate),b())}),d.$cube.addEventListener("mouseout",c),e&&document.addEventListener("touchstart",function(a){var b=a.target;d._hasParent(b,d.$cube)||c()})},_spinTo:function(a){function b(){for(g=0;3>g;)c=k[p[g]],e=a.speed?j[0]:a["speed"+q[g]],0!==c&&0!==e?(d=h["pos"+q[g]],f=h.iterators.spinTo[p[g]],d=0===e?0:h._ease[a.easing](f,0,c,e),"right"===n[p[g]]?(d+=i[p[g]],c+=i[p[g]],c>d?f+=1:(d=c,o[p[g]]=!0)):(d=i[p[g]]-d,c=i[p[g]]-c,d>c?f+=1:(d=c,o[p[g]]=!0)),h["pos"+q[g]]=d,h.iterators.spinTo[p[g]]=f):o[p[g]]=!0,g+=1;for(h.applyRotation(),g=0;3>g;)o[p[g]]&&a.repeat&&(h["pos"+q[g]]=i[p[g]],h.iterators.spinTo[p[g]]=0,o[p[g]]=!1),g+=1;return o.x&&o.y&&o.z&&!a.repeat?(h.isFocusing=!1,void(a.callback&&a.callback())):void(h.timers[a.timer]=requestAnimationFrame(b))}var c,d,e,f,g=0,h=this,i={},j=[],k={},l={},m={},n={},o={},p=h.xyz,q=h.XYZ;for(a.speed=h._calculateIterations(a.speed),h.isFocusing=a.repeat?!1:!0;3>g;)i[p[g]]=h["pos"+q[g]],a["speed"+q[g]]&&(a["speed"+q[g]]=h._calculateIterations(a["speed"+q[g]])),a.repeat?k[p[g]]=Math.abs(i[p[g]]-a["spinTo"+q[g]]):(l[p[g]]=Math.abs(i[p[g]]-a["spinTo"+q[g]]),m[p[g]]=Math.abs(i[p[g]]>a["spinTo"+q[g]]?i[p[g]]-a["spinTo"+q[g]]-360:i[p[g]]-a["spinTo"+q[g]]+360),l[p[g]]a["spinTo"+q[g]]?a["spinTo"+q[g]]+=360:a["spinTo"+q[g]]-=360,k[p[g]]=m[p[g]])),n[p[g]]=i[p[g]] li > div {
135 | -moz-box-sizing: border-box; /* firefox */
136 | -ms-box-sizing: border-box; /* ie */
137 | -webkit-box-sizing: border-box; /* webkit */
138 | -khtml-box-sizing: border-box; /* konqueror */
139 | box-sizing: border-box; /* css3 */
140 | }
141 |
142 |
143 | /*---------------------- Jump Page -----------------------------*/
144 | #jump_to, #jump_page {
145 | margin: 0;
146 | background: white;
147 | -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
148 | -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
149 | font: 16px Arial;
150 | cursor: pointer;
151 | text-align: right;
152 | list-style: none;
153 | }
154 |
155 | #jump_to a {
156 | text-decoration: none;
157 | }
158 |
159 | #jump_to a.large {
160 | display: none;
161 | }
162 | #jump_to a.small {
163 | font-size: 22px;
164 | font-weight: bold;
165 | color: #676767;
166 | }
167 |
168 | #jump_to, #jump_wrapper {
169 | position: fixed;
170 | right: 0; top: 0;
171 | padding: 10px 15px;
172 | margin:0;
173 | }
174 |
175 | #jump_wrapper {
176 | display: none;
177 | padding:0;
178 | }
179 |
180 | #jump_to:hover #jump_wrapper {
181 | display: block;
182 | }
183 |
184 | #jump_page {
185 | padding: 5px 0 3px;
186 | margin: 0 0 25px 25px;
187 | }
188 |
189 | #jump_page .source {
190 | display: block;
191 | padding: 15px;
192 | text-decoration: none;
193 | border-top: 1px solid #eee;
194 | }
195 |
196 | #jump_page .source:hover {
197 | background: #f5f5ff;
198 | }
199 |
200 | #jump_page .source:first-child {
201 | }
202 |
203 | /*---------------------- Low resolutions (> 320px) ---------------------*/
204 | @media only screen and (min-width: 320px) {
205 | .pilwrap { display: none; }
206 |
207 | ul.sections > li > div {
208 | display: block;
209 | padding:5px 10px 0 10px;
210 | }
211 |
212 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol {
213 | padding-left: 30px;
214 | }
215 |
216 | ul.sections > li > div.content {
217 | overflow-x:auto;
218 | -webkit-box-shadow: inset 0 0 5px #e5e5ee;
219 | box-shadow: inset 0 0 5px #e5e5ee;
220 | border: 1px solid #dedede;
221 | margin:5px 10px 5px 10px;
222 | padding-bottom: 5px;
223 | }
224 |
225 | ul.sections > li > div.annotation pre {
226 | margin: 7px 0 7px;
227 | padding-left: 15px;
228 | }
229 |
230 | ul.sections > li > div.annotation p tt, .annotation code {
231 | background: #f8f8ff;
232 | border: 1px solid #dedede;
233 | font-size: 12px;
234 | padding: 0 0.2em;
235 | }
236 | }
237 |
238 | /*---------------------- (> 481px) ---------------------*/
239 | @media only screen and (min-width: 481px) {
240 | #container {
241 | position: relative;
242 | }
243 | body {
244 | background-color: #F5F5FF;
245 | font-size: 15px;
246 | line-height: 21px;
247 | }
248 | pre, tt, code {
249 | line-height: 18px;
250 | }
251 | p, ul, ol {
252 | margin: 0 0 15px;
253 | }
254 |
255 |
256 | #jump_to {
257 | padding: 5px 10px;
258 | }
259 | #jump_wrapper {
260 | padding: 0;
261 | }
262 | #jump_to, #jump_page {
263 | font: 10px Arial;
264 | text-transform: uppercase;
265 | }
266 | #jump_page .source {
267 | padding: 5px 10px;
268 | }
269 | #jump_to a.large {
270 | display: inline-block;
271 | }
272 | #jump_to a.small {
273 | display: none;
274 | }
275 |
276 |
277 |
278 | #background {
279 | position: absolute;
280 | top: 0; bottom: 0;
281 | width: 350px;
282 | background: #fff;
283 | border-right: 1px solid #e5e5ee;
284 | z-index: -1;
285 | }
286 |
287 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol {
288 | padding-left: 40px;
289 | }
290 |
291 | ul.sections > li {
292 | white-space: nowrap;
293 | margin-bottom: 30px;
294 | }
295 |
296 | ul.sections > li > div {
297 | display: inline-block;
298 | }
299 |
300 | ul.sections > li > div.annotation {
301 | max-width: 350px;
302 | min-width: 350px;
303 | min-height: 5px;
304 | padding: 13px;
305 | overflow-x: hidden;
306 | white-space: normal;
307 | vertical-align: top;
308 | text-align: left;
309 | }
310 | ul.sections > li > div.annotation pre {
311 | margin: 15px 0 15px;
312 | padding-left: 15px;
313 | }
314 |
315 | ul.sections > li > div.content {
316 | padding: 13px;
317 | vertical-align: top;
318 | border: none;
319 | -webkit-box-shadow: none;
320 | box-shadow: none;
321 | }
322 |
323 | .pilwrap {
324 | position: relative;
325 | display: inline;
326 | }
327 |
328 | .pilcrow {
329 | font: 12px Arial;
330 | text-decoration: none;
331 | color: #454545;
332 | position: absolute;
333 | top: -2px; left: -20px;
334 | padding: 1px 2px;
335 | opacity: 0;
336 | -webkit-transition: opacity 0.2s linear;
337 | }
338 | .for-h1 .pilcrow {
339 | top: 47px;
340 | }
341 | .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow {
342 | top: 35px;
343 | }
344 |
345 | ul.sections > li > div.annotation:hover .pilcrow {
346 | opacity: 1;
347 | }
348 | }
349 |
350 | /*---------------------- (> 1025px) ---------------------*/
351 | @media only screen and (min-width: 1025px) {
352 |
353 | body {
354 | font-size: 16px;
355 | line-height: 24px;
356 | }
357 |
358 | #background {
359 | width: 525px;
360 | }
361 | ul.sections > li > div.annotation {
362 | max-width: 525px;
363 | min-width: 525px;
364 | padding: 10px 25px 1px 50px;
365 | }
366 | ul.sections > li > div.content {
367 | padding: 9px 15px 16px 25px;
368 | }
369 | }
370 |
371 | /*---------------------- Syntax Highlighting -----------------------------*/
372 |
373 | td.linenos { background-color: #f0f0f0; padding-right: 10px; }
374 | span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
375 | /*
376 |
377 | github.com style (c) Vasily Polovnyov
378 |
379 | */
380 |
381 | pre code {
382 | display: block; padding: 0.5em;
383 | color: #000;
384 | background: #f8f8ff
385 | }
386 |
387 | pre .hljs-comment,
388 | pre .hljs-template_comment,
389 | pre .hljs-diff .hljs-header,
390 | pre .hljs-javadoc {
391 | color: #408080;
392 | font-style: italic
393 | }
394 |
395 | pre .hljs-keyword,
396 | pre .hljs-assignment,
397 | pre .hljs-literal,
398 | pre .hljs-css .hljs-rule .hljs-keyword,
399 | pre .hljs-winutils,
400 | pre .hljs-javascript .hljs-title,
401 | pre .hljs-lisp .hljs-title,
402 | pre .hljs-subst {
403 | color: #954121;
404 | /*font-weight: bold*/
405 | }
406 |
407 | pre .hljs-number,
408 | pre .hljs-hexcolor {
409 | color: #40a070
410 | }
411 |
412 | pre .hljs-string,
413 | pre .hljs-tag .hljs-value,
414 | pre .hljs-phpdoc,
415 | pre .hljs-tex .hljs-formula {
416 | color: #219161;
417 | }
418 |
419 | pre .hljs-title,
420 | pre .hljs-id {
421 | color: #19469D;
422 | }
423 | pre .hljs-params {
424 | color: #00F;
425 | }
426 |
427 | pre .hljs-javascript .hljs-title,
428 | pre .hljs-lisp .hljs-title,
429 | pre .hljs-subst {
430 | font-weight: normal
431 | }
432 |
433 | pre .hljs-class .hljs-title,
434 | pre .hljs-haskell .hljs-label,
435 | pre .hljs-tex .hljs-command {
436 | color: #458;
437 | font-weight: bold
438 | }
439 |
440 | pre .hljs-tag,
441 | pre .hljs-tag .hljs-title,
442 | pre .hljs-rules .hljs-property,
443 | pre .hljs-django .hljs-tag .hljs-keyword {
444 | color: #000080;
445 | font-weight: normal
446 | }
447 |
448 | pre .hljs-attribute,
449 | pre .hljs-variable,
450 | pre .hljs-instancevar,
451 | pre .hljs-lisp .hljs-body {
452 | color: #008080
453 | }
454 |
455 | pre .hljs-regexp {
456 | color: #B68
457 | }
458 |
459 | pre .hljs-class {
460 | color: #458;
461 | font-weight: bold
462 | }
463 |
464 | pre .hljs-symbol,
465 | pre .hljs-ruby .hljs-symbol .hljs-string,
466 | pre .hljs-ruby .hljs-symbol .hljs-keyword,
467 | pre .hljs-ruby .hljs-symbol .hljs-keymethods,
468 | pre .hljs-lisp .hljs-keyword,
469 | pre .hljs-tex .hljs-special,
470 | pre .hljs-input_number {
471 | color: #990073
472 | }
473 |
474 | pre .hljs-builtin,
475 | pre .hljs-constructor,
476 | pre .hljs-built_in,
477 | pre .hljs-lisp .hljs-title {
478 | color: #0086b3
479 | }
480 |
481 | pre .hljs-preprocessor,
482 | pre .hljs-pi,
483 | pre .hljs-doctype,
484 | pre .hljs-shebang,
485 | pre .hljs-cdata {
486 | color: #999;
487 | font-weight: bold
488 | }
489 |
490 | pre .hljs-deletion {
491 | background: #fdd
492 | }
493 |
494 | pre .hljs-addition {
495 | background: #dfd
496 | }
497 |
498 | pre .hljs-diff .hljs-change {
499 | background: #0086b3
500 | }
501 |
502 | pre .hljs-chunk {
503 | color: #aaa
504 | }
505 |
506 | pre .hljs-tex .hljs-formula {
507 | opacity: 0.5;
508 | }
509 |
--------------------------------------------------------------------------------
/images/cube/cube-texture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/images/cube/cube-texture.jpg
--------------------------------------------------------------------------------
/images/cube/cube-texture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/images/cube/cube-texture.png
--------------------------------------------------------------------------------
/images/cube/cube-texture.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/images/cube/cube-texture.psd
--------------------------------------------------------------------------------
/images/cube/cube-texture.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xfiveco/cube/45d4f1bf497192133b93f0d39c4293843f6bab24/images/cube/cube-texture.zip
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | CSS3 Cube - Xfive Open Source Plugin
8 |
9 |
10 |
11 |
12 |
13 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
33 |
34 |
35 |
36 |
37 | Quick Start
38 |
39 | Please check the compatibility notes before using this script.
40 |
41 |
42 |
43 | Add either cube.js or cube.min.js script to your page.
44 | Example: <script src="cube.min.js"></script>
45 |
46 |
47 |
48 | Add styles responsible for the cube to you style sheet(s). Exemplary background image can be found here .
49 | cube.css or cube.scss if you use Sass and Compass.
50 |
51 |
52 |
53 | Add cube's markup to your HTML:
54 |
55 |
56 |
57 |
58 | Add some styles to customise your cube:
59 |
60 |
61 |
62 |
63 | Initiate the script:
64 |
65 |
66 |
67 |
68 | And you are ready to go!
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | Options
87 |
88 |
89 | Apply Rotation
90 |
91 | Set rotation of the cube.
92 |
93 |
94 |
95 | or
96 |
97 |
98 |
99 | Example:
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | Example:
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | Rotate
132 |
133 | Start infinite rotation animation.
134 |
135 |
136 |
137 | Example:
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 | Example:
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 | Example:
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 | Focus On
185 |
186 | Animate to the specified side of the cube on mouseover or touchstart event.
187 |
188 |
189 |
190 | Example:
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 | Example:
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 | Example:
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 | Example:
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 | Cube Texture
254 |
255 | Below you can see an exemplary image used on this page. Feel free to use it as an template for your own cube. You can find a PSD template here .
256 |
257 |
258 | Note:
259 | The cube texture doesn't have to have the exact size as the image presented here. You can decrease/increase its resolution as long as the image ratio is correct.
260 |
261 |
262 |
263 |
264 |
265 |
266 | Compatibility
267 |
268 | Please mind this script uses CSS 3d to render the cube. This means that the script won't work on any IE available thus far. This is because of the lack of support for preserve-3d CSS property.
269 |
270 | It's also possible that with some browsers/OS combinations rendering of 3d CSS is not possible, hence it's important to always use a fallback .
271 |
272 | The script adds .cube-3d-available class at the top of the document if it can work.
273 |
274 |
275 |
276 | Documentation
277 | If you'd like to take a closer look at the code visit GitHub or check the documentation .
278 |
279 |
280 |
283 |
284 |
285 | Back to the top
286 |
287 |
288 |
289 |
290 |
291 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cube-plugin",
3 | "devDependencies": {
4 | "grunt": "~0.4.2",
5 | "grunt-contrib-sass": "~0.6.0",
6 | "grunt-contrib-watch": "~0.5.3",
7 | "grunt-contrib-jshint": "~0.8.0",
8 | "grunt-docco": "~0.3.2",
9 | "grunt-contrib-uglify": "~0.3.2"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------