JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.12.5/vue.min.js"></script>
<div id="graph">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300" version="1.1" v-on="click: add">
<g>
<circle
v-on="click: selectFunc"
v-repeat="nodes"
id="{{id}}"
cx="{{cx}}"
cy="{{cy}}"
r="30"
v-class="selected: selected"
>
</circle>
</g>
</svg>
<pre>{{ $data | json }}</pre>
<button
class="btn btn-default"
v-on="click:
(
funcs.add = ! funcs.add,
funcs.move = false,
funcs.remove = false
)"
v-class="active: funcs.add"
>
Add Node
</button>
<button
class="btn btn-default"
v-on="click:
(
funcs.move = ! funcs.move,
funcs.add = false,
funcs.remove = false
)"
v-class="active: funcs.move"
>
Move
</button>
<button
class="btn btn-default"
v-on="click:
(
funcs.remove = ! funcs.remove,
funcs.add = false,
funcs.move = false
)"
v-class="active: funcs.remove"
>
Remove
</button>
</div>
CSS
circle {
fill: blue;
stroke: black;
stroke-width: 3;
}
#raw {
position: absolute;
top: 0;
left: 300px;
}
.selected {
stroke-width: 5;
}
JavaScript
new Vue({
el: '#graph',
data: {
funcs: {
add: false,
move: false,
remove: false
},
nodes: [
{
cx: 100,
cy: 100,
id: 0,
selected: false,
ini: false,
final: false
}
],
posMouse: {
x: 0,
y: 0
},
selected: {
sx: null,
sy: null,
id: null
}
},
methods: {
selectFunc: function (node) {
node.preventDefault();
if (this.funcs.move) {
this.move(node);
} else if (this.funcs.remove) {
this.remove(node);
}
},
add: function (node) {
node.preventDefault();
// Recebe tag do objeto a ser clicado
var parentPosition = getPosition(node.currentTarget);
// Posição do mouse em X
this.posMouse.x = node.clientX - parentPosition.x;
// Posição do mouse em Y
this.posMouse.y = node.clientY - parentPosition.y;
// Adiciona novo nó caso botão Add ativado
if (this.funcs.add) {
this.nodes.push({
cx: this.posMouse.x, // X set para posição do mouse
cy: this.posMouse.y, // Y set para posição do mouse
id: this.nodes.length, // ID do nó
selected: false, // Se nó esta selecionado
ini: false, // Nó é inicial?
final: false // Nó é final?
});
}
},
move: function (node) {
node.preventDefault();
// Recebe a seleção do nó
this.selected.id = parseInt(node.target.id);
// Seleção do nó (visual)
this.nodes.forEach(function(id, index){
if(id.selected === true)
id.selected = false;
});
var index = getIndex(this.nodes, this.selected.id);
this.nodes[index].selected = ! this.nodes[index].selected;
},
remove: function (node) {
node.preventDefault();
this.selected.id = parseInt(node.target.id);
var index = getIndex(this.nodes, this.selected.id);
//Remove nó pelo index
this.nodes.$remove(index);
}
}
});
// Método para pegar a posição correta do mouse
function getPosition(element) {
var xPosition = 0;
var yPosition = 0;
while (element) {
xPosition += (element.offsetLeft...