Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validating value in HTML number input with Konva

I'm developing a website that can draw graphs using konva, but I'm currently running into this weird problem:

If I change the unit per tick to anything other than *.5 or an integer, it will become something like this:

enter image description here

Here's the code:

https://codepen.io/ItsTheWolf/pen/jrdkNX

var stage, axeslayer, gridslayer, axes, grids, errTxt;
var w, h;
var linex, liney;
var centx, centy;
var maxx, maxy, miny;
var x, y;
var distx, disty;
var i, j;
var tg = 1, err = 0;
document.getElementById('togG').disabled = true; // disable button Toggle Grids

function draw() {
    getValues(); // get values from input box
    createStage(); // create stage
    validate();
    if (err === 0) {
        drawAxes(); // draw axes
        drawGrids(); // draw grids
    } else {
        displayErr(); // display error message if validation failed
    }
}

function getValues() {
    w = parseFloat(document.getElementById('w').value); // get value for Konva.Stage width, convert to float
    h = parseFloat(document.getElementById('h').value); // get value for Konva.Stage height, convert to float
    maxy = parseFloat(document.getElementById('by').value); // get value for maximum number of y, convert to float
    miny = parseFloat(document.getElementById('sy').value); // get value for minimum number of y, convert to float
    upty = parseFloat(document.getElementById('upty').value); // get value for unit per tick of y axis, convert to float
    maxx = parseFloat(document.getElementById('bx').value); // get value for maximum number of x, convert to float
    minx = parseFloat(document.getElementById('sx').value); // get the value for minimum number of x, convert to float
    uptx = parseFloat(document.getElementById('uptx').value); // get value for unit per tick of x axis, convert to float
}

function validate() {
    if (minx < 0 || upty <= 0 || uptx <= 0 || upty > maxy - miny || uptx > maxx - minx) {
        err = 1;
    } else {
        err = 0;
    }
}

function createStage() {
    stage = new Konva.Stage({
        container: 'container',
        width: w,
        height: h
    });
}

function drawAxes() {
    axeslayer = new Konva.Layer();

    axes = new Konva.Shape({
        sceneFunc: function (ctx) {
            linex = stage.getWidth() - 70; // length of x axis
            liney = stage.getHeight() - 40; // length of y axis

            //count the elements on x axis
            j = 0;
            for (x = minx; x <= maxx; x = x + uptx) {
                j++;
            }

            // count the elements on y axis
            i = 0;
            for (y = miny; y <= maxy; y = y + upty) {
                i++;
            }

            distx = linex / (j - 1); // distance between the elements on x axis
            disty = liney / (i - 1); // distance between the elements on y axis

            // draw y axis
            ctx.beginPath();
            ctx.strokeStyle = '#888';
            ctx.moveTo(20, 20);
            ctx.lineTo(20, stage.getHeight() - 20);
            ctx.stroke();
            ctx.closePath();

            // draw elements of y axis
            i = 0;
            for (y = maxy; y >= miny; y = y - upty) {
                i++; //count the elements on y axis
                posy = disty * i - (disty - 20); // position of elements on y axis

                ctx.fillText(y, 0, posy);

                // draw x axis at y = 0
                if (y === 0) {
                    ctx.beginPath();
                    ctx.strokeStyle = '#888';
                    ctx.moveTo(20, posy);
                    ctx.lineTo(stage.getWidth() - 50, posy);
                    ctx.stroke();
                    ctx.closePath();
                    j = 0;
                    for (x = minx; x <= maxx; x = x + uptx) {
                        j++; //count the elements on x axis
                        posx = distx * j - (distx - 20); // position of elements on y axis

                        ctx.fillText(x, posx + 5, posy + 10);
                    }
                }
            }
        }
    });
    axeslayer.add(axes);
    stage.add(axeslayer);
    document.getElementById('togG').disabled = false;
}

function drawGrids() {
    gridslayer = new Konva.Layer();

    grids = new Konva.Shape({
        sceneFunc: function (ctx) {
            ctx.strokeStyle = '#ddd';

            // draw lines of y axis
            i = 0;
            for (y = maxy; y >= miny; y = y - upty) {
                i++; //count the elements on y axis
                posy = disty * i - (disty - 20); // position of elements on y axis

                ctx.beginPath();
                ctx.moveTo(20, posy);
                ctx.lineTo(stage.getWidth() - 50, posy);
                ctx.stroke();
                ctx.closePath();
            }

            // draw lines of x axis
            j = 0;
            for (x = 0; x <= maxx; x = x + uptx) {
                j++; //count the elements on x axis
                posx = distx * j - (distx - 20); // position of elements on x axis

                ctx.beginPath();
                ctx.moveTo(posx, 20);
                ctx.lineTo(posx, stage.getHeight() - 20);
                ctx.stroke();
                ctx.closePath();
            }
        }
    });
    gridslayer.add(grids);
    stage.add(gridslayer);
}

function toggleGrids() {
    if (tg === 1) {
        gridslayer.clear();
        tg = 0;
    } else if (tg === 0) {
        gridslayer.add(grids);
        stage.add(gridslayer);
        tg = 1;
    }
}

function displayErr() {
    error = new Konva.Layer();

    errTxt = new Konva.Shape({
        sceneFunc: function(ctx) {
            ctx.fillText("There's an error in the input field, please recheck." , stage.getHeight() / 2, 50);
        }
    });
    error.add(errTxt);
    stage.add(error);
}

Here's the HTML5 code if it helps:

<body>
    <table width="100%">
        <tr>
            <td width="25%">Width : <input type="number" id="w" value ="500"/></td>
            <td width="25%">Height : <input type="number" id="h" value ="200"/></td>
            <td width="25%"></td>
            <td width="25%"></td>
        </tr>
        <tr>
            <td width="25%">Max y : <input type="number" id="by" value ="2.5"/></td>
            <td width="25%">Min y : <input type="number" id="sy" value ="-0.5"/></td>
            <td width="25%">Unit per ticks y : <input type="number" id="upty" value ="0.5"/></td>
            <td width="25%"></td>
        </tr>
        <tr>
            <td width="25%">Max x : <input type="number" id="bx" value ="400"/></td>
            <td width="25%">Min x : <input type="number" id="sx" value ="0" min="0"/></td>
            <td width="25%">Unit per ticks x : <input type="number" id="uptx" value ="100"/></td>
            <td width="25%"><button onclick="draw();">Change</button><br/></td>
        </tr>
    </table>
    <div id="container"></div>
    <button onclick="toggleGrids();" id="togG" disabled>Toggle Grid</button><br/>
</body>

Also, is there a way to check if the value in input type = "number" is empty or just weird (like when a user inputs 0-5) then set err = 1? I tried something like minx === null and minx.length === 0 but it doesn't work.

like image 600
ItsTheWolf Avatar asked Nov 08 '22 07:11

ItsTheWolf


1 Answers

That is because of Javascript float division. All you need is to convert your "y" axis label to fixed:

 ctx.fillText(y.toFixed(1), 0, posy);

https://codepen.io/lavrton/pen/LRqaJr

This questions may help you:

  • Division of float numbers in JavaScript
  • How to use division in JavaScript
like image 97
lavrton Avatar answered Nov 14 '22 22:11

lavrton