#codevember 13 - Geometry

A simpler way to draw shapes on canvas. Based on math geometries, this is a part of my future framework for drawing on canvas with js. What is a #codevember 13 - geometry How do you make a #codevember 13 - geometry? This script and codes were developed by Pedro Cacique on 24 January 2022, Monday.

How do I make an #codevember 13 - geometry?
  1. #codevember 13 - Geometry Previews
  2. #codevember 13 - Geometry HTML Codes
  3. #codevember 13 - Geometry CSS Codes
  4. #codevember 13 - Geometry JS Codes
#codevember 13 - Geometry Previews

#codevember 13 - Geometry HTML Codes

<!DOCTYPE html>
<html >
<head>
  <meta charset="UTF-8">
  <title>#codevember 13 - Geometry</title>
  
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>
  <canvas id="canvas"></canvas>
    <section>
        <h1>Geometry Pack</h1>
        <h2>Shape:</h2>
        <p>Determines a visible object, described by a specific geometry. Attributes:</p>
        <ul>
            <li>Geometry - <b>Point, Rect, Rectangle, Circle, Polygon, Heart</b></li>
            <li>Position - <b>Point</b> element</li>
            <li>Color - <b>Color</b> or <b>Gradient</b> element</li>
            <li>Properties:
                <ul>
                    <li>lineColor</li>
                    <li>lineWidth</li>
                    <li>scale</li>
                    <li>decay</li>
                </ul>
            </li>
        </ul>
        <p>Methods:</p>
        <ul>
            <li>setProperties(properties)</li>
            <li>draw(canvas)</li>
        </ul>
        <p>Example:</p>
        <p style="font-family: 'Courier New'">var star = new Shape(new Polygon(50, 5, true), new Point(0, 0), new Color(0, 0, 255, 1));<br>
        star.draw(canvas);</p>
        
        <h2>Geometries:</h2>
        <h3>Point:</h3>
        <p>2D Spatial point. Attributes:</p>
        <ul>
            <li>x</li>
            <li>y</li>
        </ul>
        <p>Methods:</p>
        <ul>
            <li>add(p2) - add another point to the current one and return a copy</li>
            <li>distance(p2) - return the euclidean distance from the current to the other point</li>
            <li>manhatan(p2) - return the manhatan distance from the current to the other point</li>
            <li>multiply(p2) - multiply the current point by another and return a copy</li>
            <li>isNear(p2, offset) - verify if the distance of two points is less than the offset</li>
        </ul>

        <h3>Rect:</h3>
        <p>Rect between two points. Attributes:</p>
        <ul>
            <li>p1 - start point</li>
            <li>p2 - end point</li>
        </ul>
        <p>Methods:</p>

        <ul>
            <li>getX(y) - calculate the new X, given Y</li>
            <li>getY(x) - calculate the new Y, given X</li>
            <li>isParallel(r2) - check if r2 is parallel to the current rect</li>
        </ul>
        
        
        <h3>Circle:</h3>
        <p>Circle geometry. Attributes:</p>
        <ul>
            <li>radius</li>
        </ul>
        <p>Methods:</p>

        <ul>
            <li>getPositionByX(x) - calculate the Y value and return a point </li>
            <li>getPositionByAngle(angle) - calculate the X and Y values and return a point </li>
        </ul>
        
        
        <h3>Rectangle:</h3>
        <p>Rectangle geometry. Attributes:</p>
        <ul>
            <li>width</li>
            <li>height</li>
        </ul>
        
        
        <h3>Polygon:</h3>
        <p>Polygon geometry. Attributes:</p>
        <ul>
            <li>isStar - true to draw a star or false to draw a polygon</li>
            <li>radius - radius of the container circle</li>
            <li>innerRadius - radius of the middle circle</li>
            <li>points - points of the star or sides of the polygon</li>
        </ul>
        
        
        
        <h3>Heart:</h3>
        <p>Heart geometry.</p>
        
        <p>Methods:</p>

        <ul>
            <li>getPositionByAngle(angle) - calculate the X and Y values and return a point </li>
        </ul>
        
        
        <h2>Colors</h2>
        <h3>Color</h3>
        <p>Simple color element. Attributes:</p>
        <ul>
            <li>r - Red channel (0 - 255)</li>
            <li>g - Green channel (0 - 255)</li>
            <li>b - Blue channel (0 - 255)</li>
            <li>a - Alpha channel (0 - 1)</li>
        </ul>
        <p>Methods:</p>
        <ul>
            <li>toHex - convert channels to hexadecimal value</li>
            <li>toRGBA - return string of rgba values</li>
            <li>setHex - recieve an hex value and set the new color</li>
        </ul>
        
        <h3>Gradient</h3>
        <p>Gradient color element. Attributes:</p>
        <ul>
            <li>rect - Rect element to represent the linear direction or the center points fo the radial gradient circles</li>
            <li>colors - array of Color elements</li>
            <li>radius1 - radius of the inner circle (optional)</li>
            <li>radius2 - radius of the out circle (optional)</li>
            
        </ul>
        <p>Methods:</p>
        <ul>
            <li>addColor(color) - add a color to the colors array</li>
            <li>getGradient() - return the gradient element for painting in canvas</li>
        </ul>

        <h2>GenericObject</h2>
        <p>Every element is child of the Generic Object. That allow you to clone an object without breaking references, get an String that represent it, trace it on console and compare it with another object.</p>
    </section>
    <footer>
        <span>made by <a href="http://www.pedrocacique.com"><img alt="avatar" src="https://scontent.fcgh7-1.fna.fbcdn.net/t31.0-8/p960x960/11958099_10200916172781826_3235614628416290419_o.jpg"/></a>
            </span>
    </footer>
  
    <script src="js/index.js"></script>

</body>
</html>

#codevember 13 - Geometry CSS Codes

html, body{height: 100%;}
body {
    margin: 0;
    font-family: Helvetica, Arial;
    font-weight: 100;
    overflow: hidden;
}

canvas {
    background-color: rgb(244, 244, 244);
}

section{
    padding: 10px;
    overflow: auto;
    height: 45%;
}

footer{
    position: fixed;
    top:50%;
    width: 100%;
}

footer img{
    border-radius: 100%;
    width: 30px;
    height: 30px;
    margin-left: 10px;
}
footer span{
    display: block;
    padding: 10px;
    display: flex;
    justify-content: flex-end;
    align-items: center;
}

#codevember 13 - Geometry JS Codes

//---------- MAIN FUNCTION ----------
function init() {

    //-- CIRCLE --
    var grd1 = new Gradient([], new Rect(new Point(cw / 4, ch / 4), new Point(cw / 4 , ch / 4)), 1, 50);
    grd1.addColor(new Color(81, 157, 239, 1));
    grd1.addColor(new Color(97, 117, 137, 1));

    var circle = new Shape(new Circle(10), new Point(cw / 4, ch / 4), grd1, {
        scale: 4
    });
    circle.draw(canvas);

    //-- HEART --
    var grd = new Gradient([], new Rect(new Point(cw / 2 - 10, ch / 4), new Point(cw / 2 + 50, ch / 4)));
    grd.addColor(new Color(173, 60, 15, 1));
    grd.addColor(new Color(229, 140, 105, 1));

    var heart = new Shape(new Heart(), new Point(cw / 2, ch / 4), grd, {
        scale: 3
    });
    heart.draw(canvas);

    //-- Rectangle --
    var rectangle = new Shape(new Rectangle(100, 50), new Point(3 * cw / 4 - 50, ch / 4 - 25), new Color(135, 206, 130, 1));
    rectangle.draw(canvas);

    //-- Polygon: Triangle --
    var rectangle = new Shape(new Polygon(50, 3), new Point(cw / 4, 3 * ch / 4), new Color(62, 74, 188, 1));
    rectangle.draw(canvas);

    //-- Polygon: Star --
    var star = new Shape(new Polygon(50, 5, true), new Point(cw / 2, 3 * ch / 4), new Color(242, 173, 55, 1));
    star.draw(canvas);

    //-- Polygon --
    var star = new Shape(new Polygon(50, 10), new Point(3 * cw / 4, 3 * ch / 4), new Color(191, 131, 193, 1));
    star.draw(canvas);
}

//-----------------------------------
var canvas, ctx, cw, ch;
var FPS = 60;

var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
    return setTimeout(callback, FPS);
};

window.onload = function () {
    initCanvas();
    ctx.clearRect(0, 0, cw, ch);
    init();

}
window.onresize = function () {
    initCanvas();
    ctx.clearRect(0, 0, cw, ch);
    init();
};

function initCanvas() {
    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d');
    cw = window.innerWidth;
    ch = window.innerHeight / 2;
    canvas.width = cw;
    canvas.height = ch;
}

//---------------- APP UTIL ------------------
function getRandomNumber(min, max) {
    return Math.random() * (max - min + 1) + min;
}


//---------- MY FRAMEWORK ------------
//----------- PROTOTYPES -------------

//===== GEOMETRY =====

//----- SHAPE -----
function Shape(geometry, position, color, properties) {
    this.position = (position == null || position.classname != "Point") ? new Point() : position;
    this.geometry = (geometry == null || geometry.constructor.name != "GenericObject") ? new Circle() : geometry;
    this.color = (color != null && geometry.constructor.name == "GenericObject" && ((color.classname == "Color") || color.classname == "Gradient")) ? color : null;
    this.lineColor = null;
    this.lineWidth = 1;
    this.scale = 1;
    this.decay = 0;
    if (properties != null) this.setProperties(properties);
    GenericObject.call(this, "Shape");
}
Shape.prototype = new GenericObject();
Shape.prototype.setProperties = function (properties) {
    for (var p in properties) {
        this[p] = properties[p];
    }
}
Shape.prototype.draw = function (canvas) {
    if (this.scale > 0) {
        var ctx = canvas.getContext('2d');
        var cw = canvas.width;
        var ch = canvas.height;

        ctx.beginPath();
        if (this.lineWidth > 0 && (this.lineColor != null && (this.lineColor.classname == "Color" || this.lineColor.classname == "Gradient"))) {
            ctx.strokeStyle = (this.lineColor.classname == "Color") ? this.lineColor.toRGBA() : this.lineColor.getGradient();
            ctx.lineWidth = this.lineWidth;
        }
        if (this.color != null && (this.color.classname == "Color" || this.color.classname == "Gradient")) {
            ctx.fillStyle = (this.color.classname == "Color") ? this.color.toRGBA() : this.color.getGradient();
        }

        switch (this.geometry.classname) {
        case "Circle":
            ctx.arc(this.position.x, this.position.y, this.geometry.radius * this.scale, 0, Math.PI * 2);
            break;
        case "Rectangle":
            ctx.rect(this.position.x, this.position.y, this.geometry.width * this.scale, this.geometry.height * this.scale);
            break;
        case "Rect":
            ctx.moveTo(this.position.x, this.position.y);
            ctx.lineTo(this.geometry.p2.x * this.scale, this.geometry.p2.y * this.scale);
            break;
        case "Heart":
            for (var i = 0; i < Math.PI * 2; i += 0.05) {
                var p = this.geometry.getPositionByAngle(i);
                p.multiply(this.scale);
                p.add(this.position);
                if (i == 0) ctx.moveTo(p.x, p.y);
                else ctx.lineTo(p.x, p.y);
            }
            break;
        case "Polygon":
            var step = Math.PI * 2 / this.geometry.points;
            var angle = -Math.PI / 2;
            this.geometry.circle.radius *= this.scale;
            this.geometry.innerCircle.radius *= this.scale;
            for (var i = 0; i <= this.geometry.points; i++) {
                var p = this.geometry.circle.getPositionByAngle(angle);
                var p2 = this.geometry.innerCircle.getPositionByAngle(angle - step / 2);
                angle += step;
                if (i == 0) ctx.moveTo(this.position.x + p.x, this.position.y + p.y);
                else {
                    if (this.geometry.isStar) {

                        ctx.lineTo(this.position.x + p2.x, this.position.y + p2.y);
                    }
                    ctx.lineTo(this.position.x + p.x, this.position.y + p.y);
                }
            }
            break;
        }

        if (this.lineColor != null && this.lineColor.classname == "Color") ctx.stroke();
        if (this.color != null) ctx.fill();
        this.scale -= this.decay;
    }
}

//----- POINT -----
function Point(x, y) {
    this.x = (x != null && !isNaN(x)) ? x : 0;
    this.y = (y != null && !isNaN(y)) ? y : 0;
    GenericObject.call(this, "Point");
}
Point.prototype = new GenericObject();
Point.prototype.add = function (p2) {
    if (p2.classname != this.classname) return null;
    this.x += p2.x;
    this.y += p2.y;
    return this;
}
Point.prototype.distance = function (p2) {
    if (p2.classname != this.classname) return null;
    //Euclidean Disctance
    return Math.sqrt(Math.pow(this.x - p2.x, 2) + Math.pow(this.y - p2.y, 2) + Math.pow(this.z - p2.z, 2));
}
Point.prototype.manhatan = function (p2) {
    if (p2.classname != this.classname) return null;
    return (p2.x - p1.x) + (p2.y - p1.y) + (p2.z - p1.z);
}
Point.prototype.multiply = function (scale) {
    this.x *= scale;
    this.y *= scale;
    return this;
}
Point.prototype.isNear = function (p2, offset) {
    if (p2.classname != this.classname) return false;
    return (this.x > p2.x - offset && this.x < p2.x + offset && this.y > p2.y - offset && this.y < p2.y + offset)
}

//----- RECT -----
function Rect(p1, p2) {
    this.p1 = (p1 == null || p1.classname != "Point") ? new Point() : p1;
    this.p2 = (p2 == null || p2.classname != "Point") ? new Point(10, 0) : p2;
    this.m = (this.p2.y - this.p1.y) / (this.p2.x - this.p1.x);
    this.n = this.p2.y - this.m * this.p2.x;
    GenericObject.call(this, "Rect");
}
Rect.prototype = new GenericObject();
Rect.prototype.getX = function (y) {
    if (y == null || isNaN(y)) return null;
    return (y - this.n) / this.m;
}
Rect.prototype.getY = function (x) {
    if (x == null || isNaN(x)) return null;
    return this.m * x + this.n;
}
Rect.prototype.isParallel = function (r2) {
    if (r2.classname != this.classname) return false;
    else return this.m == r2.m;
}

//----- CIRCLE -----
function Circle(radius) {
    this.center = new Point();
    this.radius = (radius != null && !isNaN(radius)) ? radius : 1;
    GenericObject.call(this, "Circle");
}
Circle.prototype = new GenericObject();
Circle.prototype.getPositionByX = function (x) {
    if (x == null || isNaN(x)) return null;
    else return new Point(x, Math.sqrt(Math.pow(this.radius, 2) - Math.pow(x, 2)));
}
Circle.prototype.getPositionByAngle = function (angle) {
    if (angle == null || isNaN(angle)) return null;
    var x = this.center.x + this.radius * Math.cos(angle);
    var y = this.center.y + this.radius * Math.sin(angle);
    return new Point(x, y);
}

//----- RECTANGLE -----
function Rectangle(width, height) {
    this.width = (width != null && !isNaN(width)) ? width : 1;
    this.height = (height != null && !isNaN(height)) ? height : this.width;
    GenericObject.call(this, "Rectangle");
}
Rectangle.prototype = new GenericObject();

//----- POLYGON/STAR -----
function Polygon(radius, points, isStar, innerRadius) {
    this.isStar = (isStar != null) ? isStar : false;
    this.radius = (radius != null && !isNaN(radius)) ? radius : 5;
    this.innerRadius = (innerRadius != null && !isNaN(innerRadius)) ? innerRadius : ((isStar) ? (this.radius / 2) : this.radius);
    this.points = (points != null && !isNaN(points)) ? points : 5;
    this.circle = new Circle(this.radius);
    this.innerCircle = new Circle(this.innerRadius);
    GenericObject.call(this, "Polygon");
}
Polygon.prototype = new GenericObject();

//----- HEART -----
function Heart() {
    GenericObject.call(this, "Heart");
}
Heart.prototype = new GenericObject();
Heart.prototype.getPositionByAngle = function (angle) {
    if (angle == null || isNaN(angle)) return null;
    var x = 16 * Math.pow(Math.sin(angle), 3);
    var y = -(13 * Math.cos(angle) - 5 * Math.cos(2 * angle) - 2 * Math.cos(3 * angle) - Math.cos(4 * angle));
    return new Point(x, y);
}


//===== COLOR =====
//----- Color -----
function Color(r, g, b, a) {
    this.r = (r != null && !isNaN(r)) ? r : 0;
    this.g = (g != null && !isNaN(g)) ? g : 0;
    this.b = (b != null && !isNaN(b)) ? b : 0;
    this.a = (a != null && !isNaN(a)) ? a : 1;
    this.hex = this.toHex();
    GenericObject.call(this, "Color");
}
Color.prototype = new GenericObject();
Color.prototype.toHex = function () {
    var bin = this.r << 16 | this.g << 8 | this.b;
    return (function (h) {
        return "#" + new Array(7 - h.length).join("0") + h
    })(bin.toString(16).toUpperCase())
}
Color.prototype.toRGBA = function () {
    return "rgba(" + this.r + "," + this.g + "," + this.b + "," + this.a + ")";
}
Color.prototype.setHex = function (hex) {
    this.r = hex >> 16;
    this.g = hex >> 8 & 0xFF;
    this.b = hex & 0xFF;
    this.hex = this.toHex();
}

//----- GRADIENT -----
function Gradient(colors, rect, radius1, radius2) {
    this.rect = (rect != null && (rect.constructor.name == "GenericObject" && rect.classname == "Rect")) ? rect : new Rect();
    this.colors = (colors != null && Array.isArray(colors)) ? colors : [];
    this.radius1 = (radius1 == null || isNaN(radius1)) ? 0 : radius1;
    this.radius2 = (radius2 == null || isNaN(radius2)) ? 0 : radius2;
    GenericObject.call(this, "Gradient");
}
Gradient.prototype = new GenericObject();
Gradient.prototype.addColor = function (color) {
    if (color.constructor.name == "GenericObject" && color.classname == "Color") {
        this.colors.push(color);
    }
}
Gradient.prototype.getGradient = function () {
    var grd = null;
    if (this.radius1 == 0 || this.radius2 == 0) {
        grd = ctx.createLinearGradient(this.rect.p1.x, this.rect.p1.y, this.rect.p2.x, this.rect.p2.y);
    } else {
        grd = ctx.createRadialGradient(this.rect.p1.x, this.rect.p1.y, this.radius1, this.rect.p2.x, this.rect.p2.y, this.radius2);
    }
    for (var i = 0; i < this.colors.length; i++) {
        grd.addColorStop(i, this.colors[i].toHex());
    }
    return grd;
}



//===== GENERICOBJECT =====
function GenericObject(name) {
    this.classname = name;
}
GenericObject.prototype.clone = function () {
    var copy = new GenericObject(this.classname);
    for (var attr in this) {
        if (this.hasOwnProperty(attr)) {
            if (this[attr].constructor.name == "GenericObject") copy[attr] = this[attr].clone();
            else copy[attr] = this[attr];
        }
    }
    return copy;
}
GenericObject.prototype.equals = function (obj2) {
    var isEquals = true;
    if (this.classname != obj2.classname) return false;
    for (var attr in this) {
        if (this.hasOwnProperty(attr) && obj2.hasOwnProperty(attr)) {
            if (this[attr].constructor.name == "GenericObject" && obj2[attr].constructor.name == "GenericObject") {
                if (!this[attr].equals(obj2[attr])) isEquals = false;
            } else if (this[attr] != obj2[attr]) isEquals = false;
        }
    }
    return isEquals;
}
GenericObject.prototype.toString = function () {
    var str = this.classname + "{";
    for (var attr in this) {
        if (attr != "classname" && this.hasOwnProperty(attr)) {
            var obj2 = this[attr];
            var substr = "";
            if (obj2.constructor.name == "GenericObject") substr = obj2.toString();
            else substr = this[attr];
            str += attr + ": " + substr + ",";
        }
    }
    str = str.substring(0, str.length - 1);
    str += "}";
    return str;
}
GenericObject.prototype.trace = function () {
    console.log(this.toString())
}
Do you want hide your ip address?Surf anonymously, prevent hackers from acquiring your IP address, send anonymous email, and encrypt your Internet connection. High speed, ultra secure, and easy to use. Instant setup.