JSFiddle - React, Tailwind, and code Playground

by rgendron

HTML

<svg width="600" height="500" style="display:none">
  <marker id="triangle" viewBox="0 0 10 10" refX="0" refY="5" markerUnits="strokeWidth" markerWidth="4" markerHeight="3" orient="auto">
    <path d="M 0 0 L 10 5 L 0 10 z" />
  </marker>
  <marker id="triangle2" markerWidth="8" markerHeight="6" refX="10" refY="5" viewBox="0 0 10 10" orient="auto">
    <path id="SvgjsPath1019" d="M0 0L10 5L0 10Z "></path>
  </marker>

  <path id="test" stroke-width="1px" fill="none" stroke="#000" marker-end="url(#triangle2)"></path>
  <g id="xfoo" class="highcharts-series highcharts-series-0 highcharts-tracker" transform="translate(0,0) scale(1 1)" style="">
    <path fill="rgb(149,206,255)" d="M 95 0         L 285 0                  285 0                  285 154.73274458755486 95 154.73274458755486 95 0 Z" stroke="#FFFFFF" stroke-width="1"></path>
    <path fill="#434348" d="M 95 154.73274458755486 L 285 154.73274458755486 285 208.32749053450885 95 208.32749053450885 Z" stroke="#FFFFFF" stroke-width="1"></path>
    <path fill="#90ed7d" d="M 95 208.32749053450885 L 285 208.32749053450885 285 240.74561790088165 95 240.74561790088165 Z" stroke="#FFFFFF" stroke-width="1"></path>
    <path fill="#f7a35c" d="M 95 240.74561790088165 L 285 240.74561790088165 285 273.16374526725446 95 273.16374526725446 Z" stroke="#FFFFFF" stroke-width="1"></path>
    <path fill="#8085e9" d="M 95 273.16374526725446 L 285 273.16374526725446 285 305.58187263362726 95 305.58187263362726 Z" stroke="#FFFFFF" stroke-width="1"></path>
    <path fill="#f15c80" d="M 95 305.58187263362726 L 285 305.58187263362726 285 338.00000000000006 95 338.00000000000006 Z" stroke="#FFFFFF" stroke-width="1"></path>
  </g>
  <g id="g2"></g>

</svg>

<svg version="1.1" style="font-family:&quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Arial, Helvetica, sans-serif;font-size:12px;" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
  <marker id="triangle2" markerWidth="8" markerHeight="6" refX="10" refY="5"...

JavaScript

(function() {

  var Funnel = function(g_el, data) {
    this.el = $(g_el);
    this.paths = this.el.children('path');
    var that = this;

    this.levels = jQuery.map(this.paths, function(path, i) {
      return new Level(path, that, i)
    });

    this.connections = [];
    //['Created', 932821,[1]];
    this.init = function() {
      data.forEach(function(d, l1_i) {
        d[2].forEach(function(l2_i) {
            that.connect(l1_i, l2_i, (Math.round(data[l2_i][1]/data[l1_i][1] *1000))/10 + '%')
          })
          //
      })
     this.optimize_connections()
    }
    this.connect = function(l1i, l2i, text) {
      text = text || '87%'
      new GatedConnection(this.levels[l1i], this.levels[l2i], text)
    }

    this.draw_connections = function() {
      this.connections.forEach(function(c) {
        c.draw()
      })
    }

    this.optimize_connections = function() {
      this.levels.forEach(function(le, li, la) {
        le.gates.optimize_locations()
        le.gates.optimize_connection_lengths()
        console.log("Optimizing :" + li)
      })
      this.draw_connections()
    }

    this.init();
  }


  var Level = function(path_el, funnel, index) {
    this.el = $(path_el);
    this.funnel = funnel;
    this.index = index;
    this.g_el = funnel.el;
    this.d_arr = this.el.attr('d').split(/\s+/);
    this.x1 = +(this.d_arr[1]);
    this.x2 = +(this.d_arr[4]);
    this.y1 = +(this.d_arr[2]);
    this.y2 = +(this.d_arr[9]);
    this.mid_y = this.y1 + (this.y2 - this.y1) / 2;

    //this.gates_l = new GateList('left');
    //this.gates_r = new GateList('right');
    this.gates = new LevelGates(this)
    this.gates_l = this.gates.left
    this.gates_r = this.gates.right
      /*
      this.optimal_gate_loc = function(side) {
        if (this.gates_r.empty() && (side != 'left')) {
          return [this.gates_r.optimal(), 'right'];
        } else if (this.gates_l.empty() || this.gates_r.full() || side == 'left') {
          return...