New styling WIP, with square images

This commit is contained in:
Ruben van de Ven 2018-09-22 19:22:05 +02:00
parent e1072f9899
commit b21c467c54
6 changed files with 272 additions and 19464 deletions

View file

@ -6,6 +6,10 @@ var rename = require('gulp-rename');
var uglify = require('gulp-uglify'); var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps'); var sourcemaps = require('gulp-sourcemaps');
var browserSync = require('browser-sync'); var browserSync = require('browser-sync');
var jsonld = require('jsonld');
var through = require('through2')
// todo: rollup for d3 & possibly jsonld // todo: rollup for d3 & possibly jsonld
var paths = { var paths = {
@ -19,7 +23,7 @@ var paths = {
}, },
"data": { "data": {
"src": "./rubenvandeven.jsonld", "src": "./rubenvandeven.jsonld",
"dest": "./assets/rubenvandeven.jsonld" "dest": "./assets/js/"
} }
}; };
@ -47,9 +51,24 @@ gulp.task('scripts', function() {
.pipe(gulp.dest(paths.scripts.dest)) // save .min.js .pipe(gulp.dest(paths.scripts.dest)) // save .min.js
}); });
gulp.task('jsonld', function(){
return gulp.src(paths.data.src)
.pipe(through.obj(function (file, enc, callback) {
let data = JSON.parse(file.contents.toString(enc));
var transformedFile = file.clone();
// console.log(data);
jsonld.flatten(data, {"@context": "https://schema.org/"}, (err, flattened)=> {
transformedFile.contents = Buffer.from(JSON.stringify(flattened), enc);
callback(null, transformedFile)
});
}))
.pipe(gulp.dest(paths.data.dest));
});
var watchStylesAndScripts = function() { var watchStylesAndScripts = function() {
gulp.watch(paths.styles.src,['styles']); gulp.watch(paths.styles.src,['styles']);
gulp.watch(paths.scripts.src,['scripts', browserSync.reload]); gulp.watch(paths.scripts.src,['scripts', browserSync.reload]);
gulp.watch([paths.data.src], ['jsonld', browserSync.reload]);
} }
gulp.task('watch', watchStylesAndScripts); gulp.task('watch', watchStylesAndScripts);

View file

@ -2,7 +2,7 @@
<html xmlns:xlink="http://www.w3.org/1999/xlink"> <html xmlns:xlink="http://www.w3.org/1999/xlink">
<head> <head>
<title></title> <title></title>
<link href="rubenvandeven.jsonld" rel="alternate" type="application/ld+json" /> <link href="/rubenvandeven.jsonld" rel="alternate" type="application/ld+json" />
<link rel="stylesheet" href="/assets/css/portfolio.css"> <link rel="stylesheet" href="/assets/css/portfolio.css">
</head> </head>
<body> <body>
@ -44,6 +44,10 @@
<clipPath id="clipNodeImage"> <clipPath id="clipNodeImage">
<circle cx="40" cy="40" r="40" /> <circle cx="40" cy="40" r="40" />
</clipPath> </clipPath>
<pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="testback.png" x="0" y="0" width="100" height="100" />
</pattern>
</defs> </defs>
</svg> </svg>
<div id="nodeDetails"> <div id="nodeDetails">
@ -52,6 +56,8 @@
<div id="graphControls"> <div id="graphControls">
<span class="typeJump">Show:</span> <span class="typeJump">Show:</span>
<ul id='typeLinks'></ul> <ul id='typeLinks'></ul>
<span class="showMoreTypeLinks">...</span>
<ul id='moreTypeLinks'></ul>
<!-- <ul id='relLinks'></ul> --> <!-- <ul id='relLinks'></ul> -->
</div> </div>
<!-- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jsonld@0.5.21/dist/jsonld.js"></script> --> <!-- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jsonld@0.5.21/dist/jsonld.js"></script> -->

View file

@ -4,11 +4,25 @@
"url": "https://rubenvandeven.com", "url": "https://rubenvandeven.com",
"author": "author":
{ {
"@id": "https://rubenvandeven.com/ruben",
"@type": "Person", "@type": "Person",
"name": "Ruben van de Ven", "name": "Ruben van de Ven",
"email": "info@rubenvandeven.com", "email": "info@rubenvandeven.com",
"nationality": "The Netherlands", "nationality": "The Netherlands",
"jobTitle": "digital artist / researcher of software culture",
"@reverse": { "@reverse": {
"member": [
{
"@id": "http://plottingd.at/a",
"@type": "PerformingGroup",
"name": "PlottingD.at/a",
"url": "http://plottingd.at/a",
"description": "A collaboration between Ruben van de Ven and Cristina Cochior.",
"member": [
{"@id": "http://randomizer.info"}
]
}
],
"author": [ "author": [
{ {
"@type": "MediaObject", "@type": "MediaObject",
@ -56,7 +70,7 @@
"@reverse": { "@reverse": {
"workFeatured": [ "workFeatured": [
{ {
"@id": "kick2018exhibit", "@id": "https://rubenvandeven.com/#kick2018exhibit",
"@type": "ExhibitionEvent", "@type": "ExhibitionEvent",
"name": "KickstART", "name": "KickstART",
"location": { "location": {
@ -68,7 +82,7 @@
"endDate": "2018-03-28" "endDate": "2018-03-28"
}, },
{ {
"@id": "in4artSalon", "@id": "https://rubenvandeven.com/#in4artSalon",
"@type": "ExhibitionEvent", "@type": "ExhibitionEvent",
"name": "Salon VI - Innovatism", "name": "Salon VI - Innovatism",
"location": { "location": {
@ -92,7 +106,7 @@
"@reverse": { "@reverse": {
"workFeatured": "workFeatured":
{ {
"@id": "kick2018exhibit" "@id": "https://rubenvandeven.com/#kick2018exhibit"
} }
}, },
"image": [ "image": [
@ -106,7 +120,7 @@
"@reverse": { "@reverse": {
"workFeatured": "workFeatured":
{ {
"@id": "kick2018exhibit" "@id": "https://rubenvandeven.com/#kick2018exhibit"
} }
}, },
"image": [ "image": [
@ -126,7 +140,7 @@
"name": "The Black Box Concern", "name": "The Black Box Concern",
"url": "....", "url": "....",
"location": { "location": {
"@id": "v2_" "@id": "https://rubenvandeven.com/#v2_"
}, },
"startDate": "2017-12", "startDate": "2017-12",
"workFeatured": [] "workFeatured": []
@ -140,7 +154,7 @@
{ {
"@type": "MediaObject", "@type": "MediaObject",
"name": "Emotion Hero", "name": "Emotion Hero",
"description": "Emotion recognition software is being used both as a tool for \u2018objective\u2019 measurements as well as a tool for training one\u2019s facial expressions, eg. for job interviews. Emotion Hero is a literal translation of the paradoxical relation between these applications of the technology.\n\nEmotion Hero is a two-part artwork. On the one hand is a video-game that is freely downloadable for everybody with an Android device (see <a href=\"https://play.google.com\/store\/apps\/details?id=com.rubenvandeven.emotion_hero\">Google Play<\/a>). Inspired by Guitar Hero, the user scores points by following given cues. It provides detailed feedback on the mechanics of the face (eg. \u201cYou showed on 10% Joy when you had to show 100%, smile 99.32% more.\u201d), revealing that rather than being a window into the brain, the face is a controllable surface.\n\nThe second part is a projection that shows the aggregated scores of the game. In order to substantiate their discourse, companies in facial expression measurement employ a huge amount of data collection and processing. The results are displayed in a fixed grid, recalling historical practices that, trough extensive measurement and administration, also aimed to delineate something which is conceptually undelineated: think of Duchenne de Boulogne, Lombroso, and Charcot.\n\nEmotion Hero is a playful invitation to open up the box of expression analysis to reveal the assumptions that underlie this technology.\n\nThe game's emotional intelligence is powered by Affectiva (I was also <a href=\"http://blog.affectiva.com\/sdk-on-the-spot-emotion-hero-app-encourages-play-with-facial-expressions\">interviewed<\/a> by them). This project is produced as part of the <a href=\"http://summersessions.net\/17-projects\/projects-2016\/55-emotion-hero\">Summer Sessions Network for Talent Development<\/a> in a co-production of Arquivo 237 and V2_ Lab for the Unstable Media, with support of the Creative Industries Fund NL.\nIt has been exhibited at the <a href=\"http://www.statefestival.org\/2016\/program-entry\/2016\/emotion-hero-2016\">State Festival 2016<\/a> (Berlin, DE) and Digital &lt;Dis&gt;orders (Frankfurt, DE).", "description": "Emotion recognition software is being used both as a tool for \u2018objective\u2019 measurements as well as a tool for training one\u2019s facial expressions, eg. for job interviews. Emotion Hero is a literal translation of the paradoxical relation between these applications of the technology.\n\nEmotion Hero is a two-part artwork. On the one hand is a video-game that is freely downloadable for everybody with an Android device (see <a href=\"https://play.google.com\/store\/apps\/details?id=com.rubenvandeven.emotion_hero\">Google Play<\/a>). Inspired by Guitar Hero, the user scores points by following given cues. It provides detailed feedback on the mechanics of the face (eg. \u201cYou showed on 10% Joy when you had to show 100%, smile 99.32% more.\u201d), revealing that rather than being a window into the brain, the face is a controllable surface.\n\nThe second part is a projection that shows the aggregated scores of the game. In order to substantiate their discourse, companies in facial expression measurement employ a huge amount of data collection and processing. The results are displayed in a fixed grid, recalling historical practices that, trough extensive measurement and administration, also aimed to delineate something which is conceptually undelineated: think of Duchenne de Boulogne, Lombroso, and Charcot.\n\nEmotion Hero is a playful invitation to open up the box of expression analysis to reveal the assumptions that underlie this technology.\nThe game's emotional intelligence is powered by Affectiva (I was also <a href=\"http://blog.affectiva.com\/sdk-on-the-spot-emotion-hero-app-encourages-play-with-facial-expressions\">interviewed<\/a> by them). This project is produced as part of the <a href=\"http://summersessions.net\/17-projects\/projects-2016\/55-emotion-hero\">Summer Sessions Network for Talent Development<\/a> in a co-production of Arquivo 237 and V2_ Lab for the Unstable Media, with support of the Creative Industries Fund NL.\nIt has been exhibited at the <a href=\"http://www.statefestival.org\/2016\/program-entry\/2016\/emotion-hero-2016\">State Festival 2016<\/a> (Berlin, DE) and Digital &lt;Dis&gt;orders (Frankfurt, DE).",
"url": "https://emotionhero.com", "url": "https://emotionhero.com",
"@reverse": { "@reverse": {
"workFeatured": [ "workFeatured": [
@ -190,7 +204,7 @@
}, },
"startDate": "2017-09", "startDate": "2017-09",
"endDate": "2017-09", "endDate": "2017-09",
"organiser": { "@id":"v2_" }, "organiser": { "@id":"vhttps://rubenvandeven.com/#2_" },
"funded": "Creative Industries Fund", "funded": "Creative Industries Fund",
"workFeatured": [] "workFeatured": []
}, },
@ -209,7 +223,7 @@
"workFeatured": [] "workFeatured": []
}, },
{ {
"@id": "codesandmodes", "@id": "https://rubenvandeven.com/#codesandmodes",
"@type": "ExhibitionEvent", "@type": "ExhibitionEvent",
"name": "Codes & Modes II", "name": "Codes & Modes II",
"organiser": "Integrated Media Arts MFA", "organiser": "Integrated Media Arts MFA",
@ -223,7 +237,7 @@
"workFeatured": [] "workFeatured": []
}, },
{ {
"@id": "stateofemotion", "@id": "https://rubenvandeven.com/#stateofemotion",
"@type": "ExhibitionEvent", "@type": "ExhibitionEvent",
"name": "STATE of Emotion", "name": "STATE of Emotion",
"location": { "location": {
@ -293,7 +307,7 @@
"name": "Test_Lab the Graduation Edition", "name": "Test_Lab the Graduation Edition",
"url": "...", "url": "...",
"location": { "location": {
"@id": "v2_", "@id": "https://rubenvandeven.com/#v2_",
"@type": "Place", "@type": "Place",
"name": "V2_", "name": "V2_",
"address": "Rotterdam" "address": "Rotterdam"
@ -334,6 +348,7 @@
"dateCreated": "2016", "dateCreated": "2016",
"description": "...", "description": "...",
"author": { "author": {
"@id": "http://randomizer.info",
"@type": "Person", "@type": "Person",
"name": "Cristina Cochior", "name": "Cristina Cochior",
"url": "http://randomizer.info" "url": "http://randomizer.info"
@ -412,10 +427,10 @@
"@reverse": { "@reverse": {
"workFeatured": [ "workFeatured": [
{ {
"@id": "codesandmodes" "@id": "https://rubenvandeven.com/#codesandmodes"
}, },
{ {
"@id": "stateofemotion" "@id": "https://rubenvandeven.com/#stateofemotion"
}, },
{ {
"@type": "ExhibitionEvent", "@type": "ExhibitionEvent",
@ -424,7 +439,7 @@
"startDate": "2015-06", "startDate": "2015-06",
"endDate": "2015-06", "endDate": "2015-06",
"location": { "location": {
"@id": "v2_" "@id": "https://rubenvandeven.com/#v2_"
} }
} }
] ]

File diff suppressed because it is too large Load diff

View file

@ -79,19 +79,23 @@ function jsonLdToGraph(data){
} }
var graph; var graph;
// map nodes to their ID
var nodeMap = {}; var nodeMap = {};
jsonld.flatten(window.location.protocol + "//" + window.location.host + "/rubenvandeven.jsonld", {"@context": "https://schema.org/"},(err, flattened)=> { // TODO: map node IDs to their linked node IDs
console.log(err); var linkMap = {};
data = flattened; // TODO: use linkMap to create breadcrumbs per node
graph = jsonLdToGraph(flattened['@graph']); var breadcrumbs = {};
// load the flattened jsonld file
const requestPromise = fetch('/assets/js/rubenvandeven.jsonld')
.then(r => r.json())
.then(data => {
graph = jsonLdToGraph(data['@graph']);
// create a map of nodes by id. // create a map of nodes by id.
for(let i in graph.nodes) { for(let i in graph.nodes) {
nodeMap[graph.nodes[i]['id']] = graph.nodes[i]; nodeMap[graph.nodes[i]['id']] = graph.nodes[i];
} }
// console.log(graph);
startGraph(graph); startGraph(graph);
}); });
function inCircle(dx, dy, r) { function inCircle(dx, dy, r) {
// fastest check if in circle: https://stackoverflow.com/a/7227057 // fastest check if in circle: https://stackoverflow.com/a/7227057
@ -109,6 +113,43 @@ function inCircle(dx, dy, r) {
} }
} }
function createLinkMap(graph) {
let linkMap = {};
for(let link of graph['links']){
if(typeof linkMap[link['source']] == 'undefined') {
linkMap[link['source']] = [];
}
linkMap[link['source']][linkMap[link['source']].length] = {'id': link['target'], 'name': link['name']};
if(typeof linkMap[link['target']] == 'undefined') {
linkMap[link['target']] = [];
}
linkMap[link['target']][linkMap[link['target']].length] = {'id': link['source'], 'name': link['name']};
}
return linkMap;
}
// TODO: make sure, 'shortest' path is favoured.
function createBreadcrumbs(linkMap, srcId) {
let crumbs = {};
let path = [];
let collectLinks = function(srcId, path){
if(typeof crumbs[srcId] !== 'undefined') {
return;
}
crumbs[srcId] = path.slice();
path[path.length] = srcId;
let links = linkMap[srcId];
// collect links, append given list & skip srcId
for(let link of links) {
collectLinks(link['id'], path.slice());
}
}
collectLinks(srcId, path);
return crumbs;
}
var nodePositions = {}; var nodePositions = {};
function startGraph(graph){ function startGraph(graph){
@ -116,11 +157,16 @@ function startGraph(graph){
// config // config
var nodeSize = 40; var nodeSize = 40;
var selectedNodeSize = 140; var selectedNodeSize = 140;
var firstNodeId = "https://rubenvandeven.com/ruben";
// set some vars // set some vars
var currentNodeIdx = 0; var currentNodeIdx = 0;
var currentNodePositionRadius = 0; var currentNodePositionRadius = 0;
var types = {}; var types = {};
linkMap = createLinkMap(graph);
breadcrumbs = createBreadcrumbs(linkMap, firstNodeId);
for (let nodeIdx in graph['nodes']) { for (let nodeIdx in graph['nodes']) {
let type = graph['nodes'][nodeIdx]["type"]; let type = graph['nodes'][nodeIdx]["type"];
if(typeof types[type] == 'undefined') { if(typeof types[type] == 'undefined') {
@ -130,19 +176,26 @@ for (let nodeIdx in graph['nodes']) {
} }
var graphControlsEl = document.getElementById('graphControls'); var graphControlsEl = document.getElementById('graphControls');
var typeLinksEl = document.getElementById('typeLinks'); var typeLinksEl = document.getElementById('typeLinks');
var moreTypeLinksEl = document.getElementById('moreTypeLinks');
var relLinksEl = document.getElementById('relLinks'); var relLinksEl = document.getElementById('relLinks');
// make controls // make controls
let i = 0;
for (let typeName in types) { for (let typeName in types) {
let typeLinkEl = document.createElement("li"); let typeLinkEl = document.createElement("li");
let typeLinkAEl = document.createElement("a"); let typeLinkAEl = document.createElement("a");
let typeLinkCountEl = document.createElement("span");
typeLinkCountEl.innerHTML = types[typeName].length;
typeLinkAEl.innerHTML = typeName; typeLinkAEl.innerHTML = typeName;
typeLinkAEl.addEventListener('click', function(){ typeLinkAEl.addEventListener('click', function(){
centerByType(typeName); centerByType(typeName);
// positionNodesInCenter(types[typeName]); // positionNodesInCenter(types[typeName]);
}); });
typeLinkEl.append(typeLinkAEl); typeLinkEl.append(typeLinkAEl);
typeLinksEl.appendChild(typeLinkEl); typeLinkEl.append(typeLinkCountEl);
(i < 5 ? typeLinksEl: moreTypeLinksEl).appendChild(typeLinkEl);
i++;
// typeLinksEl.appendChild(typeLinkEl);
} }
@ -237,6 +290,7 @@ var positionNodesInCenter = function(idxs) {
nodeEls[nIdx].classList.add('visibleNode'); nodeEls[nIdx].classList.add('visibleNode');
} else { } else {
nodeEls[nIdx].classList.remove('centeredNode'); nodeEls[nIdx].classList.remove('centeredNode');
nodeEls[nIdx].classList.remove('visibleNode');
} }
}); });
@ -319,9 +373,16 @@ var setDetails = function(nodeDatum, nodeIdx) {
nodeDetailEl.removeChild(nodeDetailEl.lastChild); nodeDetailEl.removeChild(nodeDetailEl.lastChild);
} }
// TODO: replace relUp & relDown with linkMap
let relUp = []; let relUp = [];
let relDown = []; let relDown = [];
let breadcrumbsEl = document.createElement('div');
breadcrumbsEl.classList.add('breadcrumbs');
for(let crumbNodeId of breadcrumbs[nodeDatum['id']]) {
breadcrumbsEl.innerHTML += ` <span class='crumb'>${getNodeTitle(nodeMap[crumbNodeId])}</span>`;
}
nodeDetailEl.appendChild(breadcrumbsEl);
let titleAttr = getTitleAttribute(nodeDatum); let titleAttr = getTitleAttribute(nodeDatum);
let titleEl = document.createElement('h2'); let titleEl = document.createElement('h2');
titleEl.innerHTML = getNodeTitle(nodeDatum); titleEl.innerHTML = getNodeTitle(nodeDatum);
@ -457,30 +518,14 @@ var selectNode = function(idx){
// set global var // set global var
positionNodesInCenter(idx); positionNodesInCenter(idx);
/* DISABLED: Make selected nodes bigger let currentCrumbs = breadcrumbs[nodeDatum['id']].slice();
// update collision: the selected node should get plenty of space. currentCrumbs[currentCrumbs.length] = nodeDatum['id'];
simulation.force("collision").radius(function(d, idx){ console.log(currentCrumbs);
if(typeof nodePositions[idx] != 'undefined'){
return selectedNodeSize * 1.2;
}
return nodeSize * 1.1;
});
node.each(function(d, idx, nodeEls){
let nodeEl = nodeEls[idx];
let nodeD3 = d3.select(nodeEl);
let circleD3 = nodeD3.select('circle');
if(typeof nodePositions[idx] !== 'undefined') { // set active links.
circleD3.transition(selectedNodeTransition).attr('r', selectedNodeSize);
// nodeEl.getElementsByTagName("circle")[0].attributes.r.value = selectedNodeSize;
} else {
circleD3.transition(selectedNodeTransition).attr('r', nodeSize);
// nodeEl.getElementsByTagName("circle")[0].attributes.r.value = nodeSize;
}
});
*/
let linkedIdxs = []; let linkedIdxs = [];
link.each(function(d,idx,linkEls,q){ link.each(function(d,idx,linkEls,q){
// set nodes 'visible'/highlighted when linked to active node
if(d.source == nodeDatum || d.target == nodeDatum) { if(d.source == nodeDatum || d.target == nodeDatum) {
linkEls[idx].classList.add('activeLink','visibleLink'); linkEls[idx].classList.add('activeLink','visibleLink');
linkEls[idx].getElementsByTagName("line")[0].setAttribute("marker-end", "url(#arrowHeadSelected)"); linkEls[idx].getElementsByTagName("line")[0].setAttribute("marker-end", "url(#arrowHeadSelected)");
@ -491,11 +536,19 @@ var selectNode = function(idx){
} }
return r; return r;
}).classed('visibleNode', true); }).classed('visibleNode', true);
} else { } else {
linkEls[idx].classList.remove('activeLink'); linkEls[idx].classList.remove('activeLink');
linkEls[idx].getElementsByTagName("line")[0].setAttribute("marker-end", "url(#arrowHead)"); linkEls[idx].getElementsByTagName("line")[0].setAttribute("marker-end", "url(#arrowHead)");
} }
// check if link is part of breadcrumb trail
let posSrc = currentCrumbs.indexOf(d.source['id']);
let posTrg = currentCrumbs.indexOf(d.target['id']);
if(posSrc > -1 && posTrg > -1 && Math.abs(posSrc - posTrg) == 1) {
linkEls[idx].classList.add('breadcrumbLink');
// linkEls[idx].getElementsByTagName("line")[0].setAttribute("marker-end", "url(#arrowHeadSelected)");
} else {
linkEls[idx].classList.remove('breadcrumbLink');
}
}); });
let i = linkedIdxs.indexOf(idx); let i = linkedIdxs.indexOf(idx);
@ -542,8 +595,8 @@ simulation.force('centerActive', function force(alpha) {
return; return;
} }
n.vx += dx * k /5; n.vx += dx * k*3;
n.vy += dy * k /5; n.vy += dy * k*3;
} }
}); });
}); });
@ -597,10 +650,7 @@ node.append('circle')
.attr("r", nodeSize) .attr("r", nodeSize)
.attr("class", "nodeBg") .attr("class", "nodeBg")
; ;
node.append('circle')
.attr("r", nodeSize * 1.08) // nodeSize + margin
.attr("class", "highlightCircle")
;
node.append('text') node.append('text')
.append("textPath") .append("textPath")
@ -608,17 +658,28 @@ node.append('text')
.text(getNodeTitle); .text(getNodeTitle);
node.each(function(d) { node.each(function(d) {
let n = d3.select(this);
if(!d.contentUrl) { if(!d.contentUrl) {
return; n.append('circle')
} .attr("r", nodeSize * 1.08) // nodeSize + margin
d3.select(this).append('svg:image') .attr("class", "highlightCircle")
;
} else {
n.append('svg:image')
.attr("xlink:href", d.contentUrl) .attr("xlink:href", d.contentUrl)
.attr("width", nodeSize*2) .attr("width", nodeSize*2)
.attr("height", nodeSize*2) .attr("height", nodeSize*2)
.attr("transform","translate(-"+nodeSize+" -"+nodeSize+")") .attr("transform","translate(-"+nodeSize+" -"+nodeSize+")")
.attr("clip-path","url(#clipNodeImage)") // .attr("clip-path","url(#clipNodeImage)")
.attr("preserveAspectRatio","xMidYMid slice") .attr("preserveAspectRatio","xMidYMid slice")
; ;
n.append('rect')
.attr("width", nodeSize * 1.08 * 2) // nodeSize + margin
.attr("height", nodeSize * 1.08 * 2) // nodeSize + margin
.attr("transform","translate(-"+nodeSize * 1.08 +" -"+nodeSize * 1.08 +")")
.attr("class", "highlightCircle")
;
}
}); });
// node.append("title") // node.append("title")
@ -713,6 +774,10 @@ function ticked() {
let x = d.source.x + dx; let x = d.source.x + dx;
let y = d.source.y + dy; let y = d.source.y + dy;
let deg = Math.atan(dy / dx) * 180 / Math.PI; let deg = Math.atan(dy / dx) * 180 / Math.PI;
// if dx/dy == 0/0 -> deg == NaN
if(isNaN(deg)) {
return "";
}
return "translate("+x+" "+y+") rotate("+deg+") translate(0, -10)"; return "translate("+x+" "+y+") rotate("+deg+") translate(0, -10)";
}); });
// linkPath.attr("d", function(d) { // linkPath.attr("d", function(d) {
@ -797,7 +862,7 @@ function moveViewboxPx(dx, dy){
// start by selecting the first node :-) // start by selecting the first node :-)
// selectNode(currentNodeIdx+1); // selectNode(currentNodeIdx+1);
// positionNodesInCenter(currentNodeIdx); // positionNodesInCenter(currentNodeIdx);
selectNode(currentNodeIdx); //deselectNode(); selectNode(graph['nodes'].length - 1);
closeDetails(); // closeDetails(); // hide details at first
// positionNodesInCenter(currentNodeIdx+1); // positionNodesInCenter(currentNodeIdx+1);
} }

View file

@ -6,36 +6,9 @@ $detailSlideMobile: -30vh;
body{ body{
margin:0;overflow: hidden; margin:0;overflow: hidden;
font-family: sans-serif; font-family: "CMU Bright", sans-serif;
/* background: #fceabb; height: 100vh;
background: -moz-linear-gradient(-45deg, #fceabb 0%, #fccd4d 50%, #f8b500 51%, #fbdf93 100%); background: black;
background: -webkit-linear-gradient(-45deg, #fceabb 0%,#fccd4d 50%,#f8b500 51%,#fbdf93 100%);
background: linear-gradient(135deg, #fceabb 0%,#fccd4d 50%,#f8b500 51%,#fbdf93 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fceabb', endColorstr='#fbdf93',GradientType=1 ); */
/*background: #f7fbfc;
background: -moz-linear-gradient(45deg, #f7fbfc 0%, #d9edf2 40%, #add9e4 100%);
background: -webkit-linear-gradient(45deg, #f7fbfc 0%,#d9edf2 40%,#add9e4 100%);
background: linear-gradient(45deg, #f7fbfc 0%,#d9edf2 40%,#add9e4 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f7fbfc', endColorstr='#add9e4',GradientType=1 );*/
/*background: #e2e2e2;
background: -moz-linear-gradient(45deg, #e2e2e2 0%, #dbdbdb 50%, #d1d1d1 51%, #fefefe 100%);
background: -webkit-linear-gradient(45deg, #e2e2e2 0%,#dbdbdb 50%,#d1d1d1 51%,#fefefe 100%);
background: linear-gradient(45deg, #e2e2e2 0%,#dbdbdb 50%,#d1d1d1 51%,#fefefe 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e2e2e2', endColorstr='#fefefe',GradientType=1 );*/
/*background: #d2dfed;
background: -moz-linear-gradient(45deg, #d2dfed 0%, #c8d7eb 26%, #bed0ea 51%, #a6c0e3 51%, #afc7e8 62%, #bad0ef 75%, #99b5db 88%, #799bc8 100%);
background: -webkit-linear-gradient(45deg, #d2dfed 0%,#c8d7eb 26%,#bed0ea 51%,#a6c0e3 51%,#afc7e8 62%,#bad0ef 75%,#99b5db 88%,#799bc8 100%);
background: linear-gradient(45deg, #d2dfed 0%,#c8d7eb 26%,#bed0ea 51%,#a6c0e3 51%,#afc7e8 62%,#bad0ef 75%,#99b5db 88%,#799bc8 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#d2dfed', endColorstr='#799bc8',GradientType=1 );*/
background: #d2dfed;
background: -moz-linear-gradient(45deg, #d2dfed 0%, #afc1d8 13%, #d5e0ef 28%, #bed0ea 51%, #a8c0dd 51%, #c0d0e5 63%, #bad0ef 75%, #a2bad8 88%, #799bc8 100%);
background: -webkit-linear-gradient(45deg, #d2dfed 0%,#afc1d8 13%,#d5e0ef 28%,#bed0ea 51%,#a8c0dd 51%,#c0d0e5 63%,#bad0ef 75%,#a2bad8 88%,#799bc8 100%);
background: linear-gradient(45deg, #d2dfed 0%,#afc1d8 13%,#d5e0ef 28%,#bed0ea 51%,#a8c0dd 51%,#c0d0e5 63%,#bad0ef 75%,#a2bad8 88%,#799bc8 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#d2dfed', endColorstr='#799bc8',GradientType=1 );
height: 100vh;
/*-moz-animation: bgShift 5s infinite;
background-size: 400% 400%;*/
// font-size:18px;
} }
a, a:link, a:visited{ a, a:link, a:visited{
@ -69,80 +42,116 @@ g.node{
stroke: blue; stroke: blue;
stroke-width: 0; stroke-width: 0;
transition: stroke-width .5s; transition: stroke-width .5s;
opacity: 0; opacity: 1;
pointer-events: none; // pointer-events: none;
transition: opacity 1s; transition: opacity 1s;
}
g.node.visibleNode/* , g.node.ImageObject */ &.visibleNode{
{
opacity: 1; opacity: 1;
pointer-events: auto; pointer-events: auto;
} *{
g.node circle.highlightCircle{ // transform: scale(1);
}
}
*{
// transform: scale(.4);
}
.highlightCircle{
fill: none; fill: none;
stroke-width:0px; stroke-width:0px;
stroke-dasharray: 3 2; stroke-dasharray: 3 2;
} }
g.node:hover circle.highlightCircle{
&:hover .highlightCircle{
stroke-width: 1px; stroke-width: 1px;
stroke: blue; stroke: yellow;
} }
g.node:active circle.highlightCircle{
stroke-width:1px; &.drag{
stroke: red; cursor: grabbing;
} }
g.node.centeredNode circle.highlightCircle{
stroke-width:1px; text{
stroke: red;
}
/* g.node.selectedNode circle.highlightCircle{
stroke-width:1px;
stroke: red;
} */
g.node.drag{
cursor:grabbing;
}
.node text{
text-anchor: start; text-anchor: start;
font-family: "CMU Bright", sans-serif;
font-size: 10pt;
}
} }
.relationship{ .relationship{
display:none; display:none;
} // opacity: .2;
.relationship.visibleLink{
&.visibleLink{
display:block; display:block;
} // opacity: 1;
.relationship line{
}
line{
fill:none; fill:none;
stroke: #999; stroke: #999;
stroke-width: 2px; stroke-width: 2px;
}
.relationship text{ }
text{
fill:black; fill:black;
/* text-transform: lowercase; */ font-family: "Noto Mono", monospace;
font-size: 75%; font-size: 9pt;
// font-size: 75%;
display:none; display:none;
} }
.relationship.activeLink text{ &.activeLink{
line{
stroke: white;
}
text{
fill:white; fill:white;
display:block; display:block;
}
}
&.breadcrumbLink{
display: block;
line {
stroke: yellow !important;
display: block;
}
text{
fill: yellow !important;
display:block;
}
}
} }
.relationship.activeLink line{
stroke: white;
}
circle.nodeBg{ circle.nodeBg{
fill: white; fill: white;
/*stroke-width:.2em;*/ // fill: url(#img1);
fill:url(#blueGrad); // fill:url(#blueGrad);
stroke-width: 3px;
stroke: black;
.visibleNode & {
stroke: yellow;
}
.MediaObject & { .MediaObject & {
fill:url(#orangeGrad); // fill:url(#orangeGrad);
} }
.Person & { .Person & {
fill:url(#redGrad); // fill:url(#redGrad);
} }
.PublicationEvent & { .PublicationEvent & {
fill:url(#limeGrad); // fill:url(#limeGrad);
}
.centeredNode &{
fill: yellow;
stroke: yellow;
} }
} }
text{ text{