График JavaScript реализация скелет


Я приступил к выполнению графической приложение для рисования на JavaScript и < холст > элемент, и я просто хотел услышать ваши мысли на прогресс, до сих пор. Я очень открыт для предложений, и мне очень интересно услышать, что вы должны сказать.
Так что вы можете видеть прогресс в настоящем Кодексе, если у вас возникли вопросы, не стесняйтесь спрашивать.

var graph = {

init: function(edges) {
    graph.vertices = {};
    graph.edges = {};
    graph.canvas = document.getElementById('platno');
    graph.width = graph.canvas.width;
    graph.height = graph.canvas.height;
    graph.hookes_test = true;
    graph.ctx = graph.canvas.getContext('2d');

    document.addEventListener("mousedown", graph.klik, false);
    document.addEventListener("mouseup", graph.drop, false);
    document.addEventListener("dblclick", graph.dblclick, false);
    graph.addNodesFromEdgesList(edges);
    graph.addEdgesFromEdgesList(edges);
    graph.mapEdges(graph.oDuljina);
    setInterval(graph.draw, 1024 / 24);
},
addNodesFromEdgesList: function(EdgesList) {
    for (var r1 = 0; r1 < EdgesList.length; r1++) {
        for (var r2 = 0; r2 < EdgesList[r1].length - 1; r2++) {

            if ((typeof graph.vertices[EdgesList[r1][r2]]) === "undefined") {
                graph.addNode({
                    id: EdgesList[r1][r2],
                    x: Math.floor(graph.width / 2 + 100 * Math.cos(Math.PI * (EdgesList[r1][r2] * 2) / 11)),
                    y: Math.floor(graph.height / 2 + 100 * Math.sin(Math.PI * (EdgesList[r1][r2] * 2 / 11))),
                    size: 6,
                    ostalo: 100
                });
            }
        }
    }
},
addEdgesFromEdgesList: function(EdgesList) {
    for (var a = 0; a < EdgesList.length; a++) {
        graph.addEdge({
            from: EdgesList[a][0],
            to: EdgesList[a][1],
            id: a
        });
    }
},
node: function(node) {
    this.id = node.id;
    this.pos = new vektor(node.x, node.y);
    this.size = node.size;
    this._size = node.size;
    this.expanded = false;
},
addNode: function(node) {
    (typeof graph.vertices[node.id]) === "undefined" ? graph.vertices[node.id] = new graph.node(node) : console.log("Duplikat cvora! Id:" + node.id);
},
removeNode: function(id) {
    if (typeof graph.vertices[id] !== "undefined") {
        graph.removeEdgeByNodeId(id);
        if (id == graph.info_node.id) graph.info_node = false;
        delete graph.vertices[id];
    } else {
        console.log("Ne postoji node! Id:" + id);
    }
},
edge: function(edge) {
    this.id = edge.id;
    this.from = graph.vertices[edge.from];
    this.to = graph.vertices[edge.to];
},
addEdge: function(edge) {
    (typeof graph.edges[edge.id]) === "undefined" ? graph.edges[edge.id] = new graph.edge(edge) : console.log("Duplikat brida! Id:" + edge.id);
},
removeEdgeByEdgeId: function(id) {
    (typeof graph.edges[id]) !== "undefined" ? delete graph.edges[id] : console.log("Ne postoji brid! Id:" + id);
},
removeEdgeByNodeId: function(id) {
    if (typeof graph.vertices[id] !== "undefined") {
        for (var edge in graph.edges) {
            if (graph.edges.hasOwnProperty(edge) && (graph.edges[edge].from.id == id || graph.edges[edge].to.id == id)) {
                delete graph.edges[edge];
            }
        }
    } else {
        console.log("Ne postoji cvor! Id:" + id);
    }

},
clearGraph: function() {
    for (var id in graph.vertices) {
        if (graph.vertices.hasOwnProperty(id)) {
            graph.removeNode(id)
        }
    }
},
mapNodes: function(funkcija, obj) {
    var res = [],
        tmp, id;
    for (id in graph.vertices) {
        if (graph.vertices.hasOwnProperty(id)) {
            tmp = funkcija.apply(graph, [graph.vertices[id], obj || {}]);
            if (tmp) res.push(tmp);
        }
    }
    return res;
},
mapEdges: function(funkcija) {
    for (var id in graph.edges) {
        if (graph.edges.hasOwnProperty(id)) {
            funkcija.apply(graph, [graph.edges[id].from, graph.edges[id].to, graph.edges[id].id]);
        }
    }
},
vuci: function(e) {

    if (graph.drag) {
        graph.drag.pos.x = (e.pageX - graph.canvas.offsetLeft);
        graph.drag.pos.y = (e.pageY - graph.canvas.offsetTop);
        if (graph.drag.pos.x > graph.width - 6) graph.drag.pos.x = graph.width - 6;
        else if (graph.drag.pos.x < 6) graph.drag.pos.x = 6;
        else if (graph.drag.pos.y > graph.height - 6) graph.drag.pos.y = graph.height - 6;
        else if (graph.drag.pos.y < 6) graph.drag.pos.y = 6;
    }

},

klik: function(e) {

    graph.drag = graph.getNodeFromXY(e.pageX - graph.canvas.offsetLeft, e.pageY - graph.canvas.offsetTop)[0];
    document.addEventListener("mousemove", graph.vuci, false);
},
drop: function() {
    graph.drag = false;
    document.removeEventListener("mousemove", graph.vuci, false);
},
getNodeFromXY: function(_x, _y) {

    return graph.mapNodes(function(node, obj) {
        if ((obj.x > node.pos.x - node.size) && (obj.x < node.pos.x + node.size) && (obj.y > node.pos.y - node.size) && (obj.y < node.pos.y + node.size)) {
            return node;
        } else {
            return false
        };

    }, {
        x: _x,
        y: _y
    });

},
draw: function() {

    graph.ctx.clearRect(0, 0, graph.width, graph.height);
    background();
    graph.mapEdges(crtaj_v);
    graph.mapNodes(crtaj_n);
    graph.info();
    if (!graph.hookes_test) graph.mapEdges(graph.hookes);

    function background() {
        var grd = graph.ctx.createRadialGradient(graph.width / 2, graph.height / 2, 30, graph.width / 2, graph.height / 2, graph.height);
        grd.addColorStop(0, "#42586d");
        grd.addColorStop(0.5, "#36495a");
        grd.addColorStop(1, "#26323e");
        graph.ctx.fillStyle = grd;
        graph.ctx.fillRect(0, 0, graph.width, graph.height);

    }

    function crtaj_n(v) {
        graph.ctx.fillStyle = 'rgba(0,0,0,0.4)';
        graph.ctx.beginPath();
        graph.ctx.arc(v.pos.x, v.pos.y, v.size, 0, Math.PI * 2, true);
        graph.ctx.fill();
        graph.ctx.strokeStyle = '#818f9a'
        graph.ctx.arc(v.pos.x, v.pos.y, v.size, 0, Math.PI * 2, true);
        graph.ctx.stroke();
        return false;
    }

    function crtaj_v(v1, v2) {
        graph.ctx.beginPath();
        graph.ctx.strokeStyle = 'rga(129,143,154,0.1)';
        var duljina = [v1.pos.udaljenost(v2.pos) - v1.size, v1.pos.udaljenost(v2.pos) - v2.size];
        var kut = Math.atan2(v2.pos.y - v1.pos.y, v2.pos.x - v1.pos.x);
        graph.ctx.moveTo(v2.pos.x - (duljina[0] * Math.cos(kut)), v2.pos.y - (duljina[0] * Math.sin(kut)));
        graph.ctx.lineTo(v1.pos.x + (duljina[1] * Math.cos(kut)), v1.pos.y + (duljina[1] * Math.sin(kut)));
        graph.ctx.stroke();
    }

},

dblclick: function(e) {
    var dbl = graph.getNodeFromXY(e.pageX - platno.offsetLeft, e.pageY - platno.offsetTop)[0] || false;
    if (dbl.expanded) {
        dbl.size = dbl._size;
        dbl.expanded = false;
        graph.info_node = false;
    } else if (dbl) {
        graph.mapNodes(function(v1) {
            if (v1.expanded) {
                v1.size = v1._size;
                v1.expanded = false;
                graph.info_node = false;
            }
        })
        dbl.size = 30;
        dbl.expanded = true;
        graph.info_node = dbl;
    }
},
info: function() {
    if (graph.info_node) {
        graph.ctx.font = "10px Verdana";
        graph.ctx.textAlign = "center";
        graph.ctx.fillStyle = '#ffffff';
        graph.ctx.fillText("Node: " + graph.info_node.id, graph.info_node.pos.x, graph.info_node.pos.y + 3, 30);
    }

},
hookes: function(v1, v2, id) {
    var duljina = v1.pos.oduzmi(v2.pos),
        udaljenost = duljina.duljina() - (graph.edges[id].duljina),
        HL = 20 * (udaljenost / duljina.duljina()),
        kut = Math.atan2(v2.pos.y - v1.pos.y, v2.pos.x - v1.pos.x);
    (graph.drag && (graph.drag.id != v1.id)) || !graph.drag ? graph.zbrojiLokacija(v1, kut, HL) : false;
    (graph.drag && (graph.drag.id != v2.id)) || !graph.drag ? graph.oduzmiLokacija(v2, kut, HL) : false;

},
oDuljina: function(v1, v2, id) {
    graph.hookes_test = false;
    graph.edges[id].duljina = v1.pos.oduzmi(v2.pos).duljina();
},
zbrojiLokacija: function(v1, kut, HL) {
    var dis = new vektor(HL * Math.cos(kut), HL * Math.sin(kut))
    if (v1.pos.x + dis.x > graph.width - v1.size || v1.pos.x + dis.x < 0 + v1.size) {
        v1.pos.x += dis.x * (-1);
        v1.pos.y += dis.y;
    } else if (v1.pos.y + dis.y > graph.height - v1.size || v1.pos.y + dis.y < 0 + v1.size) {
        v1.pos.x += dis.x;
        v1.pos.y += dis.y * (-1);
    } else {
        v1.pos = v1.pos.zbroji(dis)
    }
},

oduzmiLokacija: function(v1, kut, HL) {
    var dis = new vektor(HL * Math.cos(kut), HL * Math.sin(kut))
    if (v1.pos.x + dis.x > graph.width - v1.size || v1.pos.x + dis.x < 0 + v1.size) {
        v1.pos.x -= dis.x * (-1);
        v1.pos.y -= dis.y;
    } else if (v1.pos.y + dis.y > graph.height - v1.size || v1.pos.y + dis.y < 0 + v1.size) {
        v1.pos.x -= dis.x;
        v1.pos.y -= dis.y * (-1);
    } else {
        v1.pos = v1.pos.oduzmi(dis)
    }
}

}

function vektor(x, y) {
    this.x = x;
    this.y = y;
}
vektor.prototype.zbroji = function(v1) {
    return new vektor(this.x + v1.x, this.y + v1.y);
}
vektor.prototype.oduzmi = function(v1) {
    return new vektor(this.x - v1.x, this.y - v1.y);
}

vektor.prototype.division = function(x) {
    return new vektor(this.x / x, this.y / x);
}

vektor.prototype.multiply = function(x) {
    return new vektor(this.x * x, this.y * x);
}

vektor.prototype.udaljenost = function(v1) {
    return Math.sqrt(Math.pow(v1.x - this.x, 2) + Math.pow(v1.y - this.y, 2));
}

vektor.prototype.duljina = function() {
    return Math.max(20, Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2)));
}
//////////////////////////////////////
//  Test data                       //
/////////////////////////////////////
var edges = [
    [1, 2, 1],
    [1, 3, 1],
    [2, 3, 1],
    [3, 4, 1],
    [3, 5, 1],
    [3, 6, 1],
    [4, 1, 1],
    [4, 2, 1],
    [5, 6, 1]
    ];
graph.init(edges);

Обновление: добавлен новый код, это всего лишь превью у меня не было времени оптимизировать код, а также некоторые из названий функции и varibles написанные на моем родном языке.

Также я добавил jsfiddle ссылку, так что вы можете увидеть работу в действии. http://jsfiddle.net/nNcHJ/1/



1379
4
задан 3 сентября 2011 в 09:09 Источник Поделиться
Комментарии
1 ответ

Мне нравится код в целом, я могу работать с этим.
Мои 2 цента:


  • график.hookes_test , пожалуйста, используйте lowerCaseCamel, поэтому график.hookTest

  • график.oDuljina , пожалуйста, используйте английский язык

  • документ.метода getElementById('платно'); , если указать параметры для инициализации(ребра), то вы можете написать что-то вроде документа.метода getElementById( варианты.платно canvasID||'');

  • метод setInterval(график.рисовать, 1024 / 24); , клали магические числа вместе в секции, желательно с комментарием, что значение означает, считается, что в этот переопределяемыми вариантов , а также.

  • У вас есть это.размер = узел.размер; а также это._size = узел.размер;, любую проблему вы решаете с этим, вероятно, следует подходить по-разному

  • typeof на график.вершины[узел.идентификатор]) === "неопределенные" , наверное, заслуживает свою собственную функцию, nodeExists(), вы используете это выражение повсюду

  • clearGraph, почему вы не можете просто повторнометод init() или набор вершин и ребер в {} ?

  • в vuci , магические константы 6 должен быть ВАР

  • в рисовать и информация , вы должны иметь ВАР с вашим стилем инфо

2
ответ дан 13 декабря 2013 в 02:12 Источник Поделиться