Parcourir la source

redid how adding node works

tags/v0.2.0^2
Big Bad Waffle il y a 6 ans
Parent
révision
1e88840c32
6 fichiers modifiés avec 324 ajouts et 94 suppressions
  1. +84
    -57
      helpers/passives/generator.js
  2. +65
    -0
      helpers/passives/helpers.js
  3. +16
    -1
      helpers/passives/index.html
  4. +88
    -36
      helpers/passives/renderer.js
  5. +34
    -0
      helpers/passives/styles.css
  6. +37
    -0
      helpers/passives/ui.js

+ 84
- 57
helpers/passives/generator.js Voir le fichier

@@ -1,104 +1,130 @@
var generator = {
links: [],
nodes: [],

selected: null,

init: function () {
this.actions.addNode.call(this, null, {
x: 100,
y: 100
x: 23,
y: 14
});

renderer.center(this.nodes[0]);
},

onClick: function (button, x, y) {
var node = this.findNode(x, y);
if (!node)
return;

if (button == 0)
this.actions.addNode.call(this, node);
else if (button == 1)
this.actions.rotateNode.call(this, node);
else if (button == 2)
this.actions.extendNode.call(this, node);
if (button == 0) {
if (ui.shiftDown)
this.actions.moveNode.call(this, x, y);
else {
this.actions.addNode.call(this, null, {
x: x,
y: y
});
}
} else if (button == 1) {
var node = this.findNode(x, y);
if (node)
this.actions.selectNode.call(this, node);
} else if (button == 2) {
var node = this.findNode(x, y);
if (node)
this.actions.connectNode.call(this, node);
}

renderer.makeDirty();
},

findNode: function (x, y, nodes) {
nodes = nodes || this.nodes;

for (var i = 0; i < nodes.length; i++) {
var n = nodes[i];

if (!(
(n.pos.x > x) ||
(n.pos.y > y) ||
(n.pos.x + constants.blockSize <= x) |
(n.pos.y + constants.blockSize <= y)
))
return n;
else {
var f = this.findNode(x, y, n.children);
if (f)
return f;
}
}
findNode: function (x, y) {
return this.nodes.find(n => ((n.pos.x == x) && (n.pos.y == y)));
},

actions: {
addNode: function (parent, options = {}) {
var nodes = this.nodes;
selectNode: function (node) {
if (this.selected)
this.selected.selected = false;
node.selected = true;
this.selected = node;

if (parent)
options.angle = constants.defaultAngle;
ui.setActive(node);
},

addNode: function (parent, options = {}) {
var node = tplNode.build({
id: nodes.length,
angle: options.angle,
id: this.nodes.length,
x: options.x,
y: options.y,
parent: parent,
distance: constants.defaultDistance
y: options.y
});

if (parent)
parent.children.push(node);
else
nodes.push(node);
this.nodes.push(node);
},

rotateNode: function (node) {
var newAngle = node.angle - constants.defaultAngleInc;
node.parent.children.forEach(n => (n.angle = newAngle));
console.log(node.parent);
connectNode: function (node) {
if (this.selected) {
if (ui.shiftDown) {
this.links.spliceWhere(l => (
(
(l.from == node) ||
(l.to == node)
) &&
(
(l.from == this.selected) ||
(l.to == this.selected)
) &&
(node != this.selected)
));
} else {
this.links.push({
from: this.selected,
to: node
});
}
this.selected = null;
} else
this.selected = node;
},

moveNode: function (x, y) {
if (!this.selected)
return;

this.selected.pos.x = x;
this.selected.pos.y = y;
},

extendNode: function (node) {
node.distance += constants.defaultDistanceInc;
recolorNode: function () {
if (!this.selected)
return;

this.selected.color = (this.selected.color + 1) % 4;
},

resizeNode: function () {
if (!this.selected)
return;

this.selected.size = (this.selected.size + 1) % 3;
}
}
};

var tplNode = {
id: 0,
children: [],
color: 0,
size: 0,
pos: {
x: 0,
y: 0
},

build: function (options) {
var res = $.extend(true, {
parent: options.parent
}, this, {
var res = $.extend(true, {}, this, {
id: this.id++,
pos: {
x: options.x,
y: options.y
},
distance: options.distance,
angle: options.angle
}
});
delete res.build;

@@ -107,6 +133,7 @@ var tplNode = {
};

$(function () {
ui.init();
renderer.init();
generator.init();
})

+ 65
- 0
helpers/passives/helpers.js Voir le fichier

@@ -0,0 +1,65 @@
Array.prototype.firstIndex = function (callback, thisArg) {
var T = thisArg;
var O = Object(this);
var len = O.length >>> 0;

var k = 0;

while (k < len) {
var kValue;

if (k in O) {
kValue = O[k];

if (callback.call(T, kValue, k, O))
return k;
}
k++;
}

return -1;
};

Array.prototype.spliceWhere = function (callback, thisArg) {
var T = thisArg;
var O = Object(this);
var len = O.length >>> 0;

var k = 0;

while (k < len) {
var kValue;

if (k in O) {
kValue = O[k];

if (callback.call(T, kValue, k, O)) {
O.splice(k, 1);
k--;
}
}
k++;
}
};

Array.prototype.spliceFirstWhere = function (callback, thisArg) {
var T = thisArg;
var O = Object(this);
var len = O.length >>> 0;

var k = 0;

while (k < len) {
var kValue;

if (k in O) {
kValue = O[k];

if (callback.call(T, kValue, k, O)) {
O.splice(k, 1);
return kValue;
}
}
k++;
}
};

+ 16
- 1
helpers/passives/index.html Voir le fichier

@@ -6,8 +6,23 @@
<script src="../../src/client/plugins/jquery.min.js"></script>
<script src="renderer.js"></script>
<script src="generator.js"></script>
<script src="ui.js"></script>
<script src="helpers.js"></script>
</head>
<body>
<canvas></canvas>
<div class="left">
<canvas></canvas>
</div>
<div class="right">
<div class="id"></div>
<div class="commands">
<div class="command">a: add nodes</div>
<div class="command">e: extend nodes</div>
<div class="command">r: rotate nodes</div>
<div class="command">c: closen nodes</div>
<div class="command">f: furthen nodes</div>
<div class="command"></div>
</div>
</div>
</body>
</html>

+ 88
- 36
helpers/passives/renderer.js Voir le fichier

@@ -12,16 +12,24 @@ var renderer = {
y: 0
},

mouse: {
x: 0,
y: 0
},

dirty: false,

init: function () {
this.canvas = $('canvas')[0];
this.screen.w = this.canvas.width = $('body').width();
this.screen.h = this.canvas.height = $('body').height();
this.screen.w = this.canvas.width = $('.left').width();
this.screen.h = this.canvas.height = $('.left').height();
this.ctx = this.canvas.getContext('2d');

this.ctx.lineWidth = constants.lineWidth;

$(this.canvas)
.on('mousedown', this.events.onClick.bind(this))
.on('mousemove', this.events.onMouseMove.bind(this))
.on('contextmenu', function () {
return false;
});
@@ -30,8 +38,8 @@ var renderer = {
},

center: function (node) {
this.pos.x = node.pos.x + (constants.blockSize / 2) - (this.screen.w / 2);
this.pos.y = node.pos.y + (constants.blockSize / 2) - (this.screen.h / 2);
this.pos.x = ~~(node.pos.x * constants.gridSize) + (constants.blockSize / 2) - (this.screen.w / 2);
this.pos.y = ~~(node.pos.y * constants.gridSize) + (constants.blockSize / 2) - (this.screen.h / 2);

this.ctx.translate(-this.pos.x, -this.pos.y);
this.makeDirty();
@@ -41,32 +49,15 @@ var renderer = {
this.dirty = true;
},

render: function (nodes) {
var nodes = nodes || generator.nodes;

nodes.forEach(function (n) {
var x = n.pos.x;
var y = n.pos.y;

if (n.parent) {
var childIndex = n.parent.children.findIndex(c => (c == n));
n.pos.x = x = n.parent.pos.x + (Math.cos(n.angle * childIndex) * n.distance);
n.pos.y = y = n.parent.pos.y + (Math.sin(n.angle * childIndex) * n.distance);
}

if (n.children.length > 0)
this.render(n.children);

n.children.forEach(function (c) {
this.renderers.line.call(this, n, c);
}, this);
render: function () {
var nodes = generator.nodes;
var links = generator.links;

links.forEach(function (l) {
this.renderers.line.call(this, l.from, l.to);
}, this);

nodes.forEach(function (n) {
if (n.children.length > 0)
this.render(n.children);

this.renderers.node.call(this, n, n.pos.x, n.pos.y);
}, this);
},
@@ -75,6 +66,7 @@ var renderer = {
if (this.dirty) {
this.dirty = false;
this.renderers.clear.call(this);
this.renderers.grid.call(this);
this.render();
}

@@ -86,19 +78,64 @@ var renderer = {
this.ctx.clearRect(this.pos.x, this.pos.y, this.screen.w, this.screen.h);
},

node: function (node, x, y) {
this.ctx.fillStyle = '#c0c3cf';
this.ctx.fillRect(x, y, constants.blockSize, constants.blockSize)
grid: function () {
var gridSize = constants.gridSize;
var ctx = this.ctx;
var mouse = this.mouse;

var w = this.screen.w / gridSize;
var h = this.screen.h / gridSize;

ctx.fillStyle = '#3c3f4c';
for (var i = 0; i < w; i++) {
for (var j = 0; j < h; j++) {
if ((mouse.x == i) && (mouse.y == j)) {
ctx.fillStyle = '#ff6942';
ctx.fillRect((i * gridSize) - 25, (j * gridSize) - 25, 9, 9);
ctx.fillStyle = '#3c3f4c';
} else
ctx.fillRect((i * gridSize) - 23, (j * gridSize) - 23, 5, 5);
}
}
},

node: function (node) {
this.ctx.fillStyle = ([
'#c0c3cf',
'#3fa7dd',
'#4ac441',
'#d43346'
])[node.color];
var size = ([
constants.blockSize,
constants.blockSize * 2,
constants.blockSize * 3
])[node.size];
var x = (node.pos.x * constants.gridSize) - ((size - constants.blockSize) / 2);
var y = (node.pos.y * constants.gridSize) - ((size - constants.blockSize) / 2);

this.ctx.fillRect(x, y, size, size);

if (node == generator.selected) {
this.ctx.strokeStyle = '#fafcfc';
this.ctx.strokeRect(x, y, size, size);
}
},

line: function (fromNode, toNode) {
var ctx = this.ctx;
var halfSize = constants.blockSize / 2;

var fromX = (fromNode.pos.x * constants.gridSize) + halfSize;
var fromY = (fromNode.pos.y * constants.gridSize) + halfSize;

var toX = (toNode.pos.x * constants.gridSize) + halfSize;
var toY = (toNode.pos.y * constants.gridSize) + halfSize;

ctx.strokeStyle = '#69696e';
ctx.beginPath();
ctx.moveTo(~~(fromNode.pos.x + halfSize) + 0.5, ~~(fromNode.pos.y + halfSize) + 0.5);
ctx.lineTo(~~(toNode.pos.x + halfSize) + 0.5, ~~(toNode.pos.y + halfSize) + 0.5);
ctx.moveTo(fromX, fromY);
ctx.lineTo(toX, toY);
ctx.closePath();
ctx.stroke();
}
@@ -106,18 +143,33 @@ var renderer = {

events: {
onClick: function (e) {
generator.onClick(e.button, e.clientX + this.pos.x, e.clientY + this.pos.y);
generator.onClick(e.button, ~~((e.clientX + this.pos.x + 40) / constants.gridSize) - 1, ~~((e.clientY + this.pos.y + 40) / constants.gridSize) - 1);
e.preventDefault();
return false;
},

onMouseMove: function (e) {
var mouseX = ~~((e.clientX + this.pos.x + 40) / constants.gridSize);
var mouseY = ~~((e.clientY + this.pos.y + 40) / constants.gridSize);

if ((this.mouse.x == mouseX) && (this.mouse.y == mouseY))
return;

this.mouse = {
x: mouseX,
y: mouseY
};
this.makeDirty();
}
}
};

var constants = {
lineWidth: 5,
blockSize: 40,
defaultDistance: 100,
defaultDistanceInc: 50,
blockSize: 20,
defaultDistance: 50,
defaultDistanceInc: 60,
defaultAngle: Math.PI / 2,
defaultAngleInc: Math.PI / 8
defaultAngleInc: Math.PI / 8,
gridSize: 30
};

+ 34
- 0
helpers/passives/styles.css Voir le fichier

@@ -8,3 +8,37 @@ body {
margin: 0px;
overflow: hidden;
}

.left, .right {
float: left;
height: 100%;
}

.left {
width: 85%;
}

.right {
width: 15%;
background-color: #373041;
}

.right .id {
width: 100%;
text-align: center;
padding: 10px;
color: #fafcfc;
font-size: 36px;
}

.right .command {
width: 100%;
text-align: center;
padding: 10px;
color: #fafcfc;
font-size: 24px;
}

.right .id:before {
content: 'id: ';
}

+ 37
- 0
helpers/passives/ui.js Voir le fichier

@@ -0,0 +1,37 @@
var ui = {
node: null,
shiftDown: false,

init: function () {
$(window)
.on('keydown', this.events.onKey.bind(this, true))
.on('keyup', this.events.onKey.bind(this, false));
},

find: function (selector) {
return $('.right').find('.' + selector).eq(0);
},

setActive: function (node) {
this.node = node;
this.find('id').html(node.id);
},

events: {
onKey: function (isDown, e) {
if (e.key == 'Shift')
this.shiftDown = isDown;

if (!isDown)
return;

if (e.key == 'c') {
generator.actions.recolorNode.call(generator);
renderer.makeDirty();
} else if (e.key == 's') {
generator.actions.resizeNode.call(generator);
renderer.makeDirty();
}
}
}
};

Chargement…
Annuler
Enregistrer