Commit 6ff78c43 authored by qlobbe's avatar qlobbe

add terms paths

parent 02a8d026
...@@ -52,7 +52,10 @@ ...@@ -52,7 +52,10 @@
<button id="reset" class="button reset"> <button id="reset" class="button reset">
<i class="fas fa-expand-arrows-alt"></i> <i class="fas fa-expand-arrows-alt"></i>
</button> </button>
</div> <button id="label" class="button label">
<i class="fas fa-align-center"></i>
</button>
</div>
<!-- row 4 --> <!-- row 4 -->
...@@ -82,6 +85,7 @@ ...@@ -82,6 +85,7 @@
return function(e) { return function(e) {
try { try {
document.querySelector("#reset").style.visibility = "visible" document.querySelector("#reset").style.visibility = "visible"
document.querySelector("#label").style.visibility = "visible"
json = JSON.parse(e.target.result); json = JSON.parse(e.target.result);
draw(json) draw(json)
} catch (error) { } catch (error) {
...@@ -153,13 +157,15 @@ ...@@ -153,13 +157,15 @@
}); });
var groups = json.objects.filter(node => node.nodeType == "group").map(function(g){ var groups = json.objects.filter(node => node.nodeType == "group").map(function(g){
return { from : yearToDate(g.from) , return { from : yearToDate(g.from) ,
to : yearToDate(g.to) , to : yearToDate(g.to) ,
x : parseFloat(((g.pos).split(','))[0]) , x : parseFloat(((g.pos).split(','))[0]) ,
y : parseFloat(((g.pos).split(','))[1]) , y : parseFloat(((g.pos).split(','))[1]) ,
bId : parseInt(g.bId) , bId : parseInt(g.bId) ,
gId : parseInt(g._gvid) , gId : parseInt(g._gvid) ,
size : parseInt(g.support) } size : parseInt(g.support),
label : (g.label.slice(1, g.label.length - 1)).split('|'),
foundation : (g.foundation.slice(1, g.foundation.length - 1)).split('|') }
}); });
var links = json.edges.filter(edges => edges.edgeType == "link").map(function(l){ var links = json.edges.filter(edges => edges.edgeType == "link").map(function(l){
......
...@@ -103,7 +103,7 @@ body { ...@@ -103,7 +103,7 @@ body {
grid-row: 2 / 4; grid-row: 2 / 4;
grid-column: 15 / 16; grid-column: 15 / 16;
padding-top: 50%; padding-top: 50%;
padding-bottom: 50%; padding-bottom: 50%;
} }
/* -------------------- */ /* -------------------- */
...@@ -224,6 +224,15 @@ i.how:hover span { ...@@ -224,6 +224,15 @@ i.how:hover span {
visibility: hidden; visibility: hidden;
} }
.label {
visibility: hidden;
}
.labeled {
background-color: #0d1824;
color: white;
}
.input-file { .input-file {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
...@@ -308,18 +317,53 @@ i.how:hover span { ...@@ -308,18 +317,53 @@ i.how:hover span {
fill: #4A5C70; fill: #4A5C70;
} }
/* ---------- phylo ---------- */ /* ---------- group ---------- */
.group-outer { .group-outer {
stroke-width: 1.5px; stroke-width: 1px;
stroke: #fff; stroke: #fff;
fill: #fff; fill: #fff;
} }
.group-inner { .group-inner {
stroke-width: 1px;
stroke: #0d1824;
fill: #0d1824;
/*cursor: pointer;*/
z-index: 10;
}
.group-inner-focus {
stroke: #f8381f;
}
.group-inner-unfocus {
stroke: #A9A9A9;
}
.group-path-focus {
stroke: #A9A9A9;
}
/* ---------- labels ---------- */
.ngrams {
visibility: hidden;
}
.term {
cursor: pointer; cursor: pointer;
}
.term:hover {
font-weight: bold;
}
.term-path {
fill: none;
stroke: #f8381f;
stroke-width: 1.5px; stroke-width: 1.5px;
fill: #0d1824; z-index: 1;
} }
/* ---------- phylo ---------- */ /* ---------- phylo ---------- */
...@@ -378,4 +422,5 @@ i.how:hover span { ...@@ -378,4 +422,5 @@ i.how:hover span {
z-index: 10; z-index: 10;
position: absolute; position: absolute;
visibility: hidden; visibility: hidden;
} }
\ No newline at end of file
...@@ -119,7 +119,6 @@ function addMarkY(ticks) { ...@@ -119,7 +119,6 @@ function addMarkY(ticks) {
} }
function setYDomain(labels) { function setYDomain(labels) {
console.log(labels)
var inf = labels[0].from, var inf = labels[0].from,
sup = labels[labels.length - 1].from; sup = labels[labels.length - 1].from;
// inf = new Date((inf.getFullYear() - 1),6,0); // inf = new Date((inf.getFullYear() - 1),6,0);
...@@ -128,6 +127,21 @@ function setYDomain(labels) { ...@@ -128,6 +127,21 @@ function setYDomain(labels) {
return [inf,sup]; return [inf,sup];
} }
function groupTermsBy(elements, attr) {
let grouped = {},
curr = "";
for (var i = 0; i < elements.length; i++) {
let from = elements[i].getAttribute(attr)
if (curr != from) {
grouped[from] = [[(elements[i]).getAttribute("gx"),(elements[i]).getAttribute("gy")]];
curr = from
} else {
grouped[from].push([(elements[i]).getAttribute("gx"),(elements[i]).getAttribute("gy")]);
}
}
return Object.values(grouped);
};
function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
...@@ -182,6 +196,7 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { ...@@ -182,6 +196,7 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
.attr("stroke-width", (d, i) => i % 2 ? 0.25 : 1) .attr("stroke-width", (d, i) => i % 2 ? 0.25 : 1)
.attr("stroke-linejoin", "round"); .attr("stroke-linejoin", "round");
var label = var label =
d3.select("#phyloIsoLine") d3.select("#phyloIsoLine")
.append("div") .append("div")
...@@ -247,7 +262,7 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { ...@@ -247,7 +262,7 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
.attr("x",xo) .attr("x",xo)
.attr("y",yo); .attr("y",yo);
const panel = svg.append("g").attr("clip-path", "url(#mask)") const panel = svg.append("g").attr("clip-path", "url(#mask)").attr("id","panel")
/* highlight */ /* highlight */
...@@ -292,16 +307,7 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { ...@@ -292,16 +307,7 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
.attr("d", linkGen) .attr("d", linkGen)
.attr("fill", "none") .attr("fill", "none")
.attr("stroke","#0d1824") .attr("stroke","#0d1824")
.attr("class","link") .attr("class","group-path")
// panel
// .selectAll("path")
// .data(groupAncestors)
// .join("path")
// .attr("d", linkGen)
// .attr("fill", "none")
// .attr("stroke","#0d1824")
// .attr("class","link")
// https://observablehq.com/@mbostock/fit-text-to-circle // https://observablehq.com/@mbostock/fit-text-to-circle
...@@ -309,11 +315,7 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { ...@@ -309,11 +315,7 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
var colors = ["#f8381f","#aa8c58","#74b5ff","#0d1824"]; var colors = ["#f8381f","#aa8c58","#74b5ff","#0d1824"];
/* groups */ /* groups */
var title = ["lorem","ipsum"],
ngrams = ["lorem","ipsum","dolor","sit","amet","consectetur","adipiscing","elit"]
text = ngrams.join(' ');
groups.forEach(g => setGroup(g)); groups.forEach(g => setGroup(g));
...@@ -332,9 +334,9 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { ...@@ -332,9 +334,9 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
.extent([[xo,yo],[wo,ho]]) .extent([[xo,yo],[wo,ho]])
.on("zoom",onZoom) .on("zoom",onZoom)
svg.call(zoom) svg.call(zoom).on("dblclick.zoom",null).on("dblclick",doubleClick);
d3.select("#reset").on("click",reset); d3.select("#reset").on("click",reset);
function reset() { function reset() {
svg.transition() svg.transition()
...@@ -355,39 +357,69 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { ...@@ -355,39 +357,69 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
setAxisY(zoomY,zoomYLabels); setAxisY(zoomY,zoomYLabels);
// panel.attr("transform",d3.event.transform)
panel.selectAll("circle").attr("transform", d3.event.transform); panel.selectAll("circle").attr("transform", d3.event.transform);
panel.selectAll("text").attr("transform", d3.event.transform);
panel.selectAll("path").attr("transform", d3.event.transform); panel.selectAll("path").attr("transform", d3.event.transform);
panel.selectAll(".branch-hover").attr("transform", d3.event.transform); panel.selectAll(".branch-hover").attr("transform", d3.event.transform);
panel.selectAll(".y-highlight").attr("transform", d3.event.transform); panel.selectAll(".y-highlight").attr("transform", d3.event.transform);
panel.selectAll(".ngrams").attr("transform", d3.event.transform); panel.selectAll(".ngrams").attr("transform", d3.event.transform);
panel.selectAll(".term-path").attr("transform", d3.event.transform);
showPeak()
}
/* label */
// d3.selectAll(".ngrams").remove() // https://observablehq.com/@d3/parallel-coordinates
// drawNgrams(d3.select("#titi").node().getAttribute("cx"),d3.select("#titi").node().getAttribute("cy"),d3.select("#titi").node().getAttribute("r"))
showPeak() d3.select("#label").on("click",showLabel);
function showLabel() {
doubleClick()
let ngrams = document.getElementsByClassName("ngrams")
let groups = document.getElementsByClassName("group-inner")
if (ngrams[0].style.visibility == "hidden") {
document.getElementById("label").classList.add("labeled")
for (var i = 0; i < groups.length; i++) {
groups[i].style.fill = "#fff";
}
for (var i = 0; i < ngrams.length; i++){
ngrams[i].style.visibility = "visible";
}
} else {
document.getElementById("label").classList.remove("labeled")
for (var i = 0; i < groups.length; i++) {
groups[i].style.fill = "#61a3a9";
}
for (var i = 0; i < ngrams.length; i++){
ngrams[i].style.visibility = "hidden";
}
}
} }
/* groups */
function textWidth(text) { function textWidth(text) {
const context = document.createElement("canvas").getContext("2d"); const context = document.createElement("canvas").getContext("2d");
return context.measureText(text).width; return context.measureText(text).width;
} }
function toLines(words,targetWidth) { function toLines(words,fdt,targetWidth) {
let line; let line;
let lineWidth0 = Infinity; let lineWidth0 = Infinity;
const lines = []; const lines = [];
for (let i = 0, n = words.length; i < n; ++i) { for (let i = 0, n = words.length; i < n; ++i) {
let lineText1 = (line ? line.text + " " : "") + words[i]; let lineText1 = (line ? line.text + " " : "") + words[i];
let lineFdt1 = (line ? line.fdt + " " : "") + fdt[i];
let lineWidth1 = textWidth(lineText1); let lineWidth1 = textWidth(lineText1);
if ((lineWidth0 + lineWidth1) / 2 < targetWidth) { if ((lineWidth0 + lineWidth1) / 2 < targetWidth + 10) {
line.width = lineWidth0 = lineWidth1; line.width = lineWidth0 = lineWidth1;
line.text = lineText1; // line.text = lineText1;
line.text.push(words[i])
line.fdt.push(fdt[i])
} else { } else {
lineWidth0 = textWidth(words[i]); lineWidth0 = textWidth(words[i]);
line = {width: lineWidth0, text: words[i]}; line = {width: lineWidth0, text: [words[i]], fdt: [fdt[i]]};
lines.push(line); lines.push(line);
} }
} }
...@@ -402,89 +434,18 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { ...@@ -402,89 +434,18 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
radius = Math.max(radius, Math.sqrt(dx ** 2 + dy ** 2)); radius = Math.max(radius, Math.sqrt(dx ** 2 + dy ** 2));
} }
return radius; return radius;
} }
// lineHeight = 15
// targetWidth = Math.sqrt(textWidth(text.trim()) * lineHeight)
// lines = toLines(ngrams,targetWidth)
// textRadius = toTextRadius(lines,lineHeight);
// var toto = panel.append("circle")
// .attr("cx", 300)
// .attr("cy", 100)
// .attr("fill", "#fff")
// .attr("stroke","red")
// .attr("id","titi")
// .attr("r", 6);
// panel.append("text")
// .attr("class","ngrams")
// .attr("x",300)
// .attr("y",100)
// // .attr("transform", "translate(" + 300 +"," + 100 + ") scale(" + (6 / textRadius) + ")")
// // .attr("transform","scale(0,5)")
// .attr("text-anchor", "middle")
// .selectAll("tspan")
// .data(lines)
// .enter().append("tspan")
// .attr("x", 300)
// .attr("y", (d, i) => 100 + (i - lines.length / 2 + 0.8) * lineHeight)
// .text(d => d.text);
// function resize(r,t) {
// return Math.min(2 * r, (2 * r - 8) / t * 24) + "px";
// }
// console.log(textRadius)
// var side = 2 * 50 * Math.cos(Math.PI / 4),
// dx = 50 - side / 2;
// g.append("foreignObject")
// .attr("width", side)
// .attr("height", side)
// .append("xhtml:body")
// .html("Lorem ipsum dolor sit amet, ...");
// panel.append("text")
// .attr("class","ngrams")
// .attr("transform", `translate(300,100) scale(${10 / textRadius})`)
// // .attr("transform", `translate(300,100)`)
// .attr("text-anchor", "middle")
// .selectAll("tspan")
// .data(lines)
// .enter().append("tspan")
// .attr("x", 0)
// .attr("y", (d, i) => (i - lines.length / 2 + 0.8) * lineHeight)
// .text(d => d.text);
function setGroup(g) { function setGroup(g) {
// var role = Math.floor(Math.random() * 4) var radius = 5;
// dyn = [];
// if (role < 3) {
// dyn = ngrams.map(w => Math.floor(Math.random() * 4));
// } else {
// dyn = ngrams.map(w => 3);
// }
panel panel
.append("circle") .append("circle")
.attr("class","group-outer") .attr("class","group-outer")
.attr("cx", xScale(g.x)) .attr("cx", xScale(g.x))
.attr("cy", yScale(g.from)) .attr("cy", yScale(g.from))
.attr("r" ,6); .attr("r" , radius + 0.5);
panel panel
.append("circle") .append("circle")
...@@ -493,13 +454,59 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { ...@@ -493,13 +454,59 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
.attr("cy", yScale(g.from)) .attr("cy", yScale(g.from))
.attr("bId", g.bId) .attr("bId", g.bId)
.attr("id" , "group" + g.gId) .attr("id" , "group" + g.gId)
.attr("r" ,5) .attr("r" ,radius)
// .attr("stroke",colors[role]) // .attr("stroke",colors[role])
.attr("stroke","#0d1824") .attr("stroke","#0d1824")
.style("fill", "#61a3a9") .style("fill", "#61a3a9")
.attr("from",(g.from).getFullYear()) .attr("from",(g.from).getFullYear())
.on("mouseover",groupOver) // .on("mouseover",groupOver)
.on("mouseout" ,groupOut) // .on("mouseout" ,groupOut)
/* group label */
var lineHeight = 12,
targetWidth = Math.sqrt(textWidth(g.label.join('').trim()) * radius),
lines = toLines(g.label,g.foundation,targetWidth),
textRadius = toTextRadius(lines,lineHeight)
textRatio = (radius - 0.5) / textRadius;
for (let i = 0; i < lines.length; i++) {
let words = lines[i].text,
fdt = lines[i].fdt,
terms = mergeLists(words,fdt)
toSpan = (acc, w) => acc + "<tspan fdt=" + w[1]
+ " class='term fdt-" + (w[1]).trim() + "'"
+ " gy=" + yScale(g.from)
+ " gx=" + xScale(g.x)
+ " gid=" + g.gId
+ " from=" + (g.from).getFullYear()
+ ">" + w[0] + "</tspan>";
panel
.append("text")
.attr("class","ngrams")
.attr("text-anchor", "middle")
.style("font-size", 12 * textRatio + "px")
.style("visibility", "hidden")
.append("tspan")
.attr("x", xScale(g.x))
.attr("y", yScale(g.from) + (i - lines.length / 2.8) * (lineHeight * textRatio))
.html(terms.reduce(toSpan,""));
d3.selectAll(".term").on("click",termClick);
}
}
function mergeLists(l1,l2) {
let merged = [];
for (let i = 0; i < l1.length; i++) {
merged.push([l1[i],l2[i]])
}
return merged;
} }
function setAxisY(scale,labels) { function setAxisY(scale,labels) {
...@@ -559,6 +566,64 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { ...@@ -559,6 +566,64 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
}) })
} }
function termClick () {
// remove old focus
d3.selectAll(".term-path").remove();
var groups = document.getElementsByClassName('group-inner');
for (var i = 0; i < groups.length; i++) {
groups[i].classList.remove("group-inner-focus");
groups[i].classList.add("group-inner-unfocus");
}
var paths = document.getElementsByClassName('group-path');
for (var i = 0; i < paths.length; i++) {
paths[i].classList.add("group-path-focus");
}
// catch the last transformations
var transform = d3.select("#group" + this.getAttribute("gid")).node().getAttribute("transform");
var idx = this.getAttribute("fdt"),
terms = document.getElementsByClassName("fdt-" + idx),
periods = groupTermsBy(terms,"from");
for (var i = 0; i < terms.length; i++) {
let gid = (terms[i]).getAttribute("gid");
d3.select("#group" + gid).node().classList.remove("group-inner-unfocus")
d3.select("#group" + gid).node().classList.add("group-inner-focus")
}
for (var i = 0; i < periods.length; i++) {
if (i != periods.length - 1) {
for (var j = 0; j < periods[i].length; j++) {
var x1 = periods[i][j][0],
y1 = periods[i][j][1];
for (var k = 0; k < periods[i + 1].length; k++) {
var x2 = periods[i + 1][k][0],
y2 = periods[i + 1][k][1];
// draw the paths
panel
.append("path")
.attr("class","term-path")
.attr("d", function(d) {
return "M" + x1 + "," + y1
+ "C" + x2 + "," + y1
+ " " + x2 + "," + y2
+ " " + x2 + "," + y2;
})
.attr("transform",transform)
.style("stroke-opacity", 0.6)
.lower();
}
}
}
}
d3.selectAll(".group-path").lower();
}
function peakOver (b,i) { function peakOver (b,i) {
d3.select("#peak-" + i).node().setAttribute("class","peak peak-over"); d3.select("#peak-" + i).node().setAttribute("class","peak peak-over");
label.text(b.label.replace(/"/g,'')) label.text(b.label.replace(/"/g,''))
...@@ -603,18 +668,31 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) { ...@@ -603,18 +668,31 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
function groupOver() { function groupOver() {
var from = this.getAttribute("from"); var from = this.getAttribute("from");
d3.select("#y-highlight-" + from).style("visibility","visible"); d3.select("#y-highlight-" + from).style("visibility","visible");
d3.select("#y-mark-year-inner-" + from).node().setAttribute("class","y-mark-year-inner-highlight"); // d3.select("#y-mark-year-inner-" + from).node().setAttribute("class","y-mark-year-inner-highlight");
d3.select("#y-mark-year-outer-" + from).node().setAttribute("class","y-mark-year-outer-highlight"); // d3.select("#y-mark-year-outer-" + from).node().setAttribute("class","y-mark-year-outer-highlight");
d3.select("#y-label-" + from).node().setAttribute("class","y-label-bold"); // d3.select("#y-label-" + from).node().setAttribute("class","y-label-bold");
} }
function groupOut() { function groupOut() {
var from = this.getAttribute("from"); var from = this.getAttribute("from");
d3.select("#y-highlight-" + from).style("visibility","hidden"); d3.select("#y-highlight-" + from).style("visibility","hidden");
d3.select("#y-mark-year-inner-" + from).node().setAttribute("class","y-mark-year-inner"); // d3.select("#y-mark-year-inner-" + from).node().setAttribute("class","y-mark-year-inner");
d3.select("#y-mark-year-outer-" + from).node().setAttribute("class","y-mark-year-outer"); // d3.select("#y-mark-year-outer-" + from).node().setAttribute("class","y-mark-year-outer");
d3.select("#y-label-" + from).node().setAttribute("class","y-label"); // d3.select("#y-label-" + from).node().setAttribute("class","y-label");
} }
function doubleClick() {
d3.selectAll(".term-path").remove();
var groups = document.getElementsByClassName('group-inner');
for (var i = 0; i < groups.length; i++) {
groups[i].classList.remove("group-inner-focus");
groups[i].classList.remove("group-inner-unfocus");
}
var paths = document.getElementsByClassName('group-path');
for (var i = 0; i < paths.length; i++) {
paths[i].classList.remove("group-path-focus");
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment