Fancier markers and legend

This commit is contained in:
Ruben van de Ven 2021-04-28 11:18:02 +02:00
parent 7751fc05a8
commit 4dec76a325
2 changed files with 84 additions and 29 deletions

View file

@ -6,7 +6,7 @@
}
:root {
--color1: #f94144;
--color1: #9741f9;
--color2: #f3722c;
--color3: #f8961e;
/* --color4: #f9844a; */
@ -40,8 +40,17 @@ svg.dragging {
cursor: grabbing;
}
#arrowHead {
fill: #9df32c;
}
#arrowHeadSelected {
fill: var(--hover-color);;
}
svg .links line, svg .links path {
stroke: #f3722c;
stroke: #9df32c;
stroke-width: 6;
fill: none;
transition: stroke-width 1s;
@ -51,6 +60,7 @@ svg .links line, svg .links path {
svg .links line.hover, svg .links path.hover {
stroke: var(--hover-color);
stroke-width: 12;
marker-end: url(#arrowHeadSelected);
}
svg.zoomed .links line, svg.zoomed .links path {
@ -70,11 +80,12 @@ svg .subtitle {
font-size: 100;
}
svg #countries .country{
fill:rgba(200,200,200,0.7);
svg #countries .country {
fill: rgba(200, 200, 200, 0.7);
}
svg #countries .country.eu_country{
fill:black;
svg #countries .country.eu_country {
fill: black;
}
svg #header #titlePath, svg #header #subtitlePath {
@ -117,7 +128,8 @@ svg #header text#subtitle {
text-anchor: start;
dominant-baseline: hanging;
/*achieves a 'text-anchor: top'*/
/* font-size: 16pt; */ /*Set this in JS*/
/* font-size: 16pt; */
/*Set this in JS*/
transition: font-size .4s, opacity 1s;
fill: white;
opacity: 1;
@ -137,13 +149,14 @@ svg.zoomed.zoomed2 .node text.nodeTitle {
font-size: 3pt;
}
.node circle {
fill: white;
.node circle, .node path {
fill: lightgray;
}
/* Whenever a connected link is hovered */
.node.linkHover circle {
.node.linkHover circle, .node.linkHover path, label:hover .node path {
fill: var(--hover-color) !important;
stroke: var(--hover-color);
stroke-width: 5px;
}
@ -152,7 +165,8 @@ svg.zoomed.zoomed2 .node text.nodeTitle {
transition: opacity 0s;
}
.node:hover circle {
.node:hover circle, .node:hover path {
fill: var(--hover-color) !important;
stroke: var(--hover-color);
stroke-width: 5px;
}
@ -162,12 +176,13 @@ svg.zoomed.zoomed2 .node text.nodeTitle {
fill: var(--hover-color);
}
.node.selected circle {
.node.selected circle, .node.selected path {
fill: var(--selected-color) !important;
stroke: var(--selected-color);
stroke-width: 5px;
}
.node.City circle {
.node.City circle, .node.City path {
display: none;
}
@ -178,24 +193,24 @@ svg.zoomed.zoomed2 .node text.nodeTitle {
font-size: 20px;
}
.node.Person circle {
.node.Person circle, .node.Person path {
fill: lightgreen
}
.node.Technology circle {
fill: lightcoral;
.node.Technology circle, .node.Technology path {
fill: plum;
}
.node.Deployment circle {
.node.Deployments circle, .node.Deployments path {
fill: lightblue;
}
.node.Institution circle {
fill: lightgoldenrodyellow
.node.Institution circle, .node.Institution path {
fill: lightcoral
}
.node.Dataset circle {
fill: plum
.node.Dataset circle, .node.Dataset path {
fill: lightgoldenrodyellow
}
.labels .label text {
@ -284,29 +299,37 @@ p.subtitle {
display: none;
}
#filters h3{
text-align: center;;
#filters h3 {
text-align: center;
;
}
#filters label {
cursor: pointer;
display: block;
padding: 10px;
}
#filters label svg {
display: inline;
width: 30px;
height: 30px;
vertical-align: middle;
}
#filters span:hover {
color: var(--hover-color);
}
#filters input {
/* display: none; */
display: none;
}
#filters input+span {
display: inline-block;
padding-left: 10px;
/* background: var(--color9); */
text-decoration:line-through;
text-decoration: line-through;
}
#filters input:checked+span {

View file

@ -4,7 +4,7 @@ const CONFIG = {
'subtitle': "Connections in the European Union & beyond",
// 'nodeSize': 8,
'nodeRadius': 5,
'nodeRepositionPadding': 3,
'nodeRepositionPadding': 8,
'baseUrl': 'https://www.securityvision.io/wiki/index.php/',
'dataUrl': 'result.json',
'preSimulate': false, // run simulation before starting, so we don't start with lines jumping around
@ -58,6 +58,27 @@ const CONFIG = {
// let height = window.innerHeight;
function getSymbolForCategories(classes) {
if(!Array.isArray(classes)) {
classes = [classes];
}
if (classes.includes('Institution')) {
return d3.symbol()
.type(d3.symbolTriangle)
.size(CONFIG.nodeRadius * 16);
}
return d3.symbol()
.type(d3.symbolCircle)
.size(CONFIG.nodeRadius * 16);
}
// returns a symbol function
function getSymbolForNode(n) {
const classes = getCategories(n);
return getSymbolForCategories(classes);
}
// Slugify a string, by https://lucidar.me/en/web-dev/how-to-slugify-a-string-in-javascript/
function slugify(str) {
str = str.replace(/^\s+|\s+$/g, '');
@ -226,7 +247,7 @@ class NodeMap {
render() {
this.svg = this.root.append('svg')
this.svg.append('defs').html(`<marker markerHeight="4" markerWidth="4" refY="0" refX="6" viewBox="0 -3 8 6" preserveAspectRatio="none" orient="auto" id="arrowHead" fill="#f3722c"><path d="M0,-3L8,0L0,3"></path></marker><marker markerHeight="4" markerWidth="4" refY="0" refX="6" viewBox="0 -3 8 6" preserveAspectRatio="none" orient="auto" id="arrowHeadSelected"><path d="M0,-3L8,0L0,3" fill="white"></path></marker>
this.svg.append('defs').html(`<marker markerHeight="4" markerWidth="4" refY="0" refX="6" viewBox="0 -3 8 6" preserveAspectRatio="none" orient="auto" id="arrowHead" ><path d="M0,-3L8,0L0,3"></path></marker><marker markerHeight="4" markerWidth="4" refY="0" refX="6" viewBox="0 -3 8 6" preserveAspectRatio="none" orient="auto" id="arrowHeadSelected"><path d="M0,-3L8,0L0,3"></path></marker>
<!--Sketching:-->
<defs>
<filter id="tint">
@ -302,7 +323,7 @@ class NodeMap {
this.container.attr("transform", transform);
const oldZoom = this.svg.classed('zoomed');
const newZoom = transform.k > 2.0;
if(zoomTimeout) {
if (zoomTimeout) {
clearTimeout(zoomTimeout)
}
zoomTimeout = setTimeout(() => {
@ -522,7 +543,11 @@ class NodeMap {
let group = enter.append("g").attr("class", getClasses);
// group.call(drag(simulation));
group.on("click", (evt, n) => selectNode(evt, n, node));
group.append('circle').attr("r", 5 /*this.nodeSize*/);
// group.append('circle').attr("r", 5 /*this.nodeSize*/);
group.append('path')
.attr('d', (n) => {
return getSymbolForNode(n)(n);
})
var nodeTitle = group.append('text').attr("class", "nodeTitle").attr("y", "3").attr('x', 5);
nodeTitle
.each(function (node, i, nodes) {
@ -1288,9 +1313,16 @@ class Store {
render() {
CONFIG.filters.forEach(f => {
let labelEl = document.createElement('label')
let inputEl = document.createElement('input')
let textEl = document.createElement('span');
let svg = d3.select(labelEl).append('svg')
.attr("viewBox", [-12,-12,24,24]);
svg.append('g')
.attr("class", "node "+ f)
.append('path')
.attr('d', getSymbolForCategories(f)());
inputEl.type = "checkbox";
textEl.innerText = f;
labelEl.appendChild(inputEl);