diff --git a/css/infobar.css b/css/infobar.css index eb8bc25d48a55c2ef64bb9749b99ef624ba273d0..f76268f0f0e27c014411af173f6c0fac455bddc6 100644 --- a/css/infobar.css +++ b/css/infobar.css @@ -81,7 +81,6 @@ height: 100%; position: absolute; cursor: pointer; - } .infobar .infobutton svg { @@ -95,16 +94,21 @@ } .infobar .infobutton svg path { - fill:none; + fill: none; /*stroke: #000;*/ } +.navi.hide { + display: none; +} + .navi { z-index: 300; top: 30%; position: absolute; - left: 0; + left: 0; } + .navi .button { transition: all 0.3s; text-transform: uppercase; @@ -131,6 +135,7 @@ padding-right: 10px; /* border-right: 4px solid rgba(247, 239, 205, 0.18); */ } + .navi .button:hover:not(.active) { color: rgba(255, 255, 255, 0.75); } @@ -164,7 +169,7 @@ float: left; height: 100%; overflow-y: auto; - direction:rtl + direction: rtl } .infobar .outer::-webkit-scrollbar * { @@ -177,10 +182,11 @@ /* height: 100%; */ /* overflow-y: scroll; */ float: left; - direction:ltr; + direction: ltr; /*direction: ltr;*/ } -.infobar .inner > div { + +.infobar .inner>div { /* height: 100%; */ position: relative; /*width: 360px;*/ @@ -262,7 +268,5 @@ text-align: right; clear: both; opacity: 0.7; - padding-top: 30px; -} - - + padding-top: 30px; +} \ No newline at end of file diff --git a/index.html b/index.html index 870fe8c7b68500faa1fcacc221c71ab62d958b1a..50f0f0743299f87a2cb280e12d681a46c3a2cbf7 100644 --- a/index.html +++ b/index.html @@ -1,39 +1,41 @@ <!DOCTYPE html> <html> + <head> -<meta charset="utf-8"> -<title>VikusViewer</title> -<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" /> -<meta name="mobile-web-app-capable" content="yes" /> -<meta name="apple-mobile-web-app-capable" content="yes" /> -<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> -<meta name="format-detection" content="telephone=no" /> -<meta name="pinterest" content="nohover" /> -<base target="_blank"> - -<link rel="stylesheet" href="css/style.css"> -<link rel="stylesheet" href="css/infobar.css"> -<link rel="stylesheet" href="css/timeline.css"> - -<script src="js/d3.v3.min.js"></script> -<script src="js/vue.min.js"></script> -<script src="js/marked.min.js"></script> -<script src="js/lodash.min.js"></script> -<script src="js/pixi.min.js"></script> -<script src="js/pixi-packer-parser.js"></script> -<script src="js/loader.js"></script> -<script src="js/canvas.js"></script> -<script src="js/timeline.js"></script> -<script src="js/search.js"></script> -<script src="js/tags.js"></script> -<script src="js/utils.js"></script> -<script src="js/modernizr-custom.js"></script> -<!--[if lt IE 9]> + <meta charset="utf-8"> + <title>VikusViewer</title> + <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" + /> + <meta name="mobile-web-app-capable" content="yes" /> + <meta name="apple-mobile-web-app-capable" content="yes" /> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> + <meta name="format-detection" content="telephone=no" /> + <meta name="pinterest" content="nohover" /> + <base target="_blank"> + + <link rel="stylesheet" href="css/style.css"> + <link rel="stylesheet" href="css/infobar.css"> + <link rel="stylesheet" href="css/timeline.css"> + + <script src="js/d3.v3.min.js"></script> + <script src="js/vue.min.js"></script> + <script src="js/marked.min.js"></script> + <script src="js/lodash.min.js"></script> + <script src="js/pixi.min.js"></script> + <script src="js/pixi-packer-parser.js"></script> + <script src="js/loader.js"></script> + <script src="js/canvas.js"></script> + <script src="js/timeline.js"></script> + <script src="js/search.js"></script> + <script src="js/tags.js"></script> + <script src="js/utils.js"></script> + <script src="js/modernizr-custom.js"></script> + <!--[if lt IE 9]> <script src='http://html5shiv.googlecode.com/svn/trunk/html5.js' type='text/javascript'></script> <![endif]--> - <!-- + <!-- ,--. ,---, ,--/ /| .--.--. @@ -71,102 +73,95 @@ cpietsch@gmail.com --> </head> + <body> -<div id="hiddenreload"></div> - -<div class="browserInfo"> -<p>This visualization is not optimized for mobile phones and needs WebGL enabled.</p><p>Please come back on a Computer.</p><span>💡</span> -</div> - -<div class="search"></div> - -<div class="page"> - - <div class="detailLoader"></div> - <div class="sideLoader"></div> - - <div class="sidebar detail hide"> - <div class="slidebutton"></div> - - <div class="outer"> - <div id="detail" class="inner"> - <div class="entries" v-if="item"> - <div - v-if="item._imagenum > 1" - class="entry wide pages" - > - <div class="label">Seite</div> - <div class="content"> - <span - v-for="i in parseInt(item._imagenum)" - v-bind:key="i" - v-on:click="displayPage(i-1)" - v-bind:class="{ active: i === page+1, keyword: true }" - > - {{ i }} - </span> - </div> - </div> - <div - v-for="entry in structure" - v-bind:key="entry.name" - v-bind:class="entry.display" - class="entry" - v-if="hasData(entry)" - > - <div class="label">{{ entry.name }}</div> - <div class="content"> - <span v-if="entry.type === 'keywords'"> - <span - v-for="keyword in item[entry.source]" - v-bind:key="keyword" - class="keyword" - > - {{ keyword }} - </span> - </span> - <span v-else-if="entry.type === 'link'"> - <a :href="item[entry.source]" target="_blank">Link</a> - </span> - <span v-else-if="entry.type === 'markdown'"> - <span v-html="getContent(entry)"></span> - </span> - <span v-else> - {{ getContent(entry) }} - </span> - </div> - </div> - </div> - </div> - </div> + <div id="hiddenreload"></div> + + <div class="browserInfo"> + <p>This visualization is not optimized for mobile phones and needs WebGL enabled.</p> + <p>Please come back on a Computer.</p> + <span>💡</span> </div> - <div class="infobar sneaks"> - <div class="infobutton"> - <svg width="16px" height="24px" viewBox="0 0 16 24"> - <path d="M13.6824546,2 L3.7109392,11.9715154 L13.7394238,22" stroke="#FFF" stroke-width="5"></path> - </svg> + <div class="search"></div> + + <div class="page"> + + <div class="detailLoader"></div> + <div class="sideLoader"></div> + + <div class="sidebar detail hide"> + <div class="slidebutton"></div> + + <div class="outer"> + <div id="detail" class="inner"> + <div class="entries" v-if="item"> + <div v-if="item._imagenum > 1" class="entry wide pages"> + <div class="label">Seite</div> + <div class="content"> + <span v-for="i in parseInt(item._imagenum)" v-bind:key="i" v-on:click="displayPage(i-1)" v-bind:class="{ active: i === page+1, keyword: true }"> + {{ i }} + </span> + </div> + </div> + <div v-for="entry in structure" v-bind:key="entry.name" v-bind:class="entry.display" class="entry" v-if="hasData(entry)"> + <div class="label">{{ entry.name }}</div> + <div class="content"> + <span v-if="entry.type === 'keywords'"> + <span v-for="keyword in item[entry.source]" v-bind:key="keyword" class="keyword"> + {{ keyword }} + </span> + </span> + <span v-else-if="entry.type === 'link'"> + <a :href="item[entry.source]" target="_blank">Link</a> + </span> + <span v-else-if="entry.type === 'markdown'"> + <span v-html="getContent(entry)"></span> + </span> + <span v-else> + {{ getContent(entry) }} + </span> + </div> + </div> + </div> + </div> + </div> + </div> + + <div class="navi hide"> + <div class="time button active">time</div> + <div class="tsne button">tsne</div> </div> - - <div class="outer"> - <div class="inner"> - <div id="infobar" class="infosidebar"> - <span v-html="marked(info)"></span> - <div class="credit">Powered by <a href="https://vikusviewer.fh-potsdam.de/" target="_blank">VIKUS Viewer</a></div> - </div> + + <div class="infobar sneak"> + <div class="infobutton"> + <svg width="16px" height="24px" viewBox="0 0 16 24"> + <path d="M13.6824546,2 L3.7109392,11.9715154 L13.7394238,22" stroke="#FFF" stroke-width="5"></path> + </svg> + </div> + + <div class="outer"> + <div class="inner"> + <div id="infobar" class="infosidebar"> + <span v-html="marked(info)"></span> + <div class="credit">Powered by + <a href="https://vikusviewer.fh-potsdam.de/" target="_blank">VIKUS Viewer</a> + </div> + </div> + </div> </div> </div> - </div> - <div class="searchbar"> - <input type="input" name="suche"> - <div class="button"> - <div class="openbutton"></div> + <div class="searchbar"> + <input type="input" name="suche"> + <div class="button"> + <div class="openbutton"></div> + </div> </div> </div> -</div> -<script src="js/sidebars.js"></script> -<script src="js/viz.js"></script> + <script src="js/sidebars.js"></script> + <script src="js/viz.js"></script> </body> + </html> \ No newline at end of file diff --git a/js/canvas.js b/js/canvas.js index db6c5c1fab9ff887e34a7b448070009eefb19b6c..5a2f408ccf89646a980fc1ae7bd0dc7ab2e4ebf4 100644 --- a/js/canvas.js +++ b/js/canvas.js @@ -31,10 +31,10 @@ function Canvas() { .rangeBands([margin.left, width + margin.left], 0.2); var Quadtree = d3.geom.quadtree() - .x(function(d) { + .x(function (d) { return d.x; }) - .y(function(d) { + .y(function (d) { return d.y; }); @@ -100,18 +100,30 @@ function Canvas() { var timelineData; var stage, stage1, stage2, stage3, stage4, stage5; var timelineHover = false; + var tsne = [] + var tsneIndex = {} function canvas() {} - canvas.rangeBand = function() { return rangeBand } - canvas.width = function() { return width } - canvas.height = function() { return height } - canvas.rangeBandImage = function() { return rangeBandImage } + canvas.rangeBand = function () { + return rangeBand + } + canvas.width = function () { + return width + } + canvas.height = function () { + return height + } + canvas.rangeBandImage = function () { + return rangeBandImage + } canvas.zoom = zoom - canvas.selectedImage = function() { return selectedImage } + canvas.selectedImage = function () { + return selectedImage + } canvas.x = x - canvas.resize = function() { + canvas.resize = function () { if (!state.init) return; width = window.innerWidth - margin.left - margin.right; height = window.innerHeight < minHeight ? minHeight : window.innerHeight; @@ -121,7 +133,7 @@ function Canvas() { canvas.project(); } - canvas.makeScales = function() { + canvas.makeScales = function () { x.rangeBands([margin.left, width + margin.left], 0.2) rangeBand = x.rangeBand(); @@ -150,7 +162,7 @@ function Canvas() { zoomedToImageScale = 0.8 / (x.rangeBand() / collumns / width) } - canvas.init = function(_data, _timeline, _config) { + canvas.init = function (_data, _timeline, _config) { data = _data; config = _config; @@ -188,20 +200,28 @@ function Canvas() { stage2.addChild(stage4); stage2.addChild(stage5); - _timeline.forEach(function(d) { + _timeline.forEach(function (d) { d.type = "timeline"; }); var canvasDomain = d3.nest() - .key(function(d) { return d.year; }) + .key(function (d) { + return d.year; + }) .entries(_data.concat(_timeline)) - .sort(function(a, b) { return a.key - b.key; }) - .map(function(d) { return d.key; }) + .sort(function (a, b) { + return a.key - b.key; + }) + .map(function (d) { + return d.key; + }) - timeDomain = canvasDomain.map(function(d) { + timeDomain = canvasDomain.map(function (d) { return { key: d, - values: _timeline.filter(function(e) { return d == e.year; }) + values: _timeline.filter(function (e) { + return d == e.year; + }) } }) @@ -210,7 +230,7 @@ function Canvas() { canvas.makeScales(); // add preview pics - data.forEach(function(d, i) { + data.forEach(function (d, i) { var sprite = new PIXI.Sprite(PIXI.Texture.WHITE); sprite.anchor.x = 0.5; @@ -231,11 +251,11 @@ function Canvas() { .call(zoom) .on("mousemove", mousemove) .on("dblclick.zoom", null) - .on("touchstart", function(d) { + .on("touchstart", function (d) { mousemove(d); touchstart = new Date() * 1; }) - .on("touchend", function(d) { + .on("touchend", function (d) { var touchtime = (new Date() * 1) - touchstart; if (touchtime > 250) return; if (selectedImageDistance > 15) return; @@ -245,9 +265,12 @@ function Canvas() { zoomToImage(selectedImage, 1400 / Math.sqrt(Math.sqrt(scale))) }) - .on("click", function() { + .on("click", function () { console.log("click"); - if (spriteClick) { spriteClick = false; return; } + if (spriteClick) { + spriteClick = false; + return; + } if (selectedImage && !selectedImage.id) return; if (drag) return; if (selectedImageDistance > 15) return; @@ -271,6 +294,35 @@ function Canvas() { state.init = true; }; + canvas.addTsneData = function (d) { + console.time("tsne") + var clean = d.map(function (d) { + return { + id: d.id, + x: parseFloat(d.x), + y: parseFloat(d.y) + } + }) + var xExtent = d3.extent(clean, function (d) { + return d.x + }) + var yExtent = d3.extent(clean, function (d) { + return d.y + }) + + var x = d3.scale.linear().range([0, 1]).domain(xExtent) + var y = d3.scale.linear().range([0, 1]).domain(yExtent) + + d.forEach(function (d) { + tsneIndex[d.id] = [ + x(d.x), + y(d.y) + ] + }) + + console.timeEnd("tsne") + } + function mousemove(d) { if (timelineHover) return; @@ -298,7 +350,7 @@ function Canvas() { selectedImage = d; } - container.style("cursor", function() { + container.style("cursor", function () { return ((best.d < 5) && selectedImage.active) ? "pointer" : "default"; }); } @@ -309,19 +361,19 @@ function Canvas() { function stackLayout(data, invert) { var years = d3.nest() - .key(function(d) { + .key(function (d) { return d.year; }) .entries(data) - years.forEach(function(year) { + years.forEach(function (year) { var startX = x(year.key); var total = year.values.length; - year.values.sort(function(a, b) { + year.values.sort(function (a, b) { return b.keywords.length - a.keywords.length; }) - year.values.forEach(function(d, i) { + year.values.forEach(function (d, i) { var row = (Math.floor(i / collumns) + 2); d.ii = i; @@ -346,7 +398,7 @@ function Canvas() { }) } - canvas.distance = function(a, b) { + canvas.distance = function (a, b) { return Math.sqrt((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1])); } @@ -362,7 +414,7 @@ function Canvas() { function imageAnimation() { var sleep = true - data.forEach(function(d, i) { + data.forEach(function (d, i) { var diff; diff = (d.x1 - d.sprite.position.x); if (Math.abs(diff) > 0.1) { @@ -398,8 +450,15 @@ function Canvas() { return sleep } - - canvas.wakeup = function() { sleep = false } + + canvas.wakeup = function () { + sleep = false + } + + canvas.setMode = function (mode) { + state.mode = mode + canvas.project() + } function animate(time) { requestAnimationFrame(animate); @@ -434,7 +493,7 @@ function Canvas() { zoomedToImageScale = scale; - setTimeout(function() { + setTimeout(function () { hideTheRest(d); }, duration / 2); @@ -442,7 +501,7 @@ function Canvas() { .call(zoom.translate(translate).event) .transition().duration(duration) .call(zoom.scale(scale).translate(translateNow).event) - .each("end", function() { + .each("end", function () { zoomedToImage = true; selectedImage = d; hideTheRest(d); @@ -479,7 +538,7 @@ function Canvas() { } - canvas.changePage = function(id, page) { + canvas.changePage = function (id, page) { console.log("changePage", id, page, selectedImage); selectedImage.page = page detailVue._data.page = page @@ -489,7 +548,7 @@ function Canvas() { function hideTheRest(d) { - data.forEach(function(d2) { + data.forEach(function (d2) { if (d2.id !== d.id) { d2.alpha = 0; d2.alpha2 = 0; @@ -499,7 +558,7 @@ function Canvas() { } function showAllImages() { - data.forEach(function(d) { + data.forEach(function (d) { d.alpha = d.active ? 1 : 0.2;; d.alpha2 = d.visible ? 1 : 0; }) @@ -583,23 +642,96 @@ function Canvas() { } } - canvas.highlight = function() { - data.forEach(function(d, i) { + canvas.highlight = function () { + data.forEach(function (d, i) { d.alpha = d.highlight ? 1 : 0.2; }); canvas.wakeup(); } - canvas.project = function() { + // canvas.project = function () { + // sleep = false + // canvas.split(); + // canvas.resetZoom(); + // } + + canvas.project = function () { sleep = false - canvas.split(); + if (state.mode == "tsne") { + canvas.projectTSNE(); + } else { + canvas.split(); + } canvas.resetZoom(); } - canvas.resetZoom = function() { + canvas.projectTSNE = function () { + + var marginBottom = -height / 2.5; + + var inactive = data.filter(function (d) { + return !d.active; + }); + var inactiveSize = inactive.length; + + var active = data.filter(function (d) { + return d.active; + }); + + // inactive.sort(function (a, b) { + // return a.rTSNE - b.rTSNE + // }); + + var dimension = Math.min(width, height) * 0.8 + + inactive.forEach(function (d, i) { + var r = dimension / 1.9 + Math.random() * 40; + var a = -Math.PI / 2 + (i / inactiveSize) * 2 * Math.PI; + + d.x = r * Math.cos(a) + width / 2 + margin.left; + d.y = r * Math.sin(a) + marginBottom; + }); + + active.forEach(function (d) { + + var factor = height / 2; + var tsneEntry = tsneIndex[d.id] + // var tsneEntry = tsne.find(function (t) { + // return t.id == d.id + // }) + d.x = (tsneEntry[0] * dimension) + width / 2 - dimension / 2 + margin.left; + d.y = (tsneEntry[1] * dimension) - dimension / 2 + marginBottom; + + }) + + data.forEach(function (d) { + d.x1 = d.x * scale1 + imageSize / 2; + d.y1 = d.y * scale1 + imageSize / 2; + + if (d.sprite.position.x == 0) { + d.sprite.position.x = d.x1; + d.sprite.position.y = d.y1; + } + + if (d.sprite2) { + d.sprite2.position.x = d.x * scale2 + imageSize2 / 2; + d.sprite2.position.y = d.y * scale2 + imageSize2 / 2; + } + }); + + + quadtree = Quadtree(data); + //chart.resetZoom(); + + + } + + canvas.resetZoom = function () { var duration = 1400; - console.log(translate) - extent = d3.extent(data, function(d) { return d.y; }); + + extent = d3.extent(data, function (d) { + return d.y; + }); var y = -extent[1] - bottomPadding; y = (extent[1] / -3) - bottomPadding @@ -610,12 +742,12 @@ function Canvas() { .call(zoom.translate([0, y]).scale(1).event) } - canvas.split = function() { - var active = data.filter(function(d) { + canvas.split = function () { + var active = data.filter(function (d) { return d.active; }) stackLayout(active, false); - var inactive = data.filter(function(d) { + var inactive = data.filter(function (d) { return !d.active; }) stackLayout(inactive, true); @@ -626,7 +758,7 @@ function Canvas() { var zoomScale = scale; if (zoomedToImage) return; - data.forEach(function(d, i) { + data.forEach(function (d, i) { var p = d.sprite.position; var x = (p.x / scale1) + translate[0] / zoomScale; var y = ((p.y / scale1) + (translate[1]) / zoomScale); @@ -639,18 +771,18 @@ function Canvas() { } }); - var visible = data.filter(function(d) { + var visible = data.filter(function (d) { return d.visible; }); if (visible.length < 40) { - data.forEach(function(d) { + data.forEach(function (d) { if (d.visible && d.loaded && d.active) d.alpha2 = 1; else if (d.visible && !d.loaded && d.active) loadImagesCue.push(d); else d.alpha2 = 0; }) } else { - data.forEach(function(d) { + data.forEach(function (d) { d.alpha2 = 0; }) } @@ -663,10 +795,11 @@ function Canvas() { } // console.log("load", d) - var texture = new PIXI.Texture.fromImage(config.loader.textures.detail.url + d.id + '.jpg', true) + var url = encodeURIComponent(config.loader.textures.detail.url + d.id + '.jpg') + var texture = new PIXI.Texture.fromImage(url, true) var sprite = new PIXI.Sprite(texture); - var update = function() { + var update = function () { sleep = false } @@ -696,13 +829,13 @@ function Canvas() { state.lastZoomed = d.id; var page = d.page ? '_' + d.page : '' - var url = config.loader.textures.big.url + d.id + page + ".jpg"; + var url = encodeURIComponent(config.loader.textures.big.url + d.id + page + ".jpg"); var texture = new PIXI.Texture.fromImage(url, true) var sprite = new PIXI.Sprite(texture); var res = config.loader.textures.big.size - var updateSize = function() { + var updateSize = function () { var size = Math.max(texture.width, texture.height) sprite.scale.x = sprite.scale.y = (imageSize3 / size) * d.scaleFactor; sleep = false @@ -712,11 +845,11 @@ function Canvas() { texture.once('update', updateSize) if (d.imagenum) { - sprite.on("mousemove", function(s) { + sprite.on("mousemove", function (s) { var pos = s.data.getLocalPosition(s.currentTarget) s.currentTarget.cursor = pos.x > 0 ? "e-resize" : "w-resize" }) - sprite.on("click", function(s) { + sprite.on("click", function (s) { if (drag) return s.stopPropagation() diff --git a/js/timeline.js b/js/timeline.js index 580b9d850d1e87ed6b7a200fd1016f4ab6f23e73..194e9ad28f24023d5a409723bc6316e72d5b056f 100644 --- a/js/timeline.js +++ b/js/timeline.js @@ -1,149 +1,155 @@ - function Timeline() { - var fontScaleYear = d3.scale.linear() - .domain([1, 9]) - .range([9, 20]) - .clamp(true) - - var timelineFontScale = d3.scale.linear() - .domain([40, 8]) - .range([2, 10]) - .clamp(true) - - var timelineScale = d3.scale.threshold() - .domain([3, 10, 20]) - .range(["none", "small", "middle", "large"]) - - var timelineHover = false; - var container - var timeDomain - var fontSize = 1 - - function timeline(){ } - - timeline.init = function(_timeDomain) { - timeDomain = _timeDomain - container = d3.select(".viz").append("div").classed("timeline", true) - container.style("transform", "translate(" + 0 + "px," + (canvas.height() - 30) + "px)"); - } - - timeline.rescale = function(scale) { - timeDomain.forEach(function(d) { - d.x = canvas.x(d.key); - }); - fontSize = timelineFontScale(scale) - } - - timeline.update = function(x1, x2, scale, translate) { - - timeDomain.forEach(function(d) { - d.pos = ((d.x - x1) * scale); - d.visible = (d.pos > (-canvas.rangeBand() * scale) && d.pos < canvas.width() + 100); - }) - - var timeY = ((canvas.height()) * scale - (-1 * translate[1]) - canvas.rangeBandImage() * scale); - - container - .attr("class", "timeline " + timelineScale(scale * (fontSize/2))) - .style("font-size", function() { - return fontSize * scale + "px"; + var fontScaleYear = d3.scale.linear() + .domain([1, 9]) + .range([9, 20]) + .clamp(true) + + var timelineFontScale = d3.scale.linear() + .domain([40, 8]) + .range([2, 10]) + .clamp(true) + + var timelineScale = d3.scale.threshold() + .domain([3, 10, 20]) + .range(["none", "small", "middle", "large"]) + + var timelineHover = false; + var container + var timeDomain + var fontSize = 1 + var disabled = false + + function timeline() {} + + timeline.init = function (_timeDomain) { + timeDomain = _timeDomain + container = d3.select(".viz").append("div").classed("timeline", true) + container.style("transform", "translate(" + 0 + "px," + (canvas.height() - 30) + "px)"); + } + + timeline.rescale = function (scale) { + timeDomain.forEach(function (d) { + d.x = canvas.x(d.key); + }); + fontSize = timelineFontScale(scale) + } + + timeline.setDisabled = function (d) { + disabled = d + container.style("display", disabled ? "none" : "block") + } + + timeline.update = function (x1, x2, scale, translate) { + if (disabled) return + + timeDomain.forEach(function (d) { + d.pos = ((d.x - x1) * scale); + d.visible = (d.pos > (-canvas.rangeBand() * scale) && d.pos < canvas.width() + 100); }) - .style("transform", "translate3d(" + 0 + "px," + timeY + "px, 0px)"); - - var select = container.selectAll(".container") - .data(timeDomain) - - var enter = select - .enter() - .append("div") - .classed("container", true) - .on("mouseenter", function(d){ - timelineHover = true; - canvas.zoom.center(null); - // canvas.selectedImage() = null; - }) - .on("mouseleave", function(d){ - timelineHover = false; - }) - - enter.append("div") - .classed("year", true) - .text(function(d) { - return d.key; - }) - - var e = enter - .append("div") - .classed("entries", true) - .selectAll(".entry") - .data(function(d) { - return d.values; - }) - .enter() - .append("div") - .classed("entry", true) - - e - .append("div") - .classed("small", true) - .append("div") - .classed("title", true) - .text(function(d) { - return d.titel; - }) - - var m = e - .append("div") - .classed("middle", true) - - m - .append("div") - .classed("title", true) - .text(function(d) { - return d.titel; - }) - - m - .append("div") - .classed("text", true) - .text(function(d) { - return d.text + "."; - }) //… - - var l = e - .append("div") - .classed("large", true) - - l - .append("div") - .classed("title", true) - .text(function(d) { - return d.titel; - }) - - l - .append("div") - .classed("text", true) - .html(function(d) { - return d.text + ".<br><br>" + d.extra; - }) - - select - .style("transform", function(d) { - return "translate3d(" + parseInt(d.pos) + "px,0px,0px)"; - }) - .style("height", canvas.rangeBand() * scale + "px") - .style("width", canvas.rangeBand() * scale + "px") - .style("display", function(d) { - return d.visible ? "block" : "none"; - }) - - select - .select(".year") - .style("font-size", fontScaleYear(scale) + "px") - } - - return timeline + + var timeY = ((canvas.height()) * scale - (-1 * translate[1]) - canvas.rangeBandImage() * scale); + + container + .attr("class", "timeline " + timelineScale(scale * (fontSize / 2))) + .style("font-size", function () { + return fontSize * scale + "px"; + }) + .style("transform", "translate3d(" + 0 + "px," + timeY + "px, 0px)"); + + var select = container.selectAll(".container") + .data(timeDomain) + + var enter = select + .enter() + .append("div") + .classed("container", true) + .on("mouseenter", function (d) { + timelineHover = true; + canvas.zoom.center(null); + // canvas.selectedImage() = null; + }) + .on("mouseleave", function (d) { + timelineHover = false; + }) + + enter.append("div") + .classed("year", true) + .text(function (d) { + return d.key; + }) + + var e = enter + .append("div") + .classed("entries", true) + .selectAll(".entry") + .data(function (d) { + return d.values; + }) + .enter() + .append("div") + .classed("entry", true) + + e + .append("div") + .classed("small", true) + .append("div") + .classed("title", true) + .text(function (d) { + return d.titel; + }) + + var m = e + .append("div") + .classed("middle", true) + + m + .append("div") + .classed("title", true) + .text(function (d) { + return d.titel; + }) + + m + .append("div") + .classed("text", true) + .text(function (d) { + return d.text + "."; + }) //… + + var l = e + .append("div") + .classed("large", true) + + l + .append("div") + .classed("title", true) + .text(function (d) { + return d.titel; + }) + + l + .append("div") + .classed("text", true) + .html(function (d) { + return d.text + ".<br><br>" + d.extra; + }) + + select + .style("transform", function (d) { + return "translate3d(" + parseInt(d.pos) + "px,0px,0px)"; + }) + .style("height", canvas.rangeBand() * scale + "px") + .style("width", canvas.rangeBand() * scale + "px") + .style("display", function (d) { + return d.visible ? "block" : "none"; + }) + + select + .select(".year") + .style("font-size", fontScaleYear(scale) + "px") + } + + return timeline } \ No newline at end of file diff --git a/js/viz.js b/js/viz.js index 26db6179fac9248351dee2d7d7a812b76eaddf1d..a745527c3ad02c7a42081a09873eea7ebcb613fc 100644 --- a/js/viz.js +++ b/js/viz.js @@ -41,75 +41,96 @@ var search; var ping; if (Modernizr.webgl && !utils.isMobile()) { - init(); + init(); } - function init() { - tags = Tags(); - canvas = Canvas(); - search = Search(); - timeline = Timeline() - ping = utils.ping(); - - d3.json("data/config.json", function(config) { - - utils.initConfig(config) - - d3.csv(config.loader.timeline, function(timeline) { - Loader(config.loader.items).finished(function(data) { - - utils.clean(data); - - tags.init(data, config); - search.init(); - canvas.init(data, timeline, config); - - LoaderSprites() - .progress(function(textures) { - Object.keys(textures).forEach(function(id) { - data - .filter(function(d) { return d.id === id }) - .forEach(function(d) { - d.sprite.texture = textures[id] - }) - }) - canvas.wakeup() - }) - .load(config.loader.textures.medium.url) - }); - }); + tags = Tags(); + canvas = Canvas(); + search = Search(); + timeline = Timeline() + ping = utils.ping(); + + d3.json("data/config.json", function (config) { + + utils.initConfig(config) + + Loader(config.loader.timeline).finished(function (timeline) { + Loader(config.loader.items).finished(function (data) { + + utils.clean(data); + + tags.init(data, config); + search.init(); + canvas.init(data, timeline, config); + + if (config.loader.tsne) { + d3.csv(config.loader.tsne, function (tsne) { + console.log(tsne) + d3.select(".navi").classed("hide", false) + canvas.addTsneData(tsne) + }) + } + + LoaderSprites() + .progress(function (textures) { + Object.keys(textures).forEach(function (id) { + data + .filter(function (d) { + return d.id === id + }) + .forEach(function (d) { + d.sprite.texture = textures[id] + }) + }) + canvas.wakeup() + }) + .load(config.loader.textures.medium.url) + }); }); - - d3.select(window) - .on("resize", function() { - if (canvas !== undefined && tags !== undefined) { - clearTimeout(window.resizedFinished); - window.resizedFinished = setTimeout(function() { - canvas.resize(); - tags.resize(); - }, 250); - } - }) - .on("keydown", function(e) { - if (d3.event.keyCode != 27) return - search.reset(); - tags.reset(); - canvas.split(); - }) - - d3.select(".slidebutton") - .on("click", function() { - var s = !d3.select(".sidebar").classed("sneak"); - d3.select(".sidebar").classed("sneak", s); - }) - - d3.select(".infobutton") - .on("click", function() { - var s = !d3.select(".infobar").classed("sneak"); - d3.select(".infobar").classed("sneak", s) - }) + }); + + d3.select(window) + .on("resize", function () { + if (canvas !== undefined && tags !== undefined) { + clearTimeout(window.resizedFinished); + window.resizedFinished = setTimeout(function () { + canvas.resize(); + tags.resize(); + }, 250); + } + }) + .on("keydown", function (e) { + if (d3.event.keyCode != 27) return + search.reset(); + tags.reset(); + canvas.split(); + }) + + d3.select(".slidebutton") + .on("click", function () { + var s = !d3.select(".sidebar").classed("sneak"); + d3.select(".sidebar").classed("sneak", s); + }) + + d3.select(".infobutton") + .on("click", function () { + var s = !d3.select(".infobar").classed("sneak"); + d3.select(".infobar").classed("sneak", s) + }) + + d3.selectAll(".navi .button") + .on("click", function () { + var that = this + var mode = d3.select(this).text() + canvas.setMode(mode) + timeline.setDisabled(mode != "time") + + d3.selectAll(".navi .button").classed("active", function () { + return that === this + }); + }) } d3.select(".browserInfo").classed("show", utils.isMobile()); \ No newline at end of file