├── Makefile
├── .gitignore
├── .jshintrc
├── README.md
├── demo
├── happy-town
│ ├── hedge.js
│ ├── lil-pyramid.js
│ ├── index.html
│ └── make-building.js
├── santorini
│ ├── make-window.js
│ ├── index.html
│ ├── make-rock.js
│ ├── buildings.js
│ ├── make-building.js
│ └── santorini.js
├── curves
│ ├── index.html
│ └── curves.js
├── solid-shifter
│ ├── solid-shifter.js
│ ├── index.html
│ └── shifter.js
├── madeline
│ ├── bokeh-shape.js
│ ├── index.html
│ ├── make-bird.js
│ ├── madeline.js
│ └── make-madeline.js
├── fps-counter.js
├── translate-rotate
│ ├── index.html
│ └── translate-rotate.js
├── castle
│ ├── index.html
│ └── castle.js
├── tri-prism
│ ├── index.html
│ └── tri-prism.js
├── patties
│ ├── patties.js
│ └── index.html
├── truck-flight
│ ├── index.html
│ └── truck-flight.js
├── cones
│ ├── index.html
│ └── cones.js
├── codepen-logo
│ ├── index.html
│ └── codepen-logo.js
├── sauropod
│ ├── index.html
│ └── sauropod.js
├── crypto-kitty
│ ├── index.html
│ └── crypto-kitty.js
├── mario
│ ├── index.html
│ └── mario.js
├── mega-man
│ ├── index.html
│ └── mega-man.js
├── shade-and-shades
│ ├── index.html
│ └── shade-and-shades.js
├── bird-house
│ ├── index.html
│ └── bird-house.js
├── hemisphere-ball
│ ├── index.html
│ └── hemisphere-ball.js
├── template
│ ├── demo.js
│ └── index.html
├── inside-house
│ ├── index.html
│ └── inside-house.js
├── rgb-birdie
│ ├── index.html
│ └── rgb-birdie.js
├── gear-icon
│ ├── index.html
│ └── gear-icon.js
├── cylinders
│ ├── index.html
│ └── cylinders.js
├── la-link
│ ├── index.html
│ └── la-link.js
├── strutter
│ ├── index.html
│ └── strutter.js
├── composite-shapes-scale-svg
│ ├── index.html
│ └── composite-shapes-scale-svg.js
├── composite-shapes-scale
│ ├── index.html
│ └── composite-shapes-scale.js
├── fizzy-bear
│ └── index.html
├── little-forest
│ └── index.html
├── unpkg-explode
│ ├── index.html
│ └── unpkg-explode.js
└── davey-nippu
│ └── index.html
└── package.json
/Makefile:
--------------------------------------------------------------------------------
1 | lint:
2 | npx jshint demo/**/*.js
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | bower_components/
3 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "browser": true,
3 | "unused": true,
4 | "undef": true,
5 | "globals": {
6 | "Zdog": false
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Zdog demos
2 |
3 | _Bigger, wilder Zdog demos_
4 |
5 | View complete Zdog documentation and live demos at [zzz.dog](https://zzz.dog).
6 |
7 | ## Install
8 |
9 | ``` bash
10 | npm install
11 | ```
12 |
13 | Then view `demo/*/index.html` in your browser.
14 |
--------------------------------------------------------------------------------
/demo/happy-town/hedge.js:
--------------------------------------------------------------------------------
1 | /* globals navy */
2 |
3 | window.hedge = function( options ) {
4 | var anchor = new Zdog.Anchor({
5 | addTo: options.addTo,
6 | translate: options.translate,
7 | });
8 |
9 | var ball = new Zdog.Shape({
10 | path: [ { y: 0 }, { y: -1 } ],
11 | addTo: anchor,
12 | translate: { y: -2.5 },
13 | stroke: 5,
14 | color: options.color || navy,
15 | });
16 |
17 | ball.copy({
18 | stroke: 4,
19 | translate: { y: -5 },
20 | });
21 |
22 | ball.copy({
23 | stroke: 2.5,
24 | translate: { y: -7.5 },
25 | });
26 | };
27 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zdog-demos",
3 | "version": "1.0.0",
4 | "description": "Bigger, wilder Zdog demos",
5 | "dependencies": {
6 | "zdog": "^1.1.2"
7 | },
8 | "devDependencies": {
9 | "jshint": "^2.10.2"
10 | },
11 | "scripts": {
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "repository": {
15 | "type": "git",
16 | "url": "git+https://github.com/metafizzy/zdog-demos.git"
17 | },
18 | "author": "David DeSandro",
19 | "private": true,
20 | "license": "MIT",
21 | "bugs": {
22 | "url": "https://github.com/metafizzy/zdog-demos/issues"
23 | },
24 | "homepage": "https://zzz.dog"
25 | }
26 |
--------------------------------------------------------------------------------
/demo/happy-town/lil-pyramid.js:
--------------------------------------------------------------------------------
1 | /* globals TAU, navy, red */
2 |
3 | window.lilPyramid = function( options ) {
4 | var anchor = new Zdog.Anchor({
5 | addTo: options.addTo,
6 | translate: options.translate,
7 | });
8 |
9 | var panel = new Zdog.Shape({
10 | path: [
11 | { x: 0, y: -3, z: 0 },
12 | { x: 3, y: 0, z: 0 },
13 | { x: 0, y: 0, z: 3 },
14 | ],
15 | addTo: anchor,
16 | color: red,
17 | });
18 |
19 | panel.copy({
20 | rotate: { y: TAU/4 },
21 | color: red,
22 | });
23 | panel.copy({
24 | rotate: { y: TAU/2 },
25 | color: navy,
26 | });
27 | panel.copy({
28 | rotate: { y: TAU * 3/4 },
29 | color: navy,
30 | });
31 |
32 | };
33 |
--------------------------------------------------------------------------------
/demo/santorini/make-window.js:
--------------------------------------------------------------------------------
1 | /*jshint unused: false */
2 |
3 | function makeWindow( options ) {
4 | if ( options.style == 'circle' ) {
5 | makeCircleWindow( options );
6 | } else {
7 | makeLongWindow( options );
8 | }
9 | }
10 |
11 | function makeCircleWindow( options ) {
12 | new Zdog.Ellipse( Zdog.extend( options, {
13 | diameter: 2,
14 | }));
15 | }
16 |
17 | function makeLongWindow( options ) {
18 | var y2 = options.height - 1;
19 |
20 | var windowShape = new Zdog.Shape( Zdog.extend( options, {
21 | path: [
22 | { x: -1, y: 0 },
23 | { arc: [
24 | { x: -1, y: -1 },
25 | { x: 0, y: -1 },
26 | ]},
27 | { arc: [
28 | { x: 1, y: -1 },
29 | { x: 1, y: 0 },
30 | ]},
31 | { x: 1, y: y2 },
32 | { x: -1, y: y2 },
33 | ],
34 | }));
35 |
36 | return windowShape;
37 | }
--------------------------------------------------------------------------------
/demo/curves/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | curves
8 |
9 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Click & drag to rotate
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/demo/solid-shifter/solid-shifter.js:
--------------------------------------------------------------------------------
1 | /* globals Shifter */
2 |
3 | // ----- setup ----- //
4 |
5 | var illoElem = document.querySelector('.illo');
6 | var illoSize = 10;
7 | var minWindowSize = Math.min( window.innerWidth - 20, window.innerHeight - 20 );
8 | var zoom = Math.floor( minWindowSize / illoSize );
9 | illoElem.setAttribute( 'width', illoSize * zoom );
10 | illoElem.setAttribute( 'height', illoSize * zoom );
11 |
12 | var illo = new Zdog.Illustration({
13 | element: illoElem,
14 | zoom: zoom,
15 | dragRotate: true,
16 | });
17 |
18 | // ----- model ----- //
19 |
20 | var shifterA = new Shifter({
21 | addTo: illo,
22 | translate: { x: -3 },
23 | });
24 | var shifterB = new Shifter({
25 | addTo: illo,
26 | });
27 | var shifterC = new Shifter({
28 | addTo: illo,
29 | translate: { x: 3 },
30 | });
31 |
32 | // ----- animate ----- //
33 |
34 | var ticker = 0;
35 | var cycleCount = 80;
36 |
37 | function animate() {
38 | // update
39 | var progress = ticker / cycleCount;
40 | shifterA.update( progress + 4 );
41 | shifterB.update( progress + 2 );
42 | shifterC.update( progress + 0 );
43 | ticker++;
44 |
45 | illo.updateRenderGraph();
46 | requestAnimationFrame( animate );
47 | }
48 |
49 | animate();
50 |
51 |
--------------------------------------------------------------------------------
/demo/madeline/bokeh-shape.js:
--------------------------------------------------------------------------------
1 | var BokehShape = Zdog.Shape.subclass({
2 | bokehSize: 5,
3 | bokehLimit: 64,
4 | });
5 |
6 | BokehShape.prototype.updateBokeh = function() {
7 | // bokeh 0 -> 1
8 | this.bokeh = Math.abs( this.sortValue ) / this.bokehLimit;
9 | this.bokeh = Math.max( 0, Math.min( 1, this.bokeh ) );
10 | return this.bokeh;
11 | };
12 |
13 | BokehShape.prototype.getLineWidth = function() {
14 | return this.stroke + this.bokehSize * this.bokeh * this.bokeh;
15 | };
16 |
17 | BokehShape.prototype.getBokehAlpha = function() {
18 | var alpha = 1 - this.bokeh;
19 | alpha *= alpha;
20 | return alpha * 0.8 + 0.2;
21 | };
22 |
23 | BokehShape.prototype.renderCanvasDot = function( ctx ) {
24 | this.updateBokeh();
25 | ctx.globalAlpha = this.getBokehAlpha(); // set opacity
26 | Zdog.Shape.prototype.renderCanvasDot.apply( this, arguments );
27 | ctx.globalAlpha = 1; // reset
28 | };
29 |
30 | BokehShape.prototype.renderPath = function( ctx, renderer ) {
31 | this.updateBokeh();
32 | // set opacity
33 | if ( renderer.isCanvas ) {
34 | ctx.globalAlpha = this.getBokehAlpha();
35 | }
36 | Zdog.Shape.prototype.renderPath.apply( this, arguments );
37 | // reset opacity
38 | if ( renderer.isCanvas ) {
39 | ctx.globalAlpha = 1;
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/demo/fps-counter.js:
--------------------------------------------------------------------------------
1 | ( function() {
2 |
3 | var outputElem = document.createElement('div');
4 | outputElem.style.fontFamily = 'monospace';
5 | outputElem.style.fontSize = '20px';
6 | outputElem.style.position = 'absolute';
7 | outputElem.style.top = '10px';
8 | outputElem.style.left = '10px';
9 |
10 | var prevTickTime = new Date();
11 | var prevUpdateTime = new Date();
12 |
13 | var tickTimeDeltas = [];
14 |
15 | function tick() {
16 | var now = new Date();
17 | var tickTimeDelta = now - prevTickTime;
18 | tickTimeDeltas.push( tickTimeDelta );
19 |
20 | var updateTimeDelta = now - prevUpdateTime;
21 | // update every half second
22 | if ( updateTimeDelta > 500 ) {
23 | update( now );
24 | }
25 | prevTickTime = now;
26 | requestAnimationFrame( tick );
27 | }
28 |
29 | function update( now ) {
30 | var avgDelta = averageArray( tickTimeDeltas );
31 | outputElem.textContent = Math.round( 1000 / avgDelta );
32 |
33 | // reset
34 | tickTimeDeltas = [];
35 | prevUpdateTime = now;
36 | }
37 |
38 | function averageArray( ary ) {
39 | var sum = 0;
40 | var length = ary.length;
41 | for ( var i=0; i < length; i++ ) {
42 | sum += ary[i];
43 | }
44 | return sum / length;
45 | }
46 |
47 | document.body.appendChild( outputElem );
48 | tick();
49 |
50 | })();
51 |
--------------------------------------------------------------------------------
/demo/curves/curves.js:
--------------------------------------------------------------------------------
1 | var illoElem = document.querySelector('.illo');
2 | var w = 72;
3 | var h = 72;
4 | var zoom = 6;
5 | illoElem.setAttribute( 'width', w * zoom );
6 | illoElem.setAttribute( 'height', h * zoom );
7 | // colors
8 |
9 | var illo = new Zdog.Illustration({
10 | element: illoElem,
11 | zoom: zoom,
12 | dragRotate: true,
13 | });
14 |
15 | // -- illustration shapes --- //
16 |
17 | // rectangle with curve
18 | new Zdog.Shape({
19 | path: [
20 | { x: -6, y: -8 },
21 | { bezier: [
22 | { x: 0, y: -12, z: -5 },
23 | { x: 0, y: -4 },
24 | { x: 6, y: -8 },
25 | ]},
26 | { x: 6, y: 8 },
27 | { bezier: [
28 | { x: 0, y: 8, z: -5 },
29 | { x: 0, y: 8, z: 5 },
30 | { x: -6, y: 8 },
31 | ]},
32 | { x: -6, y: 8 },
33 | ],
34 | addTo: illo,
35 | stroke: 2,
36 | color: '#19F',
37 | });
38 |
39 | // quarter circle
40 | new Zdog.Shape({
41 | path: [
42 | { x: 10, y: 0 },
43 | { arc: [
44 | { x: 20, y: 0 },
45 | { x: 20, y: 10 }
46 | ]},
47 | { x: 10, y: 10 }
48 | ],
49 | addTo: illo,
50 | stroke: 2,
51 | color: '#A00',
52 | });
53 |
54 | // -- animate --- //
55 |
56 | function animate() {
57 | illo.updateRenderGraph();
58 | requestAnimationFrame( animate );
59 | }
60 |
61 | animate();
62 |
--------------------------------------------------------------------------------
/demo/translate-rotate/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | translate-rotate
8 |
9 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | Click & drag to rotate
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/demo/castle/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | castle
8 |
9 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/demo/tri-prism/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | tri-prism
8 |
9 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/demo/patties/patties.js:
--------------------------------------------------------------------------------
1 | // ------------------------- demo ------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var sceneSize = 48;
5 | var minWindowSize = Math.min( window.innerWidth - 20 , window.innerHeight - 20 );
6 | var zoom = Math.floor( minWindowSize / sceneSize );
7 | var illoSize = sceneSize * zoom;
8 | illoElem.setAttribute( 'width', illoSize );
9 | illoElem.setAttribute( 'height', illoSize );
10 | var isSpinning = true;
11 | var TAU = Zdog.TAU;
12 |
13 | var illo = new Zdog.Illustration({
14 | element: illoElem,
15 | zoom: zoom,
16 | dragRotate: true,
17 | onDragStart: function() {
18 | isSpinning = false;
19 | },
20 | });
21 |
22 | // ----- model ----- //
23 |
24 | var rect = new Zdog.Rect({
25 | width: 20,
26 | height: 20,
27 | addTo: illo,
28 | translate: { y: 2 },
29 | rotate: { x: TAU/4 },
30 | stroke: 2,
31 | color: '#E21',
32 | });
33 |
34 | new Zdog.Ellipse({
35 | diameter: 20,
36 | addTo: illo,
37 | translate: { y: -2 },
38 | rotate: { x: TAU/4 },
39 | stroke: 2,
40 | color: '#19F',
41 | });
42 |
43 | new Zdog.Shape({
44 | addTo: rect,
45 | translate: { y: -10, z: 2 },
46 | stroke: 2,
47 | color: '#EA0',
48 | });
49 |
50 | // ----- animate ----- //
51 |
52 | function animate() {
53 | illo.rotate.y += isSpinning ? +TAU/150 : 0;
54 | illo.updateRenderGraph();
55 | requestAnimationFrame( animate );
56 | }
57 |
58 | animate();
59 |
60 |
--------------------------------------------------------------------------------
/demo/truck-flight/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | truck-flight
8 |
9 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Click & drag to rotate
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/demo/cones/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | cones
8 |
9 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/demo/codepen-logo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | codepen-logo
8 |
9 |
29 |
30 |
31 |
32 |
33 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/demo/sauropod/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | sauropod
8 |
9 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
Click & drag to rotate
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/demo/crypto-kitty/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | crypto-kitty
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/demo/mario/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | mario
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Click & drag to rotate
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/demo/mega-man/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | mega-man
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/demo/shade-and-shades/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | shade & shades
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Click & drag to rotate
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/demo/bird-house/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | bird house
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/demo/hemisphere-ball/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | hemisphere ball
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/demo/template/demo.js:
--------------------------------------------------------------------------------
1 | // ------------------------- demo ------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var sceneSize = 48;
5 | var minWindowSize = Math.min( window.innerWidth - 20 , window.innerHeight - 20 );
6 | var zoom = Math.floor( minWindowSize / sceneSize );
7 | var illoSize = sceneSize * zoom;
8 | illoElem.setAttribute( 'width', illoSize );
9 | illoElem.setAttribute( 'height', illoSize );
10 | var isSpinning = true;
11 | var TAU = Zdog.TAU;
12 |
13 | var illo = new Zdog.Illustration({
14 | element: illoElem,
15 | zoom: zoom,
16 | dragRotate: true,
17 | onDragStart: function() {
18 | isSpinning = false;
19 | },
20 | });
21 |
22 | // ----- model ----- //
23 |
24 | new Zdog.Rect({
25 | width: 20,
26 | height: 20,
27 | addTo: illo,
28 | translate: { z: -10 },
29 | stroke: 2,
30 | color: '#E21',
31 | });
32 |
33 | new Zdog.Ellipse({
34 | diameter: 16,
35 | addTo: illo,
36 | translate: { z: 10 },
37 | stroke: 4,
38 | color: '#19F',
39 | });
40 |
41 | new Zdog.Shape({
42 | path: [
43 | { x: 0, z: 1 },
44 | { x: -1, z: -1 },
45 | { x: 1, z: -1 },
46 | ],
47 | scale: { x: 5, z: 5 },
48 | addTo: illo,
49 | stroke: 2,
50 | fill: true,
51 | color: '#EA0',
52 | });
53 |
54 | new Zdog.Shape({
55 | translate: { x: 10, y: -5 },
56 | addTo: illo,
57 | stroke: 7,
58 | color: '#246',
59 | });
60 |
61 | // ----- animate ----- //
62 |
63 | function animate() {
64 | illo.rotate.y += isSpinning ? +TAU/150 : 0;
65 | illo.updateRenderGraph();
66 | requestAnimationFrame( animate );
67 | }
68 |
69 | animate();
70 |
71 |
--------------------------------------------------------------------------------
/demo/inside-house/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | inside house
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Click & drag to rotate
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/demo/rgb-birdie/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | rgb birdie
8 |
9 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/demo/patties/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | template
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/demo/template/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | template
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/demo/gear-icon/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | gear-icon
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/demo/cylinders/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | cylinders
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/demo/la-link/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Link's Awakening Link
8 |
9 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/demo/strutter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | strutter
8 |
9 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/demo/solid-shifter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | solid-shifter
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/demo/translate-rotate/translate-rotate.js:
--------------------------------------------------------------------------------
1 | var illoElem = document.querySelector('.illo');
2 | var illoSize = 72;
3 | var zoom = 6;
4 | illoElem.setAttribute( 'width', illoSize * zoom );
5 | illoElem.setAttribute( 'height', illoSize * zoom );
6 | var TAU = Zdog.TAU;
7 |
8 |
9 | var illo = new Zdog.Illustration({
10 | element: illoElem,
11 | zoom: zoom,
12 | dragRotate: true,
13 | });
14 |
15 | // -- illustration shapes --- //
16 |
17 | var rect1 = new Zdog.Rect({
18 | width: 12,
19 | height: 16,
20 | translate: { z: -6 },
21 | // rotate: { z: 1 },
22 | stroke: 2,
23 | // fill: true,
24 | color: '#08D',
25 | addTo: illo,
26 | });
27 |
28 | var moon1 = new Zdog.Shape({
29 | path: [
30 | { z: 0 },
31 | { z: 6 }
32 | ],
33 | translate: { y: -11 },
34 | stroke: 3,
35 | color: 'white',
36 | addTo: rect1,
37 | });
38 |
39 | new Zdog.Rect({
40 | width: 12,
41 | height: 8,
42 | translate: { y: 8 },
43 | rotate: { x: TAU/4 },
44 | stroke: 2,
45 | fill: true,
46 | color: '#E21',
47 | addTo: illo,
48 | });
49 |
50 | new Zdog.Shape({
51 | path: [
52 | { y: -6, z: 4 },
53 | { y: 6, z: 4 },
54 | { y: 6, z: 0 },
55 | { y: -6, z: 0 },
56 | ],
57 | stroke: 1,
58 | fill: true,
59 | color: '#F80',
60 | addTo: illo,
61 | });
62 |
63 | // -- animate --- //
64 |
65 | var rZSpeed = 0;
66 |
67 | function animate() {
68 | // rotate
69 | moon1.rotate.y += 0.03;
70 | rect1.rotate.z -= 0.02;
71 | illo.rotate.z += rZSpeed;
72 | // update & render
73 | illo.updateRenderGraph();
74 | requestAnimationFrame( animate );
75 | }
76 |
77 | animate();
78 |
79 | // ----- inputs ----- //
80 |
81 | document.querySelector('.toggle-z-rotation-button').onclick = function() {
82 | rZSpeed = rZSpeed ? 0 : TAU/360;
83 | };
84 |
--------------------------------------------------------------------------------
/demo/composite-shapes-scale-svg/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | composite-shapes-scale-svg
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/demo/composite-shapes-scale/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | composite-shapes-scale
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/demo/madeline/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | madeline
8 |
9 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/demo/fizzy-bear/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | fizzy-bear
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Click & drag to rotate
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/demo/santorini/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | santorini
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/demo/happy-town/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | happy town
8 |
9 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Click & drag to rotate
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/demo/little-forest/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | little forest
8 |
9 |
45 |
46 |
47 |
48 |
49 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/demo/santorini/make-rock.js:
--------------------------------------------------------------------------------
1 | /* globals midnight */
2 |
3 | // width
4 | // depth
5 | // height
6 | // translate
7 | // eastOffset
8 | // westOffset
9 | // northOffset
10 | // southOffset
11 |
12 | window.makeRock = function( options ) {
13 |
14 | var x = options.width/2;
15 | var z = options.depth/2;
16 | var y = -options.height;
17 | var bottomWestNorth = { x: -x, y: 0, z: z };
18 | var bottomEastNorth = { x: x, y: 0, z: z };
19 | var bottomEastSouth = { x: x, y: 0, z: -z };
20 | var bottomWestSouth = { x: -x, y: 0, z: -z };
21 |
22 | var topWestX = x + ( options.westOffset || 0 );
23 | var topEastX = x + ( options.eastOffset || 0 );
24 | var topNorthZ = z + ( options.northOffset || 0 );
25 | var topSouthZ = z + ( options.southOffset || 0 );
26 |
27 | var topWestNorth = { x: -topWestX, y: y, z: topNorthZ };
28 | var topEastNorth = { x: topEastX, y: y, z: topNorthZ };
29 | var topEastSouth = { x: topEastX, y: y, z: -topSouthZ };
30 | var topWestSouth = { x: -topWestX, y: y, z: -topSouthZ };
31 |
32 | var anchor = new Zdog.Anchor({
33 | addTo: options.addTo,
34 | translate: options.translate,
35 | });
36 |
37 | function makeRockFace( path ) {
38 | new Zdog.Shape({
39 | path: path,
40 | addTo: anchor,
41 | color: midnight,
42 | stroke: 2,
43 | });
44 | }
45 |
46 | // north face
47 | makeRockFace([
48 | topWestNorth,
49 | topEastNorth,
50 | bottomEastNorth,
51 | bottomWestNorth,
52 | ]);
53 | // south face
54 | makeRockFace([
55 | topWestSouth,
56 | topEastSouth,
57 | bottomEastSouth,
58 | bottomWestSouth,
59 | ]);
60 | // west face
61 | makeRockFace([
62 | topWestSouth,
63 | topWestNorth,
64 | bottomWestNorth,
65 | bottomWestSouth,
66 | ]);
67 |
68 | // east face
69 | makeRockFace([
70 | topEastSouth,
71 | topEastNorth,
72 | bottomEastNorth,
73 | bottomEastSouth,
74 | ]);
75 | // top face
76 | makeRockFace([
77 | topWestNorth,
78 | topEastNorth,
79 | topEastSouth,
80 | topWestSouth,
81 | ]);
82 |
83 | };
84 |
--------------------------------------------------------------------------------
/demo/madeline/make-bird.js:
--------------------------------------------------------------------------------
1 | /* globals TAU */
2 |
3 | window.makeBird = function( options ) {
4 |
5 | var spin = options.spin || 0;
6 |
7 | var arrow = new Zdog.Anchor({
8 | addTo: options.addTo,
9 | scale: 2/3,
10 | rotate: { z: spin },
11 | });
12 |
13 | var bird = new Zdog.Group({
14 | addTo: arrow,
15 | translate: { x: 87 },
16 | rotate: { x: -spin },
17 | });
18 |
19 | // bird body
20 | new Zdog.Shape({
21 | path: [
22 | { x: -3, y: 0 },
23 | { arc: [
24 | { x: -2, y: 1.5 },
25 | { x: 0, y: 1.5 },
26 | ]},
27 | { arc: [
28 | { x: 2, y: 1.5 },
29 | { x: 2, y: 0 },
30 | ]},
31 | ],
32 | addTo: bird,
33 | translate: { x: 0.5 },
34 | stroke: 3,
35 | color: options.color,
36 | fill: true,
37 | });
38 |
39 | // bird head
40 | new Zdog.Shape({
41 | translate: { x: 4, y: -1 },
42 | addTo: bird,
43 | stroke: 4,
44 | color: options.color,
45 | });
46 |
47 | // beak
48 | new Zdog.Shape({
49 | path: [
50 | { x: 0, y: -1 },
51 | { x: 3, y: 0 },
52 | { x: 0, y: 1 },
53 | ],
54 | addTo: bird,
55 | translate: { x: 5, y: -1 },
56 | stroke: 1,
57 | color: options.color,
58 | fill: true,
59 | });
60 |
61 | // tail feather
62 | new Zdog.Shape({
63 | path: [
64 | { x: -3, z: -2 },
65 | { x: 0, z: 0 },
66 | { x: -3, z: 2 },
67 | ],
68 | addTo: bird,
69 | translate: { x: -4, y: 0 },
70 | stroke: 2,
71 | color: options.color,
72 | fill: true,
73 | });
74 |
75 | var wing = new Zdog.Shape({
76 | path: [
77 | { x: 3, y: 0 },
78 | { x: -1, y: -9 },
79 | { arc: [
80 | { x: -5, y: -4 },
81 | { x: -3, y: 0 },
82 | ]},
83 | ],
84 | addTo: bird,
85 | translate: { z: -1.5},
86 | rotate: { x: TAU/8 },
87 | stroke: 1,
88 | color: options.color,
89 | fill: true,
90 | });
91 |
92 | wing.copy({
93 | translate: { z: 1.5},
94 | scale: { z: -1 },
95 | rotate: { x: -TAU/8 },
96 | });
97 |
98 | };
99 |
--------------------------------------------------------------------------------
/demo/santorini/buildings.js:
--------------------------------------------------------------------------------
1 | /* globals makeBuilding */
2 |
3 | window.oneStoryBuilding = function( options ) {
4 |
5 | var anchor = new Zdog.Anchor({
6 | addTo: options.addTo,
7 | translate: options.translate,
8 | });
9 |
10 | var isNS = options.gable == 'ns';
11 |
12 | var buildOptions = {
13 | width: isNS ? 8 : 10,
14 | height: 8,
15 | depth: isNS ? 10 : 8,
16 | gable: options.gable,
17 | addTo: anchor,
18 | };
19 |
20 | // single window
21 | buildOptions[ options.gable + 'Windows'] = [ { x: 0 } ];
22 | // two windows on long side
23 | var oppositeSide = isNS ? 'ew' : 'ns';
24 | buildOptions[ oppositeSide + 'Windows'] = [
25 | { x: -2 },
26 | { x: 2 },
27 | ];
28 |
29 | makeBuilding( buildOptions );
30 |
31 | };
32 |
33 | window.twoStoryBuilding = function( options ) {
34 |
35 | var anchor = new Zdog.Anchor({
36 | addTo: options.addTo,
37 | translate: options.translate,
38 | });
39 |
40 | var isNS = options.gable == 'ns';
41 |
42 | var buildOptions = {
43 | width: isNS ? 8 : 10,
44 | height: 14,
45 | depth: isNS ? 10 : 8,
46 | gable: options.gable,
47 | addTo: anchor,
48 | };
49 |
50 | // single column
51 | buildOptions[ options.gable + 'Windows'] = [
52 | { x: 0, y: -5 },
53 | { x: 0, y: -11 },
54 | ];
55 | // two windows on long side
56 | var oppositeSide = isNS ? 'ew' : 'ns';
57 | buildOptions[ oppositeSide + 'Windows'] = [
58 | { x: -2, y: -5 },
59 | { x: 2, y: -5 },
60 | { x: -2, y: -11 },
61 | { x: 2, y: -11 },
62 | ];
63 |
64 | makeBuilding( buildOptions );
65 |
66 | };
67 |
68 |
69 | window.oneStorySlanter = function( options ) {
70 |
71 | var anchor = new Zdog.Anchor({
72 | addTo: options.addTo,
73 | translate: options.translate,
74 | });
75 |
76 | makeBuilding({
77 | width: 14,
78 | height: 8,
79 | depth: 6,
80 | gable: options.gable,
81 | addTo: anchor,
82 | nsWindows: [
83 | { x: -4 },
84 | { x: 0 },
85 | { x: 4 },
86 | ],
87 | ewWindows: [
88 | { x: 0 }
89 | ],
90 | });
91 |
92 | };
--------------------------------------------------------------------------------
/demo/unpkg-explode/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | unpkg explode
8 |
9 |
29 |
30 |
31 |
32 |
33 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/demo/composite-shapes-scale-svg/composite-shapes-scale-svg.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var svg = document.querySelector('svg');
4 | var sceneSize = 48;
5 | var minWindowSize = Math.min( window.innerWidth - 20 , window.innerHeight - 20 );
6 | var zoom = Math.floor( minWindowSize / sceneSize );
7 | svg.setAttribute( 'width', sceneSize * zoom );
8 | svg.setAttribute( 'height', sceneSize * zoom );
9 | var isSpinning = true;
10 | var TAU = Zdog.TAU;
11 |
12 | var illo = new Zdog.Illustration({
13 | element: svg,
14 | zoom: zoom,
15 | scale: 2,
16 | dragRotate: true,
17 | onDragStart: function() {
18 | isSpinning = false;
19 | },
20 | });
21 |
22 | // -- illustration shapes --- //
23 |
24 | new Zdog.Rect({
25 | width: 10,
26 | height: 10,
27 | addTo: illo,
28 | translate: { z: -10 },
29 | stroke: 2,
30 | color: '#E21',
31 | });
32 |
33 | /*
34 | new Zdog.Ellipse({
35 | diameter: 16,
36 | addTo: illo,
37 | translate: { z: 10 },
38 | stroke: 4,
39 | color: '#19F',
40 | });
41 |
42 | new Zdog.Shape({
43 | path: [
44 | { x: 0, z: 1 },
45 | { x: -1, z: -1 },
46 | { x: 1, z: -1 },
47 | ],
48 | scale: { x: 5, z: 5 },
49 | addTo: illo,
50 | stroke: 2,
51 | fill: true,
52 | color: '#EA0',
53 | });
54 | */
55 |
56 | new Zdog.Hemisphere({
57 | diameter: 4,
58 | scale: 2,
59 | addTo: illo,
60 | translate: { x: 8 },
61 | color: '#EA0',
62 | backface: '#456',
63 | stroke: false,
64 | });
65 |
66 | new Zdog.Cylinder({
67 | diameter: 4,
68 | length: 4,
69 | scale: 2,
70 | addTo: illo,
71 | translate: { x: 0 },
72 | color: '#C25',
73 | backface: '#E62',
74 | frontBaseColor: '#EA0',
75 | rearBaseColor: '#636',
76 | stroke: false,
77 | });
78 |
79 | new Zdog.Cone({
80 | diameter: 4,
81 | length: 3,
82 | scale: 2,
83 | addTo: illo,
84 | translate: { x: -8 },
85 | color: '#456',
86 | backface: '#EA0',
87 | stroke: false,
88 | });
89 |
90 | // -- animate --- //
91 |
92 | function animate() {
93 | illo.rotate.y += isSpinning ? +TAU/150 : 0;
94 | illo.updateGraph();
95 | illo.renderGraph();
96 | requestAnimationFrame( animate );
97 | }
98 |
99 | animate();
100 |
101 | // -- update -- //
102 |
--------------------------------------------------------------------------------
/demo/composite-shapes-scale/composite-shapes-scale.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var w = 48;
5 | var h = 48;
6 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
7 | var zoom = Math.min( 8, Math.floor( minWindowSize / w ) );
8 | illoElem.setAttribute( 'width', w * zoom );
9 | illoElem.setAttribute( 'height', h * zoom );
10 |
11 | var TAU = Zdog.TAU;
12 | var isSpinning = true;
13 |
14 | var illo = new Zdog.Illustration({
15 | element: illoElem,
16 | zoom: zoom,
17 | scale: 2,
18 | dragRotate: true,
19 | onDragStart: function() {
20 | isSpinning = false;
21 | },
22 | });
23 |
24 | // -- illustration shapes --- //
25 |
26 | new Zdog.Rect({
27 | width: 10,
28 | height: 10,
29 | addTo: illo,
30 | translate: { z: -10 },
31 | stroke: 2,
32 | color: '#E21',
33 | });
34 |
35 | /*
36 | new Zdog.Ellipse({
37 | diameter: 16,
38 | addTo: illo,
39 | translate: { z: 10 },
40 | stroke: 4,
41 | color: '#19F',
42 | });
43 |
44 | new Zdog.Shape({
45 | path: [
46 | { x: 0, z: 1 },
47 | { x: -1, z: -1 },
48 | { x: 1, z: -1 },
49 | ],
50 | scale: { x: 5, z: 5 },
51 | addTo: illo,
52 | stroke: 2,
53 | fill: true,
54 | color: '#EA0',
55 | });
56 | */
57 |
58 | new Zdog.Hemisphere({
59 | diameter: 4,
60 | scale: 2,
61 | addTo: illo,
62 | translate: { x: 8 },
63 | color: '#EA0',
64 | backface: '#456',
65 | stroke: false,
66 | });
67 |
68 | new Zdog.Cylinder({
69 | diameter: 4,
70 | length: 4,
71 | scale: 2,
72 | addTo: illo,
73 | translate: { x: 0 },
74 | color: '#C25',
75 | backface: '#E62',
76 | frontBaseColor: '#EA0',
77 | rearBaseColor: '#636',
78 | stroke: false,
79 | });
80 |
81 | new Zdog.Cone({
82 | diameter: 4,
83 | length: 3,
84 | scale: 2,
85 | addTo: illo,
86 | translate: { x: -8 },
87 | color: '#456',
88 | backface: '#EA0',
89 | stroke: false,
90 | });
91 |
92 | // -- animate --- //
93 |
94 | function animate() {
95 | illo.rotate.y += isSpinning ? +TAU/150 : 0;
96 | illo.updateGraph();
97 | illo.renderGraph();
98 | requestAnimationFrame( animate );
99 | }
100 |
101 | animate();
102 |
103 | // -- update -- //
104 |
--------------------------------------------------------------------------------
/demo/davey-nippu/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | davey nippu
8 |
9 |
48 |
49 |
50 |
51 |
52 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/demo/codepen-logo/codepen-logo.js:
--------------------------------------------------------------------------------
1 | // ----- setup ----- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var illoSize = 48;
5 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
6 | var zoom = Math.floor( minWindowSize / illoSize );
7 | illoElem.setAttribute( 'width', illoSize * zoom );
8 | illoElem.setAttribute( 'height', illoSize * zoom );
9 |
10 | var TAU = Zdog.TAU;
11 | var isSpinning = true;
12 |
13 | var illo = new Zdog.Illustration({
14 | element: illoElem,
15 | scale: 4,
16 | zoom: zoom,
17 | dragRotate: true,
18 | onDragStart: function() {
19 | isSpinning = false;
20 | },
21 | });
22 |
23 | var tiltAngle = Math.asin(2/3);
24 |
25 | var prism = new Zdog.Anchor({
26 | addTo: illo,
27 | });
28 |
29 | // ----- model ----- //
30 |
31 | var RT2 = Math.sqrt(2);
32 | var capLength = 6/RT2;
33 | var sideLength = 2 / Math.cos( tiltAngle );
34 | var sideZ = sideLength/2;
35 |
36 | var cap = new Zdog.Rect({
37 | width: capLength,
38 | height: capLength,
39 | addTo: prism,
40 | translate: { z: -sideZ },
41 | stroke: 2,
42 | color: 'white',
43 | });
44 |
45 | cap.copy({
46 | translate: { z: sideZ },
47 | });
48 |
49 | var side = new Zdog.Shape({
50 | addTo: prism,
51 | path: [ { z: -1 }, { z: 1 } ],
52 | scale: sideZ,
53 | translate: { x: capLength/2, y: capLength/2 },
54 | stroke: 2,
55 | color: 'white',
56 | });
57 | side.copy({
58 | translate: { x: -capLength/2, y: capLength/2 },
59 | });
60 | side.copy({
61 | translate: { x: -capLength/2, y: -capLength/2 },
62 | });
63 | side.copy({
64 | translate: { x: capLength/2, y: -capLength/2 },
65 | });
66 |
67 | // -- animate --- //
68 |
69 | var ticker = 0;
70 | var cycleCount = 90;
71 |
72 | function animate() {
73 | // update
74 | if ( isSpinning ) {
75 | var progress = ticker / cycleCount;
76 | var tween = Zdog.easeInOut( progress % 1, 3 );
77 | var turn = Math.floor( progress );
78 | if ( turn === 0 ) {
79 | illo.rotate.z = Zdog.lerp( TAU/8 * -3, TAU/8, tween );
80 | illo.rotate.x = Zdog.lerp( 0, tiltAngle, tween );
81 | } else if ( turn == 1 ) {
82 | prism.rotate.x = Zdog.lerp( -TAU/2, 0, tween );
83 | }
84 | ticker++;
85 | }
86 |
87 | illo.updateRenderGraph();
88 | requestAnimationFrame( animate );
89 | }
90 |
91 | animate();
92 |
93 |
94 | // ----- inputs ----- //
95 |
96 | document.querySelector('.reset-button').onclick = reset;
97 |
98 | function reset() {
99 | ticker = 0;
100 | illo.rotate.set({});
101 | isSpinning = true;
102 | }
103 |
--------------------------------------------------------------------------------
/demo/hemisphere-ball/hemisphere-ball.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var w = 48;
5 | var h = 48;
6 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
7 | var zoom = Math.min( 10, Math.floor( minWindowSize / w ) );
8 | illoElem.setAttribute( 'width', w * zoom );
9 | illoElem.setAttribute( 'height', h * zoom );
10 |
11 | var isSpinning = true;
12 | var TAU = Zdog.TAU;
13 |
14 | var illo = new Zdog.Illustration({
15 | element: illoElem,
16 | zoom: zoom,
17 | dragRotate: true,
18 | onDragStart: function() {
19 | isSpinning = false;
20 | },
21 | });
22 |
23 | // colors
24 | var yellow = '#ED0';
25 | var gold = '#EA0';
26 | var orange = '#E62';
27 | var garnet = '#C25';
28 | var eggplant = '#636';
29 |
30 | // -- illustration shapes --- //
31 |
32 | var hemi = new Zdog.Hemisphere({
33 | diameter: 13,
34 | addTo: illo,
35 | translate: { y: -16 },
36 | rotate: { x: -TAU/4 },
37 | color: garnet,
38 | backface: eggplant,
39 | stroke: false,
40 | });
41 | hemi.copy({
42 | translate: { y: 16 },
43 | rotate: { x: TAU/4 },
44 | color: garnet,
45 | backface: eggplant,
46 | });
47 |
48 | var colorWheel = [ eggplant, garnet, orange, gold, yellow, ];
49 |
50 | [ -1, 1 ].forEach( function( ySide ) {
51 | for ( var i=0; i < 5; i++ ) {
52 | var rotor1 = new Zdog.Anchor({
53 | addTo: illo,
54 | rotate: { y: TAU/5 * i },
55 | });
56 | var rotor2 = new Zdog.Anchor({
57 | addTo: rotor1,
58 | rotate: { x: TAU/6 },
59 | });
60 |
61 | hemi.copy({
62 | addTo: rotor2,
63 | translate: { y: 16*ySide },
64 | rotate: { x: TAU/4*ySide },
65 | color: colorWheel[i],
66 | backface: colorWheel[ (i+7) % 5 ],
67 | });
68 | }
69 | });
70 |
71 | // -- animate --- //
72 |
73 | var keyframes = [
74 | { x: TAU * 0, y: TAU * 0 },
75 | { x: TAU * 1/2, y: TAU * 1/2 },
76 | { x: TAU * 1, y: TAU * 1 },
77 | ];
78 |
79 | var t = 0;
80 |
81 | function animate() {
82 | rotate();
83 | illo.updateRenderGraph();
84 | requestAnimationFrame( animate );
85 | }
86 |
87 | animate();
88 |
89 | // -- update -- //
90 |
91 | function rotate() {
92 | if ( !isSpinning ) {
93 | return;
94 | }
95 | var easeT = Zdog.easeInOut( t % 1, 3 );
96 | var turnLimit = keyframes.length - 1;
97 | var turn = Math.floor( t % turnLimit );
98 | var keyA = keyframes[ turn ];
99 | var keyB = keyframes[ turn + 1 ];
100 | var thetaX = Zdog.lerp( keyA.x, keyB.x, easeT );
101 | illo.rotate.x = Math.cos( thetaX ) * TAU/12;
102 | illo.rotate.y = Zdog.lerp( keyA.y, keyB.y, easeT ) ;
103 | t += 1/180;
104 | }
105 |
--------------------------------------------------------------------------------
/demo/gear-icon/gear-icon.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var w = 48;
5 | var h = 48;
6 | var minWindowSize = Math.min( window.innerWidth - 20 , window.innerHeight - 20 );
7 | var zoom = Math.floor( minWindowSize / w );
8 | illoElem.setAttribute( 'width', w * zoom );
9 | illoElem.setAttribute( 'height', h * zoom );
10 | var isSpinning = true;
11 | var TAU = Zdog.TAU;
12 |
13 | var illo = new Zdog.Illustration({
14 | element: illoElem,
15 | zoom: zoom,
16 | rotate: { x: -TAU/8 },
17 | dragRotate: true,
18 | onDragStart: function() {
19 | isSpinning = false;
20 | },
21 | });
22 |
23 | // -- illustration shapes --- //
24 |
25 | var teeth = 8;
26 | var frontZ = { z: 3 };
27 | var backZ = { z: -3 };
28 |
29 | var colorA = '#EA0';
30 | var colorB = '#345';
31 |
32 | var gearPath = ( function() {
33 | var path = [];
34 | var teethCount = teeth * 4;
35 | for ( var i=0; i < teethCount; i++ ) {
36 | var isOuter = i % 4 < 2;
37 | var radius = isOuter ? 12 : 9.5;
38 | var theta = Math.ceil( i/2 ) * 2;
39 | theta += i % 2 ? -0.2 : 0.2;
40 | theta = ( theta/teethCount + 1/teethCount ) * TAU ;
41 | path.push({
42 | x: Math.cos( theta ) * radius,
43 | y: Math.sin( theta ) * radius,
44 | });
45 | }
46 | return path;
47 | })();
48 |
49 | var gear = new Zdog.Anchor({
50 | addTo: illo,
51 | rotate: { x: TAU/4 },
52 | });
53 |
54 | var gearSide = new Zdog.Anchor({
55 | addTo: gear,
56 | translate: frontZ,
57 | });
58 | // gear face
59 | new Zdog.Shape({
60 | addTo: gearSide,
61 | path: gearPath,
62 | color: colorA,
63 | backface: false,
64 | fill: true,
65 | stroke: 1/zoom,
66 | closed: false,
67 | // visible: false,
68 | });
69 | // nub
70 | new Zdog.Cylinder({
71 | addTo: gearSide,
72 | diameter: 6,
73 | length: 2,
74 | color: colorB,
75 | backface: 'white',
76 | translate: { z: 1 },
77 | fill: true,
78 | stroke: false,
79 | });
80 |
81 | gearSide.copyGraph({
82 | rotate: { y: TAU/2 },
83 | translate: backZ,
84 | });
85 |
86 | gearPath.forEach( function( corner, i ) {
87 | var nextCorner = gearPath[ i + 1 ] || gearPath[0];
88 | new Zdog.Shape({
89 | addTo: gear,
90 | path: [
91 | new Zdog.Vector( corner ).add( frontZ ),
92 | new Zdog.Vector( corner ).add( backZ ),
93 | new Zdog.Vector( nextCorner ).add( backZ ),
94 | new Zdog.Vector( nextCorner ).add( frontZ ),
95 | ],
96 | color: i % 2 ? colorA : colorB,
97 | fill: true,
98 | stroke: 1/zoom,
99 | });
100 | });
101 |
102 | // -- animate --- //
103 |
104 | function animate() {
105 | illo.rotate.y += isSpinning ? +TAU/240 : 0;
106 | illo.updateRenderGraph();
107 | requestAnimationFrame( animate );
108 | }
109 |
110 | animate();
111 |
112 |
--------------------------------------------------------------------------------
/demo/cylinders/cylinders.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var w = 48;
5 | var h = 48;
6 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
7 | var zoom = Math.min( 10, Math.floor( minWindowSize / w ) );
8 | illoElem.setAttribute( 'width', w * zoom );
9 | illoElem.setAttribute( 'height', h * zoom );
10 |
11 | var isSpinning = true;
12 | var TAU = Zdog.TAU;
13 |
14 | var illo = new Zdog.Illustration({
15 | element: illoElem,
16 | zoom: zoom,
17 | dragRotate: true,
18 | onDragStart: function() {
19 | isSpinning = false;
20 | },
21 | });
22 |
23 | // colors
24 | var yellow = '#ED0';
25 | var gold = '#EA0';
26 | var orange = '#E62';
27 | var magenta = '#C25';
28 | var navy = '#249';
29 |
30 | // -- illustration shapes --- //
31 |
32 | var y = 12;
33 |
34 | var cylinder = new Zdog.Cylinder({
35 | diameter: 10,
36 | length: 5,
37 | addTo: illo,
38 | translate: { y: -y },
39 | rotate: { x: -TAU/4 },
40 | // rotate: { x: -TAU/8 },
41 | color: magenta,
42 | backface: navy,
43 | stroke: false,
44 | });
45 | cylinder.copy({
46 | addTo: illo,
47 | translate: { y: y },
48 | rotate: { x: TAU/4 },
49 | color: magenta,
50 | backface: navy,
51 | });
52 |
53 | var colorWheel = [ navy, magenta, orange, gold, yellow, ];
54 |
55 | [ -1, 1 ].forEach( function( ySide ) {
56 | for ( var i=0; i < 5; i++ ) {
57 | var rotor1 = new Zdog.Anchor({
58 | addTo: illo,
59 | rotate: { y: TAU/5 * i },
60 | });
61 | var rotor2 = new Zdog.Anchor({
62 | addTo: rotor1,
63 | rotate: { x: TAU/6 },
64 | });
65 |
66 | cylinder.copy({
67 | addTo: rotor2,
68 | translate: { y: y*ySide },
69 | rotate: { x: TAU/4*ySide },
70 | color: colorWheel[i],
71 | backface: colorWheel[ (i+7) % 5 ],
72 | });
73 | }
74 | });
75 |
76 | new Zdog.Shape({
77 | visible: false,
78 | addTo: illo,
79 | stroke: 18,
80 | // color: '#FED',
81 | color: 'hsla(50, 50%, 90%, 0.8)',
82 | });
83 |
84 | // -- animate --- //
85 |
86 | var keyframes = [
87 | { x: TAU * 0, y: TAU * 0 },
88 | { x: TAU * 1/2, y: TAU * 1/2 },
89 | { x: TAU * 1, y: TAU * 1 },
90 | ];
91 |
92 | var t = 0;
93 |
94 | function animate() {
95 | spin();
96 | illo.updateRenderGraph();
97 | requestAnimationFrame( animate );
98 | }
99 |
100 | animate();
101 |
102 | // -- update -- //
103 |
104 | function spin() {
105 | if ( !isSpinning ) {
106 | return;
107 | }
108 | var easeT = Zdog.easeInOut( t % 1, 3 );
109 | var turnLimit = keyframes.length - 1;
110 | var turn = Math.floor( t % turnLimit );
111 | var keyA = keyframes[ turn ];
112 | var keyB = keyframes[ turn + 1 ];
113 | var thetaX = Zdog.lerp( keyA.x, keyB.x, easeT );
114 | illo.rotate.x = Math.cos( thetaX ) * TAU/12;
115 | illo.rotate.y = Zdog.lerp( keyA.y, keyB.y, easeT ) ;
116 | t += 1/180;
117 | }
118 |
119 |
--------------------------------------------------------------------------------
/demo/bird-house/bird-house.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var w = 48;
5 | var h = 48;
6 | var minWindowSize = Math.min( window.innerWidth - 20 , window.innerHeight - 20 );
7 | var zoom = Math.floor( minWindowSize / w );
8 | illoElem.setAttribute( 'width', w * zoom );
9 | illoElem.setAttribute( 'height', h * zoom );
10 | var isSpinning = false;
11 | var TAU = Zdog.TAU;
12 | // colors
13 | var yellow = "#ED0";
14 | var gold = '#EA0';
15 | var orange = '#E62';
16 | var garnet = '#C25';
17 | var eggplant = '#636';
18 |
19 | [ Zdog.Shape, Zdog.Ellipse, Zdog.Rect ].forEach( function( ShapeClass ) {
20 | ShapeClass.defaults.stroke = 1/zoom;
21 | ShapeClass.defaults.fill = true;
22 | });
23 |
24 | var illo = new Zdog.Illustration({
25 | element: illoElem,
26 | zoom: zoom,
27 | dragRotate: true,
28 | onDragStart: function() {
29 | isSpinning = false;
30 | },
31 | });
32 |
33 | // -- illustration shapes --- //
34 |
35 | var house = new Zdog.Anchor({
36 | addTo: illo,
37 | scale: 4,
38 | });
39 |
40 | var frontGroup = new Zdog.Group({
41 | addTo: house,
42 | translate: { z: 2 },
43 | });
44 |
45 | var gable = new Zdog.Shape({
46 | addTo: frontGroup,
47 | path: [
48 | { x: 0, y: -2 },
49 | { x: 2, y: 0 },
50 | { x: 2, y: 2 },
51 | { x: -2, y: 2 },
52 | { x: -2, y: 0 },
53 | ],
54 | closed: true,
55 | color: gold,
56 | });
57 | gable.copy({
58 | addTo: house,
59 | translate: { z: -2 },
60 | color: garnet,
61 | });
62 |
63 | // hole
64 | new Zdog.Ellipse({
65 | addTo: frontGroup,
66 | diameter: 1.25,
67 | color: eggplant,
68 | stroke: false,
69 | });
70 |
71 | var side = new Zdog.Rect({
72 | addTo: house,
73 | width: 4,
74 | height: 2,
75 | rotate: { y: TAU/4 },
76 | translate: { x: 2, y: 1 },
77 | color: orange,
78 | });
79 | side.copy({
80 | translate: { x: -2, y: 1 },
81 | color: garnet,
82 | });
83 |
84 | var roofAnchor = new Zdog.Anchor({
85 | addTo: house,
86 | translate: { y: -2 },
87 | rotate: { z: -TAU/8 },
88 | });
89 |
90 | var roofW = Math.sqrt(2) * 2;
91 | // var roofW = 4;
92 |
93 | var roof = new Zdog.Rect({
94 | addTo: roofAnchor,
95 | width: roofW,
96 | height: 4,
97 | translate: { x: -roofW/2 },
98 | rotate: { x: TAU/4 },
99 | color: orange,
100 | backface: eggplant,
101 | });
102 |
103 | roof.copy({
104 | width: 1,
105 | translate: { x: -roofW - 0.5 },
106 | // color: gold,
107 | });
108 |
109 | var roofCopy = roofAnchor.copyGraph({
110 | scale: { x: -1 },
111 | rotate: { z: TAU/8 },
112 | });
113 |
114 | roofCopy.children[0].color = yellow;
115 | roofCopy.children[1].color = yellow;
116 |
117 | // base
118 | new Zdog.Rect({
119 | addTo: house,
120 | width: 4,
121 | height: 4,
122 | translate: { y: 2 },
123 | rotate: { x: TAU/4 },
124 | color: eggplant,
125 | });
126 |
127 | // -- animate --- //
128 |
129 | function animate() {
130 | illo.rotate.y += isSpinning ? +TAU/150 : 0;
131 | illo.updateRenderGraph();
132 | requestAnimationFrame( animate );
133 | }
134 |
135 | animate();
136 |
137 |
--------------------------------------------------------------------------------
/demo/rgb-birdie/rgb-birdie.js:
--------------------------------------------------------------------------------
1 | // ------------------------- demo ------------------------- //
2 |
3 | var sceneSize = 270;
4 | var TAU = Zdog.TAU;
5 | var initialRotate = new Zdog.Vector({ x: -35, y: -45 }).multiply( TAU/360 );
6 |
7 | var illo = new Zdog.Illustration({
8 | element: '.illo',
9 | rotate: initialRotate,
10 | dragRotate: true,
11 | resize: 'fullscreen',
12 | onResize: function( width, height ) {
13 | this.zoom = Math.floor( Math.min( width, height ) / sceneSize * 2 ) / 2;
14 | },
15 | });
16 |
17 | // ----- model ----- //
18 |
19 | var bird = new Zdog.Anchor({
20 | addTo: illo,
21 | translate: { z: -20 },
22 | });
23 |
24 | var letterGroup = new Zdog.Group({
25 | addTo: bird,
26 | });
27 |
28 | // R
29 | new Zdog.Shape({
30 | addTo: letterGroup,
31 | path: [
32 | { x: -55, y: -55 },
33 | { x: 15, y: -55 },
34 | { arc: [
35 | { x: 55, y: -55 },
36 | { x: 55, y: -15 },
37 | ]},
38 | { bezier: [
39 | { x: 55, y: 0 },
40 | { x: 47, y: 13 },
41 | { x: 35, y: 20 },
42 | ]},
43 | { x: 29, y: 23 },
44 | { x: 50, y: 55 },
45 | { x: -55, y: 55 },
46 | ],
47 | rotate: { x: TAU/4 },
48 | color: '#F00',
49 | stroke: 10,
50 | fill: true,
51 | });
52 |
53 | // G
54 | new Zdog.Shape({
55 | addTo: letterGroup,
56 | path: [
57 | { x: 0, y: -55 },
58 | { bezier: [
59 | { x: 18, y: -55 },
60 | { x: 32, y: -46 },
61 | { x: 40, y: -38 },
62 | ]},
63 | { x: 7, y: -5 },
64 | { x: 55, y: -5 },
65 | { x: 55, y: 53 },
66 | { x: 35, y: 47 },
67 | { bezier: [
68 | { x: 21, y: 52 },
69 | { x: 10, y: 55 },
70 | { x: 0, y: 55 },
71 | ]},
72 | { arc: [
73 | { x: -55, y: 55 },
74 | { x: -55, y: 0 },
75 | ]},
76 | { arc: [
77 | { x: -55, y: -55 },
78 | { x: 0, y: -55 },
79 | ]},
80 | ],
81 | translate: { x: -30, y: 20, z: 33 },
82 | rotate: { y: TAU/4 },
83 | color: '#0F0',
84 | stroke: 10,
85 | fill: true,
86 | });
87 |
88 | // B
89 | new Zdog.Shape({
90 | addTo: letterGroup,
91 | path: [
92 | { x: -55, y: -55 },
93 | { x: 25, y: -55 },
94 | { arc: [
95 | { x: 55, y: -55 },
96 | { x: 55, y: -25 },
97 | ]},
98 | { bezier: [
99 | { x: 55, y: -13 },
100 | { x: 49, y: -7 },
101 | { x: 42, y: -4 },
102 | ]},
103 | { x: 35, y: 0 },
104 | { x: 42, y: 4 },
105 | { bezier: [
106 | { x: 49, y: 7 },
107 | { x: 55, y: 13 },
108 | { x: 55, y: 25 },
109 | ]},
110 | { arc: [
111 | { x: 55, y: 55 },
112 | { x: 25, y: 55 },
113 | ]},
114 | { x: -55, y: 55 },
115 | ],
116 | translate: { y: -10, z: 60 },
117 | color: '#00F',
118 | stroke: 10,
119 | fill: true,
120 | });
121 |
122 | var eye = new Zdog.Shape({
123 | addTo: bird,
124 | translate: { x: -60, y: -40, z: 30 },
125 | stroke: 18,
126 | color: '#111',
127 | });
128 |
129 | // screen blend letters
130 | letterGroup.render = function( ctx ) {
131 | ctx.globalCompositeOperation = 'screen';
132 | Zdog.Group.prototype.render.apply( this, arguments );
133 | };
134 | // normal blend eye
135 | eye.render = function( ctx ) {
136 | ctx.globalCompositeOperation = 'source-over';
137 | Zdog.Shape.prototype.render.apply( this, arguments );
138 | };
139 |
140 | // ----- animate ----- //
141 |
142 | function animate() {
143 | illo.updateRenderGraph();
144 | requestAnimationFrame( animate );
145 | }
146 |
147 | animate();
148 |
149 |
--------------------------------------------------------------------------------
/demo/inside-house/inside-house.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var w = 48;
5 | var h = 48;
6 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
7 | var zoom = Math.min( 8, Math.floor( minWindowSize / w ) );
8 | illoElem.setAttribute( 'width', w * zoom );
9 | illoElem.setAttribute( 'height', h * zoom );
10 |
11 | var isSpinning = true;
12 | var TAU = Zdog.TAU;
13 |
14 | // default to flat, filled shapes
15 | [ Zdog.Shape, Zdog.Rect, Zdog.Ellipse ].forEach( function( ItemClass ) {
16 | ItemClass.defaults.fill = true;
17 | ItemClass.defaults.stroke = false;
18 | ItemClass.defaults.backface = false;
19 | ItemClass.defaults.front = { z: 1 };
20 | });
21 |
22 | var illo = new Zdog.Illustration({
23 | element: illoElem,
24 | zoom: zoom,
25 | dragRotate: true,
26 | onDragStart: function() {
27 | isSpinning = false;
28 | },
29 | });
30 |
31 | // -- house --- //
32 |
33 | var house = new Zdog.Anchor({
34 | addTo: illo,
35 | scale: 10,
36 | });
37 |
38 | var nsWall = new Zdog.Shape({
39 | path: [
40 | { x: -1, y: -1 },
41 | { x: 0, y: -2 },
42 | { x: 1, y: -1 },
43 | { x: 1, y: 1 },
44 | { x: -1, y: 1 },
45 | ],
46 | addTo: house,
47 | translate: { z: -1 },
48 | fill: true,
49 | color: 'hsla(45, 100%, 50%, 0.6)',
50 | });
51 |
52 | nsWall.copy({
53 | translate: { z: 1 },
54 | rotate: { y: TAU/2 },
55 | });
56 |
57 | var ewWall = new Zdog.Rect({
58 | width: 2,
59 | height: 2,
60 | addTo: house,
61 | translate: { x: -1 },
62 | rotate: { y: -TAU/4 },
63 | fill: true,
64 | color: 'hsla(210, 100%, 50%, 0.6)',
65 | });
66 |
67 | ewWall.copy({
68 | translate: { x: 1 },
69 | rotate: { y: TAU/4 },
70 | });
71 |
72 | // floor
73 | new Zdog.Shape({
74 | path: [
75 | { x: -1, z: -1 },
76 | { x: 1, z: -1 },
77 | { x: 1, z: 1 },
78 | { x: -1, z: 1 },
79 | ],
80 | addTo: house,
81 | backface: true,
82 | translate: { y: 1 },
83 | // front: { y: Zdog.Shape.defaults.front.z * -1 },
84 | fill: true,
85 | color: 'hsla(120, 100%, 40%, 0.8)',
86 | });
87 |
88 | // roof
89 | var roofLength = Math.sqrt(2);
90 | var roof = new Zdog.Shape({
91 | path: [
92 | { x: 0, y: -1 },
93 | { x: roofLength, y: -1 },
94 | { x: roofLength, y: 1 },
95 | { x: 0, y: 1 },
96 | ],
97 | addTo: house,
98 | translate: { y: -2 },
99 | rotate: { x: -TAU/4, y: TAU/8 },
100 | fill: true,
101 | color: 'hsla(0, 100%, 60%, 0.6)',
102 | });
103 |
104 | roof.copy({
105 | scale: { x: -1 },
106 | rotate: { x: -TAU/4, y: -TAU/8 },
107 | });
108 |
109 | // -- chair --- //
110 |
111 | var chair = new Zdog.Group({
112 | addTo: illo,
113 | scale: 2,
114 | translate: { y: 5 },
115 | });
116 | // chair back
117 | var chairLegs = new Zdog.Shape({
118 | path: [
119 | { x: -1, y: 2 },
120 | { x: -1, y: -2 },
121 | { x: 1, y: -2 },
122 | { x: 1, y: 2 },
123 | ],
124 | addTo: chair,
125 | translate: { z: 1 },
126 | closed: false,
127 | stroke: 1,
128 | fill: false,
129 | color: '#333',
130 | backface: true,
131 | });
132 | // chair front
133 | chairLegs.copy({
134 | path: [
135 | { x: -1, y: 2 },
136 | { x: -1, y: 0 },
137 | { x: 1, y: 0 },
138 | { x: 1, y: 2 },
139 | ],
140 | translate: { z: -1 },
141 | });
142 | // chair seat
143 | new Zdog.Rect({
144 | width: 2,
145 | height: 2,
146 | addTo: chair,
147 | rotate: { x: TAU/4 },
148 | stroke: 1,
149 | fill: true,
150 | color: '#333',
151 | backface: true,
152 | });
153 |
154 | // -- animate --- //
155 |
156 | function animate() {
157 | illo.rotate.y += isSpinning ? +TAU/240 : 0;
158 | illo.updateRenderGraph();
159 | requestAnimationFrame( animate );
160 | }
161 |
162 | animate();
163 |
164 |
--------------------------------------------------------------------------------
/demo/cones/cones.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var illoSize = 64;
5 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
6 | var zoom = Math.floor( minWindowSize / illoSize );
7 | illoElem.setAttribute( 'width', illoSize * zoom );
8 | illoElem.setAttribute( 'height', illoSize * zoom );
9 |
10 | var isSpinning = true;
11 | var TAU = Zdog.TAU;
12 |
13 | var illo = new Zdog.Illustration({
14 | element: illoElem,
15 | zoom: zoom,
16 | dragRotate: true,
17 | onDragStart: function() {
18 | isSpinning = false;
19 | },
20 | });
21 |
22 | // colors
23 | var yellow = '#ED0';
24 | // var gold = '#EA0';
25 | var orange = '#E62';
26 | var magenta = '#C25';
27 | // var navy = '#249';
28 | var beige = '#FEC';
29 | var blue = '#8AD';
30 |
31 |
32 | var colorWheel = [ beige, magenta, orange, blue, yellow ];
33 |
34 | // ----- model ----- //
35 |
36 | // top & bottom
37 | var cone = new Zdog.Cone({
38 | diameter: 8,
39 | length: 10,
40 | addTo: illo,
41 | translate: { y: -16 },
42 | // scale: { x: 2, y: 2 },
43 | rotate: { x: -TAU/4 },
44 | color: colorWheel[1],
45 | backface: colorWheel[0],
46 | stroke: false,
47 | });
48 | cone.copy({
49 | translate: { y: 16 },
50 | rotate: { x: TAU/4 },
51 | });
52 |
53 |
54 |
55 | [ -1, 1 ].forEach( function( ySide ) {
56 | for ( var i=0; i < 5; i++ ) {
57 | var rotor1 = new Zdog.Anchor({
58 | addTo: illo,
59 | rotate: { y: TAU/5 * i },
60 | });
61 | var rotor2 = new Zdog.Anchor({
62 | addTo: rotor1,
63 | rotate: { x: TAU/6 },
64 | });
65 |
66 | cone.copy({
67 | addTo: rotor2,
68 | translate: { y: 16*ySide },
69 | rotate: { x: TAU/4*ySide },
70 | color: colorWheel[i],
71 | backface: colorWheel[ (i+7) % 5 ],
72 | });
73 | }
74 | });
75 |
76 | [ -1, 1 ].forEach( function( ySide ) {
77 | for ( var i=0; i < 5; i++ ) {
78 | var rotor1 = new Zdog.Anchor({
79 | addTo: illo,
80 | rotate: { y: TAU/5 * (i+0.5) },
81 | });
82 | var rotor2 = new Zdog.Anchor({
83 | addTo: rotor1,
84 | rotate: { x: TAU/10 },
85 | });
86 |
87 | cone.copy({
88 | addTo: rotor2,
89 | translate: { y: -16*ySide },
90 | rotate: { x: TAU/4*ySide },
91 | color: colorWheel[ (i+3) % 5 ],
92 | backface: colorWheel[i],
93 | });
94 | }
95 | });
96 |
97 | [ -1, 1 ].forEach( function( ySide ) {
98 | for ( var i=0; i < 5; i++ ) {
99 | var rotor1 = new Zdog.Anchor({
100 | addTo: illo,
101 | rotate: { y: TAU/5 * (i+0.5) },
102 | });
103 | var rotor2 = new Zdog.Anchor({
104 | addTo: rotor1,
105 | rotate: { x: TAU/4.5 },
106 | });
107 |
108 | cone.copy({
109 | addTo: rotor2,
110 | translate: { y: -16*ySide },
111 | // scale: { y: -1 },
112 | rotate: { x: TAU/4*ySide },
113 | color: colorWheel[ (i+1) % 5 ],
114 | backface: colorWheel[ (i+4) % 5 ],
115 | });
116 | }
117 | });
118 |
119 |
120 | // -- animate --- //
121 |
122 | var keyframes = [
123 | { x: TAU * 0, y: TAU * 0 },
124 | { x: TAU * 1/2, y: TAU * -1/2 },
125 | { x: TAU * 1, y: TAU * -1 },
126 | ];
127 |
128 | var ticker = 0;
129 | var cycleCount = 180;
130 |
131 | function animate() {
132 | spin();
133 | illo.updateRenderGraph();
134 | requestAnimationFrame( animate );
135 | }
136 |
137 | animate();
138 |
139 | // -- update -- //
140 |
141 | function spin() {
142 | if ( !isSpinning ) {
143 | return;
144 | }
145 | var progress = ticker / cycleCount;
146 | var tween = Zdog.easeInOut( progress % 1, 3 );
147 | var turnLimit = keyframes.length - 1;
148 | var turn = Math.floor( progress % turnLimit );
149 | var keyA = keyframes[ turn ];
150 | var keyB = keyframes[ turn + 1 ];
151 | var thetaX = Zdog.lerp( keyA.x, keyB.x, tween );
152 | illo.rotate.x = Math.cos( thetaX ) * TAU/12;
153 | illo.rotate.y = Zdog.lerp( keyA.y, keyB.y, tween ) ;
154 | ticker++;
155 | }
156 |
--------------------------------------------------------------------------------
/demo/unpkg-explode/unpkg-explode.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var w = 48;
5 | var h = 48;
6 | var minWindowSize = Math.min( window.innerWidth, (window.innerHeight - 200) );
7 | var zoom = Math.floor( minWindowSize / w );
8 | // var zoom = 6;
9 | illoElem.setAttribute( 'width', w * zoom );
10 | illoElem.setAttribute( 'height', h * zoom );
11 | var TAU = Zdog.TAU;
12 |
13 | var isSpinning = false;
14 |
15 | var illo = new Zdog.Illustration({
16 | element: illoElem,
17 | zoom: zoom,
18 | rotate: { x: TAU * (35/360), y: TAU/8 },
19 | dragRotate: true,
20 | onDragStart: function() {
21 | isSpinning = false;
22 | },
23 | });
24 |
25 | var red = '#E21';
26 | var blue = '#19F';
27 | var gold = '#EA0';
28 | var green = '#6C6';
29 | var magenta = '#E2A';
30 |
31 | // -- illustration shapes --- //
32 |
33 | var colors = [ red, blue, gold, magenta, green ];
34 |
35 | var panelAnchors = [];
36 | var panels = [];
37 | var outlines = [];
38 |
39 | [
40 | { y: 0 },
41 | { y: TAU/4 },
42 | { y: TAU/2 },
43 | { y: TAU * 3/4 },
44 | { x: TAU/4 },
45 | ].forEach( function( rotation, i ) {
46 |
47 | var rotor = new Zdog.Anchor({
48 | addTo: illo,
49 | rotate: rotation,
50 | });
51 |
52 | var anchor = new Zdog.Anchor({
53 | addTo: rotor,
54 | translate: { z: -8 },
55 | });
56 |
57 | panelAnchors.push( anchor );
58 |
59 | var panel = new Zdog.RoundedRect({
60 | width: 16,
61 | height: 16,
62 | cornerRadius: 3,
63 | addTo: anchor,
64 | stroke: false,
65 | fill: true,
66 | color: colors[i],
67 | });
68 |
69 | panels.push( panel );
70 |
71 | var outline = panel.copy({
72 | visible: false,
73 | stroke: 1,
74 | fill: false,
75 | color: 'black',
76 | });
77 |
78 | outlines.push( outline );
79 |
80 | });
81 |
82 | // -- animate --- //
83 |
84 | illo.ctx.globalCompositeOperation = 'multiply';
85 |
86 | function animate() {
87 | illo.updateRenderGraph();
88 | requestAnimationFrame( animate );
89 | illo.rotate.y += isSpinning ? +TAU/150 : 0;
90 | }
91 |
92 | animate();
93 |
94 | // ----- animation ----- //
95 |
96 | var animateFrame;
97 |
98 | function animation( duration, onFrame ) {
99 |
100 | var start = now();
101 |
102 | animateFrame = function() {
103 | var ellasped = now() - start;
104 | var t = ellasped / duration;
105 | onFrame( t );
106 | if ( ellasped < duration ) {
107 | requestAnimationFrame( animateFrame );
108 | }
109 | };
110 |
111 | animateFrame();
112 | }
113 |
114 | function now() {
115 | return ( new Date() ).getTime();
116 | }
117 |
118 | function startAnimation() {
119 | animation( 2000, function( t ) {
120 | var easeT = Zdog.easeInOut( t, 3 );
121 | panelAnchors.forEach( function( panelAnchor ) {
122 | panelAnchor.translate.z = Zdog.lerp( -8, -11, easeT );
123 | });
124 | illo.rotate.x = Zdog.lerp( TAU/4, TAU * (35/360), easeT );
125 | illo.rotate.y = Zdog.lerp( -TAU/2, TAU/8, easeT );
126 | });
127 | }
128 |
129 | startAnimation();
130 |
131 | // ----- more inputs ----- //
132 |
133 | var fillP = document.querySelector('.fill-p');
134 | fillP.onchange = function( event ) {
135 | changePanelColor( event.target.value );
136 | };
137 |
138 | // set initial
139 | changePanelColor( fillP.querySelector(':checked').value );
140 |
141 | function changePanelColor( value ) {
142 | panels.forEach( function( panel, i ) {
143 | if ( value == 'gray' ) {
144 | panel.color = '#888';
145 | } else if ( value == 'clear' ) {
146 | panel.color = 'transparent';
147 | } else {
148 | panel.color = colors[i];
149 | }
150 | });
151 | }
152 |
153 | var outlineCheckbox = document.querySelector('.outline-checkbox');
154 | outlineCheckbox.onchange = function( event ) {
155 | outlines.forEach( function( outline ) {
156 | outline.visible = event.target.checked;
157 | });
158 | };
159 |
160 | // set initial
161 | changeOutline( outlineCheckbox.checked );
162 |
163 | function changeOutline( isRendering ) {
164 | outlines.forEach( function( outline ) {
165 | outline.visible = isRendering;
166 | });
167 | }
168 |
--------------------------------------------------------------------------------
/demo/happy-town/make-building.js:
--------------------------------------------------------------------------------
1 | /* globals TAU, red, blue, navy, gold, white */
2 |
3 | // -------------------------- makeBuilding -------------------------- //
4 |
5 | window.makeBuilding = function( options ) {
6 |
7 | var wallX = options.width/2;
8 | var wallY = options.height;
9 | var wallZ = options.depth/2;
10 |
11 | // collect walls
12 | var building = {};
13 |
14 | // south/noth walls
15 | [ true, false ].forEach( function( isSouth ) {
16 | var wallTZ = isSouth ? -wallZ : wallZ;
17 | var wallGroup = new Zdog.Group({
18 | addTo: options.addTo,
19 | translate: { z: -wallTZ },
20 | });
21 |
22 | var wallPath = [
23 | { x: -wallX, y: -wallY }
24 | ];
25 |
26 | if ( options.gable == 'ns' ) {
27 | wallPath.push({ x: 0, y: -wallY - wallX });
28 | }
29 |
30 | wallPath = wallPath.concat([
31 | { x: wallX, y: -wallY },
32 | { x: wallX, y: 0 },
33 | { x: -wallX, y: 0 },
34 | ]);
35 |
36 | // wall
37 | new Zdog.Shape({
38 | path: wallPath,
39 | addTo: wallGroup,
40 | color: isSouth ? red : gold,
41 | });
42 |
43 | var windowColor = isSouth ? navy : red;
44 | var windowProperty = isSouth ? 'southWindows' : 'northWindows';
45 | handleWindows( options, windowProperty, wallGroup, windowColor );
46 |
47 | var wallProperty = isSouth ? 'southWall' : 'northWall';
48 | building[ wallProperty ] = wallGroup;
49 |
50 | });
51 |
52 | // east/west wall
53 | [ true, false ].forEach( function( isWest ) {
54 | var wallGroup = new Zdog.Group({
55 | addTo: options.addTo,
56 | translate: { x: isWest ? -wallX : wallX },
57 | rotate: { y: TAU/4 },
58 | });
59 |
60 | var wallPath = [
61 | { x: -wallZ, y: -wallY }
62 | ];
63 |
64 | if ( options.gable == 'ew' ) {
65 | wallPath.push({ x: 0, y: -wallY - wallZ });
66 | }
67 |
68 | wallPath = wallPath.concat([
69 | { x: wallZ, y: -wallY },
70 | { x: wallZ, y: 0 },
71 | { x: -wallZ, y: 0 },
72 | ]);
73 |
74 | // wall
75 | new Zdog.Shape({
76 | path: wallPath,
77 | addTo: wallGroup,
78 | color: isWest ? blue : white,
79 | });
80 |
81 | var windowColor = isWest ? navy : blue;
82 | var windowProperty = isWest ? 'westWindows' : 'eastWindows';
83 | handleWindows( options, windowProperty, wallGroup, windowColor );
84 |
85 | var wallProperty = isWest ? 'westWall' : 'eastWall';
86 | building[ wallProperty ] = wallGroup;
87 | });
88 |
89 |
90 | var roofMakers = {
91 | ns: function() {
92 | var y0 = -wallY - wallX;
93 | var roofPanel = new Zdog.Shape({
94 | path: [
95 | { x: 0, y: y0, z: wallZ },
96 | { x: 0, y: y0, z: -wallZ },
97 | { x: wallX, y: -wallY, z: -wallZ },
98 | { x: wallX, y: -wallY, z: wallZ },
99 | ],
100 | addTo: options.addTo,
101 | color: gold,
102 | });
103 | roofPanel.copy({
104 | scale: { x: -1 },
105 | color: navy,
106 | });
107 | },
108 |
109 | ew: function() {
110 | var y0 = -wallY - wallZ;
111 | var xA = options.isChurch ? -wallX + 8 : -wallX;
112 | var roofPanel = new Zdog.Shape({
113 | path: [
114 | { z: 0, y: y0, x: xA },
115 | { z: 0, y: y0, x: wallX },
116 | { z: -wallZ, y: -wallY, x: wallX },
117 | { z: -wallZ, y: -wallY, x: xA },
118 | ],
119 | addTo: options.addTo,
120 | color: red,
121 | });
122 | roofPanel.copy({
123 | path: [
124 | { z: 0, y: y0, x: -wallX },
125 | { z: 0, y: y0, x: wallX },
126 | { z: -wallZ, y: -wallY, x: wallX },
127 | { z: -wallZ, y: -wallY, x: -wallX },
128 | ],
129 | scale: { z: -1 },
130 | color: navy,
131 | });
132 | },
133 | };
134 |
135 | var roofMaker = roofMakers[ options.gable ];
136 | if ( roofMaker ) {
137 | roofMaker();
138 | }
139 |
140 | return building;
141 | };
142 |
143 | function handleWindows( options, windowProperty, wallGroup, color ) {
144 | var windowOption = options[ windowProperty ];
145 | if ( !windowOption ) {
146 | return;
147 | }
148 |
149 | var columns = windowOption[0];
150 | var rows = windowOption[1];
151 | // var windowPaths = [];
152 | for ( var row=0; row < rows; row++ ) {
153 | for ( var col=0; col < columns; col++ ) {
154 | var x = ( col - (columns-1)/2 ) * 6;
155 | var y = -options.height + (row + 0.75) * 8;
156 | var windowPath = [
157 | { x: x + -1, y: y + -2 },
158 | { x: x + 1, y: y + -2 },
159 | { x: x + 1, y: y + 2 },
160 | { x: x + -1, y: y + 2 },
161 | ];
162 | new Zdog.Shape({
163 | path: windowPath,
164 | addTo: wallGroup,
165 | color: color,
166 | });
167 | }
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/demo/la-link/la-link.js:
--------------------------------------------------------------------------------
1 | // ------------------------- demo ------------------------- //
2 |
3 | var illoElem = document.querySelector('.zdog-canvas');
4 | var sceneSize = 128;
5 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
6 | var zoom = Math.floor( minWindowSize / sceneSize );
7 | var illoSize = sceneSize * zoom;
8 | illoElem.setAttribute( 'width', illoSize );
9 | illoElem.setAttribute( 'height', illoSize );
10 | var isSpinning = false;
11 | var TAU = Zdog.TAU;
12 |
13 | // colors
14 | var skinTone = '#FEA';
15 | var amber = '#FB2';
16 | var green = '#462';
17 | var blue = '#59F';
18 | // var brown = '#743';
19 | var brown = '#832';
20 | var black = '#222';
21 | var yellow = '#FF4';
22 | var silver = '#ABB';
23 | var lightGreen = '#3A4';
24 | var white = '#DDD';
25 |
26 | var illo = new Zdog.Illustration({
27 | element: illoElem,
28 | zoom: zoom,
29 | dragRotate: true,
30 | resize: 'fullscreen',
31 | onDragStart: function() {
32 | isSpinning = false;
33 | },
34 | onResize: function( width, height ) {
35 | this.zoom = Math.floor( Math.min( width, height ) / sceneSize );
36 | },
37 | });
38 |
39 | // ----- head ----- //
40 |
41 | var headAnchor = new Zdog.Anchor({
42 | addTo: illo,
43 | });
44 |
45 | // face
46 | var face = new Zdog.Hemisphere({
47 | addTo: headAnchor,
48 | diameter: 38,
49 | rotate: { x: -TAU/8 },
50 | color: skinTone,
51 | backface: amber,
52 | stroke: false,
53 | });
54 |
55 | // used for copying one side the other
56 | var headSide = new Zdog.Anchor({
57 | addTo: headAnchor,
58 | });
59 |
60 | var eye = new Zdog.Ellipse({
61 | addTo: headSide,
62 | width: 3,
63 | height: 8,
64 | translate: { x: -6, y: 2, z: 18 },
65 | color: black,
66 | fill: true,
67 | backface: false,
68 | });
69 |
70 | var brow = new Zdog.Shape({
71 | addTo: eye,
72 | path: [
73 | { x: -3, y: -1, z: -1 },
74 | { arc: [
75 | { x: -2, y: -3 },
76 | { x: 3, y: 0.5 },
77 | ]},
78 | ],
79 | color: brown,
80 | translate: { x: -1, y: -6 },
81 | fill: true,
82 | });
83 |
84 | // mouth
85 | new Zdog.Shape({
86 | addTo: headAnchor,
87 | path: [
88 | { x: -3 },
89 | { arc: [
90 | { y: -2, z: 1 },
91 | { x: 3 },
92 | ]},
93 | ],
94 | closed: false,
95 | translate: { y: 11, z: 15 },
96 | color: brown,
97 | });
98 |
99 | // big bang lock
100 | new Zdog.Shape({
101 | addTo: headAnchor,
102 | path: [
103 | { x: 0 },
104 | { arc: [
105 | { x: -12, y: -4, z: 4 },
106 | { x: -24, y: 6, z: -4 },
107 | ]},
108 | { arc: [
109 | { x: -12, y: -8, z: -2 },
110 | { x: 0, y: -4, z: -4 }
111 | ]},
112 | ],
113 | translate: { x: 4, y: -16, z: 19 },
114 | fill: true,
115 | color: amber,
116 | stroke: 12,
117 | });
118 |
119 | // front part lock
120 | new Zdog.Shape({
121 | addTo: headAnchor,
122 | path: [
123 | { y: 0 },
124 | { arc: [
125 | { x: 4, y: 0, z: 2 },
126 | { x: 10, y: 14, z: -6 },
127 | ]},
128 | { arc: [
129 | { x: 4, y: 0, z: -4 },
130 | { y: -2, z: -4 },
131 | ]}
132 | ],
133 | translate: { x: 12, y: -15, z: 15 },
134 | fill: true,
135 | color: amber,
136 | stroke: 10,
137 | });
138 |
139 | // hair crown
140 | // new Zdog.Ellipse({
141 | // addTo: face,
142 | // width: 24,
143 | // height: 12,
144 | // translate: { y: -12, z: -9 },
145 | // color: amber,
146 | // stroke: 18,
147 | // fill: true,
148 | // });
149 |
150 | // ear
151 | new Zdog.Shape({
152 | addTo: headSide,
153 | path: [
154 | { x: 0 },
155 | { arc: [
156 | { x: -2, y: -2 },
157 | { x: -4, y: -1 },
158 | ]},
159 | { arc: [
160 | { x: -2, y: 4 },
161 | { x: 0, y: 4, z: -4 },
162 | ]},
163 | ],
164 | scale: { x: 3 },
165 | translate: { x: -18, y: 2, z: 2 },
166 | rotate: { y: TAU/8 },
167 | color: skinTone,
168 | stroke: 4,
169 | fill: true,
170 | });
171 |
172 | // side down lock
173 | new Zdog.Shape({
174 | addTo: headSide,
175 | path: [
176 | { y: 0 },
177 | { arc: [
178 | { y: 6 },
179 | { x: -1, y: 16, z: -2 },
180 | ]},
181 | ],
182 | closed: false,
183 | translate: { x: -19, z: 5 },
184 | stroke: 6,
185 | color: amber,
186 | });
187 |
188 | // crown hair gap
189 | new Zdog.Shape({
190 | addTo: headSide,
191 | path: [
192 | { x: -1 },
193 | { arc: [
194 | { x: -1, y: -1 },
195 | { x: 0, y: -1 },
196 | ]},
197 | ],
198 | closed: false,
199 | scale: { x: 14, y: 12 },
200 | translate: { y: -8 },
201 | rotate: { x: -TAU/32 },
202 | color: amber,
203 | stroke: 20,
204 | })
205 |
206 | headSide.copyGraph({
207 | scale: { x: -1 },
208 | });
209 |
210 | // ----- animate ----- //
211 |
212 | function animate() {
213 | illo.rotate.y += isSpinning ? +TAU/150 : 0;
214 | illo.updateRenderGraph();
215 | requestAnimationFrame( animate );
216 | }
217 |
218 | animate();
219 |
220 |
--------------------------------------------------------------------------------
/demo/tri-prism/tri-prism.js:
--------------------------------------------------------------------------------
1 | // ----- setup ----- //
2 |
3 | var illoCanvas = document.querySelector('.illo');
4 | var proxyCanvas = document.createElement('canvas');
5 | var ctx = illoCanvas.getContext('2d');
6 | var illoSize = 14 * Math.sqrt(2);
7 | var minWindowSize = Math.min( window.innerWidth - 20, window.innerHeight - 20 );
8 | var zoom = Math.floor( minWindowSize / illoSize );
9 |
10 | var canvasWidth = illoCanvas.width = illoSize * zoom;
11 | var canvasHeight = illoCanvas.height = illoSize * zoom;
12 | var shrink = 1/3;
13 | proxyCanvas.width = canvasWidth * shrink;
14 | proxyCanvas.height = canvasHeight * shrink;
15 | var TAU = Zdog.TAU;
16 |
17 | var illo = new Zdog.Illustration({
18 | element: proxyCanvas,
19 | rotate: { x: -35/360 * TAU, y: 45/360 * TAU },
20 | zoom: zoom,
21 | });
22 |
23 | var isSpinning = false;
24 |
25 | var navy = '#456';
26 | var red = '#D21';
27 | var orange = '#F90';
28 |
29 | // ----- model ----- //
30 |
31 | function makePrism( options ) {
32 | var prism = new Zdog.Anchor({
33 | addTo: illo,
34 | rotate: options.rotate,
35 | });
36 |
37 | var rotor = new Zdog.Anchor({
38 | addTo: prism,
39 | });
40 |
41 | var positioner = new Zdog.Anchor({
42 | addTo: rotor,
43 | translate: { z: 1, y: -1 },
44 | });
45 |
46 | var triangle = new Zdog.Shape({
47 | addTo: positioner,
48 | path: [
49 | { z: 1, y: 1 },
50 | { z: -1, y: -1 },
51 | { z: -1, y: 1 },
52 | ],
53 | color: red,
54 | fill: true,
55 | stroke: 1/zoom,
56 | });
57 | triangle.copy({
58 | translate: { x: -2 },
59 | color: navy,
60 | });
61 |
62 | // slope
63 | new Zdog.Shape({
64 | addTo: positioner,
65 | path: [
66 | { x: -2, y: 1, z: 1 },
67 | { x: -2, y: -1, z: -1 },
68 | { x: 0, y: -1, z: -1 },
69 | { x: 0, y: 1, z: 1 },
70 | ],
71 | color: orange,
72 | fill: true,
73 | stroke: 1/zoom,
74 | });
75 |
76 | var base = new Zdog.Rect({
77 | addTo: positioner,
78 | width: 2,
79 | height: 2,
80 | translate: { x: -1, z: -1 },
81 | rotate: { y: TAU/2 },
82 | color: navy,
83 | fill: true,
84 | stroke: 1/zoom,
85 | backface: false,
86 | });
87 | base.copy({
88 | translate: { x: -1, y: 1 },
89 | rotate: { x: -TAU/4 },
90 | color: red,
91 | });
92 |
93 | return prism;
94 | }
95 |
96 | var prismA = makePrism({});
97 |
98 | var prismB = makePrism({
99 | rotate: { x: TAU/4, z: TAU/4 },
100 | });
101 |
102 | var prismC = makePrism({
103 | rotate: { y: -TAU/4, z: -TAU/4 },
104 | });
105 |
106 | // -- animate --- //
107 |
108 | var t = 0;
109 | var tSpeed = 1/80;
110 |
111 | // -- update -- //
112 |
113 | var keyframes = [
114 | { x: 0, y: 0, z: 0 },
115 | { x: 1, y: 0, z: 0 },
116 | { x: 1, y: -1, z: 0 },
117 | { x: 1, y: -2, z: 0 },
118 | { x: 1, y: -2, z: -1 },
119 | { x: 1, y: -2, z: -2 },
120 | { x: 2, y: -2, z: -2 },
121 | ];
122 |
123 | function transform( shape, turn, alpha ) {
124 | var keyA = keyframes[ turn ];
125 | var keyB = keyframes[ turn + 1 ];
126 | shape.rotate.x = Zdog.lerp( keyA.x, keyB.x, alpha ) * TAU/4;
127 | shape.rotate.y = Zdog.lerp( keyA.y, keyB.y, alpha ) * TAU/4;
128 | shape.rotate.z = Zdog.lerp( keyA.z, keyB.z, alpha ) * TAU/4;
129 | }
130 |
131 | function update() {
132 | var easeT = Zdog.easeInOut( t % 1, 4 );
133 | var turn = Math.floor( t % 6 );
134 |
135 | transform( prismA.children[0], turn, easeT );
136 | transform( prismB.children[0], turn, easeT );
137 | transform( prismC.children[0], turn, easeT );
138 |
139 | t += tSpeed;
140 |
141 | illo.updateGraph();
142 | }
143 |
144 | // -- render -- //
145 |
146 | var shiftX = Math.round( 3 * Math.sqrt(2) * zoom );
147 | var shiftY = Math.round( 2 * Math.sqrt(2) * Math.sqrt(3)/2 * zoom );
148 |
149 | function render() {
150 | illo.renderGraph();
151 |
152 | ctx.clearRect( 0, 0, canvasWidth, canvasHeight );
153 |
154 | ctx.save();
155 | var center = Math.round( illoSize * shrink * zoom );
156 | ctx.translate( center, center );
157 |
158 | for ( var col = -2; col < 3; col++ ) {
159 | for ( var row = -2; row < 3; row++ ) {
160 | var x = col * shiftX;
161 | var y = ( row * 2 + col % 2 ) * shiftY;
162 | ctx.drawImage( illo.element, x, y );
163 | }
164 | }
165 |
166 | ctx.restore();
167 | }
168 |
169 | function animate() {
170 | update();
171 | render();
172 | requestAnimationFrame( animate );
173 | }
174 |
175 | animate();
176 |
177 | // ----- inputs ----- //
178 |
179 | // click drag to rotate
180 | var dragStartRX, dragStartRY;
181 |
182 | new Zdog.Dragger({
183 | startElement: illoCanvas,
184 | onDragStart: function() {
185 | isSpinning = false;
186 | dragStartRX = illo.rotate.x;
187 | dragStartRY = illo.rotate.y;
188 | },
189 | onDragMove: function( pointer, moveX, moveY ) {
190 | illo.rotate.x = dragStartRX - moveY / canvasWidth * TAU;
191 | illo.rotate.y = dragStartRY - moveX / canvasWidth * TAU;
192 | },
193 | });
194 |
195 |
--------------------------------------------------------------------------------
/demo/sauropod/sauropod.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var illoSize = 104;
5 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
6 | var zoom = Math.min( 5, Math.floor( minWindowSize / illoSize ) );
7 | illoElem.setAttribute( 'width', illoSize * zoom );
8 | illoElem.setAttribute( 'height', illoSize * zoom );
9 | var isSpinning = true;
10 | var TAU = Zdog.TAU;
11 | // ratio to make things look square when rotated a quarter
12 | var antiTwist = 1 / Math.cos( TAU/8 );
13 | // colors
14 | var blue = '#19F';
15 |
16 | var initialRotate = { y: TAU/8 };
17 |
18 | var illo = new Zdog.Illustration({
19 | element: illoElem,
20 | zoom: zoom,
21 | scale: { x: antiTwist, z: antiTwist },
22 | rotate: initialRotate,
23 | dragRotate: true,
24 | onDragStart: function() {
25 | isSpinning = false;
26 | },
27 | });
28 |
29 | // -- illustration shapes --- //
30 |
31 | // front right leg
32 | var leg = new Zdog.Shape({
33 | path: [
34 | { x: -8, y: 0 },
35 | { arc: [
36 | { x: 0, y: 0 },
37 | { x: 0, y: 8 }
38 | ]},
39 | { arc: [
40 | { z: 0, y: 0 },
41 | { z: -8, y: 0 }
42 | ]},
43 | { move: { y: -4 } },
44 | { line: { y: 12 } },
45 | ],
46 | addTo: illo,
47 | translate: { x: 16, y: 16, z: 8 },
48 | stroke: 8,
49 | color: blue,
50 | closed: false,
51 | });
52 | // front left leg
53 | leg.copy({
54 | translate: { x: 16, y: 16, z: -8 },
55 | rotate: { y: -TAU/4 },
56 | });
57 | // back right leg
58 | leg.copy({
59 | translate: { x: -16, y: 16, z: 8 },
60 | rotate: { y: TAU/4 },
61 | });
62 | // back left leg
63 | leg.copy({
64 | translate: { x: -16, y: 16, z: -8 },
65 | rotate: { y: -TAU/2 },
66 | });
67 |
68 |
69 | // leg connectors
70 | var legConnector = new Zdog.Shape({
71 | path: [ { x: -8 }, { x: 8 } ],
72 | addTo: illo,
73 | translate: { y: 16, z: 8 },
74 | stroke: 8,
75 | color: blue,
76 | closed: false,
77 | });
78 | legConnector.copy({
79 | translate: { y: 16, z: -8 },
80 | });
81 |
82 | // body
83 | new Zdog.Shape({
84 | path: [
85 | { x: -1, z: 1 },
86 | { x: 1, z: 1 },
87 | { x: 1, z: -1 },
88 | { x: -1, z: -1 },
89 | ],
90 | // fudge these numbers
91 | scale: { x: 14.25, z: -3.75 },
92 | addTo: illo,
93 | translate: { y: 10 },
94 | stroke: 20,
95 | color: blue,
96 | });
97 |
98 | // neck squiggle
99 | new Zdog.Shape({
100 | path: [
101 | { x: 16, y: 4 },
102 | { arc: [
103 | { x: 24, y: 4 },
104 | { x: 24, y: -4 }
105 | ]},
106 | { arc: [
107 | { x: 24, y: -12 },
108 | { x: 16, y: -12 }
109 | ]},
110 | { x: -16, y: -12 },
111 | { arc: [
112 | { x: -24, y: -12 },
113 | { x: -24, y: -20 }
114 | ]},
115 | { arc: [
116 | { x: -24, y: -28 },
117 | { x: -16, y: -28 }
118 | ]},
119 | { x: 24, y: -28 },
120 | ],
121 | addTo: illo,
122 | stroke: 8,
123 | color: blue,
124 | closed: false,
125 | });
126 |
127 | // neck
128 | new Zdog.Shape({
129 | path: [
130 | { x: -16, y: -28 },
131 | { x: 24, y: -28 },
132 | ],
133 | addTo: illo,
134 | stroke: 8,
135 | color: blue,
136 | closed: false,
137 | });
138 |
139 | // head ball
140 | var head = new Zdog.Shape({
141 | translate: { x: 16, y: -31 },
142 | addTo: illo,
143 | stroke: 14,
144 | color: blue,
145 | });
146 |
147 | // eyes
148 | var eye = new Zdog.Shape({
149 | addTo: head,
150 | translate: { z: -1, x: 0 },
151 | color: 'white',
152 | stroke: 4,
153 | fill: true,
154 | closed: false,
155 | });
156 | eye.copy({
157 | translate: { z: 1, x: 0 },
158 | });
159 |
160 | // tail
161 | new Zdog.Shape({
162 | path: [
163 | { x: -16, z: 0 },
164 | { arc: [
165 | { x: -24, z: 0 },
166 | { x: -24, z: -8 },
167 | ]},
168 | { arc: [
169 | { x: -24, z: -16 },
170 | { x: -16, z: -16 },
171 | ]},
172 | { x: -12, z: -16 },
173 | { arc: [
174 | { x: -6, z: -16 },
175 | { x: -6, z: -22 },
176 | ]},
177 | { arc: [
178 | { x: -6, z: -28 },
179 | { x: -12, z: -28 },
180 | ]},
181 | { x: -18, z: -28 },
182 | ],
183 | addTo: illo,
184 | translate: { y: 4 },
185 | // rotate: { x: -0.25 },
186 | color: blue,
187 | stroke: 8,
188 | closed: false,
189 | });
190 |
191 | // -- animate --- //
192 |
193 | var t = 0;
194 |
195 | function animate() {
196 | // update
197 | if ( isSpinning ) {
198 | var easeT = Zdog.easeInOut( t % 1, 3 );
199 | illo.rotate.y = easeT*-TAU + TAU/8;
200 | illo.rotate.x = ( Math.cos( easeT * TAU ) * 0.5 + -0.5 ) * TAU/12;
201 | t += 1/210;
202 | }
203 | illo.updateRenderGraph();
204 | requestAnimationFrame( animate );
205 | }
206 |
207 | animate();
208 |
209 | // ----- inputs ----- //
210 |
211 | document.querySelector('.reset-button').onclick = function() {
212 | illo.rotate.set( initialRotate );
213 | isSpinning = false;
214 | };
215 |
216 | document.querySelector('.rotate-button').onclick = function() {
217 | isSpinning = true;
218 | t = 0;
219 | };
220 |
221 |
--------------------------------------------------------------------------------
/demo/strutter/strutter.js:
--------------------------------------------------------------------------------
1 | // Made with Zdog
2 |
3 | // ----- setup ----- //
4 |
5 | var illoElem = document.querySelector('.illo');
6 | var illoSize = 48;
7 | var minWindowSize = Math.min( window.innerWidth - 20 , window.innerHeight - 20 );
8 | var zoom = Math.floor( minWindowSize / illoSize );
9 | illoElem.width = illoElem.height = illoSize * zoom;
10 | var isRotating = true;
11 | var TAU = Zdog.TAU;
12 | // colors
13 | var gold = '#EA0';
14 | var red = '#E21';
15 | var denim = '#345';
16 |
17 | var illo = new Zdog.Illustration({
18 | element: illoElem,
19 | zoom: zoom,
20 | rotate: { y: -TAU/8 },
21 | translate: { y: 2 },
22 | dragRotate: true,
23 | onDragStart: function() {
24 | isRotating = false;
25 | },
26 | });
27 |
28 | // ----- model ----- //
29 |
30 | var hipX = 3;
31 |
32 | new Zdog.Shape({
33 | addTo: illo,
34 | path: [ { x: -1 }, { x: 1 } ],
35 | scale: hipX,
36 | color: denim,
37 | stroke: 4,
38 | });
39 |
40 | var rightLeg = new Zdog.Shape({
41 | addTo: illo,
42 | path: [ { y: 0 }, { y: 12 } ],
43 | translate: { x: -hipX },
44 | rotate: { x: TAU/4 },
45 | color: denim,
46 | stroke: 4,
47 | });
48 | // foot
49 | new Zdog.RoundedRect({
50 | addTo: rightLeg,
51 | width: 2,
52 | height: 4,
53 | radius: 1,
54 | translate: { y: 14, z: 2 },
55 | rotate: { x: TAU/4 },
56 | color: red,
57 | fill: true,
58 | stroke: 4,
59 | });
60 |
61 | var plantAngle = -TAU/32 * 3;
62 | var leftLeg = rightLeg.copyGraph({
63 | translate: { x: hipX },
64 | rotate: { x: plantAngle },
65 | color: '#234'
66 | });
67 |
68 | leftLeg.children[0].rotate.set({ x: TAU/4 - plantAngle });
69 |
70 | // chest
71 | new Zdog.Shape({
72 | addTo: illo,
73 | path: [ { x: -1 }, { x: 1 } ],
74 | scale: 1.5,
75 | translate: { y: -5.5, z: -3 },
76 | color: red,
77 | stroke: 9,
78 | fill: true,
79 | });
80 |
81 | var armSize = 6;
82 |
83 | [ true, false ].forEach( function( isRight ) {
84 | var xSide = isRight ? -1 : 1;
85 |
86 | var upperArm = new Zdog.Shape({
87 | addTo: illo,
88 | path: [ { x: 0 }, { x: armSize } ],
89 | scale: { x: xSide },
90 | translate: { x: 4.5 * xSide, y: -8, z: -4 },
91 | rotate: isRight ? { y: TAU/8, z: -TAU/16 } : { y: TAU/8 },
92 | color: denim,
93 | stroke: 4,
94 | });
95 |
96 | var forearm = new Zdog.Shape({
97 | addTo: upperArm,
98 | path: [ { x: 0 }, { x: armSize-2 } ],
99 | translate: { x: armSize },
100 | rotate: isRight ? { z: TAU/16 * 3, y: TAU/4 } : { z: -TAU/4, x: -TAU/32 * 2, y: TAU/8 },
101 | color: red,
102 | stroke: 4,
103 | });
104 | // hand
105 | new Zdog.Shape({
106 | addTo: forearm,
107 | translate: { x: armSize, z: 1 },
108 | stroke: 6,
109 | color: gold,
110 | });
111 |
112 | });
113 |
114 | var head = new Zdog.Anchor({
115 | addTo: illo,
116 | translate: { y: -12, z: -10 },
117 | rotate: { x: TAU/8 },
118 | });
119 |
120 | // face
121 | new Zdog.Hemisphere({
122 | addTo: head,
123 | diameter: 12,
124 | color: gold,
125 | backface: red,
126 | rotate: { x: -TAU/4 },
127 | stroke: false,
128 | });
129 |
130 | var eye = new Zdog.Ellipse({
131 | addTo: head,
132 | width: 2,
133 | height: 2,
134 | quarters: 2,
135 | translate: { x: -2, y: 1.5, z: 5 },
136 | rotate: { z: -TAU/4 },
137 | color: denim,
138 | stroke: 0.5,
139 | backface: false,
140 | });
141 | eye.copy({
142 | translate: { x: 2, y: 1.5, z: 5 },
143 | rotate: { z: -TAU/4 },
144 | });
145 | // smile
146 | new Zdog.Ellipse({
147 | addTo: head,
148 | width: 3,
149 | height: 3,
150 | quarters: 2,
151 | translate: { y: 3, z: 4.5 },
152 | rotate: { z: TAU/4 },
153 | closed: true,
154 | color: '#FED',
155 | stroke: 0.5,
156 | fill: true,
157 | backface: false,
158 | });
159 |
160 | new Zdog.Hemisphere({
161 | addTo: head,
162 | diameter: 12,
163 | color: red,
164 | backface: gold,
165 | rotate: { x: TAU/4 },
166 | stroke: false,
167 | });
168 |
169 | var brim = new Zdog.Anchor({
170 | addTo: head,
171 | scale: 5.5,
172 | translate: { y: -0.5, z: 6 },
173 | });
174 |
175 | new Zdog.Shape({
176 | addTo: brim,
177 | path: [
178 | { x: 0, z: 0 },
179 | { arc: [
180 | { x: -1, z: 0 },
181 | { x: -1, z: -1 },
182 | ]},
183 | { x: -1, z: 0 },
184 | ],
185 | color: denim,
186 | fill: true,
187 | });
188 |
189 | new Zdog.Shape({
190 | addTo: brim,
191 | path: [
192 | { x: -1, z: 0 },
193 | { arc: [
194 | { x: -1, z: 1 },
195 | { x: 0, z: 1 },
196 | ]},
197 | { x: 0, z: 0 },
198 | ],
199 | color: denim,
200 | fill: true,
201 | });
202 |
203 | brim.copyGraph({
204 | scale: brim.scale.copy().multiply({ x: -1 }),
205 | });
206 |
207 |
208 | // ----- model ----- //
209 |
210 | var ticker = 0;
211 | var cycleCount = 150;
212 |
213 | function animate() {
214 | if ( isRotating ) {
215 | var progress = ticker / cycleCount;
216 | var tween = Zdog.easeInOut( progress % 1, 4 );
217 | illo.rotate.y = tween * TAU - TAU/8;
218 | ticker++;
219 | }
220 | illo.updateRenderGraph();
221 | requestAnimationFrame( animate );
222 | }
223 |
224 | animate();
225 |
226 |
--------------------------------------------------------------------------------
/demo/crypto-kitty/crypto-kitty.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var illoSize = 64;
5 | var minWindowSize = Math.min( window.innerWidth - 20, window.innerHeight - 80 );
6 | var zoom = Math.floor( minWindowSize / illoSize );
7 | illoElem.setAttribute( 'width', illoSize * zoom );
8 | illoElem.setAttribute( 'height', illoSize * zoom );
9 |
10 | var isSpinning = true;
11 | var TAU = Zdog.TAU;
12 |
13 | var illo = new Zdog.Illustration({
14 | element: illoElem,
15 | zoom: zoom,
16 | rotate: { x: -TAU/32 },
17 | dragRotate: true,
18 | onDragStart: function() {
19 | isSpinning = false;
20 | },
21 | });
22 |
23 | // colors
24 | var magenta = '#F49';
25 | var midnight = '#103';
26 | var white = 'white';
27 |
28 |
29 | // -- illustration shapes --- //
30 |
31 | var cat = new Zdog.Group({
32 | addTo: illo,
33 | updateSort: true,
34 | });
35 |
36 | // body
37 | new Zdog.Shape({
38 | path: [ { y: -1 }, { y: 1} ],
39 | scale: { y: 3 },
40 | addTo: cat,
41 | stroke: 14,
42 | color: magenta,
43 | });
44 |
45 | var face = new Zdog.Anchor({
46 | addTo: cat,
47 | translate: { y: -4, z: 6.5 },
48 | });
49 |
50 | // nose
51 | new Zdog.Shape({
52 | path: [
53 | { x: -1 },
54 | { x: 1 },
55 | { y: 1 },
56 | ],
57 | scale: { x: 0.25, y: 0.25 },
58 | addTo: face,
59 | translate: { z: 1.5 },
60 | stroke: 1,
61 | color: midnight,
62 | });
63 |
64 | // tummy
65 | new Zdog.RoundedRect({
66 | width: 5,
67 | height: 7,
68 | cornerRadius: 2.5,
69 | addTo: cat,
70 | translate: { y: 3.5, z: 5 },
71 | // rotate: { x: TAU/64 },
72 | color: white,
73 | stroke: 3,
74 | fill: true,
75 | });
76 |
77 | // chin
78 | new Zdog.Shape({
79 | path: [ { x: -1 }, { x: 1 } ],
80 | scale: { x: 2 },
81 | addTo: cat,
82 | translate: { y: -3, z: 4 },
83 | stroke: 4,
84 | color: magenta,
85 | });
86 |
87 | // tail
88 | new Zdog.Shape({
89 | path: [ { y: 0 }, { y: 8 } ],
90 | addTo: cat,
91 | translate: { y: 7, z: -4 },
92 | rotate: { x: -TAU/32 },
93 | stroke: 1,
94 | color: magenta,
95 | });
96 |
97 | var backLine = new Zdog.Shape({
98 | path: [ { x: -1 }, { x: 1 } ],
99 | scale: { x: 3 },
100 | addTo: cat,
101 | translate: { y: 0, z: -6.5 },
102 | stroke: 0.5,
103 | color: '#F7A',
104 | });
105 | backLine.copy({
106 | translate: { y: -3, z: -6.5 },
107 | });
108 | backLine.copy({
109 | translate: { y: 3, z: -6.5 },
110 | });
111 |
112 | [ -1, 1 ].forEach( function( xSide ) {
113 | // eye
114 | new Zdog.Shape({
115 | path: [ { y: -1 }, { y: 1} ],
116 | scale: { y: 0.3 },
117 | addTo: face,
118 | translate: { x: 0.75*xSide, y: -1.5 },
119 | stroke: 0.8,
120 | color: midnight,
121 | });
122 |
123 | // maw
124 | new Zdog.Shape({
125 | path: [ { x: -1 }, { x: 1} ],
126 | scale: { x: 0.4 },
127 | addTo: face,
128 | translate: { x: 1*xSide, y: 0.5, z: 0.5 },
129 | stroke: 1.5,
130 | color: white,
131 | });
132 |
133 | // whisker
134 | var whisker = new Zdog.Shape({
135 | path: [
136 | { x: 0, y: 0 },
137 | { x: 1, y: 1 },
138 | ],
139 | scale: { x: xSide*3, y: 0.75 },
140 | addTo: face,
141 | translate: { x: 2.5*xSide, y: 0.5 },
142 | color: white,
143 | stroke: 0.25,
144 | });
145 | whisker.copy({
146 | scale: { x: xSide*3, y: -0.75 },
147 | });
148 |
149 | // ear
150 | new Zdog.Shape({
151 | path: [
152 | { x: 0, y: 0 },
153 | { x: 1, y: 1 },
154 | { x: 1, y: -1 },
155 | ],
156 | scale: { x: 2*xSide, y: 1.5 },
157 | addTo: cat,
158 | translate: { x: 2*xSide, y: -8 },
159 | color: magenta,
160 | stroke: 3,
161 | fill: true,
162 | });
163 |
164 | // arm
165 | var arm = new Zdog.Shape({
166 | path: [ { y: 0 }, { y: 3.5 } ],
167 | addTo: cat,
168 | translate: { x: 3.5*xSide, y: -1, z: 5.5 },
169 | rotate: { x: TAU/16 },
170 | stroke: 3,
171 | color: magenta,
172 | });
173 |
174 | // leg
175 | arm.copy({
176 | translate: { x: 3.5*xSide, y: 8, z: 2 },
177 | rotate: {},
178 | });
179 | });
180 |
181 | var diamondPanel = new Zdog.Shape({
182 | path: [
183 | { x: 0, y: 1, z: -0 },
184 | { x: -1, y: 0, z: 1 },
185 | { x: 1, y: 0, z: 1 },
186 | ],
187 | scale: { x: 12, y: 30, z: -12 },
188 | addTo: illo,
189 | stroke: false,
190 | fill: true,
191 | color: 'hsla(60, 100%, 50%, 0.1)',
192 | });
193 | diamondPanel.copy({
194 | rotate: { y: TAU/4*1 },
195 | color: 'hsla(60, 100%, 50%, 0.2)',
196 | });
197 | diamondPanel.copy({
198 | rotate: { y: TAU/4*2 },
199 | color: 'hsla(60, 100%, 50%, 0.3)',
200 | });
201 | diamondPanel.copy({
202 | rotate: { y: TAU/4*3 },
203 | color: 'hsla(60, 100%, 50%, 0.4)',
204 | });
205 | diamondPanel.copy({
206 | scale: { x: 12, y: -30, z: -12 },
207 | rotate: { y: TAU/4*0 },
208 | color: 'hsla(60, 100%, 50%, 0.4)',
209 | });
210 | diamondPanel.copy({
211 | scale: { x: 12, y: -30, z: -12 },
212 | rotate: { y: TAU/4*1 },
213 | color: 'hsla(60, 100%, 50%, 0.3)',
214 | });
215 | diamondPanel.copy({
216 | scale: { x: 12, y: -30, z: -12 },
217 | rotate: { y: TAU/4*2 },
218 | color: 'hsla(60, 100%, 50%, 0.2)',
219 | });
220 | diamondPanel.copy({
221 | scale: { x: 12, y: -30, z: -12 },
222 | rotate: { y: TAU/4*3 },
223 | color: 'hsla(60, 100%, 50%, 0.1)',
224 | });
225 |
226 | // ----- animate ----- //
227 |
228 | function animate() {
229 | illo.rotate.y += isSpinning ? -TAU/150 : 0;
230 | illo.updateRenderGraph();
231 | requestAnimationFrame( animate );
232 | }
233 |
234 | animate();
235 |
236 |
--------------------------------------------------------------------------------
/demo/madeline/madeline.js:
--------------------------------------------------------------------------------
1 | /* globals makeMadeline, BokehShape, makeBird */
2 |
3 | // -------------------------- demo -------------------------- //
4 |
5 | var illoElem = document.querySelector('.illo');
6 | var w = 160;
7 | var h = 160;
8 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
9 | var zoom = Math.min( 5, Math.floor( minWindowSize / w ) );
10 | illoElem.setAttribute( 'width', w * zoom );
11 | illoElem.setAttribute( 'height', h * zoom );
12 |
13 | var isSpinning = true;
14 | var TAU = Zdog.TAU;
15 |
16 | var illo = new Zdog.Illustration({
17 | element: illoElem,
18 | zoom: zoom,
19 | rotate: { y: -TAU/4 },
20 | dragRotate: true,
21 | onDragStart: function() {
22 | isSpinning = false;
23 | },
24 | });
25 |
26 | var madColor = {
27 | skin: '#FD9',
28 | hair: '#D53',
29 | parkaLight: '#67F',
30 | parkaDark: '#35D',
31 | tight: '#742',
32 | eye: '#333',
33 | };
34 | var badColor = {
35 | skin: '#EBC',
36 | hair: '#D4B',
37 | parkaLight: '#85A',
38 | parkaDark: '#527',
39 | tight: '#412',
40 | eye: '#D02',
41 | };
42 |
43 | var glow = 'hsla(60, 100%, 80%, 0.3)';
44 | var featherGold = '#FE5';
45 |
46 | // -- illustration shapes --- //
47 |
48 | makeMadeline( true, madColor, {
49 | addTo: illo,
50 | });
51 | makeMadeline( false, badColor, {
52 | addTo: illo,
53 | rotate: { y: TAU/2 },
54 | });
55 |
56 |
57 | // ----- feather ----- //
58 |
59 | var feather = new Zdog.Group({
60 | addTo: illo,
61 | rotate: { y: -TAU/4 },
62 | });
63 |
64 | ( function() {
65 |
66 | var featherPartCount = 8;
67 | var radius = 12;
68 | var angleX = (TAU/featherPartCount) / 2;
69 | var sector = (TAU * radius)/2 / featherPartCount;
70 |
71 | for ( var i=0; i < featherPartCount; i++ ) {
72 | var curve = Math.cos( (i/featherPartCount) * TAU*3/4 + TAU*1/4 );
73 | var x = 4 - curve*2;
74 | var y0 = sector/2;
75 | // var y2 = -sector/2;
76 | var isLast = i == featherPartCount - 1;
77 | var y3 = isLast ? sector * -1 : -y0;
78 | var z1 = -radius + 2 + curve*-1.5;
79 | var z2 = isLast ? -radius : -radius;
80 | var barb = new Zdog.Shape({
81 | path: [
82 | { x: 0, y: y0, z: -radius },
83 | { x: x, y: -sector/2, z: z1 },
84 | { x: x, y: -sector*3/4, z: z1 },
85 | { x: 0, y: y3, z: z2 },
86 | ],
87 | addTo: feather,
88 | rotate: { x: angleX * -i + TAU/8 },
89 | stroke: 1,
90 | color: featherGold,
91 | fill: true,
92 | });
93 | barb.copy({
94 | scale: { x: -1 },
95 | });
96 | }
97 |
98 | // rachis
99 | var rachis = new Zdog.Ellipse({
100 | addTo: feather,
101 | diameter: radius*2,
102 | quarters: 2,
103 | rotate: { y: -TAU/4 },
104 | stroke: 2,
105 | color: featherGold,
106 | });
107 | rachis.copy({
108 | stroke: 8,
109 | color: glow,
110 | rotate: { y: -TAU/4, x: -0.5 }
111 | });
112 | })();
113 |
114 | // ----- rods ----- //
115 |
116 | ( function() {
117 |
118 | var rodCount = 14;
119 | for ( var i=0; i < rodCount; i++ ) {
120 | var zRotor = new Zdog.Anchor({
121 | addTo: illo,
122 | rotate: { z: TAU/rodCount * i },
123 | });
124 |
125 | var y0 = 32;
126 | var y1 = y0 + 2 + Math.random()*24;
127 | new BokehShape({
128 | path: [
129 | { y: y0 },
130 | { y: y1 },
131 | ],
132 | addTo: zRotor,
133 | rotate: { x: ( Math.random() * 2 - 1 ) * TAU/8 },
134 | color: madColor.skin,
135 | stroke: 1,
136 | bokehSize: 6,
137 | bokehLimit: 70,
138 | });
139 | }
140 |
141 | })();
142 |
143 | // dots
144 |
145 | ( function() {
146 | var dotCount = 64;
147 |
148 | for ( var i=0; i < dotCount; i++ ) {
149 | var yRotor = new Zdog.Anchor({
150 | addTo: illo,
151 | rotate: { y: TAU/dotCount * i },
152 | });
153 |
154 | new BokehShape({
155 | path: [
156 | { z: 40*(1 - Math.random()*Math.random()) + 32 },
157 | ],
158 | addTo: yRotor,
159 | rotate: { x: ( Math.random() * 2 - 1 ) * TAU*3/16 },
160 | color: badColor.skin,
161 | stroke: 1 + Math.random(),
162 | bokehSize: 6,
163 | bokehLimit: 74,
164 | });
165 | }
166 |
167 | })();
168 |
169 | // ----- birds ----- //
170 |
171 | var birdRotor = new Zdog.Anchor({
172 | addTo: illo,
173 | rotate: { y: TAU*-1/8 },
174 | });
175 |
176 | makeBird({
177 | addTo: birdRotor,
178 | color: madColor.parkaLight,
179 | spin: TAU/2,
180 | });
181 |
182 | makeBird({
183 | addTo: birdRotor,
184 | color: featherGold,
185 | spin: -TAU * 3/8,
186 | });
187 |
188 | makeBird({
189 | addTo: birdRotor,
190 | color: 'white',
191 | spin: -TAU/4,
192 | });
193 |
194 | makeBird({
195 | addTo: birdRotor,
196 | color: madColor.hair,
197 | spin: -TAU/8,
198 | });
199 |
200 | makeBird({
201 | addTo: birdRotor,
202 | color: madColor.parkaDark,
203 | spin: TAU/8,
204 | });
205 |
206 | // -- animate --- //
207 |
208 | var isSpinning = true;
209 | var rotateSpeed = -TAU/60;
210 | var xClock = 0;
211 | var then = new Date() - 1/60;
212 |
213 | function animate() {
214 | update();
215 | illo.renderGraph();
216 | requestAnimationFrame( animate );
217 | }
218 |
219 | animate();
220 |
221 | // -- update -- //
222 |
223 | function update() {
224 | var now = new Date();
225 | var delta = now - then;
226 | // auto rotate
227 | if ( isSpinning ) {
228 | var theta = rotateSpeed/60 * delta * -1;
229 | illo.rotate.y += theta;
230 | xClock += theta/4;
231 | illo.rotate.x = Math.sin( xClock ) * TAU/12;
232 | }
233 |
234 | illo.updateGraph();
235 |
236 | then = now;
237 | }
238 |
239 |
--------------------------------------------------------------------------------
/demo/shade-and-shades/shade-and-shades.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var illoSize = 96;
5 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
6 | var zoom = Math.min( 8, Math.floor( minWindowSize / illoSize ) );
7 | illoElem.setAttribute( 'width', illoSize * zoom );
8 | illoElem.setAttribute( 'height', illoSize * zoom );
9 |
10 | var illo = new Zdog.Illustration({
11 | element: illoElem,
12 | zoom: zoom,
13 | });
14 |
15 | Zdog.Shape.defaults.closed = false;
16 | Zdog.Shape.defaults.stroke = 3;
17 | Zdog.Ellipse.defaults.stroke = 3;
18 |
19 | var TAU = Zdog.TAU;
20 | var quarterView = 1/Math.sin(TAU/8);
21 | var isRotateXFlat;
22 | var isSpinning = true;
23 |
24 | var illo = new Zdog.Illustration({
25 | element: illoElem,
26 | zoom: zoom,
27 | onDragStart: function() {
28 | isSpinning = false;
29 | }
30 | });
31 |
32 | var initialHatRotate = { y: -TAU/8 };
33 |
34 | var hat = new Zdog.Anchor({
35 | addTo: illo,
36 | rotate: initialHatRotate,
37 | });
38 |
39 | illo.setDragRotate( hat );
40 |
41 | // -- illustration shapes --- //
42 |
43 | // cap top
44 | var capTop = new Zdog.Shape({
45 | path: [
46 | { x: -20, y: 4 },
47 | { x: -20, y: 0 },
48 | { arc: [
49 | { x: -20, y: -20 },
50 | { x: 0, y: -20 },
51 | ]},
52 | { arc: [
53 | { x: 20, y: -20 },
54 | { x: 20, y: 0 },
55 | ]},
56 | { x: 20, y: 4 },
57 | ],
58 | addTo: illo,
59 | });
60 |
61 | // cap back
62 | new Zdog.Ellipse({
63 | addTo: hat,
64 | diameter: 40,
65 | quarters: 2,
66 | translate: { y: 4 },
67 | rotate: { x: TAU/4, z: -TAU/4 },
68 | });
69 |
70 | // brim back arch
71 | new Zdog.Ellipse({
72 | addTo: hat,
73 | diameter: 32,
74 | quarters: 2,
75 | translate: { y: 4, z: 12 },
76 | rotate: { z: -TAU/4 },
77 | });
78 |
79 | // cap back to brim bottom connect
80 | var brimConnector = new Zdog.Shape({
81 | path: [
82 | { x: -20, z: 0 },
83 | { arc: [
84 | { x: -20, z: 6 },
85 | { x: -16, z: 12 },
86 | ]},
87 | ],
88 | addTo: hat,
89 | translate: { y: 4 },
90 | });
91 |
92 | brimConnector.copy({
93 | scale: { x: -1 },
94 | });
95 |
96 | var brimTip = { x: 0, y: -12, z: 38 };
97 |
98 | new Zdog.Shape({
99 | path: [
100 | { x: 0, y: -12, z: 12 },
101 | brimTip,
102 | ],
103 | addTo: hat,
104 | });
105 |
106 | var brimBridge = new Zdog.Shape({
107 | path: [
108 | { x: -16, y: 4, z: 12 },
109 | { x: -16, y: 4, z: 22 },
110 | { bezier: [
111 | { x: -16, y: 4, z: 34 },
112 | { x: -14, y: -12, z: 38 },
113 | brimTip
114 | ]},
115 | ],
116 | addTo: hat,
117 | });
118 | brimBridge.copy({
119 | scale: { x: - 1},
120 | });
121 |
122 | // glasses front top
123 |
124 | new Zdog.Shape({
125 | path: [
126 | { x: -1 },
127 | { x: 1 },
128 | ],
129 | addTo: hat,
130 | translate: { y: 8, z: 12 },
131 | scale: { x: 16 },
132 | });
133 |
134 | // glass lens
135 | var lensScale = (quarterView - 1) * 0.75 + 1;
136 | var glassLens = new Zdog.Shape({
137 | path: [
138 | { x: 0, y: -3 },
139 | { x: 0, y: 0 },
140 | { arc: [
141 | { x: 0, y: 5 },
142 | { x: 5, y: 5 },
143 | ]},
144 | { arc: [
145 | { x: 10, y: 5 },
146 | { x: 10, y: 0 },
147 | ]},
148 | { x: 10, y: -3 },
149 | ],
150 | addTo: hat,
151 | translate: { x: -16, y: 11, z: 12 },
152 | scale: { x: lensScale },
153 | });
154 |
155 | glassLens.copy({
156 | translate: { x: 16, y: 11, z: 12 },
157 | scale: { x: -lensScale },
158 | });
159 |
160 | var glassesArm = new Zdog.Shape({
161 | path: [
162 | { x: 12, y: 0 },
163 | { x: -1, y: 0 },
164 | { arc: [
165 | { x: -1 - 8*quarterView, y: 0 },
166 | { x: -1 - 8*quarterView, y: 8 },
167 | ]},
168 | ],
169 | addTo: hat,
170 | translate: { x: -16, y: 8 },
171 | rotate: { y: TAU/4 },
172 | // only see one arm at time
173 | backface: false,
174 | });
175 | glassesArm.copy({
176 | scale: { x: -1 },
177 | translate: { x: 16, y: 8 },
178 | rotate: { y: -TAU/4 },
179 | });
180 |
181 | // -- animate --- //
182 |
183 | var t = 0;
184 | var cycleFrame = 240;
185 |
186 | function animate() {
187 | update();
188 | render();
189 | requestAnimationFrame( animate );
190 | }
191 |
192 | animate();
193 |
194 | // -- update -- //
195 |
196 |
197 | function update() {
198 |
199 |
200 | if ( isSpinning ) {
201 | t += 1/cycleFrame;
202 | t = t % 1;
203 | var isFirstHalf = t < 0.5;
204 | var halfT = isFirstHalf ? t : 1 - t;
205 | halfT /= 0.5;
206 | var easeT = Zdog.easeInOut( halfT, 3 );
207 | hat.rotate.y = easeT*TAU/4 - TAU/8;
208 | var rxDirection = isFirstHalf ? 1 : 0;
209 | hat.rotate.x = (Math.cos( halfT * TAU ) * -0.5 + 0.5 ) * -TAU/16 * rxDirection;
210 | }
211 |
212 | // normalize camera angle
213 | hat.normalizeRotate();
214 |
215 | var rx = hat.rotate.x;
216 | isRotateXFlat = rx < TAU/16 || rx > TAU * 15/16;
217 | // flip cap top
218 | var isRotateXTopSide = rx < TAU/4 || rx > TAU * 3/4;
219 | capTop.scale.y = isRotateXTopSide ? 1 : -1;
220 |
221 | illo.updateGraph();
222 | }
223 |
224 | // -- render -- //
225 |
226 | function render() {
227 | var ctx = illo.ctx;
228 | ctx.globalCompositeOperation = 'source-over';
229 | illo.renderGraph();
230 |
231 | // render gradient
232 | ctx.globalCompositeOperation = 'source-in';
233 | var gradient = ctx.createLinearGradient( 0, 0, 0, illo.height );
234 | gradient.addColorStop( 0.2, '#F00' );
235 | gradient.addColorStop( 0.75, '#19F' );
236 | ctx.fillStyle = gradient;
237 | ctx.fillRect( 0, 0, illo.width, illo.height );
238 | }
239 |
240 | // ----- inputs ----- //
241 |
242 | document.querySelector('.reset-button').onclick = function() {
243 | hat.rotate.set( initialHatRotate );
244 | };
245 |
--------------------------------------------------------------------------------
/demo/santorini/make-building.js:
--------------------------------------------------------------------------------
1 | /* jshint unused: false */
2 | /* globals makeWindow */
3 |
4 | // translate
5 | // width,
6 | // height
7 | // depth
8 | // nsWindows: function() {}
9 | // ewWindows: function() {}
10 | // gable: flat, ew, ns, slantS, slandN
11 |
12 | var TAU = Zdog.TAU;
13 | // colors
14 | var white = 'white';
15 | var southWall = white;
16 | var westWall = '#CDE';
17 | var eastWall = '#8AD';
18 | var roof = '#06B';
19 | var northWall = '#58C';
20 | var navy = '#037';
21 | var midnight = '#024';
22 |
23 |
24 | function makeBuilding( options ) {
25 |
26 | var wallX = options.width/2;
27 | var wallY = options.height;
28 | var wallZ = options.depth/2;
29 |
30 | // south/noth walls
31 | [ true, false ].forEach( function( isSouth ) {
32 | var wallTZ = isSouth ? -wallZ : wallZ;
33 | var wallGroup = new Zdog.Group({
34 | addTo: options.addTo,
35 | translate: { z: wallTZ },
36 | });
37 |
38 | var wallPath = [
39 | { x: -wallX, y: -wallY }
40 | ];
41 |
42 | if ( options.gable == 'ns' ) {
43 | wallPath.push({ x: 0, y: -wallY - wallX });
44 | } else if ( options.gable == 'slantS' && !isSouth ) {
45 | wallPath.push({ x: -wallX, y: -wallY - wallZ*2 });
46 | wallPath.push({ x: wallX, y: -wallY - wallZ*2 });
47 | }
48 |
49 | wallPath = wallPath.concat([
50 | { x: wallX, y: -wallY },
51 | { x: wallX, y: 0 },
52 | { x: -wallX, y: 0 },
53 | ]);
54 |
55 | // wall
56 | new Zdog.Shape({
57 | path: wallPath,
58 | addTo: wallGroup,
59 | color: isSouth ? southWall : northWall,
60 | });
61 |
62 | var windowColor = isSouth ? navy : midnight;
63 | handleWindows( options.nsWindows, wallGroup, windowColor );
64 |
65 | // cap border
66 | if ( options.gable == 'cap' ) {
67 | new Zdog.Rect({
68 | width: options.width,
69 | height: 2,
70 | addTo: wallGroup,
71 | translate: { y: -wallY - 1 },
72 | color: isSouth ? roof : midnight,
73 | });
74 | }
75 |
76 | });
77 |
78 | // east/west wall
79 | [ true, false ].forEach( function( isWest ) {
80 | var wallGroup = new Zdog.Group({
81 | addTo: options.addTo,
82 | translate: { x: isWest ? -wallX : wallX },
83 | rotate: { y: TAU/4 },
84 | });
85 |
86 | var wallPath = [
87 | { x: -wallZ, y: -wallY }
88 | ];
89 |
90 | if ( options.gable == 'ew' ) {
91 | wallPath.push({ x: 0, y: -wallY - wallZ });
92 | } else if ( options.gable == 'slantS' ) {
93 | wallPath.push({ x: wallZ, y: -wallY - wallZ*2 });
94 | }
95 |
96 | wallPath = wallPath.concat([
97 | { x: wallZ, y: -wallY },
98 | { x: wallZ, y: 0 },
99 | { x: -wallZ, y: 0 },
100 | ]);
101 |
102 | // wall
103 | new Zdog.Shape({
104 | path: wallPath,
105 | addTo: wallGroup,
106 | color: isWest ? westWall : eastWall,
107 | });
108 |
109 | var windowColor = isWest ? navy : midnight;
110 | handleWindows( options.ewWindows, wallGroup, windowColor );
111 |
112 | // cap border
113 | if ( options.gable == 'cap' ) {
114 | new Zdog.Rect({
115 | width: options.depth,
116 | height: 2,
117 | addTo: wallGroup,
118 | translate: { y: -wallY - 1 },
119 | color: isWest ? roof : midnight,
120 | });
121 | }
122 |
123 | });
124 |
125 |
126 | var roofMakers = {
127 | ns: function() {
128 | var y0 = -wallY - wallX;
129 | var roofPanel = new Zdog.Shape({
130 | path: [
131 | { x: 0, y: y0, z: -wallZ },
132 | { x: 0, y: y0, z: wallZ },
133 | { x: wallX, y: -wallY, z: wallZ },
134 | { x: wallX, y: -wallY, z: -wallZ },
135 | ],
136 | addTo: options.addTo,
137 | color: roof,
138 | });
139 | roofPanel.copy({
140 | scale: { x: -1 },
141 | });
142 | },
143 |
144 | ew: function() {
145 | var y0 = -wallY - wallZ;
146 | var roofPanel = new Zdog.Shape({
147 | path: [
148 | { z: 0, y: y0, x: -wallX },
149 | { z: 0, y: y0, x: wallX },
150 | { z: wallZ, y: -wallY, x: wallX },
151 | { z: wallZ, y: -wallY, x: -wallX },
152 | ],
153 | addTo: options.addTo,
154 | color: roof,
155 | });
156 | roofPanel.copy({
157 | scale: { z: -1 },
158 | });
159 | },
160 |
161 | slantS: function() {
162 | var roofY0 = -wallY;
163 | var roofY1 = -wallY - wallZ*2;
164 | new Zdog.Shape({
165 | path: [
166 | { x: -wallX, y: roofY0, z: -wallZ },
167 | { x: wallX, y: roofY0, z: -wallZ },
168 | { x: wallX, y: roofY1, z: wallZ },
169 | { x: -wallX, y: roofY1, z: wallZ },
170 | ],
171 | addTo: options.addTo,
172 | color: roof,
173 | });
174 | },
175 |
176 | flat: function() {
177 | new Zdog.Rect({
178 | width: options.width,
179 | height: options.depth,
180 | addTo: options.addTo,
181 | translate: { y: -wallY },
182 | rotate: { x: TAU/4 },
183 | color: roof,
184 | });
185 | },
186 |
187 | cap: function() {
188 | new Zdog.Rect({
189 | width: options.width,
190 | height: options.depth,
191 | addTo: options.addTo,
192 | translate: { y: -wallY - 2 },
193 | rotate: { x: TAU/4 },
194 | color: roof,
195 | });
196 | },
197 | };
198 |
199 | var roofMaker = roofMakers[ options.gable ];
200 | if ( roofMaker ) {
201 | roofMaker();
202 | }
203 |
204 | }
205 |
206 |
207 | function handleWindows( windows, wallGroup, color ) {
208 | windows = windows || [];
209 | windows.forEach( function( windowOption ) {
210 | var x = windowOption.x || 0;
211 | var y = windowOption.y || -5;
212 | var height = windowOption.height || 4;
213 | makeWindow({
214 | style: windowOption.style,
215 | addTo: wallGroup,
216 | height: height,
217 | translate: { x: x, y: y },
218 | color: color,
219 | });
220 | });
221 | }
222 |
--------------------------------------------------------------------------------
/demo/solid-shifter/shifter.js:
--------------------------------------------------------------------------------
1 | var navy = '#369';
2 | var green = '#692';
3 | var egg = '#FED';
4 | var ochre = '#E83';
5 |
6 | var TAU = Zdog.TAU;
7 |
8 | [ Zdog.Shape, Zdog.Rect, Zdog.Ellipse, Zdog.Cylinder, Zdog.Cone ]
9 | .forEach( function( ItemClass ) {
10 | ItemClass.defaults.fill = true;
11 | ItemClass.defaults.stroke = false;
12 | }
13 | );
14 |
15 |
16 | // triangle
17 | var isoTriangle = new Zdog.Shape({
18 | path: [
19 | { x: 1, y: 1 },
20 | { x: -1, y: 1 },
21 | { x: 0, y: -1 },
22 | ],
23 | color: egg,
24 | });
25 |
26 | function Shifter( options ) {
27 |
28 | var shifterAnchor = this.anchor = new Zdog.Anchor( options );
29 |
30 | this.pyramid = ( function() {
31 | var pyramid = new Zdog.Group({
32 | addTo: shifterAnchor,
33 | visible: false,
34 | // translate: { x: -3, y: -3 },
35 | updateSort: true,
36 | });
37 |
38 | var base = new Zdog.Rect({
39 | addTo: pyramid,
40 | width: 2,
41 | height: 2,
42 | translate: { y: 1 },
43 | rotate: { x: -TAU/4 },
44 | color: navy,
45 | });
46 |
47 |
48 | var triangle = new Zdog.Shape({
49 | addTo: base,
50 | path: [
51 | { x: 1, y: -1, z: 0 },
52 | { x: -1, y: -1, z: 0 },
53 | { x: 0, y: 0, z: -2 },
54 | ],
55 | color: ochre,
56 | });
57 | triangle.copy({
58 | rotate: { z: TAU/4 },
59 | });
60 | triangle.copy({
61 | rotate: { z: TAU/2 },
62 | });
63 | triangle.copy({
64 | rotate: { z: TAU * 3/4 },
65 | });
66 |
67 | return pyramid;
68 | })();
69 |
70 | // cylinder 1
71 | this.cylinder1 = new Zdog.Cylinder({
72 | addTo: shifterAnchor,
73 | visible: false,
74 | diameter: 2,
75 | length: 2,
76 | // translate: { x: 0, y: -3 },
77 | rotate: { y: TAU/4 },
78 | color: navy,
79 | backface: egg,
80 | });
81 |
82 | // cone 1
83 | // isoTriangle.copy({
84 | // translate: { x: 3, y: -3, z: -2 },
85 | // color: green,
86 | // });
87 |
88 | this.cone = ( function() {
89 | var anchor = new Zdog.Group({
90 | addTo: shifterAnchor,
91 | visible: false,
92 | // translate: { x: 3, y: -3 },
93 | updateSort: true,
94 | });
95 |
96 | new Zdog.Cone({
97 | addTo: anchor,
98 | diameter: 2,
99 | length: 2,
100 | rotate: { x: TAU/4 },
101 | translate: { y: 1 },
102 | color: ochre,
103 | backface: egg,
104 | });
105 |
106 | return anchor;
107 | })();
108 |
109 | // triangular prism
110 |
111 | this.prism = ( function() {
112 | var prism = new Zdog.Group({
113 | addTo: shifterAnchor,
114 | visible: false,
115 | // translate: { x: -3, y: 0 },
116 | updateSort: true,
117 | });
118 |
119 | var triangle = isoTriangle.copy({
120 | addTo: prism,
121 | scale: { y: -1 },
122 | rotate: { y: TAU/4 },
123 | translate: { x: -1 },
124 | color: ochre,
125 | });
126 | triangle.copy({
127 | translate: { x: 1 },
128 | });
129 |
130 | var angleFace = new Zdog.Shape({
131 | addTo: prism,
132 | path: [
133 | { x: -1, y: -1, z: 1 },
134 | { x: 1, y: -1, z: 1 },
135 | { x: 1, y: 1, z: 0 },
136 | { x: -1, y: 1, z: 0 },
137 | ],
138 | color: navy,
139 | });
140 | angleFace.copy({
141 | scale: { z: -1 },
142 | });
143 |
144 | // base
145 | new Zdog.Rect({
146 | addTo: prism,
147 | width: 2,
148 | height: 2,
149 | rotate: { x: TAU/4 },
150 | translate: { y: -1 },
151 | color: green,
152 | });
153 |
154 | return prism;
155 | })();
156 |
157 | // eccentric cylinder, triangle contour
158 |
159 | this.triCylinder = ( function() {
160 | var cylinder = new Zdog.Group({
161 | addTo: shifterAnchor,
162 | visible: false,
163 | // translate: { x: 3 },
164 | });
165 |
166 | isoTriangle.copy({
167 | translate: {},
168 | addTo: cylinder,
169 | color: ochre,
170 | });
171 |
172 | var tilt = Math.atan(1/2);
173 |
174 | var capAnchor = new Zdog.Anchor({
175 | addTo: cylinder,
176 | translate: { x: -0.5 },
177 | rotate: { y: TAU/4 },
178 | });
179 |
180 |
181 | // left outside cap
182 | var cap = new Zdog.Ellipse({
183 | addTo: capAnchor,
184 | diameter: 2,
185 | color: egg,
186 | rotate: { x: tilt },
187 | scale: { y: 1/Math.cos( tilt ) },
188 | backface: false,
189 | });
190 | cap.copy({ // left inside cap
191 | rotate: { y: TAU/2, x: tilt },
192 | color: ochre,
193 | });
194 |
195 | capAnchor.copyGraph({
196 | translate: { x: 0.5 },
197 | rotate: { y: -TAU/4 },
198 | });
199 |
200 | return cylinder;
201 | })();
202 |
203 | this.cylinder2 = this.cylinder1.copy({
204 | translate: {},
205 | visible: false,
206 | rotate: { x: TAU/4 },
207 | });
208 |
209 | }
210 |
211 | Shifter.prototype.update = function( t ) {
212 |
213 | var turn = Math.floor( t % 6 );
214 |
215 | var easeT = Zdog.easeInOut( t % 1, 4 ) * TAU/4;
216 | this.pyramid.rotate.x = easeT;
217 | this.cylinder1.rotate.y = easeT + TAU/4;
218 | this.cone.rotate.x = easeT + TAU/4;
219 | this.prism.rotate.y = easeT + TAU/4;
220 | this.cylinder2.rotate.x = easeT + TAU/4;
221 | this.triCylinder.rotate.y = easeT + TAU/4;
222 |
223 | if ( turn === 0 ) {
224 | this.triCylinder.visible = false;
225 | this.pyramid.visible = true;
226 | } else if ( turn == 1) {
227 | this.pyramid.visible = false;
228 | this.cylinder1.visible = true;
229 | } else if ( turn == 2 ) {
230 | this.cylinder1.visible = false;
231 | this.cone.visible = true;
232 | } else if ( turn == 3 ) {
233 | this.cone.visible = false;
234 | this.prism.visible = true;
235 | } else if ( turn == 4 ) {
236 | this.prism.visible = false;
237 | this.cylinder2.visible = true;
238 | } else if ( turn == 5 ) {
239 | this.cylinder2.visible = false;
240 | this.triCylinder.visible = true;
241 | }
242 | };
243 |
--------------------------------------------------------------------------------
/demo/castle/castle.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var illoSize = 24;
5 | var minWindowSize = Math.min( window.innerWidth - 20, window.innerHeight - 40 );
6 | var zoom = Math.floor( minWindowSize / illoSize );
7 | illoElem.setAttribute( 'width', illoSize * zoom );
8 | illoElem.setAttribute( 'height', illoSize * zoom );
9 |
10 | [ Zdog.Shape, Zdog.Rect ].forEach( function( ItemClass ) {
11 | ItemClass.defaults.fill = true;
12 | ItemClass.defaults.backface = false;
13 | ItemClass.defaults.stroke = 1/zoom;
14 | });
15 |
16 | var white = 'white';
17 | var black = '#333';
18 | var isSpinning = true;
19 | var TAU = Zdog.TAU;
20 | var initRotate = { y: TAU/4 };
21 |
22 | var illo = new Zdog.Illustration({
23 | element: illoElem,
24 | zoom: zoom,
25 | rotate: initRotate,
26 | dragRotate: true,
27 | onDragStart: function() {
28 | isSpinning = false;
29 | },
30 | });
31 |
32 | // -- illustration shapes --- //
33 |
34 | function makeWall( options ) {
35 | var rotor = new Zdog.Anchor({
36 | addTo: illo,
37 | rotate: options.rotate,
38 | });
39 |
40 | // rotor
41 | var wall = new Zdog.Anchor({
42 | addTo: rotor,
43 | translate: { z: 4 },
44 | });
45 |
46 | var topBlock = new Zdog.Anchor({
47 | addTo: wall,
48 | translate: { x: -4, y: -4 },
49 | });
50 |
51 | // side faces
52 | var face = new Zdog.Rect({
53 | addTo: topBlock,
54 | width: 2,
55 | height: 2,
56 | translate: { z: 1 },
57 | color: options.outside,
58 | });
59 | face.copy({
60 | translate: { x: -1 },
61 | rotate: { y: TAU/4 },
62 | color: options.left,
63 | });
64 | face.copy({
65 | translate: { x: 1 },
66 | rotate: { y: -TAU/4 },
67 | color: options.right,
68 | });
69 | face.copy({
70 | translate: { z: -1 },
71 | rotate: { y: TAU/2 },
72 | color: options.inside,
73 | });
74 | // top
75 | face.copy({
76 | translate: { y: -1 },
77 | rotate: { x: TAU/4 },
78 | color: black,
79 | });
80 |
81 | topBlock.copyGraph({
82 | translate: { x: 0, y: -4 },
83 | });
84 |
85 | var topTile = new Zdog.Rect({
86 | addTo: wall,
87 | width: 2,
88 | height: 2,
89 | color: black,
90 | rotate: { x: TAU/4 },
91 | translate: { x: -2, y: -3 },
92 | });
93 | topTile.copy({
94 | translate: { x: 2, y: -3 }
95 | });
96 |
97 | // outside arch
98 |
99 | // outside arch
100 | var arch = new Zdog.Shape({
101 | addTo: wall,
102 | path: [
103 | { x: 0, y: -3 },
104 | { x: 3, y: -3 },
105 | { x: 3, y: 2 },
106 | { arc: [
107 | { x: 3, y: -1 },
108 | { x: 0, y: -1 }
109 | ]},
110 | ],
111 | translate: { z: 1 },
112 | color: options.outside,
113 | });
114 | arch.copy({
115 | scale: { x: -1 },
116 | });
117 |
118 |
119 | // inside arch
120 | arch.copy({
121 | translate: { z: -1 },
122 | rotate: { y: TAU/2 },
123 | color: options.inside,
124 | });
125 | arch.copy({
126 | translate: { z: -1 },
127 | rotate: { y: TAU/2 },
128 | scale: { x: -1 },
129 | color: options.inside,
130 | });
131 |
132 | // outside columns
133 | var outsideColumn = new Zdog.Rect({
134 | addTo: wall,
135 | width: 2,
136 | height: 8,
137 | translate: { x: -4, y: 1, z: 1 },
138 | color: options.outside,
139 | });
140 | outsideColumn.copy({
141 | translate: { x: 4, y: 1, z: 1 },
142 | });
143 |
144 | var insideColumn = new Zdog.Rect({
145 | addTo: wall,
146 | width: 2,
147 | height: 3,
148 | translate: { x: -3, y: 3.5 },
149 | rotate: { y: -TAU/4 },
150 | color: options.right,
151 | });
152 | insideColumn.copy({
153 | translate: { x: 3, y: 3.5 },
154 | rotate: { y: TAU/4 },
155 | color: options.left,
156 | });
157 |
158 | // under arch, quarter arc
159 | var underArch = new Zdog.Shape({
160 | addTo: wall,
161 | path: [
162 | { x: 3, y: 2 },
163 | { arc: [
164 | { x: 3, y: -1 },
165 | { x: 0, y: -1 }
166 | ]},
167 | { x: 0, y: -1, z: -2 },
168 | { arc: [
169 | { x: 3, y: -1, z: -2 },
170 | { x: 3, y: 2, z: -2 },
171 | ]},
172 | ],
173 | translate: { z: 1 },
174 | backface: true,
175 | color: options.left,
176 | });
177 | underArch.copyGraph({
178 | scale: { x: -1 },
179 | color: options.right,
180 | });
181 |
182 | // feet soles
183 | new Zdog.Rect({
184 | addTo: wall,
185 | width: 2,
186 | height: 2,
187 | translate: { x: -4, y: 5, z: 0 },
188 | rotate: { x: -TAU/4 },
189 | color: white,
190 | });
191 |
192 | }
193 |
194 | makeWall({
195 | rotate: {},
196 | outside: white,
197 | inside: black,
198 | left: white,
199 | right: black,
200 | });
201 |
202 | makeWall({
203 | rotate: { y: -TAU/4 },
204 | outside: black,
205 | inside: white,
206 | left: white,
207 | right: black,
208 | });
209 |
210 | makeWall({
211 | rotate: { y: -TAU/2 },
212 | outside: black,
213 | inside: white,
214 | left: black,
215 | right: white,
216 | });
217 |
218 | makeWall({
219 | rotate: { y: TAU * -3/4 },
220 | outside: white,
221 | inside: black,
222 | left: black,
223 | right: white,
224 | });
225 |
226 |
227 | // -- animate --- //
228 |
229 | var ticker = 0;
230 | var cycleCount = 105;
231 |
232 | var keyframes = [
233 | { x: TAU * 0, y: TAU * 1/4 },
234 | { x: TAU * -35/360, y: TAU * 5/8 },
235 | { x: TAU * -1/4, y: TAU * 3/4 },
236 | { x: TAU * -35/360, y: TAU * 9/8 },
237 | { x: TAU * 0, y: TAU * 5/4 },
238 | ];
239 |
240 | function animate() {
241 | // update
242 | if ( isSpinning ) {
243 | var progress = ticker / cycleCount;
244 | var tween = Zdog.easeInOut( progress % 1, 4 );
245 | var turnLimit = keyframes.length - 1;
246 | var turn = Math.floor( progress % turnLimit );
247 | var keyA = keyframes[ turn ];
248 | var keyB = keyframes[ turn + 1 ];
249 | illo.rotate.x = Zdog.lerp( keyA.x, keyB.x, tween );
250 | illo.rotate.y = Zdog.lerp( keyA.y, keyB.y, tween );
251 | ticker++;
252 | }
253 |
254 | illo.updateRenderGraph();
255 | requestAnimationFrame( animate );
256 | }
257 |
258 | animate();
259 |
260 |
--------------------------------------------------------------------------------
/demo/madeline/make-madeline.js:
--------------------------------------------------------------------------------
1 | /* jshint unused: false */
2 |
3 | var TAU = Zdog.TAU;
4 |
5 | function makeMadeline( isGood, colors, options ) {
6 |
7 | var rotor = new Zdog.Anchor( options );
8 |
9 | var body = new Zdog.Group({
10 | addTo: rotor,
11 | rotate: { x: -TAU/8 },
12 | translate: { z: -48 },
13 | updateSort: true,
14 | });
15 |
16 | var head = new Zdog.Anchor({
17 | addTo: body,
18 | translate: { y: -11, z: -2 },
19 | rotate: { x: TAU/8 },
20 | });
21 |
22 | // face
23 | var face = new Zdog.Ellipse({
24 | diameter: 6,
25 | addTo: head,
26 | translate: { z: 4 },
27 | stroke: 8,
28 | color: colors.skin,
29 | });
30 |
31 | var eyeGroup = new Zdog.Group({
32 | addTo: face,
33 | translate: { z: face.stroke/2 - 0.5 },
34 | });
35 |
36 |
37 | // eyes
38 | [ -1, 1 ].forEach( function( xSide ) {
39 | // cheek blush
40 | if ( isGood ) {
41 | new Zdog.Ellipse({
42 | width: 2,
43 | height: 1.3,
44 | addTo: eyeGroup,
45 | translate: { x: 4.5*xSide, y: 3, z: -1 },
46 | rotate: { y: -TAU/16*xSide },
47 | stroke: 1,
48 | color: '#FA8',
49 | fill: true,
50 | });
51 | }
52 |
53 | var eyeX = 3.5*xSide;
54 |
55 | // eye
56 | new Zdog.Ellipse({
57 | width: 0.75,
58 | height: 1.5,
59 | addTo: eyeGroup,
60 | color: colors.eye,
61 | translate: { x: eyeX },
62 | stroke: 2,
63 | fill: true,
64 | });
65 |
66 | // eye brow
67 | new Zdog.Ellipse({
68 | addTo: eyeGroup,
69 | height: 3,
70 | width: 1.2,
71 | quarters: 2,
72 | translate: { x: eyeX, y: -3 },
73 | rotate: { z: -TAU/4 + 0.15*xSide * (isGood ? 1 : -1) },
74 | color: colors.hair,
75 | stroke: 1,
76 | fill: false,
77 | closed: true,
78 | });
79 |
80 | });
81 |
82 |
83 | // hair ball
84 | new Zdog.Shape({
85 | path: [
86 | { x: -1 },
87 | { x: 1 },
88 | { z: -4 },
89 | ],
90 | addTo: head,
91 | translate: { y: -4, z: -1 },
92 | stroke: 18,
93 | color: colors.hair,
94 | });
95 |
96 | var bang = new Zdog.Shape({
97 | path: [
98 | {},
99 | { arc: [
100 | { z: 4, y: 4 },
101 | { z: 0, y: 8 },
102 | ]},
103 | ],
104 | addTo: head,
105 | translate: { x: 2, y: -7.5, z: 6 },
106 | rotate: { x: 0.5, z: -0.5 },
107 | stroke: 4,
108 | color: colors.hair,
109 | closed: false,
110 | });
111 | bang.copy({
112 | translate: { x: 5, y: -6, z: 5 },
113 | rotate: { x: -0.3, z: -0.5 },
114 | });
115 | bang.copy({
116 | translate: { x: 5, y: -6, z: 3 },
117 | rotate: { y: -0.7, z: -1 },
118 | });
119 |
120 | // left side
121 | bang.copy({
122 | translate: { x: -2, y: -7.5, z: 6 },
123 | rotate: { x: 0, z: TAU/16*6 },
124 | });
125 | bang.copy({
126 | translate: { x: -5, y: -6, z: 5 },
127 | rotate: { x: 0, z: TAU/4 },
128 | });
129 | bang.copy({
130 | translate: { x: -5, y: -6, z: 3 },
131 | rotate: { y: 0.7, z: 1 },
132 | });
133 |
134 | // hair cover
135 | new Zdog.Shape({
136 | path: [
137 | { x: -3 },
138 | { x: 3 },
139 | ],
140 | addTo: head,
141 | stroke: 7,
142 | translate: { y: -8, z: 5 },
143 | color: colors.hair,
144 | });
145 |
146 | // trail locks
147 |
148 | var trailLock = new Zdog.Shape({
149 | path: [
150 | { y: -4, z: 0 },
151 | { bezier: [
152 | { y: -10, z: -14 },
153 | { y: 0, z: -16 },
154 | { y: 0, z: -26 }
155 | ]},
156 | ],
157 | addTo: head,
158 | translate: { z: -4, y: 0 },
159 | stroke: 10,
160 | color: colors.hair,
161 | closed: false,
162 | });
163 |
164 | trailLock.copy({
165 | translate: { x: -3, z: -4 },
166 | rotate: { z: -TAU/8 },
167 | stroke: 8,
168 | });
169 | trailLock.copy({
170 | translate: { x: 3, z: -4 },
171 | rotate: { z: TAU/8 },
172 | stroke: 8,
173 | });
174 | trailLock.copy({
175 | translate: { y: 2 },
176 | // rotate: { z: TAU/2 },
177 | scale: { y: 0.5 },
178 | stroke: 8,
179 | });
180 |
181 | // ----- torso ----- //
182 |
183 | // 2nd rib
184 | var torsoRib = new Zdog.Ellipse({
185 | width: 12,
186 | height: 10,
187 | addTo: body,
188 | rotate: { x: -TAU/4 },
189 | translate: { y: -1 },
190 | stroke: 6,
191 | color: colors.parkaLight,
192 | fill: true,
193 | });
194 | // neck rib
195 | torsoRib.copy({
196 | width: 6,
197 | height: 6,
198 | translate: { y: -5 },
199 | });
200 | // 3rd rib
201 | torsoRib.copy({
202 | translate: { y: 3 },
203 | });
204 | // 4th rib
205 | torsoRib.copy({
206 | translate: { y: 7 },
207 | color: colors.parkaDark,
208 | });
209 | // waist
210 | new Zdog.Ellipse({
211 | width: 10,
212 | height: 8,
213 | addTo: body,
214 | rotate: { x: -TAU/4 },
215 | translate: { y: 11 },
216 | stroke: 4,
217 | color: colors.tight,
218 | fill: true,
219 | });
220 |
221 | // arms
222 | [ -1, 1 ].forEach( function( xSide ) {
223 | var isLeft = xSide == 1;
224 | // shoulder ball
225 | new Zdog.Shape({
226 | addTo: body,
227 | stroke: 6,
228 | translate: { x: 6*xSide, y: -5, z: -1 },
229 | color: colors.parkaLight,
230 | });
231 |
232 | var shoulderJoint = new Zdog.Anchor({
233 | addTo: body,
234 | translate: { x: 9*xSide, y: -3, z: -2 },
235 | rotate: isLeft ? { x: TAU/8*3, z: -TAU/32 } : { z: TAU/16*2, x: -TAU/16*2 },
236 | });
237 |
238 | // top shoulder rib
239 | var armRib = new Zdog.Ellipse({
240 | diameter: 2,
241 | rotate: { x: -TAU/4 },
242 | addTo: shoulderJoint,
243 | translate: { x: 0*xSide },
244 | stroke: 6,
245 | color: colors.parkaLight,
246 | fill: true,
247 | });
248 | armRib.copy({
249 | translate: { y: 4 },
250 | });
251 |
252 | var elbowJoint = new Zdog.Anchor({
253 | addTo: shoulderJoint,
254 | translate: { y: 8 },
255 | rotate: isLeft ? {} : { z: TAU/8 },
256 | });
257 |
258 | armRib.copy({
259 | addTo: elbowJoint,
260 | translate: { x: 0, y: 0 },
261 | });
262 | armRib.copy({
263 | addTo: elbowJoint,
264 | translate: { y: 4 },
265 | color: colors.parkaDark,
266 | });
267 |
268 | // hand
269 | new Zdog.Shape({
270 | addTo: elbowJoint,
271 | translate: { y: 9, z: -1 },
272 | stroke: 8,
273 | color: colors.skin,
274 | });
275 |
276 | // ----- legs ----- //
277 | var knee = { y: 7 };
278 | var thigh = new Zdog.Shape({
279 | path: [ { y: 0 }, knee ],
280 | addTo: body,
281 | translate: { x: 4*xSide, y: 13 },
282 | rotate: isLeft ? {} : { x: TAU/16*3, z: TAU/16 },
283 | stroke: 8,
284 | color: colors.tight,
285 | });
286 |
287 | var shin = new Zdog.Shape({
288 | path: [ { y: 0 }, { y: 8 } ],
289 | addTo: thigh,
290 | stroke: 6,
291 | translate: knee,
292 | rotate: isLeft ? {} : { x: -TAU/16*5 },
293 | color: colors.tight,
294 | });
295 |
296 | });
297 |
298 | // butt
299 | new Zdog.Shape({
300 | path: [
301 | { x: -3 },
302 | { x: 3 },
303 | ],
304 | visible: false,
305 | addTo: body,
306 | translate: { y: 11, z: -2 },
307 | stroke: 8,
308 | color: colors.tight,
309 | });
310 |
311 | }
312 |
--------------------------------------------------------------------------------
/demo/mega-man/mega-man.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var illoSize = 72;
5 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
6 | var zoom = Math.floor( minWindowSize / illoSize );
7 | illoElem.setAttribute( 'width', illoSize * zoom );
8 | illoElem.setAttribute( 'height', illoSize * zoom );
9 | var isSpinning = true;
10 | var TAU = Zdog.TAU;
11 |
12 | var illo = new Zdog.Illustration({
13 | element: illoElem,
14 | zoom: zoom,
15 | dragRotate: true,
16 | onDragStart: function() {
17 | isSpinning = false;
18 | },
19 | });
20 |
21 | // colors
22 | var lightBlue = '#7CF';
23 | var darkBlue = '#25C';
24 | var skin = '#FCA';
25 |
26 | // -- illustration shapes --- //
27 |
28 | // keep track of pupils to change position
29 | var pupils = {};
30 |
31 | // head
32 |
33 | var head = new Zdog.Shape({
34 | translate: { y: -20 },
35 | rotate: { y: 0.5 },
36 | stroke: 21,
37 | color: darkBlue,
38 | addTo: illo,
39 | });
40 |
41 | // helmet details
42 | [ 1, 3, 4, 5, 6, 7, 8, 9 ].forEach( function( i ) {
43 | new Zdog.Shape({
44 | path: [
45 | { x: -1.25, y: -1.5, z: 11.25 },
46 | { x: 1.25, y: -1.5, z: 11.25 },
47 | { x: 1.25, y: 1.5, z: 11.25 },
48 | { x: -1.25, y: 1.5, z: 11.25 },
49 | ],
50 | rotate: { x: TAU/20 * i },
51 | stroke: 2,
52 | fill: true,
53 | color: lightBlue,
54 | addTo: head,
55 | });
56 | });
57 |
58 |
59 | // upper body
60 | new Zdog.Shape({
61 | path: [
62 | { x: -2, y: -1.25 },
63 | { x: 0, y: -1.5 },
64 | { x: 2, y: -1.25 },
65 | { x: 1.7, y: 0.5 },
66 | { x: -1.7, y: 0.5 },
67 | ],
68 | translate: { y: -4 },
69 | stroke: 11,
70 | color: lightBlue,
71 | fill: true,
72 | addTo: illo,
73 | });
74 |
75 | // undies
76 |
77 | var undieX = 4.5;
78 | var undieY0 = -1;
79 | var undieY1 = 0;
80 | var undieZ = 2.5;
81 |
82 | // front undie panel
83 | var undiePanel = new Zdog.Shape({
84 | path: [
85 | { x: -undieX, y: undieY0 },
86 | { x: undieX, y: undieY0 },
87 | { x: undieX, y: undieY1 },
88 | { x: 0, y: 1.5 },
89 | { x: -undieX, y: undieY1 },
90 | ],
91 | translate: { y: 4, z: undieZ },
92 | stroke: 5,
93 | color: darkBlue,
94 | fill: true,
95 | addTo: illo,
96 | });
97 |
98 | undiePanel.copy({
99 | translate: { y: 4, z: -undieZ },
100 | });
101 |
102 | // right undie panel
103 | var sideUndiePanel = new Zdog.Shape({
104 | path: [
105 | { y: undieY0, z: undieZ },
106 | { y: undieY0, z: -undieZ },
107 | { y: undieY1, z: -undieZ },
108 | { y: undieY1, z: undieZ },
109 | ],
110 | translate: { x: -undieX, y: 4, },
111 | stroke: 5,
112 | color: darkBlue,
113 | fill: true,
114 | addTo: illo,
115 | });
116 | // left
117 | sideUndiePanel.copy({
118 | translate: { x: undieX, y: 4, },
119 | });
120 |
121 | //
122 | var shoulderX = 5;
123 | var shoulderY = -7;
124 |
125 | // right upper arm
126 | var rightUpperArm = new Zdog.Shape({
127 | path: [
128 | { x: 0 },
129 | { x: -7 },
130 | ],
131 | translate: { x: -shoulderX, y: shoulderY },
132 | rotate: { z: -0.8, y: -0.6 },
133 | stroke: 6,
134 | color: lightBlue,
135 | addTo: illo,
136 | });
137 |
138 | var rightForeArm = new Zdog.Shape({
139 | path: [
140 | { x: -4 },
141 | { x: -8 },
142 | ],
143 | translate: rightUpperArm.path[1],
144 | rotate: { z: 1.4 },
145 | stroke: 10,
146 | color: darkBlue,
147 | addTo: rightUpperArm,
148 | });
149 |
150 | new Zdog.Shape({
151 | path: [
152 | { x: -4 },
153 | ],
154 | translate: rightForeArm.path[1],
155 | rotate: { z: 0.3 },
156 | stroke: 11,
157 | color: darkBlue,
158 | addTo: rightForeArm,
159 | });
160 |
161 | // left arm, the gun arm
162 | var leftUpperArm = new Zdog.Shape({
163 | path: [
164 | { x: 0 },
165 | { x: 11 },
166 | ],
167 | translate: { x: shoulderX, y: shoulderY-0.5 },
168 | rotate: { z: -0.2, y: 0.3 },
169 | stroke: 6,
170 | color: lightBlue,
171 | addTo: illo,
172 | });
173 |
174 | var leftForeArm = new Zdog.Shape({
175 | path: [
176 | { x: 5 },
177 | { x: 10 },
178 | ],
179 | translate: leftUpperArm.path[1],
180 | rotate: { z: -TAU/4 - leftUpperArm.rotate.z },
181 | stroke: 11,
182 | color: darkBlue,
183 | addTo: leftUpperArm,
184 | });
185 |
186 | new Zdog.Shape({
187 | path: [ { x: 4 } ],
188 | translate: leftForeArm.path[1],
189 | stroke: 7,
190 | color: darkBlue,
191 | addTo: leftForeArm,
192 | });
193 |
194 | [ -1, 1 ].forEach( function( xSide ) {
195 |
196 | var facePanelGroup = new Zdog.Group({
197 | addTo: head,
198 | });
199 |
200 | var facePanel = new Zdog.Shape({
201 | addTo: facePanelGroup,
202 | path: [
203 | { x: 4*xSide, y: -4, z: -1 }, // top inside brow
204 | { arc: [
205 | { x: 0*xSide, y: -4, z: 0.5 },
206 | { x: 0*xSide, y: 1, z: 1 }, // widows peak
207 | ]},
208 | { x: 0*xSide, y: 1, z: 1 }, // nose
209 | { x: 0*xSide, y: 5.5, z: -1 }, // chin front
210 | { arc: [
211 | { x: 7*xSide, y: 5.5, z: -4 }, // jaw
212 | { x: 7*xSide, y: 0, z: -4 }, // far side
213 | ]},
214 | { arc: [
215 | { x: 7*xSide, y: -4, z: -4 }, // top back brow
216 | { x: 4*xSide, y: -4, z: -1 }, // top inside brow
217 | ]},
218 | ],
219 | translate: { y: 4, z: 8.5 },
220 | fill: true,
221 | stroke: 1,
222 | color: skin,
223 | });
224 |
225 | // eye whites
226 | var eyeWhite = new Zdog.Ellipse({
227 | addTo: facePanel,
228 | width: 4,
229 | height: 5,
230 | translate: { x: 3.75*xSide, y: -0.5, z: 0.5 },
231 | rotate: { y: -0.2*xSide },
232 | stroke: 1,
233 | fill: true,
234 | color: 'white',
235 | backface: false,
236 | });
237 |
238 | // pupils
239 | var pupil = new Zdog.Ellipse({
240 | addTo: eyeWhite,
241 | width: 1,
242 | height: 4,
243 | translate: { x: -0.4*xSide, y: -0.2, z: 1 },
244 | rotate: { y: 0.2*xSide },
245 | stroke: 1,
246 | fill: true,
247 | color: '#128',
248 | backface: false,
249 | });
250 | // add to hash
251 | pupils[ xSide ] = pupil;
252 |
253 | // ear cone outer
254 | var earCone = new Zdog.Ellipse({
255 | diameter: 5.5,
256 | translate: { x: 10*xSide, y: 3, z: -1 },
257 | rotate: { y: (TAU/4+0.2)*-xSide, x: TAU/4, z: 1 },
258 | fill: false,
259 | stroke: 2.5,
260 | color: lightBlue,
261 | addTo: head,
262 | });
263 |
264 | // ear cone inner inner
265 | new Zdog.Ellipse({
266 | diameter: 5,
267 | addTo: earCone,
268 | translate: { z: -1 },
269 | color: '#C11',
270 | stroke: false,
271 | fill: true,
272 | });
273 |
274 | // thigh
275 | var thigh = new Zdog.Shape({
276 | path: [ { y: 0 }, { y: 3 } ],
277 | translate: { x: 4.5*xSide, y: 8 },
278 | rotate: { z: -0.35*xSide, x: -0.1 },
279 | stroke: 6,
280 | color: lightBlue,
281 | addTo: illo,
282 | });
283 |
284 | // shin
285 | var shin = new Zdog.Shape({
286 | path: [
287 | { y: 5, z: 0 },
288 | { y: 14, z: 2 },
289 | { y: 14, z: -1 },
290 | ],
291 | translate: thigh.path[1],
292 | rotate: { y: -0.5*xSide },
293 | fill: true,
294 | stroke: 11,
295 | color: darkBlue,
296 | addTo: thigh,
297 | });
298 |
299 | // sole
300 | new Zdog.Shape({
301 | path: [
302 | { y: 2.5, x: (0.5 + 2)*xSide, z: -3 },
303 | { y: 2.5, x: (0.5 + -2)*xSide, z: -3 },
304 | { y: 2.5, x: (0.5 + -1)*xSide, z: 5 },
305 | { y: 2.5, x: (0.5 + 1)*xSide, z: 5 },
306 | ],
307 | translate: shin.path[1],
308 | rotate: { z: 0.4*xSide, x: -0.1 },
309 | fill: true,
310 | stroke: 7,
311 | color: darkBlue,
312 | addTo: shin,
313 | });
314 |
315 | });
316 |
317 | // -- animate --- //
318 |
319 | var isSpinning = true;
320 |
321 | function animate() {
322 | update();
323 | illo.renderGraph();
324 | requestAnimationFrame( animate );
325 | }
326 |
327 | animate();
328 |
329 | // -- update -- //
330 |
331 | function update() {
332 | illo.rotate.y += isSpinning ? -TAU/150 : 0;
333 | illo.normalizeRotate();
334 |
335 | // change pupil position
336 | var isAngleXFlip = illo.rotate.x > TAU/4 && illo.rotate.x < TAU * 3/4;
337 | var angleXOffset = isAngleXFlip ? 0 : TAU/2;
338 | // angleXFlip *=
339 | var headAngleY = Zdog.modulo( illo.rotate.y + head.rotate.y + angleXOffset, TAU );
340 | var headAngleX = Zdog.modulo( illo.rotate.x + angleXOffset, TAU );
341 | var stareX = (headAngleY / TAU * 2 - 1) * 8;
342 | var stareY = (headAngleX / TAU * 2 - 1) * 8;
343 | stareX = Math.max( -2, Math.min( 2, stareX ) );
344 | stareY = Math.max( -1, Math.min( 1, stareY ) );
345 | stareY = isAngleXFlip ? -stareY : stareY;
346 | // console.log( stareX );
347 | pupils[-1].translate.x = 0.4 + stareX;
348 | pupils[1].translate.x = -0.4 + stareX;
349 | pupils[-1].translate.y = -0.2 + stareY;
350 | pupils[1].translate.y = -0.2 + stareY;
351 |
352 | // rotate
353 | illo.updateGraph();
354 | }
355 |
356 |
--------------------------------------------------------------------------------
/demo/truck-flight/truck-flight.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var sceneSize = 88;
5 | var zoom = 5;
6 | var illoSize = sceneSize * zoom;
7 | illoElem.setAttribute( 'width', illoSize );
8 | illoElem.setAttribute( 'height', illoSize );
9 | var TAU = Zdog.TAU;
10 | var initRotate = { x: TAU/16, y: TAU/8 };
11 |
12 | var illo = new Zdog.Illustration({
13 | element: illoElem,
14 | zoom: zoom,
15 | rotate: initRotate,
16 | dragRotate: true,
17 | });
18 |
19 | // colors
20 | var light = '#FFF';
21 | var dark = '#333';
22 |
23 | var darkStroke = {
24 | addTo: illo,
25 | color: dark,
26 | stroke: 2,
27 | fill: false,
28 | };
29 |
30 | var lightFill = {
31 | addTo: illo,
32 | color: light,
33 | stroke: false,
34 | fill: true,
35 | };
36 |
37 | var allDark = {
38 | addTo: illo,
39 | color: dark,
40 | fill: true,
41 | stroke: 2,
42 | };
43 |
44 | // -- illustration shapes --- //
45 |
46 | var bedSidePath = [
47 | { x: -32, y: -4 },
48 | { x: -8, y: -4 },
49 | { x: -8, y: 8 },
50 | { x: -32, y: 8 },
51 | ];
52 |
53 | var darkStrokeSide = Zdog.extend( {translate: { z: 12 }}, darkStroke );
54 | var lightFillSide = Zdog.extend( {translate: { z: 12 }}, lightFill );
55 | var allDarkSide = Zdog.extend( {translate: { z: -12 }}, allDark );
56 |
57 | // sides, outer
58 | [ lightFillSide, darkStrokeSide, allDarkSide ].forEach( function( sideOptions ) {
59 |
60 | // door
61 | new Zdog.Shape( Zdog.extend( {
62 | path: [
63 | { x: -8, y: -14 },
64 | { x: 10, y: -14 },
65 | { x: 20, y: -4 },
66 | { x: 20, y: 8 },
67 | { x: -8, y: 8 },
68 | ],
69 | }, sideOptions ) );
70 |
71 | // bed side
72 | new Zdog.Shape( Zdog.extend( {
73 | path: bedSidePath,
74 | }, sideOptions ) );
75 |
76 | // front side
77 | new Zdog.Shape( Zdog.extend( {
78 | path: [
79 | { x: 20, y: -4 },
80 | { x: 32, y: -4 },
81 | { x: 32, y: 8 },
82 | { x: 20, y: 8 },
83 | ],
84 | }, sideOptions ) );
85 |
86 | });
87 |
88 | // inside bed
89 | // side, dark
90 | new Zdog.Shape( Zdog.extend( {
91 | path: bedSidePath,
92 | translate: { z: 11 }
93 | }, allDark ));
94 | // side light
95 | new Zdog.Shape( Zdog.extend( {
96 | path: bedSidePath,
97 | translate: { z: -11 }
98 | }, lightFill ));
99 | new Zdog.Shape( Zdog.extend( {
100 | path: bedSidePath,
101 | translate: { z: -11 }
102 | }, darkStroke ));
103 |
104 | // underside
105 |
106 | // back underside
107 | new Zdog.Shape( Zdog.extend( {
108 | path: [
109 | { x: -32, z: 12 },
110 | { x: -8, z: 12 },
111 | { x: -8, z: -12 },
112 | { x: -32, z: -12 },
113 | ],
114 | translate: { y: 8 },
115 | }, allDark ) );
116 | // door underside
117 | new Zdog.Shape( Zdog.extend( {
118 | path: [
119 | { x: -8, z: 12 },
120 | { x: 20, z: 12 },
121 | { x: 20, z: -12 },
122 | { x: -8, z: -12 },
123 | ],
124 | translate: { y: 8 },
125 | }, allDark ) );
126 | // front underside
127 | new Zdog.Shape( Zdog.extend( {
128 | path: [
129 | { x: 20, z: 12 },
130 | { x: 32, z: 12 },
131 | { x: 32, z: -12 },
132 | { x: 20, z: -12 },
133 | ],
134 | translate: { y: 8 },
135 | }, allDark ) );
136 |
137 | // roof
138 | var roof = new Zdog.Shape( Zdog.extend( {
139 | path: [
140 | { x: -8, z: 12 },
141 | { x: 10, z: 12 },
142 | { x: 10, z: -12 },
143 | { x: -8, z: -12 },
144 | ],
145 | translate: { y: -14 },
146 | }, lightFill ) );
147 | roof.copy( darkStroke );
148 |
149 | // windshield
150 | new Zdog.Shape( Zdog.extend( {
151 | path: [
152 | { x: 10, y: -14, z: 12 },
153 | { x: 10, y: -14, z: -12 },
154 | { x: 20, y: -4, z: -12 },
155 | { x: 20, y: -4, z: 12 },
156 | ],
157 | }, allDark ) );
158 |
159 | // hood
160 | var hood = new Zdog.Shape( Zdog.extend( {
161 | path: [
162 | { x: 20, z: 12 },
163 | { x: 32, z: 12 },
164 | { x: 32, z: -12 },
165 | { x: 20, z: -12 },
166 | ],
167 | translate: { y: -4 },
168 | }, lightFill ) );
169 | hood.copy( darkStroke );
170 |
171 | var frontGroup = new Zdog.Group({
172 | addTo: illo,
173 | translate: { x: 32, y: 2 },
174 | rotate: { y: -TAU/4 },
175 | // translate: { z: 1 }
176 | });
177 |
178 | // front
179 | new Zdog.Rect({
180 | addTo: frontGroup,
181 | width: 24,
182 | height: 12,
183 | color: dark,
184 | fill: true,
185 | stroke: 2,
186 | });
187 |
188 | var frontDetails = new Zdog.Anchor({
189 | addTo: frontGroup,
190 | translate: { z: 0.5 },
191 | });
192 |
193 | // front details
194 | var headlight = new Zdog.Rect({
195 | width: 2,
196 | height: 2,
197 | addTo: frontDetails,
198 | translate: { x: -9, y: -3 },
199 | color: light,
200 | stroke: 2,
201 | });
202 | headlight.copy({
203 | translate: { x: 9, y: -3 },
204 | });
205 |
206 | // top line
207 | var grillLine = new Zdog.Shape({
208 | path: [
209 | { x: -4 },
210 | { x: 4 },
211 | ],
212 | addTo: frontDetails,
213 | translate: { y: -4 },
214 | color: light,
215 | closed: false,
216 | stroke: 2,
217 | });
218 | grillLine.copy({
219 | translate: { y: 0 },
220 | });
221 | grillLine.copy({
222 | path: [
223 | { x: -10 },
224 | { x: 10 },
225 | ],
226 | translate: { y: 4 },
227 | });
228 |
229 | // tail
230 | var tail = new Zdog.Rect( Zdog.extend({
231 | width: 24,
232 | height: 12,
233 | addTo: illo,
234 | translate: { x: -32, y: 2 },
235 | rotate: { y: TAU/4 },
236 | }, lightFill ));
237 | tail.copy( darkStroke );
238 | // tail inside
239 | tail.copy({
240 | color: dark,
241 | translate: { x: -31, y: 2 },
242 | });
243 |
244 | var tailGroup = new Zdog.Group({
245 | addTo: tail,
246 | translate: { z: -0 },
247 | });
248 |
249 | // back details
250 | var backlight = new Zdog.Rect({
251 | width: 4,
252 | height: 4,
253 | addTo: tailGroup,
254 | translate: { x: -10, y: -4 },
255 | color: dark,
256 | stroke: 2,
257 | fill: true,
258 | });
259 | backlight.copy({
260 | translate: { x: 10, y: -4 },
261 | });
262 | // back bumper
263 | new Zdog.Shape({
264 | path: [
265 | { x: -11 },
266 | { x: 11 },
267 | { move: { z: 64 } }, // 'nother hack
268 | ],
269 | addTo: tailGroup,
270 | translate: { y: 5, z: 1 },
271 | color: dark,
272 | stroke: 4,
273 | closed: false,
274 | });
275 |
276 | // cab back
277 | var cabBackTop = new Zdog.Shape({
278 | path: [
279 | { y: -14, z: 12 },
280 | { y: -4, z: 12 },
281 | { y: -4, z: -12 },
282 | { y: -14, z: -12 },
283 | ],
284 | addTo: illo,
285 | translate: { x: -8 },
286 | color: light,
287 | stroke: false,
288 | fill: true,
289 | });
290 | cabBackTop.copy({
291 | color: dark,
292 | fill: false,
293 | stroke: 2,
294 | });
295 |
296 | var cabBackBottom = new Zdog.Shape({
297 | path: [
298 | { y: -4, z: 12 },
299 | { y: 8, z: 12 },
300 | { y: 8, z: -12 },
301 | { y: -4, z: -12 },
302 | ],
303 | addTo: illo,
304 | translate: { x: -8 },
305 | color: light,
306 | stroke: false,
307 | fill: true,
308 | });
309 | cabBackBottom.copy({
310 | color: dark,
311 | fill: false,
312 | stroke: 2,
313 | });
314 |
315 | // WHEELS
316 |
317 | // front light
318 | var lightFillWheel = new Zdog.Shape( Zdog.extend({
319 | path: [
320 | { x: 0, y: -6 },
321 | { arc: [ // top right
322 | { x: 6, y: -6 },
323 | { x: 6, y: 0 },
324 | ]},
325 | { arc: [ // bottom right
326 | { x: 6, y: 6 },
327 | { x: 0, y: 6 },
328 | ]},
329 | { arc: [ // bottom left
330 | { x: -6, y: 6 },
331 | { x: -6, y: 0 },
332 | ]},
333 | { arc: [ // bottom left
334 | { x: -6, y: -6 },
335 | { x: 0, y: -6 },
336 | ]},
337 | // hack, add a big move up to fix z-sort bug
338 | { move: { x: 0, y: -64, z: 64 } },
339 | ],
340 | closed: false,
341 | translate: { x: 18, y: 8, z: 14 },
342 | }, lightFill ));
343 | var darkStrokeWheel = lightFillWheel.copy({
344 | fill: false,
345 | stroke: 4,
346 | color: dark,
347 | });
348 | var darkWheel = new Zdog.Ellipse({
349 | diameter: 12,
350 | addTo: illo,
351 | translate: { x: 18, y: 8, z: 10 },
352 | color: dark,
353 | stroke: 4,
354 | fill: true,
355 | });
356 |
357 |
358 | // back light
359 | lightFillWheel.copy({
360 | translate: { x: -18, y: 8, z: 14 }
361 | });
362 | darkStrokeWheel.copy({
363 | translate: { x: -18, y: 8, z: 14 }
364 | });
365 | darkWheel.copy({
366 | translate: { x: -18, y: 8, z: 10 },
367 | });
368 |
369 | // front dark
370 | darkWheel.copy({
371 | translate: { x: 18, y: 8, z: -14 }
372 | });
373 | darkWheel.copy({
374 | translate: { x: 18, y: 8, z: -10 }
375 | });
376 |
377 | // back dark
378 | darkWheel.copy({
379 | translate: { x: -18, y: 8, z: -14 }
380 | });
381 | darkWheel.copy({
382 | translate: { x: -18, y: 8, z: -10 }
383 | });
384 |
385 | // -- animate --- //
386 |
387 | function animate() {
388 | illo.updateRenderGraph();
389 | requestAnimationFrame( animate );
390 | }
391 |
392 | animate();
393 |
394 | // ----- inputs ----- //
395 |
396 | document.querySelector('.quarter-twist-button').onclick = function() {
397 | illo.rotate.set( initRotate );
398 | };
399 |
--------------------------------------------------------------------------------
/demo/mario/mario.js:
--------------------------------------------------------------------------------
1 | // -------------------------- demo -------------------------- //
2 |
3 | var illoElem = document.querySelector('.illo');
4 | var illoSize = 72;
5 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
6 | var zoom = Math.min( 6, Math.floor( minWindowSize / illoSize ) );
7 | illoElem.setAttribute( 'width', illoSize * zoom );
8 | illoElem.setAttribute( 'height', illoSize * zoom );
9 |
10 | var isSpinning = true;
11 | var TAU = Zdog.TAU;
12 |
13 | var illo = new Zdog.Illustration({
14 | element: illoElem,
15 | zoom: zoom,
16 | dragRotate: true,
17 | onDragStart: function() {
18 | isSpinning = false;
19 | },
20 | });
21 |
22 | // colors
23 | var colors = {
24 | eye: '#333',
25 | white: '#FFF',
26 | hair: '#631',
27 | overalls: '#24D',
28 | cloth: '#E11',
29 | skin: '#FC9',
30 | leather: '#A63',
31 | };
32 |
33 | // -- illustration shapes --- //
34 |
35 | // head
36 | var head = new Zdog.Shape({
37 | addTo: illo,
38 | translate: { y: -12, z: 1 },
39 | color: colors.skin,
40 | stroke: 23,
41 | });
42 |
43 | // nose
44 | new Zdog.Shape({
45 | addTo: head,
46 | translate: { y: 5, z: 13 },
47 | color: colors.skin,
48 | stroke: 7,
49 | });
50 |
51 |
52 |
53 | // chin
54 | var chin = new Zdog.Shape({
55 | addTo: head,
56 | path: [
57 | { x: -5, y: 6, z: 4 },
58 | { x: 0, y: 8.5, z: 6 }
59 | ],
60 | color: colors.skin,
61 | stroke: 10,
62 | });
63 | chin.copy({
64 | scale: { x: -1 },
65 | });
66 |
67 | // mouth
68 | new Zdog.Shape({
69 | path: [
70 | { x: -3, y: -3 },
71 | { x: -1, y: -1 },
72 | { x: 1, y: -1 },
73 | { x: 3, y: -3 },
74 | ],
75 | translate: { y: 12, z: 9 },
76 | color: colors.cloth,
77 | fill: true,
78 | stroke: 2,
79 | addTo: head,
80 | });
81 |
82 |
83 | var hat = new Zdog.Anchor({
84 | addTo: head,
85 | translate: { y: -8 },
86 | });
87 |
88 | // hat front
89 | var hatFrontA = new Zdog.Vector({ x: -8, y: 0, z: 5 });
90 | var hatFrontB = new Zdog.Vector({ x: -4, y: -3, z: 7 });
91 | var hatFrontC = hatFrontB.copy().multiply({ x: -1 });
92 | var hatFrontD = hatFrontA.copy().multiply({ x: -1 });
93 |
94 | // hat front
95 | new Zdog.Shape({
96 | path: [
97 | hatFrontA,
98 | hatFrontB,
99 | hatFrontC,
100 | hatFrontD,
101 | ],
102 | color: colors.cloth,
103 | closed: false,
104 | fill: false,
105 | stroke: 11,
106 | addTo: hat,
107 | });
108 |
109 | var hatTopFront = new Zdog.Vector({ x: 10, y: 1, z: 5 });
110 | var hatTopBackA = new Zdog.Vector({ x: 7, y: 3, z: -10 });
111 | var hatTopBackB = hatTopBackA.copy().multiply({ x: -1 });
112 |
113 | // hat top
114 | new Zdog.Shape({
115 | path: [
116 | hatTopFront.copy().multiply({ x: -1 }),
117 | hatTopFront,
118 | hatTopBackA,
119 | hatTopBackB,
120 | ],
121 | color: colors.cloth,
122 | fill: true,
123 | stroke: 9,
124 | addTo: hat,
125 | });
126 | // hat top back
127 | new Zdog.Shape({
128 | path: [
129 | hatTopBackA,
130 | hatTopBackB,
131 | ],
132 | color: colors.cloth,
133 | stroke: 9,
134 | addTo: hat,
135 | });
136 |
137 | // hat top side
138 | var hatTopSide = new Zdog.Shape({
139 | path: [
140 | hatTopFront,
141 | hatTopBackA,
142 | ],
143 | color: colors.cloth,
144 | stroke: 9,
145 | addTo: hat,
146 | });
147 | hatTopSide.copy({
148 | scale: { x: -1 },
149 | });
150 |
151 |
152 | // hat top cover
153 | new Zdog.Shape({
154 | path: [
155 | { x: -3, y: 0, z: -8 },
156 | { x: 3, y: 0, z: -8 },
157 | { x: 3, y: -3, z: 4 },
158 | { x: -3, y: -3, z: 4 },
159 | ],
160 | color: colors.cloth,
161 | stroke: 6,
162 | addTo: hat,
163 | });
164 |
165 | // hat brim
166 | // brim has left & right side
167 | var hatBrim = new Zdog.Shape({
168 | path: [
169 | { x: 10, y: 4, z: -0 },
170 | { x: 8, y: 4, z: 5 },
171 | { x: 0, y: 2, z: 9 },
172 | { x: 0, y: 1, z: 2 },
173 | ],
174 | translate: { z: 7 },
175 | color: colors.cloth,
176 | fill: true,
177 | stroke: 4,
178 | addTo: hat,
179 | });
180 | hatBrim.copy({
181 | scale: { x: -1 },
182 | });
183 |
184 | // eyes pupil
185 | var eye = new Zdog.Shape({
186 | path: [
187 | { y: 2 },
188 | { y: 4 },
189 | ],
190 | translate: { x: 5, z: 9 },
191 | color: colors.eye,
192 | stroke: 3,
193 | addTo: head,
194 | });
195 | eye.copy({
196 | translate: { x: -5, z: 9 },
197 | });
198 |
199 | var brow = new Zdog.Shape({
200 | path: [
201 | { x: 3, y: 0, z: -0 },
202 | { x: 1.5, y: -0.5, z: 1 },
203 | { x: 0, y: 0, z: 1 },
204 | ],
205 | translate: { x: 4, y: -1.5, z: 9 },
206 | color: colors.hair,
207 | closed: false,
208 | stroke: 2.5,
209 | addTo: head,
210 | });
211 | brow.copy({
212 | scale: { x: -1 },
213 | translate: { x: -4, y: -1.5, z: 9 },
214 | });
215 |
216 | var mustache = new Zdog.Group({
217 | addTo: head,
218 | translate: { y: 6.5, z: 10 },
219 | });
220 | // mustache line
221 | new Zdog.Shape({
222 | path: [
223 | { x: 2, y: 1, z: 1.5 },
224 | { x: 6.5, y: 0, z: -0 },
225 | ],
226 | color: colors.hair,
227 | stroke: 3,
228 | addTo: mustache,
229 | });
230 | // mustache sections
231 | var mustacheSection = new Zdog.Shape({
232 | translate: { x: 1.75, y: 1.5, z: 1 },
233 | color: colors.hair,
234 | stroke: 4,
235 | addTo: mustache,
236 | });
237 | mustacheSection.copy({
238 | translate: { x: 4.5, y: 1, z: 0.75 }
239 | });
240 |
241 | mustache.copyGraph({
242 | scale: { x: -1 },
243 | });
244 |
245 | var sideburns = new Zdog.Shape({
246 | path: [
247 | { y: 0, z: 0 },
248 | { y: -4, z: 1.5 },
249 | { y: -4, z: 1 },
250 | { y: -1, z: 2 },
251 | ],
252 | translate: { x: 10, y: 3, z: 2 },
253 | color: colors.hair,
254 | closed: false,
255 | fill: true,
256 | stroke: 3,
257 | addTo: head,
258 | });
259 | sideburns.copy({
260 | translate: sideburns.translate.copy().multiply({ x: -1 }),
261 | });
262 |
263 | var ear = new Zdog.Shape({
264 | path: [
265 | { x: 0, y: 0, z: -0 },
266 | { x: 0, y: -4, z: -0 },
267 | { x: 1, y: -4, z: -2 },
268 | { x: 0, y: 0, z: -1 },
269 | ],
270 | translate: { x: 10, y: 4, z: -2 },
271 | color: colors.skin,
272 | fill: true,
273 | stroke: 4,
274 | addTo: head,
275 | });
276 | ear.copy({
277 | scale: { x: -1 },
278 | translate: ear.translate.copy().multiply({ x: -1 }),
279 | });
280 |
281 | var sideHair = new Zdog.Anchor({
282 | addTo: head,
283 | });
284 |
285 | // hair side panel
286 | new Zdog.Shape({
287 | path: [
288 | { x: 4, y: -7, z: -1 },
289 | { x: 3, y: 0, z: -0 },
290 | { x: 0, y: 0, z: -5 },
291 | { x: 2, y: -6.5, z: -6 },
292 | ],
293 | translate: { x: 5, y: 7, z: -5 },
294 | color: colors.hair,
295 | fill: true,
296 | stroke: 3,
297 | addTo: sideHair,
298 | });
299 | // hair balls
300 | var hairBall = new Zdog.Shape({
301 | translate: { x: 6, y: 8, z: -8 },
302 | color: colors.hair,
303 | stroke: 6,
304 | addTo: sideHair,
305 | });
306 | hairBall.copy({
307 | translate: { x: 2, y: 8, z: -10 },
308 | });
309 |
310 | sideHair.copyGraph({
311 | scale: { x: -1 },
312 | });
313 |
314 | // hair back panel
315 | new Zdog.Shape({
316 | path: [
317 | { x: 5, y: 0, z: -0 },
318 | { x: 6, y: -6.5, z: -1 },
319 | { x: -6, y: -6.5, z: -1 },
320 | { x: -5, y: 0, z: -0 },
321 | ],
322 | translate: { y: 7, z: -10 },
323 | color: colors.hair,
324 | fill: true,
325 | stroke: 3,
326 | addTo: head,
327 | });
328 |
329 |
330 | var body = new Zdog.Shape({
331 | translate: { x: 0, y: 10, z: 1 },
332 | color: colors.overalls,
333 | stroke: 20,
334 | addTo: illo,
335 | });
336 |
337 | // right arm
338 | var rightShoulder = { x: -8, y: -8, z: -3 };
339 | var rightWrist = new Zdog.Vector({ x: -14, y: -17, z: -0 });
340 | new Zdog.Shape({
341 | path: [
342 | rightShoulder,
343 | rightWrist,
344 | ],
345 | color: colors.cloth,
346 | stroke: 8,
347 | addTo: body,
348 | });
349 |
350 | // right hand
351 | new Zdog.Shape({
352 | path: [
353 | { x: -17, y: -23, z: 1 },
354 | ],
355 | color: colors.white,
356 | stroke: 12,
357 | addTo: body,
358 | });
359 |
360 | // left arm
361 | var leftShoulder = { x: 6, y: -7, z: -4 };
362 | var leftElbow = { x: 8, y: -4, z: -8 };
363 | new Zdog.Shape({
364 | path: [
365 | leftShoulder,
366 | leftElbow,
367 | ],
368 | color: colors.cloth,
369 | stroke: 8,
370 | addTo: body,
371 | });
372 | new Zdog.Shape({
373 | path: [
374 | leftElbow,
375 | { x: 12, y: -2, z: -9 },
376 | ],
377 | color: colors.cloth,
378 | stroke: 8,
379 | addTo: body,
380 | });
381 | // left hand
382 | new Zdog.Shape({
383 | path: [
384 | { x: 17, y: 1, z: -8 },
385 | ],
386 | color: colors.white,
387 | stroke: 12,
388 | addTo: body,
389 | });
390 |
391 | new Zdog.Shape({
392 | path: [
393 | leftShoulder,
394 | rightShoulder,
395 | ],
396 | color: colors.cloth,
397 | stroke: 8,
398 | addTo: body,
399 | });
400 |
401 | // right leg
402 | var rightLeg = new Zdog.Shape({
403 | path: [
404 | { y: 4, z: 2 },
405 | { y: 10, z: 1 },
406 | { y: 12, z: -0 }
407 | ],
408 | translate: { x: -5 },
409 | closed: false,
410 | color: colors.overalls,
411 | stroke: 10,
412 | addTo: body,
413 | });
414 |
415 | var shoe = new Zdog.Rect({
416 | addTo: rightLeg,
417 | width: 4,
418 | height: 7,
419 | translate: { y: 15.5, z: -4 },
420 | fill: true,
421 | color: colors.leather,
422 | stroke: 6,
423 | });
424 |
425 | // toe ball
426 | new Zdog.Shape({
427 | addTo: shoe,
428 | translate: { y: 3, z: 2.5 },
429 | color: colors.leather,
430 | stroke: 11,
431 | });
432 |
433 | // left leg
434 | var leftLeg = new Zdog.Shape({
435 | path: [
436 | { y: 4, z: 2 },
437 | { y: 2, z: 7 },
438 | { y: 3, z: 11 },
439 | ],
440 | translate: { x: 5 },
441 | closed: false,
442 | color: colors.overalls,
443 | stroke: 10,
444 | addTo: body,
445 | });
446 |
447 | shoe.copyGraph({
448 | addTo: leftLeg,
449 | translate: { y: 2, z: 18 },
450 | rotate: { x: TAU * (160/360) },
451 | });
452 |
453 | // -- animate --- //
454 |
455 | function animate() {
456 | illo.rotate.y += isSpinning ? -0.05 : 0;
457 | illo.updateRenderGraph();
458 | requestAnimationFrame( animate );
459 | }
460 |
461 | animate();
462 |
463 |
--------------------------------------------------------------------------------
/demo/santorini/santorini.js:
--------------------------------------------------------------------------------
1 | /* globals makeBuilding, oneStoryBuilding, twoStoryBuilding, oneStorySlanter, makeRock */
2 |
3 | // -------------------------- demo -------------------------- //
4 |
5 | var illoElem = document.querySelector('.illo');
6 | var w = 192;
7 | var h = 164;
8 | var minWindowSize = Math.min( window.innerWidth, window.innerHeight );
9 | var zoom = Math.min( 7, Math.floor( minWindowSize / w ) );
10 | var zoom = 5;
11 | illoElem.setAttribute( 'width', w * zoom );
12 | illoElem.setAttribute( 'height', h * zoom );
13 | var isSpinning = false;
14 | var TAU = Zdog.TAU;
15 | var initRotate = { y: TAU/8 };
16 |
17 | var illo = new Zdog.Illustration({
18 | element: illoElem,
19 | zoom: zoom,
20 | rotate: initRotate,
21 | dragRotate: true,
22 | onDragStart: function() {
23 | isSpinning = false;
24 | },
25 | });
26 |
27 | // colors
28 | // var white = 'white';
29 | // var southWall = white;
30 | // var westWall = '#CDE';
31 | // var eastWall = '#8AD';
32 | var roof = '#06B';
33 | // var northWall = roof;
34 | // var navy = '#037';
35 | // var midnight = '#024';
36 |
37 | // default to flat, filled shapes
38 | [ Zdog.Shape, Zdog.Rect, Zdog.Ellipse ].forEach( function( ItemClass ) {
39 | ItemClass.defaults.fill = true;
40 | ItemClass.defaults.stroke = false;
41 | });
42 |
43 | var island = new Zdog.Anchor({
44 | addTo: illo,
45 | scale: { x: 1/Math.sin(TAU/8), z: -1/Math.sin(TAU/8) }
46 | });
47 |
48 | // -- illustration shapes --- //
49 |
50 | // lil house in front, center
51 | oneStoryBuilding({
52 | addTo: island,
53 | translate: { x: 17, z: -24 },
54 | gable: 'ns'
55 | });
56 |
57 | // lil house to the east
58 | oneStoryBuilding({
59 | addTo: island,
60 | translate: { x: 47, z: -16 },
61 | gable: 'ns'
62 | });
63 |
64 | // 2 story gable, east end
65 | twoStoryBuilding({
66 | addTo: island,
67 | translate: { x: 55, z: -4 },
68 | gable: 'ns'
69 | });
70 |
71 | // 2 story gable, center west
72 | twoStoryBuilding({
73 | addTo: island,
74 | translate: { x: 14, y: -2, z: -13 },
75 | gable: 'ew',
76 | });
77 |
78 |
79 | // 2 story gable, west end
80 | twoStoryBuilding({
81 | addTo: island,
82 | translate: { x: -14, z: -25 },
83 | gable: 'ew',
84 | });
85 |
86 |
87 | // 1 story slantS, west
88 | oneStorySlanter({
89 | addTo: island,
90 | translate: { x: 0, z: -26 },
91 | gable: 'slantS',
92 | });
93 |
94 |
95 |
96 | // ----- ----- //
97 |
98 | // 2.5 story slantS, east
99 | var buildAnchor4 = new Zdog.Anchor({
100 | addTo: island,
101 | translate: { x: 42, z: -6 },
102 | });
103 |
104 | makeBuilding({
105 | width: 14,
106 | height: 20,
107 | depth: 6,
108 | gable: 'slantS',
109 | addTo: buildAnchor4,
110 | nsWindows: [
111 | { x: -4, y: -17 },
112 | { x: 0, y: -17 },
113 | { x: 4, y: -17 },
114 | ],
115 | ewWindows: [
116 | { x: 0, y: -17 }
117 | ],
118 | });
119 |
120 | // ----- cathedral ----- //
121 |
122 | var cathBaseAnchor = new Zdog.Anchor({
123 | addTo: island,
124 | translate: { x: 28, z: -12 },
125 | });
126 |
127 | // cathedral base
128 | makeBuilding({
129 | width: 10,
130 | height: 12,
131 | depth: 18,
132 | gable: 'cap',
133 | addTo: cathBaseAnchor,
134 | nsWindows: [
135 | { x: -2, y: -3 },
136 | { x: 2, y: -3 },
137 | { x: -2, y: -9 },
138 | { x: 2, y: -9 },
139 | ],
140 | ewWindows: [
141 | { style: 'circle', x: -6, y: -9 },
142 | { style: 'circle', x: -2, y: -9 },
143 | { style: 'circle', x: 2, y: -9 },
144 | { style: 'circle', x: 6, y: -9 },
145 | { height: 6, x: -6, y: -5 },
146 | { height: 6, x: -2, y: -5 },
147 | { height: 6, x: 2, y: -5 },
148 | { height: 6, x: 6, y: -5 },
149 | ],
150 | });
151 |
152 | // cathedral 2nd story
153 | var cath2ndAnchor = new Zdog.Anchor({
154 | addTo: cathBaseAnchor,
155 | translate: { y: -14 },
156 | });
157 |
158 | makeBuilding({
159 | width: 8,
160 | height: 8,
161 | depth: 8,
162 | gable: 'cap',
163 | addTo: cath2ndAnchor,
164 | nsWindows: [
165 | { x: 0, y: -5 },
166 | ],
167 | ewWindows: [
168 | { x: 0, y: -5 },
169 | ],
170 | });
171 |
172 | // cathedral 3rd story
173 |
174 | var cath3rdAnchor = new Zdog.Anchor({
175 | addTo: cathBaseAnchor,
176 | translate: { y: -24 },
177 | });
178 |
179 | makeBuilding({
180 | width: 6,
181 | height: 6,
182 | depth: 6,
183 | addTo: cath3rdAnchor,
184 | gable: 'flat',
185 | nsWindows: [
186 | { x: 0, y: -3 },
187 | ],
188 | ewWindows: [
189 | { x: 0, y: -3 },
190 | ],
191 | });
192 |
193 | // cathedral dome
194 | var dome = new Zdog.Hemisphere({
195 | addTo: cathBaseAnchor,
196 | diameter: 6,
197 | translate: { y: -30 },
198 | rotate: { x: TAU/4 },
199 | color: roof,
200 | stroke: false,
201 | });
202 |
203 | // ----- ----- //
204 |
205 | // 2 story gable, east, behind cathdral on hill
206 | var anchor6 = new Zdog.Anchor({
207 | addTo: island,
208 | translate: { x: 27, z: 6, y: -14 },
209 | });
210 |
211 | makeBuilding({
212 | width: 8,
213 | height: 16,
214 | depth: 10,
215 | gable: 'ns',
216 | addTo: anchor6,
217 | nsWindows: [
218 | { style: 'circle', x: 0, y: -13 },
219 | ],
220 | ewWindows: [
221 | { style: 'circle', x: -2, y: -7 },
222 | { style: 'circle', x: 2, y: -7 },
223 | { x: -2, y: -13 },
224 | { x: 2, y: -13 },
225 | ],
226 | });
227 |
228 | // ----- west side ----- //
229 |
230 |
231 | // shack, west end
232 | var anchor9 = new Zdog.Anchor({
233 | addTo: island,
234 | translate: { x: -13, z: -34 },
235 | });
236 |
237 | makeBuilding({
238 | width: 8,
239 | height: 8,
240 | depth: 6,
241 | gable: 'ns',
242 | addTo: anchor9,
243 | nsWindows: [
244 | { x: 0, y: -5 },
245 | ],
246 | ewWindows: [
247 | { style: 'circle' },
248 | ],
249 | });
250 |
251 | // 2 story, west center, 1st hill
252 | var anchor10 = new Zdog.Anchor({
253 | addTo: island,
254 | translate: { x: 3, z: -10, y: -8 },
255 | });
256 |
257 | makeBuilding({
258 | width: 8,
259 | height: 16,
260 | depth: 10,
261 | gable: 'ns',
262 | addTo: anchor10,
263 | nsWindows: [
264 | { x: 0, y: -13 },
265 | ],
266 | ewWindows: [
267 | { x: -2, y: -13 },
268 | { x: 2, y: -13 },
269 | { x: -2, y: -5 },
270 | { x: 2, y: -5 },
271 | ],
272 | });
273 |
274 | // west mansion
275 | var mansionAnchor = new Zdog.Anchor({
276 | addTo: island,
277 | translate: { x: -14, z: -14, y: -8 },
278 | });
279 |
280 | makeBuilding({
281 | width: 14,
282 | height: 18,
283 | depth: 10,
284 | gable: 'cap',
285 | addTo: mansionAnchor,
286 | nsWindows: [
287 | { x: -4, y: -15, style: 'circle' },
288 | { x: 0, y: -15, style: 'circle' },
289 | { x: 4, y: -15, style: 'circle' },
290 | { x: -4, y: -11, height: 10 },
291 | { x: 0, y: -11, height: 10 },
292 | { x: 4, y: -11, height: 10 },
293 | ],
294 | ewWindows: [
295 | { x: -2, y: -15 },
296 | { x: 2, y: -15 },
297 | { x: -2, y: -9, height: 8 },
298 | { x: 2, y: -9, height: 8 },
299 | ],
300 | });
301 |
302 | // mansion rock
303 | makeRock({
304 | width: 19,
305 | depth: 14,
306 | height: 8,
307 | addTo: island,
308 | translate: { x: -13, z: -14, y: 1 },
309 | southOffset: -2,
310 | });
311 |
312 | // ----- central tower ----- //
313 |
314 | var centralTowerAnchor = new Zdog.Anchor({
315 | addTo: island,
316 | translate: { y: -14 },
317 | });
318 |
319 | makeBuilding({
320 | width: 6,
321 | depth: 6,
322 | height: 18,
323 | addTo: centralTowerAnchor,
324 | gable: 'cap',
325 | nsWindows: [
326 | { x: 0, y: -7, style: 'circle' }
327 | ],
328 | ewWindows: [
329 | { x: 0, y: -13, style: 'circle' }
330 | ],
331 | });
332 |
333 | // central tower 2nd story
334 | var centralTower2ndAnchor = new Zdog.Anchor({
335 | addTo: centralTowerAnchor,
336 | translate: { y: -20 },
337 | });
338 |
339 | makeBuilding({
340 | width: 6,
341 | depth: 6,
342 | height: 8,
343 | addTo: centralTower2ndAnchor,
344 | gable: 'flat',
345 | nsWindows: [
346 | { x: 0, y: -5 }
347 | ],
348 | ewWindows: [
349 | { x: 0, y: -5 }
350 | ],
351 | });
352 |
353 | dome.copy({
354 | diameter: 4,
355 | addTo: centralTower2ndAnchor,
356 | translate: { y: -8 },
357 | });
358 |
359 | // ----- temple ----- //
360 |
361 | var templeAnchor = new Zdog.Anchor({
362 | addTo: island,
363 | translate: { x: -20, y: -14, z: 1 },
364 | });
365 |
366 | makeBuilding({
367 | width: 12,
368 | depth: 12,
369 | height: 8,
370 | gable: 'cap',
371 | addTo: templeAnchor,
372 | nsWindows:[
373 | { x: -2, height: 6 },
374 | { x: 2, height: 6 },
375 | ],
376 | ewWindows:[
377 | { x: -2, height: 6 },
378 | { x: 2, height: 6 },
379 | ],
380 | });
381 |
382 | var temple2ndFloor = new Zdog.Anchor({
383 | addTo: templeAnchor,
384 | translate: { y: -10 },
385 | });
386 |
387 | makeBuilding({
388 | width: 8,
389 | depth: 8,
390 | height: 8,
391 | gable: 'cap',
392 | addTo: temple2ndFloor,
393 | nsWindows:[
394 | { height: 6 },
395 | ],
396 | ewWindows:[
397 | { height: 6 },
398 | ],
399 | });
400 |
401 | var temple3rdFloor = new Zdog.Anchor({
402 | addTo: temple2ndFloor,
403 | translate: { y: -10 },
404 | });
405 |
406 | makeBuilding({
407 | width: 6,
408 | depth: 6,
409 | height: 6,
410 | gable: 'flat',
411 | addTo: temple3rdFloor,
412 | nsWindows:[
413 | { y: -3 },
414 | ],
415 | ewWindows:[
416 | { y: -3 },
417 | ],
418 | });
419 |
420 | dome.copy({
421 | diameter: 4,
422 | addTo: temple3rdFloor,
423 | translate: { y: -6 },
424 | });
425 |
426 | // ----- west perch ----- //
427 |
428 | var westPerchAnchor = new Zdog.Anchor({
429 | addTo: island,
430 | translate: { x: -39, z: 11, y: -44 }
431 | });
432 |
433 | makeBuilding({
434 | width: 6,
435 | depth: 6,
436 | height: 6,
437 | gable: 'flat',
438 | addTo: westPerchAnchor,
439 | nsWindows:[
440 | { y: -3, style: 'circle', },
441 | ],
442 | ewWindows:[
443 | { y: -3, style: 'circle', },
444 | ],
445 | });
446 |
447 | dome.copy({
448 | diameter: 6,
449 | addTo: westPerchAnchor,
450 | translate: { y: -6 },
451 | });
452 |
453 | // perch rock
454 | makeRock({
455 | width: 19,
456 | depth: 9,
457 | height: 10,
458 | addTo: island,
459 | translate: { x: -36, z: 13, y: -33 },
460 | westOffset: -1,
461 | eastOffset: -7,
462 | northOffset: -3,
463 | southOffset: 0,
464 | });
465 |
466 | // beneath perch rock & 2 story
467 |
468 | makeRock({
469 | width: 24,
470 | depth: 22,
471 | height: 8,
472 | addTo: island,
473 | translate: { x: -35, z: 19, y: -25 },
474 | westOffset: -1.5,
475 | eastOffset: -3,
476 | northOffset: -2,
477 | // southOffset: 0,
478 | });
479 |
480 | // perch staircase
481 |
482 | var staircaseAnchor = new Zdog.Shape({
483 | addTo: island,
484 | visible: false,
485 | translate: { x: -35, y: -14, z: 5 },
486 | });
487 |
488 | makeBuilding({
489 | width: 6,
490 | depth: 4,
491 | height: 22,
492 | gable: 'slantS',
493 | addTo: staircaseAnchor,
494 | nsWindows: [
495 | { y: -19 },
496 | { y: -12 },
497 | { y: -5 },
498 | ]
499 | });
500 |
501 | // ----- hill buildings ----- //
502 |
503 | // center behind cathedral
504 | oneStorySlanter({
505 | addTo: island,
506 | translate: { x: -14, y: -26, z: 18 },
507 | gable: 'slantS',
508 | });
509 |
510 | // behind west perch
511 | twoStoryBuilding({
512 | addTo: island,
513 | translate: { x: -38, y: -34, z: 23 },
514 | gable: 'ns',
515 | });
516 |
517 | oneStoryBuilding({
518 | addTo: island,
519 | translate: { x: 9, y: -32, z: 24 },
520 | gable: 'ew',
521 | });
522 |
523 | // ----- back tower ----- //
524 |
525 | var backTowerAnchor = new Zdog.Anchor({
526 | addTo: island,
527 | translate: { x: -15, y: -18, z: 35 }
528 | });
529 |
530 | makeBuilding({
531 | width: 6,
532 | height: 30,
533 | depth: 6,
534 | gable: 'flat',
535 | addTo: backTowerAnchor,
536 | nsWindows: [ { y: -27 } ],
537 | ewWindows: [ { y: -27 } ],
538 | });
539 |
540 | dome.copy({
541 | addTo: backTowerAnchor,
542 | translate: { y: -30 },
543 | diameter: 4,
544 | });
545 |
546 | // -- animate --- //
547 |
548 | function animate() {
549 | illo.rotate.y += isSpinning ? TAU/150 : 0;
550 | illo.updateRenderGraph();
551 | requestAnimationFrame( animate );
552 | }
553 |
554 | animate();
555 |
556 | // ----- inputs ----- //
557 |
558 | document.querySelector('.reset-button').onclick = function() {
559 | illo.rotate.set( initRotate );
560 | };
561 |
--------------------------------------------------------------------------------