JSFiddle - React, Tailwind, and code Playground

HTML

<div style="width: 500px;">
    <div style="display: inline-block; float: left;">
        <div>
            <label>Start</label>
            <label id="matrix_fixes_1" style="color: red" />
        </div>
        <input type="text" id="matrix1" value="1, 0, 0, 1" style="width: 150px;" />
    </div>
    <div style="display: inline-block; float: right;">
        <div>
            <label>End</label>
            <label id="matrix_fixes_2" style="color: red" />
        </div>
        <input type="text" id="matrix2" value="-1, i, i, -1" style="width: 150px;" />
    </div>
</div>
<canvas id="drawCanvas" width="500px" height="200px" />

JavaScript

function complex(r, i) {
    this.r = r;
    this.i = i;
}

var real = function (c) {
    if (c instanceof complex) {
        return c.r;
    }
    return float(c);
};

complex.from = function (c) {
    if (c instanceof complex) {
        return c;
    }
    return new complex(c, 0);
};

complex.prototype.toString = function () {
    return this.r + " + " + this.i + "i";
};

complex.prototype.plus = function (c) {
    c = complex.from(c);
    return new complex(this.r + c.r, this.i + c.i);
};

complex.prototype.minus = function (c) {
    c = complex.from(c);
    return new complex(this.r - c.r, this.i - c.i);
};

complex.prototype.times = function (c) {
    c = complex.from(c);
    return new complex(this.r * c.r - this.i * c.i, this.r * c.i + this.i * c.r);
};

complex.prototype.phase = function () {
    return Math.atan2(this.i, this.r);
};

complex.prototype.dividedBy = function (c) {
    c = complex.from(c);
    var d = c.norm2();
    if (d === 0) throw "Division by Zero";

    var n = this.times(c.conjugate());
    return new complex(n.r / d, n.i / d);
};

complex.prototype.norm2 = function () {
    return this.r * this.r + this.i * this.i;
};

complex.prototype.conjugate = function () {
    return new complex(this.r, -this.i);
};

complex.prototype.unit = function () {
    var m = Math.sqrt(this.norm2());
    if (m < 0.00001) {
        var theta = Math.atan2(this.i, this.r);
        return new complex(Math.cos(theta), -Math.sin(theta));
    }
    return this.dividedBy(m);
};

function quop(v) {
    this.m = [complex.from(v[0]), complex.from(v[1]), complex.from(v[2]), complex.from(v[3])];
}

quop.prototype.toString = function () {
    return "[[" + this.m[0] + ", " + this.m[1] + "], [" + this.m[2] + ", " + this.m[3] + "]]";
};

quop.prototype.adjoint = function () {
    return new quop([this.m[0].conjugate(), this.m[2].conjugate(),
    this.m[1].conjugate(), this.m[3].conjugate()]);
};

quop.prototype.scaledBy = function (s) {
    s = complex.from(s);
   ...