Code:make-flow-diagram1.html

From the change wiki

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>