Last active
December 14, 2023 22:17
-
-
Save Hugoberry/9423b215bf16f484a18146a11dcb7d2b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<head> | |
<script type="text/javascript"> | |
mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src'; | |
</script> | |
<script type="text/javascript" src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script> | |
<script type="text/javascript"> | |
function wrangle(data) { | |
var charactersMap = {}; | |
return data.scenes.map(function(scene) { | |
return { | |
characters: scene.map(function(id) { | |
return characterById(id); | |
}).filter(function(d) { | |
return (d); | |
}) | |
}; | |
}); | |
// Helper to get characters by ID from the raw data | |
function characterById(id) { | |
charactersMap = charactersMap || {}; | |
charactersMap[id] = charactersMap[id] || data.characters.find(function(character) { | |
return character.id === id; | |
}); | |
return charactersMap[id]; | |
} | |
}; | |
function main(container) { | |
const scenes = wrangle(data); | |
const sceneWidth = 14; | |
const width = scenes.length * sceneWidth * 4; | |
const height = 300; | |
var narrative = d3.layout.narrative() | |
.scenes(scenes) | |
.size([width, height]) | |
.pathSpace(10) | |
.groupMargin(20) | |
.labelSize([110, 15]) | |
.scenePadding([5, sceneWidth / 2, 5, sceneWidth / 2]) | |
.labelPosition('left') | |
.layout(); | |
mxEvent.disableContextMenu(container); | |
const graph = new mxGraph(container); | |
const model = graph.getModel(); | |
// Disables basic selection and cell handling | |
graph.setEnabled(false); | |
graph.setConnectable(false); | |
graph.setCellsResizable(false); | |
const parent = graph.getDefaultParent(); | |
var style =[]; | |
style[mxConstants.STYLE_EDGE] = mxEdgeStyle.SegmentConnector; | |
style[mxConstants.STYLE_ENDARROW] = mxConstants.NONE; | |
style[mxConstants.STYLE_CURVED] = 1; | |
graph.getStylesheet().putDefaultEdgeStyle(style); | |
// Adds cells to the model in a single step | |
model.beginUpdate(); | |
try { | |
// Dictionary to hold references to all appearance vertices | |
const appearanceVertices = {}; | |
const introVertices = {}; | |
// Draw scenes as rectangles (clusters) | |
const scenes = narrative.scenes(); | |
scenes.forEach((scene, sceneIndex) => { | |
const cluster = graph.insertVertex( | |
parent, null, '', Math.round(scene.x) + 0.5, Math.round(scene.y) + 0.5, sceneWidth, scene.height, | |
'rounded=1;arcSize=30;'); | |
cluster.setConnectable(false); | |
//cluster.setCellsResizable(false); | |
// Draw appearances as circles inside each cluster scene | |
scene.appearances.forEach((appearance, appearanceIndex) => { | |
const characterId = appearance.character.id; | |
const appearanceVertex = graph.insertVertex( | |
cluster, null, '', appearance.x - 2, appearance.y, 4, 4, | |
'shape=ellipse;fillColor=black;strokeColor=black;' | |
); | |
// Add this appearance to the dictionary with scene and character as the key | |
if (!appearanceVertices[characterId]) { | |
appearanceVertices[characterId] = {}; | |
} | |
appearanceVertices[characterId][scene.start] = appearanceVertex; | |
}); | |
}); | |
// Function to get the vertex from appearanceVertices or introVertices | |
function getVertex(characterId, sceneStart, isSource) { | |
return isSource && sceneStart == null ? | |
introVertices[characterId] : | |
appearanceVertices[characterId] && appearanceVertices[characterId][sceneStart]; | |
}; | |
narrative.introductions().forEach(function(d) { | |
const x = Math.round(d.x); | |
const y = Math.round(d.y); | |
const label = d.character.name; | |
// Create a vertex for the introduction node | |
const intro = graph.insertVertex(parent, null, label, x, y, '', '', 'align=right'); | |
introVertices[d.character.id] = intro; | |
}); | |
// Draw links between the character appearances | |
const links = narrative.links(); | |
links.forEach((link) => { | |
const sourceCharacterId = link.source.character.id; | |
const targetCharacterId = link.target.character.id; | |
const sourceSceneStart = link.source.scene ? link.source.scene.start : null; | |
const targetSceneStart = link.target.scene ? link.target.scene.start : null; | |
const sourceVertex = getVertex(sourceCharacterId, sourceSceneStart, true); | |
const targetVertex = getVertex(targetCharacterId, targetSceneStart, false); | |
if (sourceVertex && targetVertex) { | |
graph.insertEdge(parent, null, '', sourceVertex, targetVertex,'curved=1;endArrow=None'); | |
} | |
}); | |
} finally { | |
model.endUpdate(); | |
} | |
var encoder = new mxCodec(); | |
var result = encoder.encode(graph.getModel()); | |
var xml = mxUtils.getXml(result); | |
console.log(xml); | |
}; | |
</script> | |
</head> | |
<body onload="main(document.getElementById('graphContainer'))"> | |
<div id="graphContainer" style="position:relative;overflow:hidden;width:100%;height:100%;cursor:default;"> | |
</div> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment