block by nitaku ddd57089ef8fc757c4ae59489b2059c9

Vue.js Matrix Component

Full Screen

This example uses Vue.js components to create a custom tag for a simple matrix diagram.

index.js

// Generated by CoffeeScript 1.10.0
(function() {
  var app;

  Vue.component('matrix', {
    props: {
      data: {
        type: Array,
        required: true
      },
      padding: {
        type: Number,
        "default": 1
      },
      cellsize: {
        type: Number,
        "default": 20
      }
    },
    template: '<svg :width="ncols*cellsize" :height="nrows*cellsize" class="matrix">\n  <g v-for="(row,i) in data">\n    <rect\n      v-for="(cell,j) in row"\n      class="cell"\n      :x="j*cellsize + cellsize/2 - scale(cell)/2"\n      :y="i*cellsize + cellsize/2 - scale(cell)/2"\n      :width="scale(cell)"\n      :height="scale(cell)"\n    />\n  </g>\n</svg>',
    computed: {
      max: function() {
        return d3.max(this.data, function(r) {
          return d3.max(r);
        });
      },
      nrows: function() {
        return this.data.length;
      },
      ncols: function() {
        if (this.data.length > 0) {
          return this.data[0].length;
        } else {
          return 0;
        }
      },
      scale: function() {
        return d3.scaleSqrt().domain([0, this.max]).range([0, Math.max(0, this.cellsize - this.padding)]);
      }
    }
  });

  app = new Vue({
    el: '#app',
    data: {
      matrix1: [[1, 2, 3], [4, 5, 6], [9, 9, 9]],
      matrix2: [[12, 24, 35], [45, 15, 60], [60, 60, 60]]
    }
  });

}).call(this);

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Vue.js Matrix Component</title>
  <link type="text/css" href="index.css" rel="stylesheet"/>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
  
  <div id="app">
    <matrix
      v-bind:data="matrix1"
      :cellsize="60"
    />
    <matrix
      v-bind:data="matrix2"
      :cellsize="40"
      :padding="2"
    />
  </div>
  
  <script src="index.js"></script>
</body>
</html>

index.coffee

Vue.component 'matrix',
  props:
    data:
      type: Array
      required: true
    padding:
      type: Number
      default: 1
    cellsize:
      type: Number
      default: 20
  template: '''
    <svg :width="ncols*cellsize" :height="nrows*cellsize" class="matrix">
      <g v-for="(row,i) in data">
        <rect
          v-for="(cell,j) in row"
          class="cell"
          :x="j*cellsize + cellsize/2 - scale(cell)/2"
          :y="i*cellsize + cellsize/2 - scale(cell)/2"
          :width="scale(cell)"
          :height="scale(cell)"
        />
      </g>
    </svg>
  '''
  computed:
    max: () -> d3.max @data, (r) -> d3.max r
    nrows: () -> @data.length
    ncols: () -> if @data.length > 0 then @data[0].length else 0
    scale: () ->
      d3.scaleSqrt()
        .domain [0, @max]
        .range [0, Math.max(0,@cellsize-@padding)]

app = new Vue
  el: '#app'
  data:
    matrix1: [
      [1,2,3],
      [4,5,6],
      [9,9,9]
    ],
    matrix2: [
      [12,24,35],
      [45,15,60],
      [60,60,60]
    ]
  

index.css

body, html {
  padding: 0;
  margin: 0;
  height: 100%;
}
.matrix {
  margin: 20px;
}
.cell {
  fill: teal;
}