``````<script src="https://unpkg.com/konva@^3/konva.min.js"></script>
<div id="container"></div>
``````
``````body {
margin: 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.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();

// 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();

// 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();
}

// 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.batchDraw();
}

return this;
}
``````

### External CSS

This Pen doesn't use any external CSS resources.

### External JavaScript

This Pen doesn't use any external JavaScript resources.