Metamaps.Visualize
This commit is contained in:
parent
87b6dfb739
commit
e8e866c196
3 changed files with 208 additions and 210 deletions
|
@ -25,6 +25,7 @@
|
|||
//= require ./src/views/room
|
||||
//= require ./src/JIT
|
||||
//= require ./src/Metamaps
|
||||
//= require ./src/Metamaps.Visualize
|
||||
//= require ./src/Metamaps.Util
|
||||
//= require ./src/Metamaps.Realtime
|
||||
//= require ./src/Metamaps.Control
|
||||
|
|
207
app/assets/javascripts/src/Metamaps.Visualize.js
Normal file
207
app/assets/javascripts/src/Metamaps.Visualize.js
Normal file
|
@ -0,0 +1,207 @@
|
|||
/* global Metamaps, $ */
|
||||
/*
|
||||
* Metamaps.Visualize
|
||||
*
|
||||
* Dependencies:
|
||||
* - Metamaps.Active
|
||||
* - Metamaps.JIT
|
||||
* - Metamaps.Loading
|
||||
* - Metamaps.Metacodes
|
||||
* - Metamaps.Router
|
||||
* - Metamaps.Synapses
|
||||
* - Metamaps.TopicCard
|
||||
* - Metamaps.Topics
|
||||
* - Metamaps.Touch
|
||||
* - Metamaps.Visualize
|
||||
*/
|
||||
|
||||
Metamaps.Visualize = {
|
||||
mGraph: null, // a reference to the graph object.
|
||||
cameraPosition: null, // stores the camera position when using a 3D visualization
|
||||
type: 'ForceDirected', // the type of graph we're building, could be "RGraph", "ForceDirected", or "ForceDirected3D"
|
||||
loadLater: false, // indicates whether there is JSON that should be loaded right in the offset, or whether to wait till the first topic is created
|
||||
init: function () {
|
||||
var self = Metamaps.Visualize
|
||||
// disable awkward dragging of the canvas element that would sometimes happen
|
||||
$('#infovis-canvas').on('dragstart', function (event) {
|
||||
event.preventDefault()
|
||||
})
|
||||
|
||||
// prevent touch events on the canvas from default behaviour
|
||||
$('#infovis-canvas').bind('touchstart', function (event) {
|
||||
event.preventDefault()
|
||||
self.mGraph.events.touched = true
|
||||
})
|
||||
|
||||
// prevent touch events on the canvas from default behaviour
|
||||
$('#infovis-canvas').bind('touchmove', function (event) {
|
||||
// Metamaps.JIT.touchPanZoomHandler(event)
|
||||
})
|
||||
|
||||
// prevent touch events on the canvas from default behaviour
|
||||
$('#infovis-canvas').bind('touchend touchcancel', function (event) {
|
||||
lastDist = 0
|
||||
if (!self.mGraph.events.touchMoved && !Metamaps.Touch.touchDragNode) Metamaps.TopicCard.hideCurrentCard()
|
||||
self.mGraph.events.touched = self.mGraph.events.touchMoved = false
|
||||
Metamaps.Touch.touchDragNode = false
|
||||
})
|
||||
},
|
||||
computePositions: function () {
|
||||
var self = Metamaps.Visualize,
|
||||
mapping
|
||||
|
||||
if (self.type == 'RGraph') {
|
||||
var i, l, startPos, endPos, topic, synapse
|
||||
|
||||
self.mGraph.graph.eachNode(function (n) {
|
||||
topic = Metamaps.Topics.get(n.id)
|
||||
topic.set({ node: n }, { silent: true })
|
||||
topic.updateNode()
|
||||
|
||||
n.eachAdjacency(function (edge) {
|
||||
if (!edge.getData('init')) {
|
||||
edge.setData('init', true)
|
||||
|
||||
l = edge.getData('synapseIDs').length
|
||||
for (i = 0; i < l; i++) {
|
||||
synapse = Metamaps.Synapses.get(edge.getData('synapseIDs')[i])
|
||||
synapse.set({ edge: edge }, { silent: true })
|
||||
synapse.updateEdge()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
var pos = n.getPos()
|
||||
pos.setc(-200, -200)
|
||||
})
|
||||
self.mGraph.compute('end')
|
||||
} else if (self.type == 'ForceDirected') {
|
||||
var i, l, startPos, endPos, topic, synapse
|
||||
|
||||
self.mGraph.graph.eachNode(function (n) {
|
||||
topic = Metamaps.Topics.get(n.id)
|
||||
topic.set({ node: n }, { silent: true })
|
||||
topic.updateNode()
|
||||
mapping = topic.getMapping()
|
||||
|
||||
n.eachAdjacency(function (edge) {
|
||||
if (!edge.getData('init')) {
|
||||
edge.setData('init', true)
|
||||
|
||||
l = edge.getData('synapseIDs').length
|
||||
for (i = 0; i < l; i++) {
|
||||
synapse = Metamaps.Synapses.get(edge.getData('synapseIDs')[i])
|
||||
synapse.set({ edge: edge }, { silent: true })
|
||||
synapse.updateEdge()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
startPos = new $jit.Complex(0, 0)
|
||||
endPos = new $jit.Complex(mapping.get('xloc'), mapping.get('yloc'))
|
||||
n.setPos(startPos, 'start')
|
||||
n.setPos(endPos, 'end')
|
||||
})
|
||||
} else if (self.type == 'ForceDirected3D') {
|
||||
self.mGraph.compute()
|
||||
}
|
||||
},
|
||||
/**
|
||||
* render does the heavy lifting of creating the engine that renders the graph with the properties we desire
|
||||
*
|
||||
*/
|
||||
render: function () {
|
||||
var self = Metamaps.Visualize, RGraphSettings, FDSettings
|
||||
|
||||
if (self.type == 'RGraph' && (!self.mGraph || self.mGraph instanceof $jit.ForceDirected)) {
|
||||
RGraphSettings = $.extend(true, {}, Metamaps.JIT.ForceDirected.graphSettings)
|
||||
|
||||
$jit.RGraph.Plot.NodeTypes.implement(Metamaps.JIT.ForceDirected.nodeSettings)
|
||||
$jit.RGraph.Plot.EdgeTypes.implement(Metamaps.JIT.ForceDirected.edgeSettings)
|
||||
|
||||
RGraphSettings.width = $(document).width()
|
||||
RGraphSettings.height = $(document).height()
|
||||
RGraphSettings.background = Metamaps.JIT.RGraph.background
|
||||
RGraphSettings.levelDistance = Metamaps.JIT.RGraph.levelDistance
|
||||
|
||||
self.mGraph = new $jit.RGraph(RGraphSettings)
|
||||
} else if (self.type == 'ForceDirected' && (!self.mGraph || self.mGraph instanceof $jit.RGraph)) {
|
||||
FDSettings = $.extend(true, {}, Metamaps.JIT.ForceDirected.graphSettings)
|
||||
|
||||
$jit.ForceDirected.Plot.NodeTypes.implement(Metamaps.JIT.ForceDirected.nodeSettings)
|
||||
$jit.ForceDirected.Plot.EdgeTypes.implement(Metamaps.JIT.ForceDirected.edgeSettings)
|
||||
|
||||
FDSettings.width = $('body').width()
|
||||
FDSettings.height = $('body').height()
|
||||
|
||||
self.mGraph = new $jit.ForceDirected(FDSettings)
|
||||
} else if (self.type == 'ForceDirected3D' && !self.mGraph) {
|
||||
// init ForceDirected3D
|
||||
self.mGraph = new $jit.ForceDirected3D(Metamaps.JIT.ForceDirected3D.graphSettings)
|
||||
self.cameraPosition = self.mGraph.canvas.canvases[0].camera.position
|
||||
} else {
|
||||
self.mGraph.graph.empty()
|
||||
}
|
||||
|
||||
function runAnimation () {
|
||||
Metamaps.Loading.hide()
|
||||
// load JSON data, if it's not empty
|
||||
if (!self.loadLater) {
|
||||
// load JSON data.
|
||||
var rootIndex = 0
|
||||
if (Metamaps.Active.Topic) {
|
||||
var node = _.find(Metamaps.JIT.vizData, function (node) {
|
||||
return node.id === Metamaps.Active.Topic.id
|
||||
})
|
||||
rootIndex = _.indexOf(Metamaps.JIT.vizData, node)
|
||||
}
|
||||
self.mGraph.loadJSON(Metamaps.JIT.vizData, rootIndex)
|
||||
// compute positions and plot.
|
||||
self.computePositions()
|
||||
self.mGraph.busy = true
|
||||
if (self.type == 'RGraph') {
|
||||
self.mGraph.fx.animate(Metamaps.JIT.RGraph.animate)
|
||||
} else if (self.type == 'ForceDirected') {
|
||||
self.mGraph.animate(Metamaps.JIT.ForceDirected.animateSavedLayout)
|
||||
} else if (self.type == 'ForceDirected3D') {
|
||||
self.mGraph.animate(Metamaps.JIT.ForceDirected.animateFDLayout)
|
||||
}
|
||||
}
|
||||
}
|
||||
// hold until all the needed metacode images are loaded
|
||||
// hold for a maximum of 80 passes, or 4 seconds of waiting time
|
||||
var tries = 0
|
||||
function hold () {
|
||||
var unique = _.uniq(Metamaps.Topics.models, function (metacode) { return metacode.get('metacode_id'); }),
|
||||
requiredMetacodes = _.map(unique, function (metacode) { return metacode.get('metacode_id'); }),
|
||||
loadedCount = 0
|
||||
|
||||
_.each(requiredMetacodes, function (metacode_id) {
|
||||
var metacode = Metamaps.Metacodes.get(metacode_id),
|
||||
img = metacode ? metacode.get('image') : false
|
||||
|
||||
if (img && (img.complete || (typeof img.naturalWidth !== 'undefined' && img.naturalWidth !== 0))) {
|
||||
loadedCount += 1
|
||||
}
|
||||
})
|
||||
|
||||
if (loadedCount === requiredMetacodes.length || tries > 80) runAnimation()
|
||||
else setTimeout(function () { tries++; hold() }, 50)
|
||||
}
|
||||
hold()
|
||||
|
||||
// update the url now that the map is ready
|
||||
clearTimeout(Metamaps.Router.timeoutId)
|
||||
Metamaps.Router.timeoutId = setTimeout(function () {
|
||||
var m = Metamaps.Active.Map
|
||||
var t = Metamaps.Active.Topic
|
||||
|
||||
if (m && window.location.pathname !== '/maps/' + m.id) {
|
||||
Metamaps.Router.navigate('/maps/' + m.id)
|
||||
}
|
||||
else if (t && window.location.pathname !== '/topics/' + t.id) {
|
||||
Metamaps.Router.navigate('/topics/' + t.id)
|
||||
}
|
||||
}, 800)
|
||||
}
|
||||
}; // end Metamaps.Visualize
|
|
@ -853,10 +853,6 @@ Metamaps.Create = {
|
|||
}
|
||||
}; // end Metamaps.Create
|
||||
|
||||
|
||||
////////////////// TOPIC AND SYNAPSE CARDS //////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* TOPICCARD
|
||||
|
@ -1592,209 +1588,3 @@ Metamaps.SynapseCard = {
|
|||
} // if
|
||||
} //add_direction_form
|
||||
}; // end Metamaps.SynapseCard
|
||||
|
||||
|
||||
////////////////////// END TOPIC AND SYNAPSE CARDS //////////////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* VISUALIZE
|
||||
*
|
||||
*/
|
||||
Metamaps.Visualize = {
|
||||
mGraph: null, // a reference to the graph object.
|
||||
cameraPosition: null, // stores the camera position when using a 3D visualization
|
||||
type: "ForceDirected", // the type of graph we're building, could be "RGraph", "ForceDirected", or "ForceDirected3D"
|
||||
loadLater: false, // indicates whether there is JSON that should be loaded right in the offset, or whether to wait till the first topic is created
|
||||
init: function () {
|
||||
var self = Metamaps.Visualize;
|
||||
// disable awkward dragging of the canvas element that would sometimes happen
|
||||
$('#infovis-canvas').on('dragstart', function (event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
// prevent touch events on the canvas from default behaviour
|
||||
$("#infovis-canvas").bind('touchstart', function (event) {
|
||||
event.preventDefault();
|
||||
self.mGraph.events.touched = true;
|
||||
});
|
||||
|
||||
// prevent touch events on the canvas from default behaviour
|
||||
$("#infovis-canvas").bind('touchmove', function (event) {
|
||||
//Metamaps.JIT.touchPanZoomHandler(event);
|
||||
});
|
||||
|
||||
// prevent touch events on the canvas from default behaviour
|
||||
$("#infovis-canvas").bind('touchend touchcancel', function (event) {
|
||||
lastDist = 0;
|
||||
if (!self.mGraph.events.touchMoved && !Metamaps.Touch.touchDragNode) Metamaps.TopicCard.hideCurrentCard();
|
||||
self.mGraph.events.touched = self.mGraph.events.touchMoved = false;
|
||||
Metamaps.Touch.touchDragNode = false;
|
||||
});
|
||||
},
|
||||
computePositions: function () {
|
||||
var self = Metamaps.Visualize,
|
||||
mapping;
|
||||
|
||||
if (self.type == "RGraph") {
|
||||
var i, l, startPos, endPos, topic, synapse;
|
||||
|
||||
self.mGraph.graph.eachNode(function (n) {
|
||||
topic = Metamaps.Topics.get(n.id);
|
||||
topic.set({ node: n }, { silent: true });
|
||||
topic.updateNode();
|
||||
|
||||
n.eachAdjacency(function (edge) {
|
||||
if(!edge.getData('init')) {
|
||||
edge.setData('init', true);
|
||||
|
||||
l = edge.getData('synapseIDs').length;
|
||||
for (i = 0; i < l; i++) {
|
||||
synapse = Metamaps.Synapses.get(edge.getData('synapseIDs')[i]);
|
||||
synapse.set({ edge: edge }, { silent: true });
|
||||
synapse.updateEdge();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var pos = n.getPos();
|
||||
pos.setc(-200, -200);
|
||||
});
|
||||
self.mGraph.compute('end');
|
||||
} else if (self.type == "ForceDirected") {
|
||||
var i, l, startPos, endPos, topic, synapse;
|
||||
|
||||
self.mGraph.graph.eachNode(function (n) {
|
||||
topic = Metamaps.Topics.get(n.id);
|
||||
topic.set({ node: n }, { silent: true });
|
||||
topic.updateNode();
|
||||
mapping = topic.getMapping();
|
||||
|
||||
n.eachAdjacency(function (edge) {
|
||||
if(!edge.getData('init')) {
|
||||
edge.setData('init', true);
|
||||
|
||||
l = edge.getData('synapseIDs').length;
|
||||
for (i = 0; i < l; i++) {
|
||||
synapse = Metamaps.Synapses.get(edge.getData('synapseIDs')[i]);
|
||||
synapse.set({ edge: edge }, { silent: true });
|
||||
synapse.updateEdge();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
startPos = new $jit.Complex(0, 0);
|
||||
endPos = new $jit.Complex(mapping.get('xloc'), mapping.get('yloc'));
|
||||
n.setPos(startPos, 'start');
|
||||
n.setPos(endPos, 'end');
|
||||
});
|
||||
} else if (self.type == "ForceDirected3D") {
|
||||
self.mGraph.compute();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* render does the heavy lifting of creating the engine that renders the graph with the properties we desire
|
||||
*
|
||||
*/
|
||||
render: function () {
|
||||
var self = Metamaps.Visualize, RGraphSettings, FDSettings;
|
||||
|
||||
if (self.type == "RGraph" && (!self.mGraph || self.mGraph instanceof $jit.ForceDirected)) {
|
||||
|
||||
RGraphSettings = $.extend(true, {}, Metamaps.JIT.ForceDirected.graphSettings);
|
||||
|
||||
$jit.RGraph.Plot.NodeTypes.implement(Metamaps.JIT.ForceDirected.nodeSettings);
|
||||
$jit.RGraph.Plot.EdgeTypes.implement(Metamaps.JIT.ForceDirected.edgeSettings);
|
||||
|
||||
RGraphSettings.width = $(document).width();
|
||||
RGraphSettings.height = $(document).height();
|
||||
RGraphSettings.background = Metamaps.JIT.RGraph.background;
|
||||
RGraphSettings.levelDistance = Metamaps.JIT.RGraph.levelDistance;
|
||||
|
||||
self.mGraph = new $jit.RGraph(RGraphSettings);
|
||||
|
||||
} else if (self.type == "ForceDirected" && (!self.mGraph || self.mGraph instanceof $jit.RGraph)) {
|
||||
|
||||
FDSettings = $.extend(true, {}, Metamaps.JIT.ForceDirected.graphSettings);
|
||||
|
||||
$jit.ForceDirected.Plot.NodeTypes.implement(Metamaps.JIT.ForceDirected.nodeSettings);
|
||||
$jit.ForceDirected.Plot.EdgeTypes.implement(Metamaps.JIT.ForceDirected.edgeSettings);
|
||||
|
||||
FDSettings.width = $('body').width();
|
||||
FDSettings.height = $('body').height();
|
||||
|
||||
self.mGraph = new $jit.ForceDirected(FDSettings);
|
||||
|
||||
} else if (self.type == "ForceDirected3D" && !self.mGraph) {
|
||||
// init ForceDirected3D
|
||||
self.mGraph = new $jit.ForceDirected3D(Metamaps.JIT.ForceDirected3D.graphSettings);
|
||||
self.cameraPosition = self.mGraph.canvas.canvases[0].camera.position;
|
||||
}
|
||||
else {
|
||||
self.mGraph.graph.empty();
|
||||
}
|
||||
|
||||
function runAnimation() {
|
||||
Metamaps.Loading.hide();
|
||||
// load JSON data, if it's not empty
|
||||
if (!self.loadLater) {
|
||||
//load JSON data.
|
||||
var rootIndex = 0;
|
||||
if (Metamaps.Active.Topic) {
|
||||
var node = _.find(Metamaps.JIT.vizData, function(node){
|
||||
return node.id === Metamaps.Active.Topic.id;
|
||||
});
|
||||
rootIndex = _.indexOf(Metamaps.JIT.vizData, node);
|
||||
}
|
||||
self.mGraph.loadJSON(Metamaps.JIT.vizData, rootIndex);
|
||||
//compute positions and plot.
|
||||
self.computePositions();
|
||||
self.mGraph.busy = true;
|
||||
if (self.type == "RGraph") {
|
||||
self.mGraph.fx.animate(Metamaps.JIT.RGraph.animate);
|
||||
} else if (self.type == "ForceDirected") {
|
||||
self.mGraph.animate(Metamaps.JIT.ForceDirected.animateSavedLayout);
|
||||
} else if (self.type == "ForceDirected3D") {
|
||||
self.mGraph.animate(Metamaps.JIT.ForceDirected.animateFDLayout);
|
||||
}
|
||||
}
|
||||
}
|
||||
// hold until all the needed metacode images are loaded
|
||||
// hold for a maximum of 80 passes, or 4 seconds of waiting time
|
||||
var tries = 0;
|
||||
function hold() {
|
||||
var unique = _.uniq(Metamaps.Topics.models, function (metacode) { return metacode.get('metacode_id'); }),
|
||||
requiredMetacodes = _.map(unique, function (metacode) { return metacode.get('metacode_id'); }),
|
||||
loadedCount = 0;
|
||||
|
||||
_.each(requiredMetacodes, function (metacode_id) {
|
||||
var metacode = Metamaps.Metacodes.get(metacode_id),
|
||||
img = metacode ? metacode.get('image') : false;
|
||||
|
||||
if (img && (img.complete || (typeof img.naturalWidth !== "undefined" && img.naturalWidth !== 0))) {
|
||||
loadedCount += 1;
|
||||
}
|
||||
});
|
||||
|
||||
if (loadedCount === requiredMetacodes.length || tries > 80) runAnimation();
|
||||
else setTimeout(function(){ tries++; hold() }, 50);
|
||||
}
|
||||
hold();
|
||||
|
||||
// update the url now that the map is ready
|
||||
clearTimeout(Metamaps.Router.timeoutId);
|
||||
Metamaps.Router.timeoutId = setTimeout(function(){
|
||||
var m = Metamaps.Active.Map;
|
||||
var t = Metamaps.Active.Topic;
|
||||
|
||||
if (m && window.location.pathname !== "/maps/" + m.id) {
|
||||
Metamaps.Router.navigate("/maps/" + m.id);
|
||||
}
|
||||
else if (t && window.location.pathname !== "/topics/" + t.id) {
|
||||
Metamaps.Router.navigate("/topics/" + t.id);
|
||||
}
|
||||
}, 800);
|
||||
|
||||
}
|
||||
}; // end Metamaps.Visualize
|
||||
|
|
Loading…
Add table
Reference in a new issue