elm/runtime/Render/Collage.js

186 lines
5.1 KiB
JavaScript
Raw Normal View History

2013-03-12 18:06:47 +00:00
ElmRuntime.Render.Collage = function() {
'use strict';
var Render = ElmRuntime.use(ElmRuntime.Render.Element);
var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
var newElement = Utils.newElement, addTo = Utils.addTo,
extract = Utils.extract, fromList = Utils.fromList,
fromString = Utils.fromString, addTransform = Utils.addTransform;
function trace(ctx, path) {
var points = fromList(path);
console.log(points);
2013-03-12 18:06:47 +00:00
var i = points.length - 1;
if (i <= 0) return;
ctx.moveTo(points[i]._0, points[i]._1);
while (i--) { ctx.lineTo(points[i]._0, points[i]._1); }
if (path.closed) {
i = points.length - 1;
ctx.lineTo(points[i]._0, points[i]._1);
}
2013-03-12 18:06:47 +00:00
}
function line(ctx,style,path) {
var isSolid = style.dashing.ctor === 'Nil';
isSolid ? trace(ctx, path) : customLineHelp(ctx, style, path);
2013-03-12 18:06:47 +00:00
ctx.stroke();
}
function customLineHelp(ctx, pattern, points) {
2013-03-12 18:06:47 +00:00
var i = points.length - 1;
if (i <= 0) return;
var x0 = points[i][1], y0 = points[i][2];
var x1=0, y1=0, dx=0, dy=0, remaining=0, nx=0, ny=0;
var pindex = 0, plen = pattern.length;
var draw = true, segmentLength = pattern[0];
ctx.moveTo(x0,y0);
while (i--) {
x1 = points[i][1]; y1 = points[i][2];
dx = x1 - x0; dy = y1 - y0;
remaining = Math.sqrt(dx * dx + dy * dy);
while (segmentLength <= remaining) {
x0 += dx * segmentLength / remaining;
y0 += dy * segmentLength / remaining;
ctx[draw ? 'lineTo' : 'moveTo'](x0, y0);
// update starting position
dx = x1 - x0; dy = y1 - y0;
remaining = Math.sqrt(dx * dx + dy * dy);
// update pattern
draw = !draw;
pindex = (pindex + 1) % plen;
segmentLength = pattern[pindex];
}
if (remaining > 0) {
ctx[draw ? 'lineTo' : 'moveTo'](x1, y1);
segmentLength -= remaining;
}
x0 = x1; y0 = y1;
}
}
2013-03-12 18:06:47 +00:00
function drawLine(ctx, style, path) {
ctx.lineWidth = style.width;
ctx.lineCap = style.cap.ctor.toLowerCase();
ctx.lineJoin = style.join.ctor.toLowerCase();
ctx.miterLimit = style.miterLimit;
ctx.strokeStyle = extract(style.color);
return line(ctx, style, path);
}
2013-03-12 18:06:47 +00:00
function texture(redo, ctx, src) {
var img = new Image();
img.src = fromString(src);
img.onload = redo;
return ctx.createPattern(img, 'repeat');
}
function gradient(ctx, grad) {
var g;
if (grad.ctor === 'Linear') {
var p1 = grad._1, p2 = grad._2;
g = ctx.createLinearGradient(p1._0, p1._1, p2._0, p2._1);
} else {
var p1 = grad._1, p2 = grad._3;
g = ctx.createRadialGradient(p1._0, p1._1, grad._2, p2._0, p2._1, grad._4);
2013-03-12 18:06:47 +00:00
}
var stops = fromList(grad._0);
for (var i = stops.length; i--; ) {
var stop = stops[i];
g.addColorStop(stop._0, extract(stop._1));
}
return g;
}
2013-03-12 18:06:47 +00:00
function drawShape(redo, ctx, style, path) {
console.log(style, path);
trace(ctx, path);
var sty = style.ctor;
ctx.fillStyle =
sty === 'Solid' ? extract(style._0) :
sty === 'Texture' ? texture(redo, ctx, style._0) : gradient(ctx, style._0);
ctx.fill();
}
function drawImage(redo, ctx, form) {
2013-03-12 18:06:47 +00:00
var img = new Image();
img.onload = redo;
img.src = fromString(form._3);
var w = form._0, h = form._1, pos = form._2;
console.log(w,h,pos);
ctx.drawImage(img, pos._0, pos._1, w, h, -w/2, -h/2, w, h);
2013-03-12 18:06:47 +00:00
}
function renderForm(redo,ctx,form) {
2013-03-12 18:06:47 +00:00
ctx.save();
if (form.x !== 0 || form.y !== 0) ctx.translate(form.x, form.y);
if (form.theta !== 0) ctx.rotate(form.theta);
if (form.scale !== 1) ctx.scale(form.scale, form.scale);
2013-03-12 18:06:47 +00:00
ctx.beginPath();
var f = form.form;
console.log(f);
switch(f.ctor) {
case 'FPath' : drawLine(ctx, f._0, f._1); break;
case 'FShape':
if (f._0.ctor === 'Left') {
f._1.closed = true;
drawLine(ctx, f._0._0, f._1);
} else {
drawShape(redo, ctx, f._0._0, f._1);
}
break;
case 'FImage': drawImage(redo, ctx, f); break;
case 'FGroup': renderForms(redo, ctx, f._0); break;
2013-03-12 18:06:47 +00:00
}
ctx.restore();
}
2013-03-12 18:06:47 +00:00
function renderForms(redo, ctx, forms) {
var fs = fromList(forms);
console.log(fs);
for (var i = 0, len = fs.length; i < len; ++i) {
renderForm(redo,ctx,fs[i]);
2013-03-12 18:06:47 +00:00
}
}
function collageForms(w,h,forms) {
var canvas = newElement('canvas');
w = w|0;
h = h|0;
2013-03-12 18:06:47 +00:00
canvas.style.width = w + 'px';
canvas.style.height = h + 'px';
canvas.style.display = "block";
canvas.width = w;
canvas.height = h;
function redo() { renderForms(this,ctx,forms); }
2013-03-12 18:06:47 +00:00
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
console.log(forms);
renderForms(redo,ctx,forms);
2013-03-12 18:06:47 +00:00
return canvas;
}
canvas.innerHTML = "Your browser does not support canvas.";
2013-03-12 18:06:47 +00:00
return canvas;
}
function collageElement(w, h, m, elem) {
var e = Render.render(elem);
var matrix = 'matrix(' + m[0] + ',' + m[3] + ',' + m[1] + ',' +
m[4] + ',' + m[2] + ',' + m[5] + ')';
addTransform(e.style, matrix);
var div = newElement('div');
addTo(div,e);
div.style.width = (w|0) + "px";
div.style.height = (h|0) + "px";
div.style.overflow = "hidden";
return div;
2013-03-12 18:06:47 +00:00
}
function render(model) {
console.log(model);
return collageForms(model.w, model.h, model.forms);
2013-03-12 18:06:47 +00:00
}
return { render:render };
2013-03-12 18:06:47 +00:00
};