@turbowarp/paper 0.12.202407161743

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/AUTHORS.md +18 -0
  2. package/CHANGELOG.md +701 -0
  3. package/LICENSE.txt +23 -0
  4. package/README.md +381 -0
  5. package/dist/node/canvas.js +66 -0
  6. package/dist/node/extend.js +156 -0
  7. package/dist/node/self.js +58 -0
  8. package/dist/node/xml.js +40 -0
  9. package/dist/paper-core.js +15805 -0
  10. package/dist/paper-full.js +17574 -0
  11. package/examples/Animated/AnimatedStar.html +53 -0
  12. package/examples/Animated/BooleanOperations.html +115 -0
  13. package/examples/Animated/CandyCrash.html +151 -0
  14. package/examples/Animated/Extruded.html +50 -0
  15. package/examples/Animated/Lines.html +53 -0
  16. package/examples/Animated/Smoothing.html +70 -0
  17. package/examples/Animated/Space.html +86 -0
  18. package/examples/Animated/SpaceUsingShapes.html +79 -0
  19. package/examples/Games/Paperoids.html +569 -0
  20. package/examples/JSON/Circle Testing.html +34 -0
  21. package/examples/JSON/Compound Path.html +25 -0
  22. package/examples/JSON/Empty Path Testing.html +31 -0
  23. package/examples/JSON/Gradients.html +34 -0
  24. package/examples/JSON/Group Transform.html +28 -0
  25. package/examples/JSON/Line Testing.html +44 -0
  26. package/examples/JSON/Random Path Testing.html +42 -0
  27. package/examples/JSON/Raster.html +29 -0
  28. package/examples/JSON/Rect and Attribute Testing.html +56 -0
  29. package/examples/JSON/Rotated Primitives.html +55 -0
  30. package/examples/JSON/Selection.html +43 -0
  31. package/examples/JSON/Shapes.html +54 -0
  32. package/examples/JSON/Symbols.html +30 -0
  33. package/examples/JSON/Text Testing.html +38 -0
  34. package/examples/JSON/Tiger.html +19 -0
  35. package/examples/JSON/Transform Test 1.html +32 -0
  36. package/examples/JSON/Transform Test 2.html +30 -0
  37. package/examples/Node.js/AnimatedStar.js +52 -0
  38. package/examples/Node.js/BooleanOperations.js +36 -0
  39. package/examples/Node.js/JSONtoPDF.js +20 -0
  40. package/examples/Node.js/Raster.js +32 -0
  41. package/examples/Node.js/RasterRemote.js +33 -0
  42. package/examples/Node.js/SvgExport.js +52 -0
  43. package/examples/Node.js/SvgImport.js +23 -0
  44. package/examples/Node.js/Tadpoles.js +16 -0
  45. package/examples/Node.js/Tadpoles.pjs +278 -0
  46. package/examples/Node.js/in.json +1 -0
  47. package/examples/Node.js/in.svg +16 -0
  48. package/examples/Paperjs.org/BooleanOperattions.html +115 -0
  49. package/examples/Paperjs.org/BouncingBalls.html +103 -0
  50. package/examples/Paperjs.org/Chain.html +54 -0
  51. package/examples/Paperjs.org/DivisionRaster.html +72 -0
  52. package/examples/Paperjs.org/FutureSplash.html +122 -0
  53. package/examples/Paperjs.org/HitTesting.html +103 -0
  54. package/examples/Paperjs.org/InteractiveTiger.html +777 -0
  55. package/examples/Paperjs.org/MetaBalls.html +132 -0
  56. package/examples/Paperjs.org/NyanRainbow.html +202 -0
  57. package/examples/Paperjs.org/PathIntersections.html +76 -0
  58. package/examples/Paperjs.org/Qbertify.html +146 -0
  59. package/examples/Paperjs.org/RadialRainbows.html +80 -0
  60. package/examples/Paperjs.org/RoundedRectangles.html +41 -0
  61. package/examples/Paperjs.org/SatieLikedToDraw.html +140 -0
  62. package/examples/Paperjs.org/Simplify.html +63 -0
  63. package/examples/Paperjs.org/SpiralRaster.html +120 -0
  64. package/examples/Paperjs.org/Tadpoles.html +283 -0
  65. package/examples/Paperjs.org/Voronoi.html +134 -0
  66. package/examples/Rasters/PhyllotaxisRaster.html +96 -0
  67. package/examples/Rasters/Raster.html +34 -0
  68. package/examples/Rasters/RotationRaster.html +44 -0
  69. package/examples/Rasters/Smoothing.html +48 -0
  70. package/examples/SVG Export/Circle Testing.html +32 -0
  71. package/examples/SVG Export/Clipping.html +17 -0
  72. package/examples/SVG Export/Compound Path.html +22 -0
  73. package/examples/SVG Export/Empty Path Testing.html +28 -0
  74. package/examples/SVG Export/Gradients.html +52 -0
  75. package/examples/SVG Export/Group Transform.html +25 -0
  76. package/examples/SVG Export/Line Testing.html +41 -0
  77. package/examples/SVG Export/Random Path Testing.html +39 -0
  78. package/examples/SVG Export/Raster.html +21 -0
  79. package/examples/SVG Export/Rect and Attribute Testing.html +53 -0
  80. package/examples/SVG Export/Rotated Primitives.html +80 -0
  81. package/examples/SVG Export/Shapes.html +58 -0
  82. package/examples/SVG Export/Symbols.html +27 -0
  83. package/examples/SVG Export/Text Testing.html +45 -0
  84. package/examples/SVG Export/Tiger.html +23 -0
  85. package/examples/SVG Export/Transform Test 1.html +29 -0
  86. package/examples/SVG Export/Transform Test 2.html +27 -0
  87. package/examples/SVG Import/Arcs.html +78 -0
  88. package/examples/SVG Import/Butterfly.html +223 -0
  89. package/examples/SVG Import/Circle and Ellipse Testing.html +26 -0
  90. package/examples/SVG Import/Clipping.html +100 -0
  91. package/examples/SVG Import/From File.html +30 -0
  92. package/examples/SVG Import/Gradient.html +138 -0
  93. package/examples/SVG Import/Gradients.html +30 -0
  94. package/examples/SVG Import/Inkscape Pivot.html +52 -0
  95. package/examples/SVG Import/Inkscape.html +88 -0
  96. package/examples/SVG Import/Line Testing.html +24 -0
  97. package/examples/SVG Import/MoreGradients.html +107 -0
  98. package/examples/SVG Import/Multiple Paths Test 1.html +42 -0
  99. package/examples/SVG Import/Multiple Paths Test 2.html +33 -0
  100. package/examples/SVG Import/Nested Groups Test.html +78 -0
  101. package/examples/SVG Import/Polybezier.html +43 -0
  102. package/examples/SVG Import/Rect Testing.html +25 -0
  103. package/examples/SVG Import/Symbols.html +24 -0
  104. package/examples/SVG Import/Testing.html +40 -0
  105. package/examples/SVG Import/Text Testing.html +19 -0
  106. package/examples/SVG Import/Tiger.html +742 -0
  107. package/examples/SVG Import/Transform Testing.html +22 -0
  108. package/examples/SVG Import/Viewbox.html +38 -0
  109. package/examples/Scripts/Arcs.html +39 -0
  110. package/examples/Scripts/BlendModes.html +77 -0
  111. package/examples/Scripts/BooleanOperations.html +937 -0
  112. package/examples/Scripts/CompoundPath.html +19 -0
  113. package/examples/Scripts/CurveTimeParameterization.html +61 -0
  114. package/examples/Scripts/HslColor.html +53 -0
  115. package/examples/Scripts/PathStructure.html +82 -0
  116. package/examples/Scripts/PathTangents.html +73 -0
  117. package/examples/Scripts/Resize.html +42 -0
  118. package/examples/Scripts/RoundRectangle.html +28 -0
  119. package/examples/Scripts/Shapes.html +54 -0
  120. package/examples/Scripts/StrokeBounds.html +101 -0
  121. package/examples/Scripts/StrokeScaling.html +65 -0
  122. package/examples/Tools/BezierTool.html +90 -0
  123. package/examples/Tools/Circles.html +28 -0
  124. package/examples/Tools/Clouds.html +35 -0
  125. package/examples/Tools/DrippingBrush.html +73 -0
  126. package/examples/Tools/FancyBrush.html +82 -0
  127. package/examples/Tools/Grid.html +44 -0
  128. package/examples/Tools/MultiLines.html +44 -0
  129. package/examples/Tools/MultipleTools.html +44 -0
  130. package/examples/Tools/PathEditing.html +95 -0
  131. package/examples/Tools/SquareRounded.html +76 -0
  132. package/examples/Tools/Stars.html +38 -0
  133. package/examples/Tools/Vektor.html +200 -0
  134. package/examples/Tools/Wave.html +50 -0
  135. package/examples/Tools/WormFarm.html +88 -0
  136. package/examples/Worker/Main.html +53 -0
  137. package/examples/Worker/Worker.js +14 -0
  138. package/examples/css/style.css +12 -0
  139. package/package.json +109 -0
@@ -0,0 +1,132 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Meta Balls</title>
6
+ <link rel="stylesheet" href="../css/style.css">
7
+ <script type="text/javascript" src="../../dist/paper-full.js"></script>
8
+ <script type="text/paperscript" canvas="canvas">
9
+ // Ported from original Metaball script by SATO Hiroyuki
10
+ // http://park12.wakwak.com/~shp/lc/et/en_aics_script.html
11
+ project.currentStyle = {
12
+ fillColor: 'black'
13
+ };
14
+
15
+ var ballPositions = [[255, 129], [610, 73], [486, 363],
16
+ [117, 459], [484, 726], [843, 306], [789, 615], [1049, 82],
17
+ [1292, 428], [1117, 733], [1352, 86], [92, 798]];
18
+
19
+ var handle_len_rate = 2.4;
20
+ var circlePaths = [];
21
+ var radius = 50;
22
+ for (var i = 0, l = ballPositions.length; i < l; i++) {
23
+ var circlePath = new Path.Circle({
24
+ center: ballPositions[i],
25
+ radius: 50
26
+ });
27
+ circlePaths.push(circlePath);
28
+ }
29
+
30
+ var largeCircle = new Path.Circle({
31
+ center: [676, 433],
32
+ radius: 100
33
+ });
34
+ circlePaths.push(largeCircle);
35
+
36
+ function onMouseMove(event) {
37
+ largeCircle.position = event.point;
38
+ generateConnections(circlePaths);
39
+ }
40
+
41
+ var connections = new Group();
42
+ function generateConnections(paths) {
43
+ // Remove the last connection paths:
44
+ connections.removeChildren();
45
+
46
+ for (var i = 0, l = paths.length; i < l; i++) {
47
+ for (var j = i - 1; j >= 0; j--) {
48
+ var path = metaball(paths[i], paths[j], 0.5, handle_len_rate, 300);
49
+ if (path) {
50
+ connections.appendTop(path);
51
+ path.removeOnMove();
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ generateConnections(circlePaths);
58
+
59
+ // ---------------------------------------------
60
+ function metaball(ball1, ball2, v, handle_len_rate, maxDistance) {
61
+ var center1 = ball1.position;
62
+ var center2 = ball2.position;
63
+ var radius1 = ball1.bounds.width / 2;
64
+ var radius2 = ball2.bounds.width / 2;
65
+ var pi2 = Math.PI / 2;
66
+ var d = center1.getDistance(center2);
67
+ var u1, u2;
68
+
69
+ if (radius1 == 0 || radius2 == 0)
70
+ return;
71
+
72
+ if (d > maxDistance || d <= Math.abs(radius1 - radius2)) {
73
+ return;
74
+ } else if (d < radius1 + radius2) { // case circles are overlapping
75
+ u1 = Math.acos((radius1 * radius1 + d * d - radius2 * radius2) /
76
+ (2 * radius1 * d));
77
+ u2 = Math.acos((radius2 * radius2 + d * d - radius1 * radius1) /
78
+ (2 * radius2 * d));
79
+ } else {
80
+ u1 = 0;
81
+ u2 = 0;
82
+ }
83
+
84
+ var angle1 = (center2 - center1).getAngleInRadians();
85
+ var angle2 = Math.acos((radius1 - radius2) / d);
86
+ var angle1a = angle1 + u1 + (angle2 - u1) * v;
87
+ var angle1b = angle1 - u1 - (angle2 - u1) * v;
88
+ var angle2a = angle1 + Math.PI - u2 - (Math.PI - u2 - angle2) * v;
89
+ var angle2b = angle1 - Math.PI + u2 + (Math.PI - u2 - angle2) * v;
90
+ var p1a = center1 + getVector(angle1a, radius1);
91
+ var p1b = center1 + getVector(angle1b, radius1);
92
+ var p2a = center2 + getVector(angle2a, radius2);
93
+ var p2b = center2 + getVector(angle2b, radius2);
94
+
95
+ // define handle length by the distance between
96
+ // both ends of the curve to draw
97
+ var totalRadius = (radius1 + radius2);
98
+ var d2 = Math.min(v * handle_len_rate, (p1a - p2a).length / totalRadius);
99
+
100
+ // case circles are overlapping:
101
+ d2 *= Math.min(1, d * 2 / (radius1 + radius2));
102
+
103
+ radius1 *= d2;
104
+ radius2 *= d2;
105
+
106
+ var path = new Path({
107
+ segments: [p1a, p2a, p2b, p1b],
108
+ style: ball1.style,
109
+ closed: true
110
+ });
111
+ var segments = path.segments;
112
+ segments[0].handleOut = getVector(angle1a - pi2, radius1);
113
+ segments[1].handleIn = getVector(angle2a + pi2, radius2);
114
+ segments[2].handleOut = getVector(angle2b - pi2, radius2);
115
+ segments[3].handleIn = getVector(angle1b + pi2, radius1);
116
+ return path;
117
+ }
118
+
119
+ // ------------------------------------------------
120
+ function getVector(radians, length) {
121
+ return new Point({
122
+ // Convert radians to degrees:
123
+ angle: radians * 180 / Math.PI,
124
+ length: length
125
+ });
126
+ }
127
+ </script>
128
+ </head>
129
+ <body>
130
+ <canvas id="canvas" resize></canvas>
131
+ </body>
132
+ </html>
@@ -0,0 +1,202 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Nyan Rainbow</title>
6
+ <link rel="stylesheet" href="../css/style.css">
7
+ <script type="text/javascript" src="../../dist/paper-full.js"></script>
8
+ <script type="text/javascript" src="http://paperjs.org/assets/mediaelement/mediaelement.js"></script>
9
+ <script type="text/paperscript" canvas="canvas">
10
+ // A tribute to Nyan Cat http://www.youtube.com/watch?v=QH2-TGUlwu4
11
+ var mediaElement;
12
+ var playing = false;
13
+ MediaElement('nyan', {
14
+ pluginPath: '/assets/mediaelement/',
15
+ success: function(me) {
16
+ mediaElement = me;
17
+ me.play();
18
+ me.addEventListener('timeupdate', function(time) {
19
+ if (me.currentTime > 3.7)
20
+ playing = true;
21
+ });
22
+ }
23
+ });
24
+
25
+ var mousePos = view.center + [view.bounds.width / 3, 100];
26
+ var position = view.center;
27
+
28
+ function onFrame(event) {
29
+ position += (mousePos - position) / 10;
30
+ var vector = (view.center - position) / 10;
31
+ moveStars(vector * 3);
32
+ moveRainbow(vector, event);
33
+ }
34
+
35
+ function onMouseMove(event) {
36
+ mousePos = event.point;
37
+ }
38
+
39
+ function onKeyDown(event) {
40
+ if (event.key == 'space')
41
+ project.activeLayer.selected = !project.activeLayer.selected;
42
+ }
43
+
44
+ var moveStars = new function() {
45
+ // The amount of symbol we want to place;
46
+ var count = 50;
47
+
48
+ // Create a symbol, which we will use to place instances of later:
49
+ var path = new Path.Circle({
50
+ center: new Point(0, 0),
51
+ radius: 5,
52
+ fillColor: 'white',
53
+ strokeColor: 'black'
54
+ });
55
+
56
+ var symbol = new SymbolDefinition(path);
57
+
58
+ // Place the instances of the symbol:
59
+ for (var i = 0; i < count; i++) {
60
+ // The center position is a random point in the view:
61
+ var center = Point.random() * view.size;
62
+ var placed = symbol.place(center);
63
+ placed.scale(i / count + 0.01);
64
+ placed.data = {
65
+ vector: new Point({
66
+ angle: Math.random() * 360,
67
+ length : (i / count) * Math.random() / 5
68
+ })
69
+ };
70
+ }
71
+
72
+ var vector = new Point({
73
+ angle: 45,
74
+ length: 0
75
+ });
76
+
77
+ function keepInView(item) {
78
+ var position = item.position;
79
+ var viewBounds = view.bounds;
80
+ if (position.isInside(viewBounds))
81
+ return;
82
+ var itemBounds = item.bounds;
83
+ if (position.x > viewBounds.width + 5) {
84
+ position.x = -item.bounds.width;
85
+ }
86
+
87
+ if (position.x < -itemBounds.width - 5) {
88
+ position.x = viewBounds.width;
89
+ }
90
+
91
+ if (position.y > viewBounds.height + 5) {
92
+ position.y = -itemBounds.height;
93
+ }
94
+
95
+ if (position.y < -itemBounds.height - 5) {
96
+ position.y = viewBounds.height
97
+ }
98
+ }
99
+
100
+ return function(vector) {
101
+ // Run through the active layer's children list and change
102
+ // the position of the placed symbols:
103
+ var layer = project.activeLayer;
104
+ for (var i = 0; i < count; i++) {
105
+ var item = layer.children[i];
106
+ var size = item.bounds.size;
107
+ var length = vector.length / 10 * size.width / 10;
108
+ item.position += vector.normalize(length) + item.data.vector;
109
+ keepInView(item);
110
+ }
111
+ };
112
+ };
113
+
114
+ var moveRainbow = new function() {
115
+ var paths = [];
116
+ var colors = ['red', 'orange', 'yellow', 'lime', 'blue', 'purple'];
117
+ for (var i = 0; i < colors.length; i++) {
118
+ var path = new Path({
119
+ fillColor: colors[i]
120
+ });
121
+ paths.push(path);
122
+ }
123
+
124
+ var count = 30;
125
+ var group = new Group(paths);
126
+ var headGroup;
127
+ var eyePosition = new Point();
128
+ var eyeFollow = (Point.random() - 0.5);
129
+ var blinkTime = 200;
130
+ function createHead(vector, count) {
131
+ var eyeVector = (eyePosition - eyeFollow);
132
+ eyePosition -= eyeVector / 4;
133
+ if (eyeVector.length < 0.00001)
134
+ eyeFollow = (Point.random() - 0.5);
135
+ if (headGroup)
136
+ headGroup.remove();
137
+ var top = paths[0].lastSegment.point;
138
+ var bottom = paths[paths.length - 1].firstSegment.point;
139
+ var radius = (bottom - top).length / 2;
140
+ var circle = new Path.Circle({
141
+ center: top + (bottom - top) / 2,
142
+ radius: radius,
143
+ fillColor: 'black'
144
+ });
145
+ circle.scale(vector.length / 100, 1);
146
+ circle.rotate(vector.angle, circle.center);
147
+
148
+ innerCircle = circle.clone();
149
+ innerCircle.scale(0.5);
150
+ innerCircle.fillColor = (count % blinkTime < 3)
151
+ || (count % (blinkTime + 5) < 3) ? 'black' : 'white';
152
+ if (count % (blinkTime + 40) == 0)
153
+ blinkTime = Math.round(Math.random() * 40) + 200;
154
+ var eye = circle.clone();
155
+ eye.position += eyePosition * radius;
156
+ eye.scale(0.15, innerCircle.position);
157
+ eye.fillColor = 'black';
158
+ headGroup = new Group(circle, innerCircle, eye);
159
+ }
160
+
161
+ return function(vector, event) {
162
+ var vector = (view.center - position) / 10;
163
+
164
+ if (vector.length < 5)
165
+ vector.length = 5;
166
+ count += vector.length / 100;
167
+ group.translate(vector);
168
+ var rotated = vector.rotate(90);
169
+ var middle = paths.length / 2;
170
+ for (var j = 0; j < paths.length; j++) {
171
+ var path = paths[j];
172
+ var nyanSwing = playing ? Math.sin(event.count / 2) * vector.length : 1;
173
+ var unitLength = vector.length * (2 + Math.sin(event.count / 10)) / 2;
174
+ var length = (j - middle) * unitLength + nyanSwing;
175
+ var top = view.center + rotated.normalize(length);
176
+ var bottom = view.center + rotated.normalize(length + unitLength);
177
+ path.add(top);
178
+ path.insert(0, bottom);
179
+ if (path.segments.length > 200) {
180
+ var index = Math.round(path.segments.length / 2);
181
+ path.segments[index].remove();
182
+ path.segments[index - 1].remove();
183
+ }
184
+ path.smooth();
185
+ }
186
+ createHead(vector, event.count);
187
+ if (mediaElement)
188
+ mediaElement.setVolume(vector.length / 200);
189
+ }
190
+ }
191
+ </script>
192
+ <style>
193
+ body {
194
+ background: black;
195
+ }
196
+ </style>
197
+ </head>
198
+ <body>
199
+ <audio id="nyan" src="http://dl.dropbox.com/u/31703/nyan.mp3" autoplay autobuffer preload=none loop style="display:none"></audio>
200
+ <canvas id="canvas" resize hidpi="off"></canvas>
201
+ </body>
202
+ </html>
@@ -0,0 +1,76 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Path Intersections</title>
6
+ <link rel="stylesheet" href="../css/style.css">
7
+ <script type="text/javascript" src="../../dist/paper-full.js"></script>
8
+ <script type="text/paperscript" canvas="canvas">
9
+ // Imported SVG Groups have their applyMatrix flag turned off by
10
+ // default. This is required for SVG importing to work correctly. Turn
11
+ // it on now, so we don't have to deal with nested coordinate spaces.
12
+ var words = project.importSVG(document.getElementById('svg'));
13
+ words.visible = true; // Turn off the effect of display:none;
14
+ words.fillColor = null;
15
+ words.strokeColor = 'black';
16
+ var yesGroup = words.children.yes;
17
+
18
+ var noGroup = words.children.no;
19
+ // Resize the words to fit snugly inside the view:
20
+ words.fitBounds(view.bounds);
21
+ words.scale(0.8);
22
+
23
+ yesGroup.position = view.center;
24
+ noGroup.position = [-900, -900];
25
+
26
+ function onMouseMove(event) {
27
+ noGroup.position = event.point;
28
+ for (var i = 0; i < yesGroup.children.length; i++) {
29
+ for (var j = 0; j < noGroup.children.length; j++) {
30
+ showIntersections(noGroup.children[j], yesGroup.children[i])
31
+ }
32
+ }
33
+ }
34
+
35
+ function showIntersections(path1, path2) {
36
+ var intersections = path1.getIntersections(path2);
37
+ for (var i = 0; i < intersections.length; i++) {
38
+ new Path.Circle({
39
+ center: intersections[i].point,
40
+ radius: 5,
41
+ fillColor: '#009dec'
42
+ }).removeOnMove();
43
+ }
44
+ }
45
+ </script>
46
+ </head>
47
+ <body>
48
+ <canvas id="canvas" resize></canvas>
49
+ <svg xmlns="http://www.w3.org/2000/svg"
50
+ xmlns:xlink="http://www.w3.org/1999/xlink"
51
+ height="600" width="600" id="svg" style="display:none">
52
+ <g id="yes">
53
+ <path d="M427.151,85.781h27.331l-38.608,72.151v43.283h-24.121v-43.283l-39.94-72.151h28.428l23.964,50.277L427.151,85.781z"/>
54
+ <path d="M553.467,106.221h-61.084v24.512h56.073v20.048h-56.073v29.681h63.905v20.753H468.81V85.781h84.657V106.221z"/>
55
+ <path d="M592.307,165.583c0.746,5.274,2.213,9.215,4.396,11.826c3.998,4.751,10.848,7.126,20.551,7.126
56
+ c5.811,0,10.529-0.626,14.152-1.88c6.877-2.4,10.316-6.864,10.316-13.392c0-3.811-1.686-6.761-5.053-8.849
57
+ c-3.371-2.036-8.713-3.837-16.027-5.404l-12.498-2.741c-12.283-2.714-20.721-5.664-25.314-8.849
58
+ c-7.779-5.326-11.668-13.652-11.668-24.982c0-10.337,3.805-18.925,11.414-25.765c7.611-6.839,18.789-10.259,33.537-10.259
59
+ c12.312,0,22.816,3.224,31.512,9.671c8.693,6.449,13.252,15.807,13.676,28.076h-23.182c-0.428-6.943-3.531-11.877-9.312-14.801
60
+ c-3.855-1.931-8.645-2.897-14.371-2.897c-6.369,0-11.455,1.253-15.254,3.759c-3.801,2.506-5.701,6.004-5.701,10.494
61
+ c0,4.125,1.873,7.205,5.621,9.241c2.408,1.358,7.52,2.95,15.336,4.777l20.258,4.777c8.879,2.089,15.533,4.882,19.965,8.379
62
+ c6.881,5.431,10.32,13.288,10.32,23.572c0,10.547-4.076,19.305-12.23,26.274c-8.152,6.97-19.67,10.455-34.551,10.455
63
+ c-15.197,0-27.15-3.433-35.857-10.298c-8.707-6.865-13.061-16.302-13.061-28.311H592.307z"/>
64
+ </g>
65
+ <g id="no">
66
+ <path d="M400.993,246.168h25.287l45.821,80.49v-80.49h22.476v115.435h-24.115l-46.993-81.906v81.906h-22.476V246.168z"/>
67
+ <path d="M605.936,351.343c-8.721,8.98-21.33,13.471-37.826,13.471c-16.498,0-29.107-4.49-37.824-13.471
68
+ c-11.697-11.016-17.542-26.887-17.542-47.615c0-21.144,5.845-37.015,17.542-47.614c8.717-8.979,21.326-13.47,37.824-13.47
69
+ c16.496,0,29.105,4.491,37.826,13.47c11.641,10.6,17.463,26.47,17.463,47.614C623.398,324.457,617.576,340.328,605.936,351.343z
70
+ M590.859,333.801c5.611-7.048,8.418-17.072,8.418-30.073c0-12.947-2.807-22.958-8.418-30.033
71
+ c-5.613-7.074-13.195-10.611-22.75-10.611s-17.178,3.524-22.867,10.572c-5.691,7.048-8.537,17.072-8.537,30.072
72
+ c0,13.001,2.846,23.025,8.537,30.073c5.689,7.048,13.312,10.572,22.867,10.572S585.246,340.849,590.859,333.801z"/>
73
+ </g>
74
+ </svg>
75
+ </body>
76
+ </html>
@@ -0,0 +1,146 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Q*bertify</title>
6
+ <link rel="stylesheet" href="../css/style.css">
7
+ <script type="text/javascript" src="../../dist/paper-full.js"></script>
8
+ <script type="text/paperscript" canvas="canvas">
9
+ // Please note: dragging and dropping images only works for
10
+ // certain browsers when serving this script online:
11
+
12
+ var values = {
13
+ amount: 30
14
+ };
15
+
16
+ var raster,
17
+ group;
18
+ var piece = createPiece();
19
+ var count = 0;
20
+
21
+ handleImage('mona');
22
+
23
+ var text = new PointText({
24
+ point: view.center,
25
+ justification: 'center',
26
+ fillColor: 'white',
27
+ fontSize: 15,
28
+ content: window.FileReader
29
+ ? 'Drag & drop an image from your desktop'
30
+ : 'To drag & drop images, please use Webkit, Firefox, Chrome or IE 10'
31
+ });
32
+
33
+ function createPiece() {
34
+ var group = new Group();
35
+ var hexagon = new Path.RegularPolygon({
36
+ center: view.center,
37
+ sides: 6,
38
+ radius: 50,
39
+ fillColor: 'gray',
40
+ parent: group
41
+ });
42
+ for (var i = 0; i < 2; i++) {
43
+ var path = new Path({
44
+ closed: true,
45
+ parent: group,
46
+ fillColor: i == 0 ? 'white' : 'black'
47
+ });
48
+ for (var j = 0; j < 3; j++) {
49
+ var index = (i * 2 + j) % hexagon.segments.length;
50
+ path.add(hexagon.segments[index].clone());
51
+ }
52
+ path.add(hexagon.bounds.center);
53
+ }
54
+ // Remove the group from the document, so it is not drawn:
55
+ group.remove();
56
+ return group;
57
+ }
58
+
59
+ function handleImage(image) {
60
+ count = 0;
61
+ var size = piece.bounds.size;
62
+
63
+ if (group)
64
+ group.remove();
65
+
66
+ // As the web is asynchronous, we need to wait for the raster to
67
+ // load before we can perform any operation on its pixels.
68
+ raster = new Raster(image);
69
+ raster.visible = false;
70
+ raster.on('load', function() {
71
+ // Transform the raster, so it fills the view:
72
+ raster.fitBounds(view.bounds, true);
73
+ group = new Group();
74
+ for (var y = 0; y < values.amount; y++) {
75
+ for (var x = 0; x < values.amount; x++) {
76
+ var copy = piece.clone();
77
+ copy.position += size * [x + (y % 2 ? 0.5 : 0), y * 0.75];
78
+ group.addChild(copy);
79
+ }
80
+ }
81
+
82
+ // Transform the group so it covers the view:
83
+ group.fitBounds(view.bounds, true);
84
+ group.scale(1.1);
85
+ })
86
+ }
87
+
88
+ function onFrame(event) {
89
+ if (!group)
90
+ return;
91
+ // Loop through the uncolored hexagons in the group and fill them
92
+ // with the average color:
93
+ var length = Math.min(count + values.amount, group.children.length);
94
+ for (var i = count; i < length; i++) {
95
+ piece = group.children[i];
96
+ var hexagon = piece.children[0];
97
+ var color = raster.getAverageColor(hexagon);
98
+ if (color) {
99
+ hexagon.fillColor = color;
100
+ var top = piece.children[1];
101
+ top.fillColor = color.clone();
102
+ top.fillColor.brightness *= 1.5;
103
+
104
+ var right = piece.children[2];
105
+ right.fillColor = color.clone();
106
+ right.fillColor.brightness *= 0.5;
107
+ }
108
+ }
109
+ count += values.amount;
110
+ }
111
+
112
+ function onResize() {
113
+ project.activeLayer.position = view.center;
114
+ }
115
+
116
+ function onDocumentDrag(event) {
117
+ event.preventDefault();
118
+ }
119
+
120
+ function onDocumentDrop(event) {
121
+ event.preventDefault();
122
+
123
+ var file = event.dataTransfer.files[0];
124
+ var reader = new FileReader();
125
+
126
+ reader.onload = function(event) {
127
+ var image = document.createElement('img');
128
+ image.onload = function () {
129
+ handleImage(image);
130
+ view.draw();
131
+ };
132
+ image.src = event.target.result;
133
+ };
134
+ reader.readAsDataURL(file);
135
+ }
136
+
137
+ document.addEventListener('drop', onDocumentDrop, false);
138
+ document.addEventListener('dragover', onDocumentDrag, false);
139
+ document.addEventListener('dragleave', onDocumentDrag, false);
140
+ </script>
141
+ </head>
142
+ <body>
143
+ <canvas id="canvas" resize></canvas>
144
+ <img width="512" height="512" id="mona" style="display: none;" src="data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAATAAD/4QMraHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjAtYzA2MCA2MS4xMzQ3NzcsIDIwMTAvMDIvMTItMTc6MzI6MDAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzUgTWFjaW50b3NoIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjA1NUZCMzkwOTFGMTExRTBCNTg4OEQ5RDIyNkE4Qjc5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjA1NUZCMzkxOTFGMTExRTBCNTg4OEQ5RDIyNkE4Qjc5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDU1RkIzOEU5MUYxMTFFMEI1ODg4RDlEMjI2QThCNzkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU1RkIzOEY5MUYxMTFFMEI1ODg4RDlEMjI2QThCNzkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAATDw8WEBYkFRUkLSIcIi0pIyIiIyk4Ly8vLy84QTs7Ozs7O0FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBARQWFh0ZHSMYGCMxIx0jMT8xJiYxP0E/Oy87P0FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUH/wAARCAEsAZADASIAAhEBAxEB/8QAhwAAAgMBAQEAAAAAAAAAAAAAAgMBBAUABgcBAAMBAQEAAAAAAAAAAAAAAAABAgMEBRAAAQMDAwIFAwMEAQQDAAAAAQARAiExA0ESBFFhcYEiEwWRoTLwscHRQiMU4fFSghVikgYRAQEBAQACAwACAgMAAAAAAAABEQIhMUESA1ETcTJhgSL/2gAMAwEAAhEDEQA/AKhAdcCKFkRj6qoQHbRc9OOiSD9EUQZWURFUYi1SpMBDfumx0XNuCOgHmiCuIXEMXXMxquBdO0pBxPVSQ6gAW1RFTVOMA/VdKNFAlViuJ3WQHGOllDPXUpkQ11xG13ukYNp0XMjHqXMzJaMTEOpAaygqQHsjTRtJDqYwdH2RDugqWY1cImTGQCJdMkCKNqICRAPIgDxVbL8px8f94cdFXn4GLYiEYa6yD81iP4iR8kP/ALyJoIn7J5Tbga4UWWPH53F/cJBWMfymDLaX1SsoxfoVzMlxzwnUWTBJSEgVqmCKXQ2RDsgCFEd0BJ10UgEVStCSllkxjcoWrQoND16LhSyhutlIrRBpJLd1Do7BrqAKoocCwR3qhEWRxDVTKoAojayGkhQOijd9QE5Uok5KkVouL6/r9MUUQQK3ZGhEg6E0YlMkDa5SiKP5pUQsDqp7LutaKBVOCsCcjIsEwUoukBE3URr2VIlHGNVBGi4S3W/VEEn0SMUUYlQC6Db9E0BwkpAjRvBcAjLktqpiwQYNv3RsVMQfsutdAQzt9UZhZSAzdkZA1SARFlxDiiMkFCeyWgsguVIhZMlZEKeKWqhRiI+CMDoFLPVGI9USgEY6siIL91JDJHJ5cMETImqcTYblyxww3SLMsHmfOl9mDzl/RUObzcvNlWmPSP6uq4xAMTdbc8Sf7Df4PM8vKk85ElV5jbJrrQww24t30VIhy6qXbTsJ3l6WU+4RdEYOXZRLGxcrRDvdBupiRIuls6FiEYNXY5JY6wJCvcf5nJipNpDXqsiHIMaGoTTMZK2UXlUr1vG5+Lkh4Hy1CuRK8HDJPDJ4FivR/F/MxzNiy0n10Ky64s8z0etyNUygqgBcOmPV1iAEsUJJNkZC7ayoBGihlMgxBXDugamIopA0/ZFGoUsmNRGLuERiQFMASEciRRFIkdP5RRiyIhEQQWUaAGIYogGq11xFVyrQ6YDMgIBHgjk9igkGS0FGPRcAAKJhFKICqgrBJ3VK4wJc0siiQK3TmLd6FWj0QHFA7I9pdMEWrquvZTTAIl00aeChmZQEjFbRSI07rh3OiIHQap5gdZEA1ELItUjSwdSaiinapLD6IAWAQiIsjobdFDUSDohTepXRFm6ow9gkpF7ImeqKIaqlmVSEr8rLHBAzlYCi8jyuZLk5CT+Oi0fm+Z70jiiaC6qcP43JyK/jHqVrzJzPtS83wrY7BWMeH3JekHstzjfCQgBuqVpY+BixBhEKOv0nwucvPTx5IQFHAZ1RljkCaUqvaR48Yhilz40DcOVE/TFXnXiZAhJfQr2c+FhNwPos7l/F4i5jQrTn9p8pv534ecYISrebhmFlWlAi63ll9MrLC6miioPdFUKBVMhRk5XOYFxcKP3XSOhQb1fw3yn+xH2sn5j7rfxjcHXzfHllhkJwoQvcfF86PMwg2l/cFzfpxl2elS60dwQEBlIHmjgFE8ggA6aIwD5oyKrtuqeYANqjBLFcAKE6ImdAcCSpuHXMHZFEE3SoSKhlJDBSOigtIICAHuukCuHpXFjTRBBQTBuEZJ1QyoKpWGE1CWmGgQGNAqDz8SW8FYjMJZBFAHdFtaLhNBkahQAXfQpZO1wdE2BegQBghvJQQfBdGt05rJUyoxP3UiLJgGrqDECgqlVQMa2RgPRSA1FwDFIxALiGRKCGumQAFIFEyMQ3kuIIFEU4EAAhk2MaUUQiCjEToiSlsQQVR5/K9jEZD8rR8VfnQE6Lx3y/OObKYQPpjr3WnPNtwtnsvi4jyMzyrV2XquNx5UDt4LF+HxbYORden44WX69bc/htxMmmY8AAc1one2GXA0CJ1HgkCLhDKARbmUk0SoV5Yh0VXPhDUCvSDpOUBlGtI8/yeNGrrH5ODa7L0nJisjk4txK2/Lup75YkoslF1cywZ1XZ12yuewBUgOulBlDJkjVaXxHLPGzh/wATdZzdFIk1QlZsw54fSsUnAKZb1HVY/wADzP8AYwB/yj6T5W+y1z+IJXLZlUlhcLhW6AzRj1VTIZi4ChqsuJAAZFEhKm4AfRc6IFQVIQ1FIi1VD6BGPTdECBFdtomELjH0q4kiYZKIdWZCjlKMSyiqhZOiA3TJBABVEDIBcsyIQBgUjfoEwlgx1V1CIQBJcotwiUqWURKXHI0gDZ0jaERoyOhShMhiLIg6YMEGXbdVICkyjGhukp0YArmYumRAuEDVUgMiFJYsokFI7pwCBYITSNv06YgYkfrqjyHQv5KxFgghH9v6KORk9mG7XRVz1hWaq8/M8faH/kf4/Wi8Xy4j35CNnWx8hyTADHEsTWSxR6soHUrXjfPQsyY9L8ZH0ALdwdlk8KG0BrLWxnaFy9eba6J4ixuUbrqIM9FO1SQxKigyQCiJTfIBOQ+iRkk9E+QdIlFLFxUzRdUM2LVa08blIyYeiJ4o9vN58BqVnzhsuF6jNhEdFg82HqXZ+Xe+GPfOeVAyXChUgBihNKaLoYolQqFJFHUIDe//ADvI9vLLGTSQf/6r00s9HLt2XhOFkOLPCQ6j7r10ptFysP0nn/J/DQBo/SqL3fT+ypxynaK+JUnKI26VWXlfhcEyb6J2Mt4qljkrgkwdKp0wSeRHQLgxoUuFKnVQJvN+qClNiUwVQgUojAZJTiSD4ow/khLC66yekgjognZHKqCQo5KWnCJVIXOLi6LIwqEh6snBXmpZACDZRLly3Nd1Wy5N9dAkby7tVbSI+WjPcYmxSxMuN1PFDHJvDahdNpBnZ1CmriyjIK3TseUN3WTjkYAbqpu9g7Ml/g8aU87U+qA5Hd1UjmDkdVEsrBlOHWnDLso6dY11WSJ13GoujPLlkkHoAE/qj7NNt1V2xm6qri5YID9FeEiYONU/hWpEdeymMWD/AKuoD6dEcLJARjVxRUOeWAj5q7LI8SCsb5LON5awAH8qc0487y8hnmPZVMBJzxOrp3Ml/kM4qpjkRMHuuzmeP+k329xxRuAGi0BEAeCy+Hkh7YJNU2fOjHVcN3y6fbShTWiZuWLD5EPei0oZhOLhTdLFl0EpiN0qWbaCsbl/INIh0pLfEPM9tg54gqTkiV5/Hy91qqweTkiH2ybwTyn4aspJU8jB1kH5SNpEhKn8nGTsVX06/gr1F/NMELz3MmDIlXjyBkWfyxr3Wv585WfV1QkXshRFQutggVUkMuFETumHQk0gdQvWHKCATqHC8l0W8M2/HAig2hZ9z0F7DlBd7AqxGDl2VCDRiGvdWY8mQ0WFh7F3GTCh66pnvSlQXVc5CwlGrooSqjE2r4n6vBIx5CZA/VRHKIxJkeyVgyAmTWCWFGsMgsLo3VCBaXmrt1la1MJdSGChuimBehQBbXCVlpFk92oUnIQqpRVySVZ6q1MBgOqSQIsiHa8NEmdl0aVUxcRTCAGC66zNxMIE2RDIxoHrdLMSz6CiOHarLOnKsD0hzdLlNnrRBkJ+uqE1FksUbCRuollkTbxXAFmNko5Iwmwr3SkFp3vTkL3TsJO4DpEKpDqrOCbT8kUTFkgglzXotD46ZniIJsSsjLmO8N/8Qtnjwhx4GEDXVT6iflcgLE9EWOVCPFUs3KGKBe7FU8HyMoEwn/cPu6J5VfDUySIoF5/5HIY5T0IcLXx5PdBN2LLI+amzRFSzy7J8+8EYuSQIqqtNwTZUiSlYY78sY9SF0wVf97JEiDsKVWlj5PtYTkx4dwj/AHT1V8cUZYjdEEg6hWD7MYHHIemzLk6/SX4b8815+Hy0c0ts8YHeOi3Pj5H8DUGoKrY8HHfbjhQal1q8fFtkKM1gs++pf9ZiuZZ7L50vbgSvNSxSzzB0Icr03yg9CyuNj2SBCOOvrKV8rHFw5IRbDH/yksvmfIc/FlOEGxagXpYTMQ2mir5vayS3GIJ6slz3l8zTvO+vDy882TkvHLFyNQgxfH58tIxK9KMRmWxxYeDK7ixGIYrT+7P9Yj+vfbHw/HHHB53VHmYwKBelzszLznPkzslx1b0fUkjFnQ9lBounJyuMnC7nOHc3iu0dCQiAomSQtniTHsgGrOFjMy1fj8oOPYRUH91n36C3GQaiPHMvW/VLhlFmco4SJWZL2LJEQomQzB1XxQAFqlQCNyVSdmkCfShw5Jg9kBpHwTYEfWiVE9r3HmJ1HVacC4WLxzskXtda3HyUBdY9RrKsXXMy4zAUbkYEyKTMlHKYal0qadEIyEi6TOQonyHVVJ1klydeQpt/4TYTeQerJExtLkhGADWi7GR02kijJrWuq8TEkVbpROeJHVTYBTmJfyhc1JYB0mchEU/ZdCRyGqMOVZx8gV3XuqwvuK7LUsNApjLcwRJh2nSPQUGq6OfoVE6a/RIoC/VGaWrOXK84yNBT91dw88+5Mk+ku38LKnLcw6Lg9I9UrzsONLNmM2rVRlIiAexKq2ILuAp5E/qpnOHu+V3g8rbik5sQVV5Et4kKvc9ykQzDHjkNSR9ihlnAEgR2Dq/r5EqhKVwVPDLZ4E/9wUGL1KGBOOYPQrX4Hy+gceQZWRGMqMs7hH3IA9lowG1ebn8uq/yGOKMbBcxkXTJEANZDAB0hqvzI7gyp4cQiX0V/k1NLqriOhCeDWhiiCKpohE6BIiWCYJJQURAfRlWyyZNMlTzz1Sp8wjNkovO8+YJK1s+QrB5ctxdb/jz51H6XwoSuuBUuFwXa5gkKYqbKLJgx3DK78cBLcPBUQr3xk4QyS3ihFGU9eg0o4xHuUcCHYn6JvuYD6g3hVNwe1k0s+qwowMMjRdvuull3BiArPs49BpoujgxmjFkaVinIiIcVURyiVWV+PGgaVbxUjiQNtErUquOcndlq8bIAGNHVePFiNSEccAjqpvo5saW4XXb3FVViG1UubArNZ5IKHcEmRkA5KScu25RD8HSk6Q7VKD3DKyiI6qobw0uqPGaMUGQdFMSYsQu5kbZdGjAV8FID+CXWMlIOlUOnYgNLMq9xT7LhSqWBbiHJDXS4xDsKUQjKSGN04EUbop8wyzACTy6JRdwQnzFKIWADohADs4qwRSsGuCpjIBwwqhcCNEzcCR6TYoTNjVSCHH7IJa9QgFzyGg7ugJ3E91OQapbNV1ZwTkVSjJ0fuHbt7pbJivX/ABOcHGCei2ol6heS+IzehuhXoseZxdcH6TOq6+bsW55AyPEAQ6TGHuDxVSebJwYtkrHSX9VlDsWOTJuypykI+p1ic75PJOXpKTh5OfMRFbf1XNqPvPT2cGIBGoTAUjiy244voEU8o0WVXiJ5Gos/kZNE/NkWdnkSESaLcVc+QkLGzScrRzvFZmUrs/KYw6JN1IPkhcsuF1syGQLoLqSdFCAl1YxS2yEvqq7tVMiSmGlDJJyAX/4+qYJnuFVg72+ifGUhQhj1ZZ2Et488tTXunDLMmhpqqW40/lFEyBYvRTYS4M89SVMOTMPVU/do2qmE5yL1ZLCxpx5srSHmrMM5lF1kXZNMyABHzSsDW98gqDn3LM/2EyGZ1P1LaszzEmiVmnTbqlRyEEldlJMm/wCKBGGVDKYl63oFYPyA20uqeV7BLINzZPDYDOV1jXRSRVQzldQOgTtqiu5UABqLiNFAdENE/qqmJqyAlHiiAXKAktVkeMjrooECaogwukZmSYMWF0G4gIdwP/CgO7d7FLAIPcI5PtqTrR0o+mjBSJ7g39AmTnfoQEJ6ldK7oQHTAJj0uNNWSH6q0YsCOyryDJw4EDcaKCCLpkB5IJy3FM174uQE9vWy9HBwKWXkcGX28gkNF63i5hkiCDdcv7zLrf8AK+MXcOcQIBN1ZykTgYkg9lQlwo8ghyQOyP8A0I4z6ckh41XL4bMnL8XjjLd9k/Dix4rJ2bhSma5AwVCfCINZrWdbPNRZnqNCXNEfSCn4pSndUuPwMWM7y8pdytKJAuoufBzfknKKVVHJQK9lnRZubIPJPmCqeeX0WXlYlX+TKtFnSquv845+iyuZcVIpVbICaLlx6rkBwTIoBVFGl+qCaWKYMQyfDdJ9rMztZVuKSxCtggPR3WXRCYUp9AuD+X9V0RE0t/yijBiG6US0gEEVioDkEMmCJZzXzUiFwkAxBICYMRIfRQKGmiaJO7oCYwCbHDrqgEmj4ojkaRBKmwjizaMkGfq6BvolyzxAcOSgnPeGsjFAyZaEUolnLKdWZSYn+FBc0ZlQYU0eJgguUUWdl0A3cb2Qg6ugdj2R9iVIGJABFGUTU3KEAEMgskDoz6Bu6AEdXCCJBUsJWZBi29Fxib6KT2/ZGDEsCEB0ZTDm7odv1ThjgIuKlGANqVpECMXcUTINEWr3TI4oHWrooxiAxkptBGUDZQKrJqtZak8Y2SDvQ/q6oSjECifNVFUyYMhRTFaLthC0BZDLT+P55xeiRos/aUCXXM6mUS2V7njcncKFW8kDldrrx3x3yMsB2ysvYcPPHJHcNVwfp+d4rq56+0Z8+DmJNSohxJj8nW6ZxZUs2QOwUS01JiKOj3kByhnkAPdUsvJAonJaVuGZ87VWdlyuUOXMSUiXit+eMZ3rQ5S6qZC6dkm1lVJcro5jK1zrnXLlZIXIiGKg0QSYlkcEEUcCAlTaXFAkQT0Vg3oCPBU+JNqNoVpAvEUAOqxvsUqBJDEJ4xkiwvqgiIhmoKq0IgDdU+anq4WESgYglnfugyboln0TpBy5GrpLmUuyJaLEbi976KRIvQkfZdUVb+EUSSGNCqSHcfE9EBkS4/6KwDECx80EpQiTQGnRA0ljG6YYm2mqMEE0iH0ZcSwYVKDDCL0NyhIDLt5Ad7+TpUpPc18UwxRVCxUumQAoTpotwUQWUxJ/EqTJ0IJjVAWaEAISHq67HIs1l0aD+ik3AMoIahui9RuFG0kpBwIIqji57hQMckz2ZeCNDrijilVMIykA1U2WKW0EX1BXRxTMabaJb4GOGGTh6DomR4pkHd37KY4cg1AdWcUZR8lNowvHxmDEkg9ll5Y7XibgrcqQyyOZjbJuGoRz7UqMGdDu0XbmKFakIyowS1JohTJLstT4/wCTlxvTK3VZa51PXM6mU5bPMeu/9vCUQxSMnycdKrzcJF2CZ64XCx/p5a/2WtTLzJZKiiqnISqpyl3ZCchKucSI+yyZgXSp5d1BZKYmhRCJVZIW678r2USjtKaI36ohiMmJRoxWIXbU6WMRSTUpwnOoJXFQQmQgWoijdDEOiZkYa1xS2Si0oyALVKxsciCw1ay0cc5AC4dR1C06Wd2DJ4yliQq3tyfSndNYXEnPgpuA8SIGoeqWcoJfquENxqUE4iNAXKnwQpZY7Wu50UQyAB7ukEtS39V25/ToaSJTw1iOYyiS3pQznEkt5JGSQY7T5rgd1SWRgNhkgPxpJOGSMo9SO6qRBZ76pmOYxu9yyMFWsQgAxofFBlwi4YIDkMhQXS45SJDdUdEiYa7cWZSXZQzroCAjkQGOqCxquqSgGwluomxkwqPNLjAxDtVHGEiWp9UqDBOllMZgGvdHHGGqQmR2xqGoptMMZbrfsibJb7JkQ2qmrM6jTFHHkd38U3GDEMZIARr+vuoxhjISIHRBHPu1NOy4yu3VLjXT9fVGCBQH7KcNwkQNVU5MDkFLj6q09OzdkmcvPyRPFNiyNVABNk3M3uSbqlxkRQareEghCUVQVBTJwUFSuKAdxAPei9iWW7n4glUBeehLbIEaL2fG25ICXULn/a5ljTjzsefycRqtZVJ4dtF6bJgcEBU8nFEdFPP6neWMIOLJscb6K/7FbI44Nqq9lIrY+PR2Ryw7RQK5jxMKBMlio6y/sX9WHnhR1TkFs8rDR9KOszJD1Fhqt+OtiOphEhqoAcOiPdRcrXUOAc0UsixwcqSLvcI0Dw/kA7LQEnO17C6yBJj4LR4+WMjulbsp6gWzulT+EyOKZNA/gghycbgs30VzHy8bPr3Kxtv8DIrbcsD+LaKAJz9IjbqrB5ImR+yZ7gjqkFHJjlZraKY43ABCvRxnJXREcGOMCTpZP7DGccLO10P+vL6K9hG4+kKyICpop67kOc2s0cYg1UDiCRWqDjgC5QZOTjAI2KPvV/RkzxCLsHIKWBWt7BaAMchaEQAEggRkCQAFpOkWMElSpAKIkldSAbHNkQg+ikGTo4OlQgQqBZOx8aRrooEpDVkZlKctr07qKHSBESRYfuh9wgAtVOlLbT9OkZZuGjVwyU8mKUyIOAzsUMc5Dg1pQpZxsKnyT9jYu/8ACPEM/jZo5QdCNFMdu8gELJkTCVE6HIOMsU/r/BLwnAHunEAVLAXeiy8vIlMMKRXYsjgjr+yX1o1oDJAwJBcgdlWxZhB4yOriqomZBJF0UjuDp/UFym5JGqF/suXM6sJMnLoSVKgJhylSIkmlVo8X42U2MwwKnrqc+zk1U4/HOUsF6jgAwgInRTxPj4xsFcjxthZcn6fp9vDbnnHbRL6JGTECa1ZXBABCYVWDTGf7LBMGF1cOPsijiLItGK/tADoonj9IIFqq4cQDvdDt9LdlOmycuMbWNlh8iBxyprVepnheJeoZYPNxFwTddH5decR3GZKL0FV0YBwjPptdOxj3JarqtxjIVgh/kAOqHkR2yYUTxExyFtEjkO7FE9i+lYhkzESHbRCXXEMXVoPgSrEITkKtVV4BwD5JwlMF+iiwxzjLGAbhXONI7RkkHA07KgDKdFY9nKY+kMCooXMnyAMRLHQAWVOPPySk02I+iMcHIY6AIY8KYk0rKf8AzBlbPGzwIEWurcjBis3jYJAhzY0WmYmY0XL1m7G/Pryr7XJB+qqZJSnIwAAD3TOXkOH0PUpfubIuLmy05R10aIxxRkY00VDKZSk5sLK/GkPVUM6o8o7adv3VcbqLWIJPQIhZDKFaKBMxXYjBE7Cpx5ZbmSpSUwPVAxajk9xtAmR2xFPNJxRA8kX5WWd8qkdObFxcoAXJJup2XdHHjmJeVH+qeyB0w8Nx8FMZaGzJs8YArYV8UvP6beJdTLp4pZD6lErvooN07GAAxs7laekk+4RY06JmIbpEdikGhTsRYHwTAcgYpb6IpAlAiBK4dFCkFimEyu3RMw4ZZS0Q5QAOvQ/FcP07tT+yz77+k1fPP2ruH8WMQ3S/JaeHinc5+it4sLCisiDdHXB13er5bzmQgR2WFU3aJMmmDijv2U7dwqpoIABCEYxX6qxsAoPooEfokoAxhHsRBhZExbugtJIo2iA0o19U0mlPulyJH7JHFfIaOadfBYXMyChH91lt5Y7oys7WWBzY+5kAGmi1/LLS69KBP+Td/Cs8OFTLqyVtjH9aqzhyPE+S6urcZSK8R/kkWsqc9CrMps+ipyIdXzEWuI9KFvomBiyF3NFaRwyHGaWKuY8wlScQW1LqhKLUTIZDZLqaGvCWKVKDsAtHDHGYO4uywI5HDhXOPmJo9HC5++T1vDjx6IvajGwXR5HuR9Lt1/kItksgpZc91rMLOQAOAAyVnyynClHXZMBBBs2iGWIzt90vQtVhgcuapebGbUorHtyAYC/VKnAMaG1lpKiwmc2EjGwVV5TpdX4cXfQdqFTLjGJFHC0nUibHnRUpZBJRRBko/oV1ECUUzHGqZJhAAXSoyID6hkboWW20UQDAm6sRxmcN0fqj2tER6MsvsarGRMxRWBP/ACDfd3U7HLAdHTMsQ4IFVNstMnkZaO+qqZCSC2qt5cbpBAjFiKuq5wlXYWdMiQQQFMoykSEwQcALTSVMkWNEWIOmSG41XPtunoKNElMyT3WSwnCcihFyuAcq1DAdrtRFpyaPBgGWQiL6r1XBw7RQWWPwcW2TCruV6TjxbzXF+3W+HRxMh0QyZGtEQDBlIGi55DqRGlVH40ROyEglFNDoYh7omDLohj2SCQLIiuZkJNEyBUpU4sKXTJFkuZcKcVFbLPaCVh87bFskbha/JkdhJ0WByt2Vz/aCtvxnkur4BlkJgGyHCSYyJF1E4S2An8VMHidvYrq+GV9qvIo/cqqDV0/klpFKhEkLaemVFEkVTcWMko+PxJyqR9VoDHDGHkR0os+u5PCpGVKL+KXKi0pziTairZZRNAAqlKwvHkbsP5WhhlGQ9RZZG7QKzx+UMZcgeYdHXOwm7DlCMdpJbwTRyiADtduqzcMnkJn8SXKviQzS3bo0sCuTrnFxbHKlFhKAD9UzHkyz9QgG8P6pe3cGo+iaMU2EXA0os7FRX/3jM0Ap1RNPLJiwB/JgpHCEJO6ZLFI2sjx8H/kn3Ig7YlyqnJMjIAEkUV//AEomJAO09UP+mLOqlk8llryG4RKAElMZDGNV6DAUz6R4JUDdcXZTGBQa7w+SMcJR1dwrnFyxzOZBiCyyQGrouhnnikdpWfXG6qVumAdwl5MZFSFSw8+UfzDjU6q+ckZxEom6wvN59nuhOMyBqzqmYCJfR1ZmCA7gnVBMAudFXNwrFMSEpfwn0uUIxsN3VDmyCFNGV+/REZJsXVWctxdTOZkUC2kwrXKVCkVTCxxse41W1h47NI01+qpfG4t0rOF6LDxgfUW3A26suX9e8uN/z58EcHjzM9ws2ujrbxQAoBaiVgxggNZWYO2q5OrrRNro4gKNq4G6SU9lBUuuZ0GERp4LgOqNlAGiMAqaoJCroiGUMgESDJcgQHLKxIKvkmaAskqKPIHoOlFjyJdyHWpy8m0MKn+iyMhJBkTU+C1/KF0r5ifxahKgyL+SM8aUjuuSrOLBCF6k3ZdGyRlZaoR4ZyF5UfTVXcfAlEMIt3krccojTEAKXAVqOLLk89Vn1+nX+DnMUP8ATnOXrmKVou/1sYLSkS2i0p8fHiH+QgnuXSZZsGKp+zKZ3arIoZseCDNBwWq6qTlhtsV/N8phHphEeSoZOfMhwPstuZ0zuKOb2ySQCEkxOhTcueeS9vBJMnXRGQoZp4zTzC0IcgTi5NVlqdxiUdcynK2o5dpeEyD2Vnj82UZeqe5/+4OsXEd7K3ujGDRIfUrHrj4XK3TyqPQtqyCfyBx+oEN/2rEhmnjb7Io5jKQGij+s/s9DDljLHdRM/wBqJG80WC+SRaIICuwxzAAA8FneT+1eflMGiiIrRcRrqoddrIwxBilykAVByGwUxjXukEM4DKDDqnCD3UTiUaYAwCu8fIYwJl19Pmq4xOaVTGkfysKKevIh2TOYmrSHQKxgnCZb9/2SIY6uIk91YxYDFzM1Nll1mKicmGIG5YnKyb50LgLS+Q5QhHbE1KxbrT8ubm1PVSuC5ctkOR4hVAE3FF0qcbvxhiBS5W/ixb4sadl5Hj5DikJBer4XMjkF69Fw/tzZddPFmY0YRZgOiIRbwQRlGVmdNFQ6wFC+llzt4ISdpdDEk+aDNCJRAOmCyIVrttHUEIgpLGgVYnSjH+FNUZooJaiVPSZggKrkDGiuyc+Sp55CJuFNXGbmiRUXIsqZgYh5M6u5swApUm6zpFwJTPkteJcLqgD5CwCtx4cDEHKS7qqeZDEKAAlUuR8hKVlr9euvXiI2T22/e4+AekANqVT5PzJkWBp9FhyyzyGrkldt21JA+605/GT35Te/4XMnyE8hqWVWXJepLlJlKD0r4oCQdFtOJEWmSzvpRAchKB1zqsSnd1ULnUVTDlLuKqApQBRJiVfh6g8bLPCbiyGJ7dFNmqlxa3D+5QYA/iUZgNSuOIgOPsoUPDyc/G/A0Omi1cPycczRkGlapZYu+UU8CGTSvZR1zKJ4Uj6rBDLGURsixtuG77raoFjwOLI44d0mJ+iYXRj8Rtvqs7qvAo4scKXS5SgTayn1ebFLx/kX/FRPflXhZxmBqYp/uQiHIAVKTvR0Pq81Nk/kL2TmkVis/k86QpeX7KJOxa6zpvuO66rj6aV1MpmRc1KFcoXSySpZlAXICYiqsYg9TRKg2tlZxs5e2qVOLDANIXT8M2A2SbVVp3r3t1an2XDdRlj1nyua1cPyuXFJpgnutXB8tiyAPJqPVedg9N3Uv+vouy27/f8ATrn6n5/y1n2enlyo5JARLjqreOQLLxeL3nGx+y2OL/utRv8AyWVnPx0rb8x6UAVUEUI8VQxf7LDdengmj330dCVr3B59EQSI76P5ohu0TpGGTBL3dkMt2irZ/caWxu6lXgWfkjGDoFi8jnb7lgu5Huv67OP1+qLNl+X+R/4V8zn5pXfg/LyL7bfq6y82eTkuw7Kzyvc20ZtGssz+713XT+f1ZXU7jK1ENnJLKZP/ANEC3QL3GpGiW6KLPVRROBDFTtunZNrR6IKMUyLZQjLMGuhQELlxUhAcuPVcVP7oNIOikUNUIdkRdkyaPEyCcDAiosVYEHcEsXWdw9+/0/oLT9XuUswuufv34b8+vIZ42Dsk+l6hWJb9p2qtJ39bIgv/AA//2Q==">
145
+ </body>
146
+ </html>
@@ -0,0 +1,80 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Radial Rainbows</title>
6
+ <link rel="stylesheet" href="../css/style.css">
7
+ <script type="text/javascript" src="../../dist/paper-full.js"></script>
8
+ <script type="text/paperscript" canvas="canvas">
9
+ var point = view.center;
10
+
11
+ var colors = [];
12
+ var cycles = 4;
13
+ for (var i = 0, l = 60; i < l; i++) {
14
+ var brightness = 1 - (i / l) * 1.5;
15
+ var hue = i / l * cycles * 360;
16
+ var color = {
17
+ hue: hue,
18
+ saturation: 1,
19
+ brightness: brightness
20
+ };
21
+ colors.push(color);
22
+ }
23
+
24
+ var path = new Path.Rectangle(view.bounds);
25
+ var gradient = new Gradient(colors, true);
26
+ var radius = Math.max(view.size.width, view.size.height) * 0.75;
27
+ path.fillColor = new Color(gradient, point, point + [radius, 0]);
28
+ var gradientColor = path.fillColor;
29
+
30
+ var mouseDown = false,
31
+ mousePoint = view.center;
32
+
33
+ function onMouseDown(event) {
34
+ mouseDown = true;
35
+ mousePoint = event.point;
36
+ }
37
+
38
+ function onMouseDrag(event) {
39
+ mousePoint = event.point;
40
+ }
41
+
42
+ function onMouseUp(event) {
43
+ vector.length = 10;
44
+ mouseDown = false;
45
+ }
46
+
47
+ var grow = false;
48
+ var vector = new Point(150, 0);
49
+
50
+ function onFrame() {
51
+ for (var i = 0, l = gradient.stops.length; i < l; i++)
52
+ gradient.stops[i].color.hue -= 20;
53
+ if (grow && vector.length > 300) {
54
+ grow = false;
55
+ } else if (!grow && vector.length < 75) {
56
+ grow = true;
57
+ }
58
+ if (mouseDown) {
59
+ point = point + (mousePoint - point) / 10;
60
+ } else {
61
+ vector.length += (grow ? 1 : -1);
62
+ vector.angle += 5;
63
+ }
64
+ gradientColor.highlight = mouseDown ? point : point + vector;
65
+ }
66
+
67
+ function onResize(event) {
68
+ point = view.center;
69
+ path.bounds = view.bounds;
70
+ var gradientColor = path.fillColor;
71
+ gradientColor.origin = point;
72
+ var radius = Math.max(view.size.width, view.size.height) * 0.75;
73
+ gradientColor.destination = point + [radius, 0];
74
+ }
75
+ </script>
76
+ </head>
77
+ <body>
78
+ <canvas id="canvas" hidpi="off" resize></canvas>
79
+ </body>
80
+ </html>