SOURCE

class Nodes{
    nodeList = [];
    p = null;
    constructor(p){
        this.p = p;
    }
    add(node){
        this.nodeList.push(node);
    }
    draw(){
        let drawList = [];
        this.nodeList.forEach(
            item => {
                let draws = item.draw({
                    width: this.p.width,
                    height: this.p.height
                });
                drawList = drawList.concat(draws);
            }
        )
        drawList.forEach(
            item => {
                if(this.p[item.use]){
                    this.p[item.use].apply(this.p , item.args || []);
                }
            }
        )
    }
    remove(index){
        this.nodeList.splice(index , 1);
    }

    removeById(id){
        this.nodeList.forEach(
            (item , index) => {
                this.nodeList.splice(index , 1);
            }
        )
    }

    findNodeById(id){
        let node = null;
        this.nodeList.forEach(
            item => {
                if(item.id == id){
                    node = item;
                }
            }
        )
        return node;
    }
    findNodeByPoint(x , y){
        let node = null;
        this.nodeList.forEach(
            item => {
                if(item.x == x && item.y == y){
                    node = item;
                }
            }
        )
        return node;
    }
}

class MiCanvas{

    nodes = null;
    width = 400;
    height = 400;

    p = null;
    pInstan = null;

    constructor(opts){
        opts = opts || {};
        var self = this;
        this.pInstan = new p5(function(p){
            self.p = p;
        });

        this.nodes = new Nodes(this.p);

        this.width = opts.width || 400;
        this.height = opts.height || 400;

        this.p.setup = function(){
            this.p.createCanvas(this.width , this.height);
        }.bind(this)
        this.p.draw = function(){
            this.nodes.draw();
        }.bind(this);
    }
    
}

class NodeBaseStyles{
    zIndex = 0;
    x = 0;
    y = 0;
    fill = '#fff';
    stroke = '#000';
    constructor(opts){
        if(opts && typeof opts === 'object'){
            Object.keys(opts).forEach(
                key => {
                    if(this[key] !== undefined){
                        this[key] = opts[key];
                    }
                }
            );
        }
    }
}

class Node{

    styles = new NodeBaseStyles();

    type = 'node';
    id = '';
    __drwaList__ = [];
    updated = false;
    p = null;

    constructor(){

    }

    update(opts){
        this.styles = new NodeBaseStyles(opts);
        this.__drwaList__ = [];
        this.updated = true;
    }

    draw(p){
        this.p = p;
        if(this.updated){
            this.updated = false;
            this.calculation();
        }
        return this.__drwaList__;
    }

    calculation(){

    }

    addDraw(use , args){
        let argument = [];
        if(use && args && (args instanceof Array)){
            argument = [use].concat(args);
        }else{
            argument = Array.prototype.slice.call(arguments);
        }
        this.__drwaList__.push({
            use: argument.shift(),
            args: argument
        });
        return this;
    }

}

class Polygon extends Node{

    points = [];
    type = "polygon";

    constructor(opts){
        super();
        this.update(opts);
        this.points = opts.points || [];
        this.id = opts.id || ('Node-' + Date.now());
    }

    calculation(){
        if(this.points && this.points.length >= 2){

            this.addDraw('fill' , this.styles.fill)
            .addDraw('stroke' , this.styles.stroke)
            .addDraw('beginShape');

            for(let i = 0; i <= this.points.length; i++){
                let p = this.points[i % this.points.length];
                this.addDraw('vertex' , p.x , p.y);
            }

            this.addDraw('endShape');

        }
    }
    

}
console 命令行工具 X clear

                    
>
console