I have made some engineering drawings using graphviz. They use a model of risk using the bow-tie approach (popular in some heavy engineering industries). Graphviz can model risk this way really well though they are not strictly graphs.
My graphviz bow-ties are exported to SVG and I embed them directly in HTML and publish them as static files.
Some of the graph nodes are called "Threats" in the bow-tie model. I make these Threat nodes hyperlink to other HTML pages dedicaded to these threats.
I have copies of the same SVG bow-tie at the top of every Threat page, to help the reader (I reproduce it each time rather than link to it.)
It all works as planned but I would like the pages to be a bit more lively.
I can add the static node fill colour in graphviz but I don't know what to do with the SVG or CSS code.
Here is the SVG export from graphviz, followed by the (much shorter) graphviz dot code. I don't usually edit the SVG code by hand at all directly so I would like any changes to please be as basic as possible.
I have made a generic example here to keep the length down but all my risk drawings are identical in concept.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.26.3 (20100126.1600)
-->
<!-- Title: tiger Pages: 1 -->
<svg width="864pt" height="354pt"
viewBox="0.00 0.00 864.00 354.43" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(0.44582 0.44582) rotate(0) translate(4 791)">
<title>tiger</title>
<polygon fill="white" stroke="white" points="-4,5 -4,-791 1935,-791 1935,5 -4,5"/>
<!-- ESCAPED \nTIGER -->
<g id="node1" class="node"><title>ESCAPED \nTIGER</title>
<a xlink:title="Top Event">
<ellipse fill="crimson" stroke="crimson" cx="977" cy="-372" rx="148.01" ry="148.01"/>
<ellipse fill="none" stroke="crimson" cx="977" cy="-372" rx="148.01" ry="148.01"/>
<ellipse fill="none" stroke="crimson" cx="977" cy="-372" rx="152.01" ry="152.01"/>
<text text-anchor="middle" x="977" y="-382" font-family="Times Roman,serif" font-size="40.00" fill="white">ESCAPED </text>
<text text-anchor="middle" x="977" y="-336" font-family="Times Roman,serif" font-size="40.00" fill="white">TIGER</text>
</a>
</g>
<!-- TIGERPIC -->
<g id="node2" class="node"><title>TIGERPIC</title>
<a xlink:title="Hazard">
<image xlink:href="tiger.gif" width="376px" height="203px" preserveAspectRatio="xMinYMin meet" x="789" y="-202.5"/>
<polygon fill="none" stroke="none" points="1165,-202.5 789,-202.5 789,0.5 1165,0.5 1165,-202.5"/>
</a>
</g>
<!-- ESCAPED \nTIGER->TIGERPIC -->
<g id="edge5" class="edge"><title>ESCAPED \nTIGER->TIGERPIC</title>
<path fill="none" stroke="black" stroke-width="10" d="M977,-219.683C977,-213.821 977,-207.958 977,-202.096"/>
</g>
<!-- SEARCH\nPLAN -->
<g id="node14" class="node"><title>SEARCH\nPLAN</title>
<a xlink:href="./search.html" xlink:title="Control">
<polygon fill="darkgreen" stroke="darkgreen" points="1318,-437 1202,-437 1202,-369 1318,-369 1318,-437"/>
<polygon fill="none" stroke="darkgreen" points="1318,-437 1202,-437 1202,-369 1318,-369 1318,-437"/>
<text text-anchor="middle" x="1260" y="-410.5" font-family="Times Roman,serif" font-size="25.00" fill="white">SEARCH</text>
<text text-anchor="middle" x="1260" y="-380.5" font-family="Times Roman,serif" font-size="25.00" fill="white">PLAN</text>
</a>
</g>
<!-- ESCAPED \nTIGER->SEARCH\nPLAN -->
<g id="edge15" class="edge"><title>ESCAPED \nTIGER->SEARCH\nPLAN</title>
<path fill="none" stroke="green" stroke-width="10" d="M1128.44,-388.589C1154.59,-391.454 1180.29,-394.269 1201.94,-396.64"/>
</g>
<!-- INSURANCE -->
<g id="node16" class="node"><title>INSURANCE</title>
<a xlink:href="./insurance.html" xlink:title="Control">
<polygon fill="darkgreen" stroke="darkgreen" points="1513,-354 1355,-354 1355,-316 1513,-316 1513,-354"/>
<polygon fill="none" stroke="darkgreen" points="1513,-354 1355,-354 1355,-316 1513,-316 1513,-354"/>
<text text-anchor="middle" x="1434" y="-327.5" font-family="Times Roman,serif" font-size="25.00" fill="white">INSURANCE</text>
</a>
</g>
<!-- ESCAPED \nTIGER->INSURANCE -->
<g id="edge19" class="edge"><title>ESCAPED \nTIGER->INSURANCE</title>
<path fill="none" stroke="brown" stroke-width="10" d="M1128.54,-359.731C1204.02,-353.62 1292.18,-346.482 1354.34,-341.45"/>
</g>
<!-- GATE\nPASSABLE\n\by\nTIGER -->
<g id="node4" class="node"><title>GATE\nPASSABLE\n\by\nTIGER</title>
<a xlink:title="Threat">
<polygon fill="red" stroke="red" points="202,-743.019 -0.232539,-471.49 404.233,-471.49 202,-743.019"/>
<polygon fill="none" stroke="red" points="202,-743.019 -0.232539,-471.49 404.233,-471.49 202,-743.019"/>
<text text-anchor="middle" x="202" y="-599.5" font-family="Times Roman,serif" font-size="25.00" fill="white">GATE</text>
<text text-anchor="middle" x="202" y="-569.5" font-family="Times Roman,serif" font-size="25.00" fill="white">PASSABLE</text>
<text text-anchor="middle" x="202" y="-539.5" font-family="Times Roman,serif" font-size="25.00" fill="white">by</text>
<text text-anchor="middle" x="202" y="-509.5" font-family="Times Roman,serif" font-size="25.00" fill="white">TIGER</text>
</a>
</g>
<!-- GATE\nDESIGN -->
<g id="node11" class="node"><title>GATE\nDESIGN</title>
<a xlink:href="./design.html" xlink:title="Control">
<polygon fill="darkgreen" stroke="darkgreen" points="551,-406 441,-406 441,-338 551,-338 551,-406"/>
<polygon fill="none" stroke="darkgreen" points="551,-406 441,-406 441,-338 551,-338 551,-406"/>
<text text-anchor="middle" x="496" y="-379.5" font-family="Times Roman,serif" font-size="25.00" fill="white">GATE</text>
<text text-anchor="middle" x="496" y="-349.5" font-family="Times Roman,serif" font-size="25.00" fill="white">DESIGN</text>
</a>
</g>
<!-- GATE\nPASSABLE\n\by\nTIGER->GATE\nDESIGN -->
<g id="edge7" class="edge"><title>GATE\nPASSABLE\n\by\nTIGER->GATE\nDESIGN</title>
<path fill="none" stroke="red" stroke-width="10" d="M342.112,-471.452C378.198,-448.13 414.84,-424.451 443.311,-406.05"/>
</g>
<!-- KEEPER\nLEAVES\nGATE\nOPEN -->
<g id="node5" class="node"><title>KEEPER\nLEAVES\nGATE\nOPEN</title>
<a xlink:title="Threat">
<polygon fill="red" stroke="red" points="202,-363.019 45.0223,-91.4903 358.978,-91.4903 202,-363.019"/>
<polygon fill="none" stroke="red" points="202,-363.019 45.0223,-91.4903 358.978,-91.4903 202,-363.019"/>
<text text-anchor="middle" x="202" y="-219.5" font-family="Times Roman,serif" font-size="25.00" fill="white">KEEPER</text>
<text text-anchor="middle" x="202" y="-189.5" font-family="Times Roman,serif" font-size="25.00" fill="white">LEAVES</text>
<text text-anchor="middle" x="202" y="-159.5" font-family="Times Roman,serif" font-size="25.00" fill="white">GATE</text>
<text text-anchor="middle" x="202" y="-129.5" font-family="Times Roman,serif" font-size="25.00" fill="white">OPEN</text>
</a>
</g>
<!-- KEEPER\nLEAVES\nGATE\nOPEN->GATE\nDESIGN -->
<g id="edge11" class="edge"><title>KEEPER\nLEAVES\nGATE\nOPEN->GATE\nDESIGN</title>
<path fill="none" stroke="blue" stroke-width="10" d="M278.478,-231.424C330.2,-264.85 397.187,-308.141 443.078,-337.799"/>
</g>
<!-- EATS\nMEMBER\nof\nPUBLIC -->
<g id="node7" class="node"><title>EATS\nMEMBER\nof\nPUBLIC</title>
<a xlink:title="Consequence">
<polygon fill="red" stroke="red" points="1740,-787.019 1566.05,-515.49 1913.95,-515.49 1740,-787.019"/>
<polygon fill="none" stroke="red" points="1740,-787.019 1566.05,-515.49 1913.95,-515.49 1740,-787.019"/>
<text text-anchor="middle" x="1740" y="-643.5" font-family="Times Roman,serif" font-size="25.00" fill="white">EATS</text>
<text text-anchor="middle" x="1740" y="-613.5" font-family="Times Roman,serif" font-size="25.00" fill="white">MEMBER</text>
<text text-anchor="middle" x="1740" y="-583.5" font-family="Times Roman,serif" font-size="25.00" fill="white">of</text>
<text text-anchor="middle" x="1740" y="-553.5" font-family="Times Roman,serif" font-size="25.00" fill="white">PUBLIC</text>
</a>
</g>
<!-- LOSS\nof\nREVENUE -->
<g id="node8" class="node"><title>LOSS\nof\nREVENUE</title>
<a xlink:title="Consequence">
<polygon fill="red" stroke="red" points="1740,-407.593 1551,-199.704 1929,-199.704 1740,-407.593"/>
<polygon fill="none" stroke="red" points="1740,-407.593 1551,-199.704 1929,-199.704 1740,-407.593"/>
<text text-anchor="middle" x="1740" y="-291.5" font-family="Times Roman,serif" font-size="25.00" fill="white">LOSS</text>
<text text-anchor="middle" x="1740" y="-261.5" font-family="Times Roman,serif" font-size="25.00" fill="white">of</text>
<text text-anchor="middle" x="1740" y="-231.5" font-family="Times Roman,serif" font-size="25.00" fill="white">REVENUE</text>
</a>
</g>
<!-- INSPECTION\n\&\nTESTING -->
<g id="node12" class="node"><title>INSPECTION\n\&\nTESTING</title>
<a xlink:href="./inspection.html" xlink:title="Control">
<polygon fill="darkgreen" stroke="darkgreen" points="752,-464 588,-464 588,-366 752,-366 752,-464"/>
<polygon fill="none" stroke="darkgreen" points="752,-464 588,-464 588,-366 752,-366 752,-464"/>
<text text-anchor="middle" x="670" y="-437.5" font-family="Times Roman,serif" font-size="25.00" fill="white">INSPECTION</text>
<text text-anchor="middle" x="670" y="-407.5" font-family="Times Roman,serif" font-size="25.00" fill="white">&</text>
<text text-anchor="middle" x="670" y="-377.5" font-family="Times Roman,serif" font-size="25.00" fill="white">TESTING</text>
</a>
</g>
<!-- GATE\nDESIGN->INSPECTION\n\&\nTESTING -->
<g id="edge8" class="edge"><title>GATE\nDESIGN->INSPECTION\n\&\nTESTING</title>
<path fill="none" stroke="red" stroke-width="10" d="M551.533,-385.724C563.07,-388.575 575.46,-391.637 587.725,-394.668"/>
</g>
<!-- TRAINING -->
<g id="node13" class="node"><title>TRAINING</title>
<a xlink:href="./training.html" xlink:title="Control">
<polygon fill="darkgreen" stroke="darkgreen" points="737,-348 603,-348 603,-310 737,-310 737,-348"/>
<polygon fill="none" stroke="darkgreen" points="737,-348 603,-348 603,-310 737,-310 737,-348"/>
<text text-anchor="middle" x="670" y="-321.5" font-family="Times Roman,serif" font-size="25.00" fill="white">TRAINING</text>
</a>
</g>
<!-- GATE\nDESIGN->TRAINING -->
<g id="edge12" class="edge"><title>GATE\nDESIGN->TRAINING</title>
<path fill="none" stroke="blue" stroke-width="10" d="M551.533,-358.276C567.844,-354.245 585.861,-349.793 602.817,-345.603"/>
</g>
<!-- INSPECTION\n\&\nTESTING->ESCAPED \nTIGER -->
<g id="edge9" class="edge"><title>INSPECTION\n\&\nTESTING->ESCAPED \nTIGER</title>
<path fill="none" stroke="red" stroke-width="10" d="M752.27,-403.477C775.182,-400.268 800.815,-396.677 826.342,-393.102"/>
</g>
<!-- TRAINING->ESCAPED \nTIGER -->
<g id="edge13" class="edge"><title>TRAINING->ESCAPED \nTIGER</title>
<path fill="none" stroke="blue" stroke-width="10" d="M737.372,-338.437C763.76,-342.132 795.168,-346.532 826.415,-350.908"/>
</g>
<!-- DART\nGUN -->
<g id="node15" class="node"><title>DART\nGUN</title>
<a xlink:href="./dartgun.html" xlink:title="Control">
<polygon fill="darkgreen" stroke="darkgreen" points="1475,-573 1393,-573 1393,-505 1475,-505 1475,-573"/>
<polygon fill="none" stroke="darkgreen" points="1475,-573 1393,-573 1393,-505 1475,-505 1475,-573"/>
<text text-anchor="middle" x="1434" y="-546.5" font-family="Times Roman,serif" font-size="25.00" fill="white">DART</text>
<text text-anchor="middle" x="1434" y="-516.5" font-family="Times Roman,serif" font-size="25.00" fill="white">GUN</text>
</a>
</g>
<!-- SEARCH\nPLAN->DART\nGUN -->
<g id="edge16" class="edge"><title>SEARCH\nPLAN->DART\nGUN</title>
<path fill="none" stroke="green" stroke-width="10" d="M1303.91,-437.319C1331.19,-458.643 1366.04,-485.88 1392.8,-506.797"/>
</g>
<!-- DART\nGUN->EATS\nMEMBER\nof\nPUBLIC -->
<g id="edge17" class="edge"><title>DART\nGUN->EATS\nMEMBER\nof\nPUBLIC</title>
<path fill="none" stroke="green" stroke-width="10" d="M1475.27,-548.036C1508.79,-555.376 1558.05,-566.162 1605.02,-576.445"/>
</g>
<!-- INSURANCE->LOSS\nof\nREVENUE -->
<g id="edge20" class="edge"><title>INSURANCE->LOSS\nof\nREVENUE</title>
<path fill="none" stroke="brown" stroke-width="10" d="M1513.6,-317.832C1550.43,-309.887 1594.7,-300.338 1634.29,-291.8"/>
</g>
</g>
</svg>
This is graphviz dot code for the bow-ties:
digraph tiger {
overlap=scale;
splines=true;
// clusters=dotted;
ordering=out;
size="12,12!"
bgcolor=white;
rankdir=LR;
root="ESCAPED \nTIGER" // for twopi and circo
// Middle nodes
"ESCAPED \nTIGER" [tooltip="Top Event", fontsize=40, width=2, height=2, shape=doublecircle, style=filled, color=crimson, fontcolor=white];
"TIGERPIC" [label="", image="tiger.gif", tooltip="Hazard", fontsize=40, width=2, height=2, shape=rectangle, color=none];
// Lining up!
{rank=same; "GATE\nPASSABLE\n\by\nTIGER" "KEEPER\nLEAVES\nGATE\nOPEN"}
{rank=same; "EATS\nMEMBER\nof\nPUBLIC" "LOSS\nof\nREVENUE"}
{rank=same; "ESCAPED \nTIGER" "TIGERPIC"}
// Top Event and Risk!
"ESCAPED \nTIGER" -> "TIGERPIC" [arrowhead = none, penwidth=10];
// Threats and consequences
"GATE\nPASSABLE\n\by\nTIGER" [tooltip="Threat", color=red, shape=triangle, style=filled, fontcolor=white, fontsize=25];
"KEEPER\nLEAVES\nGATE\nOPEN" [tooltip="Threat", color=red, shape=triangle, style=filled, fontcolor=white, fontsize=25];
"EATS\nMEMBER\nof\nPUBLIC" [tooltip="Consequence", color=red, shape=triangle, style=filled, fontcolor=white, fontsize=25];
"LOSS\nof\nREVENUE" [tooltip="Consequence", color=red, shape=triangle, style=filled, fontcolor=white, fontsize=25];
// Controls!
"GATE\nDESIGN" [URL="./design.html", tooltip="Control", shape=box, style=filled, color=darkgreen, fontcolor=white, fontsize=25];
"INSPECTION\n\&\nTESTING" [URL="./inspection.html", tooltip="Control", shape=box, style=filled, color=darkgreen, fontcolor=white, fontsize=25];
"TRAINING" [URL="./training.html", tooltip="Control", shape=box, style=filled, color=darkgreen, fontcolor=white, fontsize=25];
"SEARCH\nPLAN" [URL="./search.html", tooltip="Control", shape=box, style=filled, color=darkgreen, fontcolor=white, fontsize=25];
"DART\nGUN" [URL="./dartgun.html", tooltip="Control", shape=box, style=filled, color=darkgreen, fontcolor=white, fontsize=25];
"INSURANCE" [URL="./insurance.html", tooltip="Control", shape=box, style=filled, color=darkgreen, fontcolor=white, fontsize=25];
// Joining up
"GATE\nPASSABLE\n\by\nTIGER" -> "GATE\nDESIGN" -> "INSPECTION\n\&\nTESTING" -> "ESCAPED \nTIGER" [arrowhead = none, penwidth=10, color=red];
"KEEPER\nLEAVES\nGATE\nOPEN" -> "GATE\nDESIGN" -> "TRAINING" -> "ESCAPED \nTIGER" [arrowhead = none, penwidth=10, color=blue];
"ESCAPED \nTIGER" -> "SEARCH\nPLAN" -> "DART\nGUN" -> "EATS\nMEMBER\nof\nPUBLIC" [arrowhead = none, penwidth=10, color=green];
"ESCAPED \nTIGER" -> "INSURANCE" -> "LOSS\nof\nREVENUE" [arrowhead = none, penwidth=10, color=brown];
}
//---------------------
// ----- The End! -----
//---------------------
Here's how you can animate the threats with a pulsating color with 2 steps:
Add an id attribute to each threat starting with threat, for example threat1, threat2, ...:
"GATE\nPASSABLE\n\by\nTIGER" [tooltip="Threat", id="threat1", ...];
"KEEPER\nLEAVES\nGATE\nOPEN" [tooltip="Threat", id="threat2", ...];
This will use this attribute as the id in the graphviz svg output.
Add CSS which animates properties based on those id's to the html page which contains the svg. The following CSS will make pulsate color of threats between red and yellow:
g [id*="threat"] polygon {
-webkit-animation: pulse 2s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
animation: pulse 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
@-webkit-keyframes pulse {
from {fill: red;}
to {fill: yellow;}
}
@keyframes pulse {
from {fill: red;}
to {fill: yellow;}
}
As to your second question, the mouse pointer should already change to a hand icon when passing over a hyperlink in the browser. Otherwise, you may use the above technique to add some special effect to those links, too.