Code:make-flow-diagram1.html
This javascript/HTML canvas generates the "flow diagram" of File:food-funnel.png.
If you want to generate a different flow diagram, you can save your own version of this and modify the draw() function to your liking.
<html><head>
<script>
// This draw() is the main function: Change it according to how you want your diagram:
function draw() {
primary = 5454; // crops harvested
leftStart();
go(5000);
branch(491); // biofuel
go(9000);
branch(493); // food loss
end();
rightStart();
go(5000);
transform(1964,518); // livestock
go(5000);
branch(591); // food waste
go(14000);
merge(252); // for comparison: what would be needed to end global hunger
end();
}
// The rest of these functions are just the "internals" to make it all work:
function ctx_moveTo(x,y) { ctx.moveTo(Math.round(x), Math.round(y)); }
function ctx_lineTo(x,y) { ctx.lineTo(Math.round(x), Math.round(y)); }
function leftStart() { sign = -1; start(); }
function rightStart() { sign = 1; start(); }
function start() {
scale = first/primary;
cursor_x = (width + sign*first)/2;
cursor_y = rim;
ctx.beginPath();
ctx.lineWidth = "2";
ctx.strokeStyle = "#000000";
ctx_moveTo(cursor_x + sign*rim, 0);
ctx_lineTo(cursor_x, rim);
ctx.stroke();
}
function go(distance) {
ctx.beginPath();
ctx_moveTo(cursor_x, cursor_y);
cursor_y += distance*scale;
ctx_lineTo(cursor_x, cursor_y);
ctx.stroke();
}
function branch(thickness) {
ctx.beginPath();
ctx_moveTo(cursor_x, cursor_y);
ctx_lineTo(cursor_x + sign*reach, cursor_y + reach);
ctx_lineTo(sign<0 ? 0:width, cursor_y + reach);
ctx_moveTo(sign<0 ? 0:width, cursor_y + reach + thickness*scale);
ctx_lineTo(cursor_x + sign*reach - sign*thickness*scale*(SQRT2-1),
cursor_y + reach + thickness*scale);
cursor_x -= thickness*scale*sign;
cursor_y += thickness*scale*(SQRT2-1);
ctx_lineTo(cursor_x, cursor_y);
ctx.stroke();
}
function merge(thickness) {
ctx.beginPath();
ctx_moveTo(cursor_x, cursor_y);
ctx_lineTo(cursor_x + sign*reach, cursor_y - reach);
ctx_lineTo(sign<0 ? 0:width, cursor_y - reach);
ctx_moveTo(sign<0 ? 0:width, cursor_y - reach + thickness*scale);
ctx_lineTo(cursor_x + sign*reach + sign*thickness*scale*(SQRT2-1),
cursor_y - reach + thickness*scale);
cursor_x += thickness*scale*sign;
cursor_y += thickness*scale*(SQRT2-1);
ctx_lineTo(cursor_x, cursor_y);
ctx.stroke();
}
function transform(before, after) {
before *= scale; after *= scale;
var dif = before-after; var adif = Math.abs(dif);
ctx.beginPath();
ctx_moveTo(cursor_x - sign*before, cursor_y);
ctx_lineTo(cursor_x - sign*before, cursor_y + adif*3);
ctx_moveTo(cursor_x - sign*dif, cursor_y + adif*3);
ctx_lineTo(cursor_x - sign*dif, cursor_y + adif*2);
ctx_lineTo(cursor_x, cursor_y + adif);
ctx_lineTo(cursor_x, cursor_y);
ctx.stroke();
cursor_x -= sign*(before-after);
cursor_y += adif*3;
}
function end() {
ctx.beginPath();
ctx_moveTo(cursor_x, cursor_y);
cursor_y = height;
ctx_lineTo(cursor_x, cursor_y);
ctx.stroke();
}
function init() {
ctx = document.getElementById("canvas").getContext("2d");
ctx.canvas.height = document.body.clientHeight * 2; // temporary height to get the scrollbar so clientWidth is accurate below
width = ctx.canvas.width = document.body.clientWidth; // fit canvas to width
height= ctx.canvas.height = ctx.canvas.width * 4; // 1:4 aspect ratio
rim = 8; // pixels at the at the top of the diagram ("the rim of the funnel")
first = width * 0.4; // the width of the first part of the diagram ("the primary")
reach = width * 0.1; // how far the branches/merges reach
SQRT2 = Math.sqrt(2); // constant
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, width, height);
draw();
}
</script>
</head><body onload="init()" onresize="init()" style="margin:0;padding:0;text-align:center">
<canvas id="canvas"></canvas>
</body></html>