Cleaner story tree in Panopticon

This commit is contained in:
Ruben van de Ven 2019-02-18 22:33:31 +01:00
parent 79424ccfbf
commit 8722203704
4 changed files with 77 additions and 9 deletions

View file

@ -162,6 +162,11 @@ img.icon {
width: 385px;
max-height: 100%;
overflow-y: auto; }
#story #msg .directions h3 {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
margin-right: 5em; }
#story #msg .msg__info, #story #msg .directions > div {
padding: 10px;
margin-bottom: 10px;

View file

@ -70,7 +70,7 @@
<div id="btn-addMsg" class="btn">Create message</div>
</div>
<div id="msg"></div>
<svg id='graph' viewbox="0 0 1280 1024"
<svg id='graph' viewbox="-640 -512 1280 1024"
preserveAspectRatio="xMidYMid">
<defs>
<marker markerHeight="8" markerWidth="8" refY="0"

View file

@ -447,7 +447,7 @@ class Graph {
crel(
'h3',
{'title': direction['@id']},
direction['source'] == msg ? `To ${direction['target']['@id']}`: `From ${direction['source']['@id']}`
direction['source'] == msg ? `To ${direction['target']['text']}`: `From ${direction['source']['text']}`
),
crel('div', {
'class':'btn btn--delete',
@ -982,6 +982,8 @@ class Graph {
document.getElementById('current_lang').appendChild(crel('span', {
'class': 'flag-icon ' + this.language_code
}));
this.distances = this.calculateDistancesFromStart();
// save state;
this.saveState();
@ -1018,12 +1020,18 @@ class Graph {
build( isInit ) {
this.simulation = d3.forceSimulation( this.messages )
.force( "link", d3.forceLink( this.directions ).id( d => d['@id'] ) )
.force( "charge", d3.forceManyBody().strength( 100 ) )
.force( "center", d3.forceCenter( this.width / 2, this.height / 2 ) )
.force( "collide", d3.forceCollide( this.nodeSize * 1.7 ) )
.force( "link", d3.forceLink( this.directions ).id( d => d['@id'] ).strength(0) )
// .force( "charge", d3.forceManyBody().strength( 100 ) )
// .force( "center", d3.forceCenter( this.width / 2, this.height / 2 ) )
.force( "collide", d3.forceCollide( this.nodeSize * 2.3 ) )
.force( "forceX", d3.forceX(function(m){
let fx = panopticon.graph.distances[m['@id']] !== null ? panopticon.graph.distances[m['@id']] * panopticon.graph.nodeSize * 4 : 0
console.log('fx', m['@id'], panopticon.graph.distances[m['@id']], fx);
return fx;
}).strength(50))
.force( "forceY", d3.forceY(m => panopticon.graph.distances[m['@id']] !== null ? 0 : panopticon.graph.nodeSize * 3 ).strength(30))
;
this.simulation.velocityDecay(.99);
this.simulation.velocityDecay(.98);
// Update existing nodes
let node = this.nodesG
@ -1036,7 +1044,7 @@ class Graph {
let newNodeG = newNode.append( "g" )
.attr( 'id', d => d['@id'] )
.call( d3.drag( this.simulation ) )
// .call( d3.drag( this.simulation ) )
.on( 'click', function( d ) {
this.clickMsg( d );
}.bind( this ) )
@ -1162,10 +1170,56 @@ class Graph {
// this.simulation.restart();
if ( typeof isInit != 'undefined' && isInit ) {
for ( let i = 0, n = Math.ceil( Math.log( this.simulation.alphaMin() ) / Math.log( 1 - this.simulation.alphaDecay() ) ); i < n; ++i ) {
this.simulation.tick();
// this.simulation.tick();
}
}
return this.svg.node();
}
calculateDistancesFromStart() {
let starts = this.messages.filter( m => m.hasOwnProperty('start') && m['start'] == true);
if (starts.length < 1) {
console.error("No start set");
return;
}
let startMsg = starts[0];
//initiate distances
let distances = {};
for(let msg of this.messages) {
distances[msg['@id']] = msg === startMsg ? 0 : null;
}
let directionsPerMsg = {};
console.log("dir", this.directions);
for(let direction of this.directions) {
let from = typeof direction['source'] == "string" ? direction['source'] : direction['source']['@id'];
let to = typeof direction['target'] == "string" ? direction['target'] : direction['target']['@id'];
if(!directionsPerMsg.hasOwnProperty(from)) {
directionsPerMsg[from] = [];
}
directionsPerMsg[from].push(to);
}
let traverseMsg = function(msgId, depth) {
if(!directionsPerMsg.hasOwnProperty(msgId)) {
// end of trail
return;
}
for(let childMsgId of directionsPerMsg[msgId]) {
if(distances[childMsgId] === null || distances[childMsgId] > depth) {
distances[childMsgId] = depth;
traverseMsg(childMsgId, depth+1);
} else {
// apparently, there is a loop. Don't traverse it.
}
}
}
traverseMsg(startMsg['@id'], 1);
return distances;
}
}

View file

@ -265,6 +265,15 @@ img.icon{
max-height:100%;
overflow-y: auto;
.directions{
h3{
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
margin-right: 5em;
}
}
.msg__info, .directions > div{
padding: 10px;
margin-bottom: 10px;