<script src="https://unpkg.com/konva@^3/konva.min.js"></script>
<div id="container"></div>
body {
  margin: 10;
  padding: 10;
  overflow: hidden;
  background-color: #ffffff;
}
#container {
  border: 1px solid silver;
}
/** Developing a graphing component based on Konva.
*/

// Set up a stage
let stage = new Konva.Stage({
  container: "container",
  width: window.innerWidth,
  height: 400,
  draggable: true
  }),
    
  // add a layer to draw on
  layer = new Konva.Layer();
   
stage.add(layer);
stage.draw();

// Instantiate a vwGraph object and pass it the initial options to draw the grid.
let d = new vwGraph({
  stage: stage,
  origin: {x: 100, y: 250},
  range: {posX: 1000, posY: 1000, negX: -500, negY: -300},
  direction: 'y-dn'
  })

d.drawGrid(50);

function vwGraph(opts){
  
  let origin = opts.origin,
      range = opts.range, stage = opts.stage,
      direction = opts.direction === 'y-up' ? -1 : 1;

  // calculate the width and height of the range
  range.width = range.posX + Math.abs(range.negX);
  range.height = range.posY + Math.abs(range.negY);
  
  // Get a reliable top Y position regardless of direction 
  range.minY = direction === 1 ? range.negY : range.posY;

  // turn a logical x into a physical x
  function getX(x){
    return x + origin.x;
  }
  
  // turn a logical x into a physical x
  function getY(y, msg){
    return origin.y + (direction * y);
  }
  
  // draw the grid
  this.drawGrid = function drawGrid(step){
    let gridLayer = new Konva.Layer({listening: false}),
        ln = new Konva.Line({x: 0, y: 0, points: [], stroke: 'black', strokeWidth: 0.5, listening: false, perfectDrawEnabled: false, transformsEnabled: 'position', shadowEnabled: false, shadowForStrokeEnabled: false }),
        txt = new Konva.Text({x:0, y: 0, width: 40, height: 10, fontSize: 10, fontFamily: 'Calibri', align: 'left', fill: 'black', listening: false, perfectDrawEnabled: false, transformsEnabled: 'position', shadowEnabled: false, shadowForStrokeEnabled: false}),
        ln1 = null, 
        t1 = null;

    // output the x-axis
    ln1 = ln.clone({x: getX(range.negX), y: getY(0), points: [0, 0, range.width, 0], strokeWidth: 1.5});
    ln1.cache();
    gridLayer.add(ln1)
    
    // output the Y axis
    ln1 = ln.clone({x: getX(0), y: getY(range.minY), points: [0, 0, 0, range.height], strokeWidth: 1.5});
    ln1.cache();
    gridLayer.add(ln1)

    // X axis lines & text
    for (let i = 0; i <= range.width; i = i + step ){
      ln1 = ln.clone({ x:  getX(range.negX) + i, y: getY(range.minY), points: [0, 0, 0, range.height]});
      t1 = txt.clone({x:  getX(range.negX) + i - 20, y: getY(0) + 5, text:  range.negX + i, align: 'center'});
      ln1.cache();
      t1.cache();
      gridLayer.add(ln1, t1);      
    }    
 
    // Y axis lines & text
    for (let i = 0; i <= range.height; i = i + step ){
      ln1 = ln.clone({x: getX(range.negX), y: getY(range.minY) + i, points: [0, 0, range.width, 0]});
      t1 = txt.clone({x: getX(10), y: getY(range.minY) + i - 5, text:   range.minY + (direction * i)});      
      ln1.cache();
      t1.cache();
      gridLayer.add(ln1, t1);      
    }    
   
    stage.add(gridLayer);
    gridLayer.batchDraw();
  }  

  return this;
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.