on aa7a67f help sign in
elk/runtime/Render/Collage.js
197 lines 5.8 kB history raw
2ElmRuntime.Render.Collage = function() {
3'use strict';
5var Render = ElmRuntime.use(ElmRuntime.Render.Element);
6var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
7var newElement = Utils.newElement, addTo = Utils.addTo,
8 extract = Utils.extract, fromList = Utils.fromList,
9 fromString = Utils.fromString, addTransform = Utils.addTransform;
11function trace(ctx, path) {
12 var points = fromList(path);
13 var i = points.length - 1;
14 if (i <= 0) return;
15 ctx.moveTo(points[i]._0, points[i]._1);
16 while (i--) { ctx.lineTo(points[i]._0, points[i]._1); }
17 if (path.closed) {
18 i = points.length - 1;
19 ctx.lineTo(points[i]._0, points[i]._1);
20 }
23function line(ctx,style,path) {
24 style.dashing.ctor === 'Nil' ? trace(ctx, path) : customLineHelp(ctx, style, path);
25 ctx.stroke();
28function customLineHelp(ctx, style, path) {
29 var points = fromList(path);
30 if (path.closed) points.push(points[0]);
31 var pattern = fromList(style.dashing);
32 var i = points.length - 1;
33 if (i <= 0) return;
34 var x0 = points[i]._0, y0 = points[i]._1;
35 var x1=0, y1=0, dx=0, dy=0, remaining=0, nx=0, ny=0;
36 var pindex = 0, plen = pattern.length;
37 var draw = true, segmentLength = pattern[0];
38 ctx.moveTo(x0,y0);
39 while (i--) {
40 x1 = points[i]._0; y1 = points[i]._1;
41 dx = x1 - x0; dy = y1 - y0;
42 remaining = Math.sqrt(dx * dx + dy * dy);
43 while (segmentLength <= remaining) {
44 x0 += dx * segmentLength / remaining;
45 y0 += dy * segmentLength / remaining;
46 ctx[draw ? 'lineTo' : 'moveTo'](x0, y0);
47 // update starting position
48 dx = x1 - x0; dy = y1 - y0;
49 remaining = Math.sqrt(dx * dx + dy * dy);
50 // update pattern
51 draw = !draw;
52 pindex = (pindex + 1) % plen;
53 segmentLength = pattern[pindex];
54 }
55 if (remaining > 0) {
56 ctx[draw ? 'lineTo' : 'moveTo'](x1, y1);
57 segmentLength -= remaining;
58 }
59 x0 = x1; y0 = y1;
60 }
63function drawLine(ctx, style, path) {
64 ctx.lineWidth = style.width;
65 ctx.lineCap = style.cap.ctor.toLowerCase();
66 var join = style.join.ctor;
67 ctx.lineJoin = join === 'Smooth' ? 'round' :
68 join === 'Sharp' ? 'miter' : 'bevel';
69 ctx.miterLimit = style.miterLimit;
70 ctx.strokeStyle = extract(style.color);
71 return line(ctx, style, path);
74function texture(redo, ctx, src) {
75 var img = new Image();
76 img.src = fromString(src);
77 img.onload = redo;
78 return ctx.createPattern(img, 'repeat');
81function gradient(ctx, grad) {
82 var g;
83 if (grad.ctor === 'Linear') {
84 var p1 = grad._1, p2 = grad._2;
85 g = ctx.createLinearGradient(p1._0, p1._1, p2._0, p2._1);
86 } else {
87 var p1 = grad._1, p2 = grad._3;
88 g = ctx.createRadialGradient(p1._0, p1._1, grad._2, p2._0, p2._1, grad._4);
89 }
90 var stops = fromList(grad._0);
91 for (var i = stops.length; i--; ) {
92 var stop = stops[i];
93 g.addColorStop(stop._0, extract(stop._1));
94 }
95 return g;
98function drawShape(redo, ctx, style, path) {
99 trace(ctx, path);
100 var sty = style.ctor;
101 ctx.fillStyle =
102 sty === 'Solid' ? extract(style._0) :
103 sty === 'Texture' ? texture(redo, ctx, style._0) : gradient(ctx, style._0);
104 ctx.fill();
107function drawImage(redo, ctx, form) {
108 var img = new Image();
109 img.onload = redo;
110 img.src = fromString(form._3);
111 var w = form._0, h = form._1, pos = form._2;
112 ctx.drawImage(img, pos._0, pos._1, w, h, -w/2, -h/2, w, h);
115function renderForm(redo,ctx,form) {
116 ctx.save();
117 if (form.x !== 0 || form.y !== 0) ctx.translate(form.x, -form.y);
118 if (form.theta !== 0) ctx.rotate(form.theta);
119 if (form.scale !== 1) ctx.scale(form.scale, form.scale);
120 ctx.beginPath();
121 var f = form.form;
122 switch(f.ctor) {
123 case 'FPath' : drawLine(ctx, f._0, f._1); break;
124 case 'FShape':
125 if (f._0.ctor === 'Left') {
126 f._1.closed = true;
127 drawLine(ctx, f._0._0, f._1);
128 } else {
129 drawShape(redo, ctx, f._0._0, f._1);
130 }
131 break;
132 case 'FImage': drawImage(redo, ctx, f); break;
133 case 'FGroup':
134 ctx.save();
135 var m = f._0;
136 ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
137 renderForms(redo, ctx, f._1);
138 ctx.restore();
139 break;
140 }
141 ctx.restore();
144function renderForms(redo, ctx, forms) {
145 var fs = fromList(forms);
146 for (var i = 0, len = fs.length; i < len; ++i) {
147 renderForm(redo, ctx, fs[i]);
148 }
151function collageForms(w,h,forms) {
152 var canvas = newElement('canvas');
153 canvas.style.width = w + 'px';
154 canvas.style.height = h + 'px';
155 canvas.style.display = "block";
156 canvas.width = w;
157 canvas.height = h;
158 function redo() { renderForms(this,ctx,forms); }
159 if (canvas.getContext) {
160 var ctx = canvas.getContext('2d');
161 ctx.translate(w/2, h/2);
162 renderForms(redo,ctx,forms);
163 return canvas;
164 }
165 canvas.innerHTML = "Your browser does not support canvas.";
166 return canvas;
169function collageElement(width, height, x, y, theta, scale, elem) {
170 var e = Render.render(elem);
171 var w = elem.props.width,
172 h = elem.props.height,
173 t = 'translate(' + (width + f.x - w/2) + 'px,'+ (height - f.y - h/2) + 'px)',
174 r = theta === 0 ? '' : 'rotate(' + theta + 'rad)',
175 s = scale === 1 ? '' : 'scale(' + scale + ',' + scale + ')';
176 // var m = 'matrix(' + mtrx[0] + ',' + mtrx[3] + ',' + mtrx[1] + ',' +
177 // mtrx[4] + ',' + mtrx[2] + ',' + mtrx[5] + ')';
178 addTransform(e.style, t + ' ' + s + ' ' + r);
179 var div = newElement('div');
180 addTo(div,e);
181 div.style.width = width + 'px';
182 div.style.height = height + 'px';
183 div.style.overflow = 'hidden';
184 return div;
187function render(model) {
188 return collageForms(model.w, model.h, model.forms);
191function update(node, oldModel, newModel) {
192 node.parentNode.replaceChild(render(newModel), node);
195return { render:render, update:update };
197};