Sources
Main html file: | dhtml/H-menu.html |
ge1doot mini library: | /library/ge1doot.js |
SVG mini library: | /library/svg.js |
CSS
html {
overflow: hidden;
-ms-touch-action: none;
-ms-content-zooming: none;
}
body {
margin: 0;
padding: 0;
background: #111;
position: absolute;
width: 100%;
height: 100%;
}
#screen {
position:absolute;
width: 100%;
height: 100%;
overflow: hidden;
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select: none;
user-select: none;
cursor:default;
}
#tree {
display: none;
}
.search {
background:#0065CB !important;
}
HTML
<div id="screen"></div>
<div id="tree" style="color:#f00">I think
<div style="color:#ff0">I do
<div>this
<a>all the time pretty much.</a>
<a>because is keeps me interested.</a>
<a>for a good reason.</a>
</div>
<div>agree
<a>with your comment.</a>
<a>on the whole.</a>
<div>that something
<a>needs to be done.</a>
<a>is off.</a>
<a>should have been noticed.</a>
</div>
</div>
<div>not
<div>know
<div>what I am exactly
<a>going to achieve.</a>
<a>looking for.</a>
<a>doing wrong with it.</a>
</div>
<a>what they have said.</a>
<a>more than half of the whole system.</a>
</div>
<a>love you anymore.</a>
<div>have to
<a>say anything more.</a>
<a>go in details.</a>
<a>understand it.</a>
</div>
<a>get your answer.</a>
</div>
</div>
<div style="color:#f80">of You
<a>everytime.</a>
<div>as
<a>my Guardian Angel.</a>
<a>a brother.</a>
<div>a source for
<a>inspiration.</a>
<a>support.</a>
<a>guidance.</a>
</div>
</div>
<div>even when
<a>I am trying not to.</a>
<a>I sleep.</a>
<a>I'm with you.</a>
</div>
<a>and it's gone!</a>
</div>
<div style="color:#0f0">they like
<a>me best.</a>
<a>the music too.</a>
<a>to be intrigued.</a>
<div>to be first,
<div>but they're so young
<div>they don't
<div>realize
<div>they weren't
<a href="http://www.dhteumeuleu.com">the first.</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
JS
/*
* ======================================================
* SVG vector menu
* http://www.dhteumeuleu.com/i-think
* Author Gerard Ferrandez - June 28, 2006
* ---------------------------------------------------
* Released under the MIT license
* http://www.dhteumeuleu.com/LICENSE.html
* ---------------------------------------------------
* Last updated: 17 Jan 2013
* - mobilized & modernized
* - removed VML/oldIE support
* ======================================================
*/
"use strict";
(function () {
// ----- private vars -----
var pointer, scr, svg,
nodes = [],
drag = {
X: 0,
Y: 0,
ox: 0,
oy: 0,
node: false,
ing: false
},
rotation = 0,
nodeOver, setup;
// ==== node constructor ====
var Node = function (parent, label, col, link) {
// ---- init variables ----
this.link = link;
this.col = col;
this.pR = 0;
this.len = 0;
this.lex = 0;
this.angle = 0;
this.expanded = false;
this.children = [];
this.parent = parent;
this.visible = false;
this.x = 0;
this.y = 0;
this.ini = {
len: 0,
lex: 0,
angle: 0,
parent: parent
}
if (parent != "") {
// ---- push child ----
parent.children.push(this);
// ---- calculate lengths & angles ----
var a = (2 * Math.PI) / parent.children.length;
var b = (parent != "") ? Math.random():0;
for (var i in parent.children) {
var c = parent.children[i];
c.angle = c.ini.angle = Math.PI / 2 + a * i + b;
c.len = c.ini.len = c.parent.ini.len / setup.reduction;
}
} else {
// ---- root ----
this.visible = true;
this.ini.len = setup.length * setup.reduction;
}
// ---- create line & text elements ----
this.line = svg.createLine(1, setup.lineColor);
this.text = svg.createText(label, setup.textFont, false, setup.defaultTextColor);
}
/* ==== create plot (separately > z-index) ==== */
Node.prototype.createPlot = function () {
this.pR = Math.round(Math.max(5, setup.dotSize * this.ini.len / 200));
this.plot = svg.createOval(this.pR * 2, true);
this.plot.strokeColor(setup.defaultNodeStrokeColor);
this.plot.strokeWidth(1);
this.plot.obj = this;
// ---- font size ----
this.text.fontSize(4 + this.pR);
}
/* ==== main animation ==== */
Node.prototype.run = function () {
if (this.visible) {
// ---- parent coordinates ----
var xp = this.parent ? this.parent.x : drag.X;
var yp = this.parent ? this.parent.y : drag.Y;
// ---- trigonometry ----
var a = Math.atan2(
(this.y + Math.sin(this.angle + rotation) * setup.friction) - yp,
(this.x + Math.cos(this.angle + rotation) * setup.friction) - xp
);
if (this.lex < this.len) this.lex += (this.len - this.lex) * .1;
this.x = xp + Math.cos(a) * this.lex;
this.y = yp + Math.sin(a) * this.lex;
// ---- screen limits ----
if (this.x < this.pR) this.x = this.pR;
else if (this.x > scr.width - this.pR) this.x = scr.width - this.pR;
if (this.y < this.pR) this.y = this.pR;
else if (this.y > scr.height - this.pR) this.y = scr.height - this.pR;
// ---- move elements ----
this.line.move(this.x, this.y, xp, yp);
this.plot.move(this.x, this.y, this.pR);
this.text.move(this.x + this.pR + 5, this.y + this.pR * 0.25);
}
}
/* ==== collapse node ==== */
Node.prototype.collapse = function () {
this.expanded = false;
this.text.fillColor(setup.defaultTextColor);
this.plot.fillColor((this.children.length) ? setup.collapsedNodeColor : this.col);
for (var i = 0; i < this.children.length; i++) {
var c = this.children[i];
c.visible = false;
c.lex = 0;
c.line.move(-1, -1, -1, -2);
c.plot.move(-1000, -1, 0);
c.text.move(-1000,0);
c.expanded = false;
c.collapse();
}
}
/* ==== expand node ==== */
Node.prototype.expand = function () {
// ---- close all other branchs ----
if (this.ini.parent != "") {
for (var i = 0; i < this.ini.parent.children.length; i++) {
this.ini.parent.children[i].collapse();
}
}
// ---- expand ----
this.expanded = true;
this.text.fillColor(setup.selectedTextColor);
this.plot.fillColor(setup.expandedNodeColor);
for (var i = 0; i < this.children.length; i++) {
this.children[i].visible = true;
this.children[i].lex = 0;
}
}
/* ==== down ==== */
Node.prototype.down = function () {
if (pointer.isDraging) return;
// ---- offset mouse ----
drag.ox = pointer.X - this.x;
drag.oy = pointer.Y - this.y;
// ---- change root ----
if (drag.node != this) {
// ---- expanded color ----
this.text.fillColor(setup.selectedTextColor);
this.plot.fillColor(setup.expandedNodeColor);
// ---- reset ----
var i = 0, node;
while ( node = nodes[i++]) {
node.parent = node.ini.parent;
node.len = node.ini.len;
node.lex = node.ini.len;
node.angle = node.ini.angle;
}
// ---- search for root path ----
var oc = [];
var ow = this;
oc.push(ow);
while(ow.parent != "") {
ow = ow.parent;
oc.push(ow);
}
// ---- inverse vectors ----
for (var i = 1; i < oc.length; i++) {
oc[i].lex = oc[i-1].ini.len;
oc[i].len = oc[i-1].ini.len;
oc[i].angle = oc[i-1].ini.angle - Math.PI;
oc[i].parent = oc[i-1];
}
// ---- switch root ----
this.parent = "";
this.len = 0;
this.lex = 0;
this.angle = 0;
drag.node.plot.strokeColor(setup.defaultNodeStrokeColor);
drag.node.plot.strokeWidth(1);
drag.node = this;
}
}
/* ==== main loop ==== */
var run = function () {
if (drag.ing) {
drag.X = pointer.X - drag.ox,
drag.Y = pointer.Y - drag.oy;
}
rotation += setup.rotationSpeed;
var i = 0, node;
while ( node = nodes[i++]) {
node.run();
}
// ---- loop ----
requestAnimFrame(run);
}
/* ==== parse menu DOM ==== */
var setMenuTree = function (theNode, parent) {
if (theNode.tagName == "DIV" || theNode.tagName == "A") {
// ---- Node Label ----
var s = theNode.innerHTML;
var d = s.toUpperCase().indexOf("