diff --git a/css/style.css b/css/style.css index 7a733c64fe1ca3d72cf9fc386509c21e9a9fcb12..f310be091a7692e0769d5f6714160eb40f227834 100644 --- a/css/style.css +++ b/css/style.css @@ -50,6 +50,10 @@ body { #map { position: absolute; top: 0; bottom: 0; width: 100%; z-index: 1;} +#map.hide { + opacity: 0; +} + canvas { position: absolute; @@ -342,6 +346,7 @@ svg { .timeline { z-index: 200; color: #000; + position: absolute; } .timeline * { diff --git a/index.html b/index.html index 672c5906e725b476f50971a94d049666ce2bd37f..d2d08cc61dff1775a3320ab516862d69db77aabf 100644 --- a/index.html +++ b/index.html @@ -36,9 +36,12 @@ <script src="js/modernizr-custom.js"></script> <script src="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.js"></script> - <link href="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.css" rel="stylesheet" /> + <link + href="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.css" + rel="stylesheet" + /> -<!-- <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" + <!-- <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/> <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js" @@ -188,9 +191,9 @@ cpietsch@gmail.com <span v-html="marked(info)"></span> <div class="credit"> Powered by - <a href="https://vikusviewer.fh-potsdam.de/" target="_blank" - >VIKUS Viewer</a - > + <a href="https://vikusviewer.fh-potsdam.de/" target="_blank"> + VIKUS Viewer + </a> </div> </div> </div> @@ -204,7 +207,7 @@ cpietsch@gmail.com </div> </div> - <div id="map"></div> + <div id="map" class="hide"></div> <script src="js/sidebars.js"></script> <script src="js/viz.js"></script> diff --git a/js/canvas.js b/js/canvas.js index c15dcd6ad9095fd7bcb07525f43314b7a5a1b8c7..8fe5cd76e0ac031ee17551066319cd379c9adf0d 100644 --- a/js/canvas.js +++ b/js/canvas.js @@ -8,351 +8,361 @@ function Canvas() { right: 50, bottom: 30, left: 50, - }; + } - var minHeight = 400; - var width = window.innerWidth - margin.left - margin.right; - var widthOuter = window.innerWidth; - var height = window.innerHeight < minHeight ? minHeight : window.innerHeight; + var minHeight = 400 + var width = window.innerWidth - margin.left - margin.right + var widthOuter = window.innerWidth + var height = window.innerHeight < minHeight ? minHeight : window.innerHeight - var scale; - var scale1 = 1; - var scale2 = 1; - var scale3 = 1; - var allData = []; + var scale + var scale1 = 1 + var scale2 = 1 + var scale3 = 1 + var allData = [] - var translate = [0, 0]; - var scale = 1; - var timeDomain = []; - var loadImagesCue = []; + var translate = [0, 0] + var scale = 1 + var timeDomain = [] + var loadImagesCue = [] - var x = d3.scale - .ordinal() - .rangeBands([margin.left, width + margin.left], 0.2); + var x = d3.scale.ordinal().rangeBands([margin.left, width + margin.left], 0.2) var Quadtree = d3.geom .quadtree() .x(function (d) { - return d.x; + return d.x }) .y(function (d) { - return d.y; - }); + return d.y + }) - var quadtree; + var quadtree - var maxZoomLevel = utils.isMobile() ? 5000 : 2500; + var maxZoomLevel = utils.isMobile() ? 5000 : 2500 var zoom = d3.behavior .zoom() .scaleExtent([1, maxZoomLevel]) .size([width, height]) - .on("zoom", zoomed) - .on("zoomend", zoomend) - .on("zoomstart", zoomstart); - - var canvas; - var config; - var container; - var entries; - var years; - var data; - var rangeBand = 0; - var rangeBandImage = 0; - var imageSize = 256; - var imageSize2 = 1024; - var imageSize3 = 4000; - var collumns = 4; - var renderer, stage; - - var svgscale, voronoi; - - var selectedImageDistance = 0; - var selectedImage = null; - - var drag = false; - var sleep = false; - - var stagePadding = 40; - var imgPadding; - - var bottomPadding = 70; - var extent = [0, 0]; - var bottomZooming = true; - - var touchstart = 0; - var vizContainer; - var spriteClick = false; + .on('zoom', zoomed) + .on('zoomend', zoomend) + .on('zoomstart', zoomstart) + + var canvas + var config + var container + var entries + var years + var data + var rangeBand = 0 + var rangeBandImage = 0 + var imageSize = 256 + var imageSize2 = 1024 + var imageSize3 = 4000 + var collumns = 4 + var renderer, stage + + var svgscale, voronoi + + var selectedImageDistance = 0 + var selectedImage = null + + var drag = false + var sleep = false + + var stagePadding = 40 + var imgPadding + + var bottomPadding = 70 + var extent = [0, 0] + var bottomZooming = true + + var touchstart = 0 + var vizContainer + var spriteClick = false var state = { lastZoomed: 0, zoomingToImage: false, - mode: "map", + mode: 'time', init: false, - }; - - var zoomedToImage = false; - var zoomedToImageScale = 117; - var zoomBarrier = 2; - - var startTranslate = [0, 0]; - var startScale = 0; - var cursorCutoff = 1; - var zooming = false; - var detailContainer = d3.select(".sidebar"); - var timelineData; - var stage, stage1, stage2, stage3, stage4, stage5; - var timelineHover = false; - var tsne = []; - var tsneIndex = {}; - var mapIndex = {}; + } + + var zoomedToImage = false + var zoomedToImageScale = 117 + var zoomBarrier = 2 + + var startTranslate = [0, 0] + var startScale = 0 + var cursorCutoff = 1 + var zooming = false + var detailContainer = d3.select('.sidebar') + var timelineData + var stage, stage1, stage2, stage3, stage4, stage5 + var timelineHover = false + var tsne = [] + var tsneIndex = {} + var mapIndex = {} function canvas() {} canvas.rangeBand = function () { - return rangeBand; - }; + return rangeBand + } canvas.width = function () { - return width; - }; + return width + } canvas.height = function () { - return height; - }; + return height + } + canvas.imgPadding = function () { + return imgPadding + } canvas.rangeBandImage = function () { - return rangeBandImage; - }; - canvas.zoom = zoom; + return rangeBandImage + } + canvas.zoom = zoom canvas.selectedImage = function () { - return selectedImage; - }; - canvas.x = x; + return selectedImage + } + canvas.x = x canvas.resize = function () { - if (!state.init) return; - width = window.innerWidth - margin.left - margin.right; - height = window.innerHeight < minHeight ? minHeight : window.innerHeight; - widthOuter = window.innerWidth; - renderer.resize(width + margin.left + margin.right, height); - canvas.makeScales(); - canvas.project(); - }; + if (!state.init) return + width = window.innerWidth - margin.left - margin.right + height = window.innerHeight < minHeight ? minHeight : window.innerHeight + widthOuter = window.innerWidth + renderer.resize(width + margin.left + margin.right, height) + canvas.makeScales() + if (state.mode === 'map') { + map.project() + canvas.project() + canvas.resetZoom() + } else { + canvas.project() + } + } canvas.makeScales = function () { - x.rangeBands([margin.left, width + margin.left], 0.2); + x.rangeBands([margin.left, width + margin.left], 0.2) - rangeBand = x.rangeBand(); - rangeBandImage = x.rangeBand() / collumns; + rangeBand = x.rangeBand() + rangeBandImage = x.rangeBand() / collumns - imgPadding = rangeBand / collumns / 2; + imgPadding = rangeBand / collumns / 2 - scale1 = imageSize / (x.rangeBand() / collumns); - scale2 = imageSize2 / (x.rangeBand() / collumns); - scale3 = imageSize3 / (x.rangeBand() / collumns); + scale1 = imageSize / (x.rangeBand() / collumns) + scale2 = imageSize2 / (x.rangeBand() / collumns) + scale3 = imageSize3 / (x.rangeBand() / collumns) - stage3.scale.x = 1 / scale1; - stage3.scale.y = 1 / scale1; - stage3.y = height; + stage3.scale.x = 1 / scale1 + stage3.scale.y = 1 / scale1 + stage3.y = height - stage4.scale.x = 1 / scale2; - stage4.scale.y = 1 / scale2; - stage4.y = height; + stage4.scale.x = 1 / scale2 + stage4.scale.y = 1 / scale2 + stage4.y = height - stage5.scale.x = 1 / scale3; - stage5.scale.y = 1 / scale3; - stage5.y = height; + stage5.scale.x = 1 / scale3 + stage5.scale.y = 1 / scale3 + stage5.y = height - timeline.rescale(scale1); + timeline.rescale(scale1) - cursorCutoff = (1 / scale1) * imageSize * 0.48; - zoomedToImageScale = 0.8 / (x.rangeBand() / collumns / width); + cursorCutoff = (1 / scale1) * imageSize * 0.48 + zoomedToImageScale = 0.8 / (x.rangeBand() / collumns / width) // console.log("zoomedToImageScale", zoomedToImageScale) - }; + } canvas.init = function (_data, _timeline, _config) { - data = _data; - config = _config; + data = _data + config = _config - container = d3.select(".page").append("div").classed("viz", true); - detailVue._data.structure = config.detail.structure; + container = d3.select('.page').append('div').classed('viz', true) + detailVue._data.structure = config.detail.structure - collumns = config.projection.columns; - imageSize = config.loader.textures.medium.size; - imageSize2 = config.loader.textures.detail.size; + collumns = config.projection.columns + imageSize = config.loader.textures.medium.size + imageSize2 = config.loader.textures.detail.size if (config.loader.textures.big) { - imageSize3 = config.loader.textures.big.size; + imageSize3 = config.loader.textures.big.size } - PIXI.settings.SCALE_MODE = 1; + PIXI.settings.SCALE_MODE = 1 PIXI.settings.SPRITE_MAX_TEXTURES = Math.min( PIXI.settings.SPRITE_MAX_TEXTURES, - 16 - ); + 16, + ) var renderOptions = { resolution: 1, antialiasing: false, width: width + margin.left + margin.right, height: height, - transparent: true - }; - renderer = new PIXI.Renderer(renderOptions); + transparent: true, + } + renderer = new PIXI.Renderer(renderOptions) // renderer.backgroundColor = parseInt( // config.style.canvasBackground.substring(1), // 16 // ); - window.renderer = renderer; + window.renderer = renderer - var renderElem = d3.select(container.node().appendChild(renderer.view)); + var renderElem = d3.select(container.node().appendChild(renderer.view)) - stage = new PIXI.Container(); - stage2 = new PIXI.Container(); - stage3 = new PIXI.Container(); - stage4 = new PIXI.Container(); - stage5 = new PIXI.Container(); + stage = new PIXI.Container() + stage2 = new PIXI.Container() + stage3 = new PIXI.Container() + stage4 = new PIXI.Container() + stage5 = new PIXI.Container() - stage.addChild(stage2); - stage2.addChild(stage3); - stage2.addChild(stage4); - stage2.addChild(stage5); + stage.addChild(stage2) + stage2.addChild(stage3) + stage2.addChild(stage4) + stage2.addChild(stage5) _timeline.forEach(function (d) { - d.type = "timeline"; - }); + d.type = 'timeline' + }) var canvasDomain = d3 .nest() .key(function (d) { - return d.year; + return d.year }) .entries(_data.concat(_timeline)) .sort(function (a, b) { - return a.key - b.key; + return a.key - b.key }) .map(function (d) { - return d.key; - }); + return d.key + }) timeDomain = canvasDomain.map(function (d) { return { key: d, values: _timeline.filter(function (e) { - return d == e.year; + return d == e.year }), - }; - }); + } + }) - timeline.init(timeDomain); - x.domain(canvasDomain); - canvas.makeScales(); + timeline.init(timeDomain) + x.domain(canvasDomain) + canvas.makeScales() // add preview pics data.forEach(function (d, i) { - var sprite = new PIXI.Sprite(PIXI.Texture.WHITE); + var sprite = new PIXI.Sprite(PIXI.Texture.WHITE) - sprite.anchor.x = 0.5; - sprite.anchor.y = 0.5; + sprite.anchor.x = 0.5 + sprite.anchor.y = 0.5 - sprite.scale.x = d.scaleFactor; - sprite.scale.y = d.scaleFactor; + sprite.scale.x = d.scaleFactor + sprite.scale.y = d.scaleFactor - sprite._data = d; - d.sprite = sprite; + sprite._data = d + d.sprite = sprite - stage3.addChild(sprite); - }); + stage3.addChild(sprite) + }) vizContainer = d3 - .select(".viz") + .select('.viz') .call(zoom) - .on("mousemove", mousemove) - .on("dblclick.zoom", null) - .on("touchstart", function (d) { - mousemove(d); - touchstart = new Date() * 1; + .on('mousemove', mousemove) + .on('dblclick.zoom', null) + .on('touchstart', function (d) { + mousemove(d) + touchstart = new Date() * 1 }) - .on("touchend", function (d) { - var touchtime = new Date() * 1 - touchstart; - if (touchtime > 250) return; - if (selectedImageDistance > 15) return; - if (selectedImage && !selectedImage.id) return; - if (selectedImage && !selectedImage.active) return; - if (drag) return; - - zoomToImage(selectedImage, 1400 / Math.sqrt(Math.sqrt(scale))); + .on('touchend', function (d) { + var touchtime = new Date() * 1 - touchstart + if (touchtime > 250) return + if (selectedImageDistance > 15) return + if (selectedImage && !selectedImage.id) return + if (selectedImage && !selectedImage.active) return + if (drag) return + + zoomToImage(selectedImage, 1400 / Math.sqrt(Math.sqrt(scale))) }) - .on("click", function () { - console.log("click"); + .on('click', function () { + console.log('click') if (spriteClick) { - spriteClick = false; - return; + spriteClick = false + return } - if (selectedImage && !selectedImage.id) return; - if (drag) return; - if (selectedImageDistance > cursorCutoff) return; - if (selectedImage && !selectedImage.active) return; - if (timelineHover) return; + if (selectedImage && !selectedImage.id) return + if (drag) return + if (selectedImageDistance > cursorCutoff) return + if (selectedImage && !selectedImage.active) return + if (timelineHover) return // console.log(selectedImage) if (Math.abs(zoomedToImageScale - scale) < 0.1) { - canvas.resetZoom(); + canvas.resetZoom() } else { - zoomToImage(selectedImage, 1400 / Math.sqrt(Math.sqrt(scale))); + zoomToImage(selectedImage, 1400 / Math.sqrt(Math.sqrt(scale))) } - }); + }) - canvas.project(); - animate(); + canvas.project() + animate() // selectedImage = data.find(d => d.id == 88413) // showDetail(selectedImage) - state.init = true; - }; + state.init = true + } canvas.addTsneData = function (d) { - console.time("tsne"); + 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; - }); + return d.x + }) var yExtent = d3.extent(clean, function (d) { - return d.y; - }); + return d.y + }) - var x = d3.scale.linear().range([0, 1]).domain(xExtent); - var y = d3.scale.linear().range([0, 1]).domain(yExtent); + 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)]; - }); + tsneIndex[d.id] = [x(d.x), y(d.y)] + }) - console.timeEnd("tsne"); - }; + console.timeEnd('tsne') + } - canvas.addMapData = function (d) { - console.time("map"); + canvas.setMapData = function (d) { + console.time('map') d.forEach(function (d) { - mapIndex[d.id] = [d.x,d.y]; - }); + mapIndex[d.id] = [d.x, d.y] + }) - console.timeEnd("map"); - }; + console.timeEnd('map') + } + var mousePos function mousemove(d) { - if (timelineHover) return; + if (timelineHover) return - var mouse = d3.mouse(vizContainer.node()); - var p = toScreenPoint(mouse); + var mouse = d3.mouse(vizContainer.node()) + var p = toScreenPoint(mouse) - var distance = 200; + mousePos = p + + var distance = 200 var best = nearest( p[0] - imgPadding, @@ -361,32 +371,32 @@ function Canvas() { d: distance, p: null, }, - quadtree - ); + quadtree, + ) - selectedImageDistance = best.d; + selectedImageDistance = best.d // console.log(cursorCutoff,scale, scale1, selectedImageDistance) if (bottomZooming && best.p && best.p.ii < 3 && selectedImageDistance > 7) { - selectedImage = null; - zoom.center(null); - container.style("cursor", "default"); + selectedImage = null + zoom.center(null) + container.style('cursor', 'default') } else { if (best.p && !zoomedToImage) { - var d = best.p; + var d = best.p var center = [ (d.x + imgPadding) * scale + translate[0], (height + d.y + imgPadding) * scale + translate[1], - ]; - zoom.center(center); - selectedImage = d; + ] + zoom.center(center) + selectedImage = d } - container.style("cursor", function () { + container.style('cursor', function () { return selectedImageDistance < cursorCutoff && selectedImage.active - ? "pointer" - : "default"; - }); + ? 'pointer' + : 'default' + }) } } @@ -394,225 +404,225 @@ function Canvas() { var years = d3 .nest() .key(function (d) { - return d.year; + return d.year }) - .entries(data); + .entries(data) years.forEach(function (year) { - var startX = x(year.key); - var total = year.values.length; + var startX = x(year.key) + var total = year.values.length year.values.sort(function (a, b) { - return b.keywords.length - a.keywords.length; - }); + return b.keywords.length - a.keywords.length + }) year.values.forEach(function (d, i) { - var row = Math.floor(i / collumns) + 2; - d.ii = i; + var row = Math.floor(i / collumns) + 2 + d.ii = i - d.x = startX + (i % collumns) * (rangeBand / collumns); - d.y = (invert ? 1 : -1) * (row * (rangeBand / collumns)); + d.x = startX + (i % collumns) * (rangeBand / collumns) + d.y = (invert ? 1 : -1) * (row * (rangeBand / collumns)) - d.x1 = d.x * scale1 + imageSize / 2; - d.y1 = d.y * scale1 + imageSize / 2; + 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; + 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; + d.sprite2.position.x = d.x * scale2 + imageSize2 / 2 + d.sprite2.position.y = d.y * scale2 + imageSize2 / 2 } - d.order = (invert ? 1 : 1) * (total - i); - }); - }); + d.order = (invert ? 1 : 1) * (total - i) + }) + }) } canvas.distance = function (a, b) { return Math.sqrt( - (a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]) - ); - }; + (a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]), + ) + } function toScreenPoint(p) { - var p2 = [0, 0]; + var p2 = [0, 0] - p2[0] = p[0] / scale - translate[0] / scale; - p2[1] = p[1] / scale - height - translate[1] / scale; + p2[0] = p[0] / scale - translate[0] / scale + p2[1] = p[1] / scale - height - translate[1] / scale - return p2; + return p2 } function imageAnimation() { - var sleep = true; + var sleep = true data.forEach(function (d, i) { - var diff; - diff = d.x1 - d.sprite.position.x; + var diff + diff = d.x1 - d.sprite.position.x if (Math.abs(diff) > 0.1) { - d.sprite.position.x += diff * 0.1; - sleep = false; + d.sprite.position.x += diff * 0.1 + sleep = false } - diff = d.y1 - d.sprite.position.y; + diff = d.y1 - d.sprite.position.y if (Math.abs(diff) > 0.1) { - d.sprite.position.y += diff * 0.1; - sleep = false; + d.sprite.position.y += diff * 0.1 + sleep = false } - diff = d.alpha - d.sprite.alpha; + diff = d.alpha - d.sprite.alpha if (Math.abs(diff) > 0.01) { - d.sprite.alpha += diff * 0.2; - sleep = false; + d.sprite.alpha += diff * 0.2 + sleep = false } - d.sprite.visible = d.sprite.alpha > 0.1; + d.sprite.visible = d.sprite.alpha > 0.1 if (d.sprite2) { - diff = d.alpha2 - d.sprite2.alpha; + diff = d.alpha2 - d.sprite2.alpha if (Math.abs(diff) > 0.01) { - d.sprite2.alpha += diff * 0.2; - sleep = false; + d.sprite2.alpha += diff * 0.2 + sleep = false } - d.sprite2.visible = d.sprite2.alpha > 0.1; + d.sprite2.visible = d.sprite2.alpha > 0.1 //else d.sprite2.visible = d.visible; } - }); - return sleep; + }) + return sleep } canvas.wakeup = function () { - sleep = false; - }; + sleep = false + } canvas.setMode = function (mode) { - state.mode = mode; - canvas.project(); - }; + state.mode = mode + canvas.project() + } function animate(time) { - requestAnimationFrame(animate); - loadImages(); - if (sleep) return; - sleep = imageAnimation(); - renderer.render(stage); + requestAnimationFrame(animate) + loadImages() + if (sleep) return + sleep = imageAnimation() + renderer.render(stage) } function zoomToYear(d) { - var xYear = x(d.year); - var scale = 1 / ((rangeBand * 4) / width); - var padding = rangeBand * 1.5; - var translateNow = [-scale * (xYear - padding), -scale * (height + d.y)]; + var xYear = x(d.year) + var scale = 1 / ((rangeBand * 4) / width) + var padding = rangeBand * 1.5 + var translateNow = [-scale * (xYear - padding), -scale * (height + d.y)] vizContainer .call(zoom.translate(translate).event) .transition() .duration(2000) - .call(zoom.scale(scale).translate(translateNow).event); + .call(zoom.scale(scale).translate(translateNow).event) } function zoomToImage(d, duration) { - state.zoomingToImage = true; - zoom.center(null); - loadMiddleImage(d); - d3.select(".tagcloud").classed("hide", true); - var padding = x.rangeBand() / collumns / 2; - var sidbar = width / 8; - var scale = 0.8 / (x.rangeBand() / collumns / width); + state.zoomingToImage = true + zoom.center(null) + loadMiddleImage(d) + d3.select('.tagcloud').classed('hide', true) + var padding = x.rangeBand() / collumns / 2 + var sidbar = width / 8 + var scale = 0.8 / (x.rangeBand() / collumns / width) var translateNow = [ -scale * (d.x - padding / 2) - sidbar, -scale * (height + d.y), - ]; + ] - zoomedToImageScale = scale; + zoomedToImageScale = scale setTimeout(function () { - hideTheRest(d); - }, duration / 2); + hideTheRest(d) + }, duration / 2) vizContainer .call(zoom.translate(translate).event) .transition() .duration(duration) .call(zoom.scale(scale).translate(translateNow).event) - .each("end", function () { - zoomedToImage = true; - selectedImage = d; - hideTheRest(d); - showDetail(d); - loadBigImage(d, "click"); - state.zoomingToImage = false; - }); + .each('end', function () { + zoomedToImage = true + selectedImage = d + hideTheRest(d) + showDetail(d) + loadBigImage(d, 'click') + state.zoomingToImage = false + }) } function showDetail(d) { // console.log("show detail", d) - detailContainer.select(".outer").node().scrollTop = 0; + detailContainer.select('.outer').node().scrollTop = 0 - detailContainer.classed("hide", false).classed("sneak", utils.isMobile()); + detailContainer.classed('hide', false).classed('sneak', utils.isMobile()) // needs to be done better - var detailData = {}; + var detailData = {} for (field in selectedImage) { - if (field[0] === "_") detailData[field] = selectedImage[field]; + if (field[0] === '_') detailData[field] = selectedImage[field] } - detailData["_id"] = selectedImage.id; - detailData["_keywords"] = selectedImage.keywords; - detailData["_year"] = selectedImage.year; - detailData["_imagenum"] = selectedImage.imagenum || 1; - detailVue._data.item = detailData; - detailVue._data.id = d.id; - detailVue._data.page = d.page; + detailData['_id'] = selectedImage.id + detailData['_keywords'] = selectedImage.keywords + detailData['_year'] = selectedImage.year + detailData['_imagenum'] = selectedImage.imagenum || 1 + detailVue._data.item = detailData + detailVue._data.id = d.id + detailVue._data.page = d.page } canvas.changePage = function (id, page) { - console.log("changePage", id, page, selectedImage); - selectedImage.page = page; - detailVue._data.page = page; - clearBigImages(); - loadBigImage(selectedImage); - }; + console.log('changePage', id, page, selectedImage) + selectedImage.page = page + detailVue._data.page = page + clearBigImages() + loadBigImage(selectedImage) + } function hideTheRest(d) { data.forEach(function (d2) { if (d2.id !== d.id) { - d2.alpha = 0; - d2.alpha2 = 0; + d2.alpha = 0 + d2.alpha2 = 0 } - }); + }) } function showAllImages() { data.forEach(function (d) { - d.alpha = d.active ? 1 : 0.2; - d.alpha2 = d.visible ? 1 : 0; - }); + d.alpha = d.active ? 1 : 0.2 + d.alpha2 = d.visible ? 1 : 0 + }) } function zoomed() { - translate = d3.event.translate; - scale = d3.event.scale; - if (!startTranslate) startTranslate = translate; - drag = startTranslate && translate !== startTranslate; + translate = d3.event.translate + scale = d3.event.scale + if (!startTranslate) startTranslate = translate + drag = startTranslate && translate !== startTranslate // check borders - var x1 = (-1 * translate[0]) / scale; - var x2 = x1 + widthOuter / scale; + var x1 = (-1 * translate[0]) / scale + var x2 = x1 + widthOuter / scale - if (d3.event.sourceEvent != null) { + if (d3.event.sourceEvent != null && state.mode !== 'map') { if (x1 < 0) { - translate[0] = 0; + translate[0] = 0 } else if (x2 > widthOuter) { - translate[0] = (widthOuter * scale - widthOuter) * -1; + translate[0] = (widthOuter * scale - widthOuter) * -1 } - zoom.translate([translate[0], translate[1]]); + zoom.translate([translate[0], translate[1]]) - x1 = (-1 * translate[0]) / scale; - x2 = x1 + width / scale; + x1 = (-1 * translate[0]) / scale + x2 = x1 + width / scale } if ( @@ -620,56 +630,57 @@ function Canvas() { scale > zoomedToImageScale * 0.9 && !zoomedToImage && selectedImage && - selectedImage.type == "image" + selectedImage.type == 'image' ) { - zoomedToImage = true; - zoom.center(null); - zoomedToImageScale = scale; - hideTheRest(selectedImage); - showDetail(selectedImage); + zoomedToImage = true + zoom.center(null) + zoomedToImageScale = scale + hideTheRest(selectedImage) + showDetail(selectedImage) } if (zoomedToImage && zoomedToImageScale * 0.8 > scale) { // console.log("clear") - zoomedToImage = false; - state.lastZoomed = 0; - showAllImages(); - clearBigImages(); - detailContainer.classed("hide", true); + zoomedToImage = false + state.lastZoomed = 0 + showAllImages() + clearBigImages() + detailContainer.classed('hide', true) } - timeline.update(x1, x2, scale, translate, scale1); - if(state.mode === "map") map.zoom(selectedImage, scale, translate, scale1) + timeline.update(x1, x2, scale, translate, scale1) + if (state.mode === 'map') + map.zoom(selectedImage, mousePos, scale, translate, imageSize) // toggle zoom overlays if (scale > zoomBarrier) { - d3.select(".tagcloud").classed("hide", true); - d3.select(".searchbar").classed("hide", true); - d3.select(".infobar").classed("sneak", true); + d3.select('.tagcloud').classed('hide', true) + d3.select('.searchbar').classed('hide', true) + d3.select('.infobar').classed('sneak', true) } else { - d3.select(".tagcloud").classed("hide", false); - d3.select(".searchbar").classed("hide", false); + d3.select('.tagcloud').classed('hide', false) + d3.select('.searchbar').classed('hide', false) } - stage2.scale.x = d3.event.scale; - stage2.scale.y = d3.event.scale; - stage2.x = d3.event.translate[0]; - stage2.y = d3.event.translate[1]; + stage2.scale.x = d3.event.scale + stage2.scale.y = d3.event.scale + stage2.x = d3.event.translate[0] + stage2.y = d3.event.translate[1] - sleep = false; + sleep = false } function zoomstart(d) { - zooming = true; - startTranslate = false; - drag = false; - startScale = scale; + zooming = true + startTranslate = false + drag = false + startScale = scale } function zoomend(d) { - drag = startTranslate && translate !== startTranslate; - zooming = false; - filterVisible(); + drag = startTranslate && translate !== startTranslate + zooming = false + filterVisible() if ( zoomedToImage && @@ -677,16 +688,16 @@ function Canvas() { state.lastZoomed != selectedImage.id && !state.zoomingToImage ) { - loadBigImage(selectedImage, "zoom"); + loadBigImage(selectedImage, 'zoom') } } canvas.highlight = function () { data.forEach(function (d, i) { - d.alpha = d.highlight ? 1 : 0.2; - }); - canvas.wakeup(); - }; + d.alpha = d.highlight ? 1 : 0.2 + }) + canvas.wakeup() + } // canvas.project = function () { // sleep = false @@ -695,162 +706,162 @@ function Canvas() { // } canvas.project = function () { - sleep = false; - if (state.mode == "tsne") { - canvas.projectTSNE(); - } else if (state.mode == "map") { - canvas.projectMap(); + sleep = false + if (state.mode == 'tsne') { + canvas.projectTSNE() + } else if (state.mode == 'map') { + canvas.projectMap() } else { - canvas.split(); + canvas.split() } - canvas.resetZoom(); - }; + canvas.resetZoom() + } canvas.projectMap = function () { - // console.log(mapIndex) var inactive = data.filter(function (d) { - return !d.active; - }); + return !d.active + }) var active = data.filter(function (d) { - return d.active; - }); + return d.active + }) - active.forEach(function (d) { - var mapEntry = mapIndex[d.id]; + data.forEach(function (d) { + var mapEntry = mapIndex[d.id] if (mapEntry) { - d.x = mapEntry[0]; - d.y = mapEntry[1]; + d.x = mapEntry[0] - margin.left - imgPadding + d.y = mapEntry[1] - imgPadding - height // console.log(mapEntry) + } else { + // if there is no geo for entry + d.x = 100 + d.y = -100 } - // var tsneEntry = tsne.find(function (t) { - // return t.id == d.id - // }) - }); + }) data.forEach(function (d) { - d.x1 = d.x * scale1 + imageSize / 2; - d.y1 = d.y * scale1 + imageSize / 2; + d.x1 = d.x * scale1 + imageSize / 2 + d.y1 = d.y * scale1 + imageSize / 2 - d.sprite.scale.x = d.sprite.scale.y = 10 + // d.sprite.scale.x = d.sprite.scale.y = 10 if (d.sprite.position.x == 0) { - d.sprite.position.x = d.x1; - d.sprite.position.y = d.y1; + 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; + d.sprite2.position.x = d.x * scale2 + imageSize2 / 2 + d.sprite2.position.y = d.y * scale2 + imageSize2 / 2 } - }); + }) - quadtree = Quadtree(data); + quadtree = Quadtree(data) //chart.resetZoom(); - }; + } canvas.projectTSNE = function () { - var marginBottom = -height / 2.5; + var marginBottom = -height / 2.5 var inactive = data.filter(function (d) { - return !d.active; - }); - var inactiveSize = inactive.length; + return !d.active + }) + var inactiveSize = inactive.length var active = data.filter(function (d) { - return d.active; - }); + return d.active + }) // inactive.sort(function (a, b) { // return a.rTSNE - b.rTSNE // }); - var dimension = Math.min(width, height) * 0.8; + 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; + 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; - }); + 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 factor = height / 2 + var tsneEntry = tsneIndex[d.id] if (tsneEntry) { - d.x = - tsneEntry[0] * dimension + width / 2 - dimension / 2 + margin.left; - d.y = tsneEntry[1] * dimension - dimension / 2 + marginBottom; + d.x = tsneEntry[0] * dimension + width / 2 - dimension / 2 + margin.left + d.y = tsneEntry[1] * dimension - dimension / 2 + marginBottom } // var tsneEntry = tsne.find(function (t) { // return t.id == d.id // }) - }); + }) data.forEach(function (d) { - d.x1 = d.x * scale1 + imageSize / 2; - d.y1 = d.y * scale1 + imageSize / 2; + 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; + 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; + d.sprite2.position.x = d.x * scale2 + imageSize2 / 2 + d.sprite2.position.y = d.y * scale2 + imageSize2 / 2 } - }); + }) - quadtree = Quadtree(data); + quadtree = Quadtree(data) //chart.resetZoom(); - }; + } canvas.resetZoom = function () { - var duration = 1400; + var duration = 1400 extent = d3.extent(data, function (d) { - return d.y; - }); + return d.y + }) - var y = -extent[1] - bottomPadding; - y = extent[1] / -3 - bottomPadding; + var y = -extent[1] - bottomPadding + y = extent[1] / -3 - bottomPadding - if(state.mode === "map"){ - y = 0 - } + // if (state.mode === 'map') { + // y = translate[1] + // } + console.log(translate, y) vizContainer .call(zoom.translate(translate).event) .transition() .duration(duration) - .call(zoom.translate([0, y]).scale(1).event); - }; + .call(zoom.translate([0, y]).scale(1).event) + } canvas.split = function () { var active = data.filter(function (d) { - return d.active; - }); - stackLayout(active, false); + return d.active + }) + stackLayout(active, false) var inactive = data.filter(function (d) { - return !d.active; - }); - stackLayout(inactive, true); - quadtree = Quadtree(data); - }; + return !d.active + }) + stackLayout(inactive, true) + quadtree = Quadtree(data) + } function filterVisible() { - var zoomScale = scale; - if (zoomedToImage) return; + var zoomScale = scale + if (zoomedToImage) return 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; - var padding = width / 3 / scale; + var p = d.sprite.position + var x = p.x / scale1 + translate[0] / zoomScale + var y = p.y / scale1 + translate[1] / zoomScale + var padding = width / 3 / scale if ( x > -padding && @@ -858,137 +869,137 @@ function Canvas() { y + height < height / zoomScale + padding && y > height * -1 - padding ) { - d.visible = true; + d.visible = true } else { - d.visible = false; + d.visible = false } - }); + }) var visible = data.filter(function (d) { - return d.visible; - }); + return d.visible + }) if (visible.length < 40) { 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; - }); + 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) { - d.alpha2 = 0; - }); + d.alpha2 = 0 + }) } } function loadMiddleImage(d) { if (d.loaded) { - d.alpha2 = 1; - return; + d.alpha2 = 1 + return } // console.log("load", d) - var url = config.loader.textures.detail.url + d.id + ".jpg"; - var texture = new PIXI.Texture.fromImage(url); - var sprite = new PIXI.Sprite(texture); + var url = config.loader.textures.detail.url + d.id + '.jpg' + var texture = new PIXI.Texture.fromImage(url) + var sprite = new PIXI.Sprite(texture) var update = function () { - sleep = false; - }; - - sprite.on("added", update); - texture.once("update", update); - - sprite.scale.x = d.scaleFactor; - sprite.scale.y = d.scaleFactor; - - sprite.anchor.x = 0.5; - sprite.anchor.y = 0.5; - sprite.position.x = d.x * scale2 + imageSize2 / 2; - sprite.position.y = d.y * scale2 + imageSize2 / 2; - sprite._data = d; - stage4.addChild(sprite); - d.sprite2 = sprite; - d.alpha2 = d.highlight; - d.loaded = true; - sleep = false; + sleep = false + } + + sprite.on('added', update) + texture.once('update', update) + + sprite.scale.x = d.scaleFactor + sprite.scale.y = d.scaleFactor + + sprite.anchor.x = 0.5 + sprite.anchor.y = 0.5 + sprite.position.x = d.x * scale2 + imageSize2 / 2 + sprite.position.y = d.y * scale2 + imageSize2 / 2 + sprite._data = d + stage4.addChild(sprite) + d.sprite2 = sprite + d.alpha2 = d.highlight + d.loaded = true + sleep = false } function loadBigImage(d) { if (!config.loader.textures.big) { - loadMiddleImage(d); - return; + loadMiddleImage(d) + return } - state.lastZoomed = d.id; - var page = d.page ? "_" + d.page : ""; - var url = config.loader.textures.big.url + d.id + page + ".jpg"; + state.lastZoomed = d.id + var page = d.page ? '_' + d.page : '' + var url = config.loader.textures.big.url + d.id + page + '.jpg' - var texture = new PIXI.Texture.from(url); - var sprite = new PIXI.Sprite(texture); - var res = config.loader.textures.big.size; + var texture = new PIXI.Texture.from(url) + var sprite = new PIXI.Sprite(texture) + var res = config.loader.textures.big.size var updateSize = function (t) { - var size = Math.max(texture.width, texture.height); - sprite.scale.x = sprite.scale.y = (imageSize3 / size) * d.scaleFactor; - sleep = false; - if(t.valid){ - d.alpha = 0; - d.alpha2 = 0; + var size = Math.max(texture.width, texture.height) + sprite.scale.x = sprite.scale.y = (imageSize3 / size) * d.scaleFactor + sleep = false + if (t.valid) { + d.alpha = 0 + d.alpha2 = 0 } - }; + } - sprite.on("added", updateSize); - texture.once("update", updateSize); + sprite.on('added', updateSize) + texture.once('update', updateSize) if (d.imagenum > 1) { - 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) { - if (drag) return; - - s.stopPropagation(); - spriteClick = true; - var pos = s.data.getLocalPosition(s.currentTarget); - var dir = pos.x > 0 ? 1 : -1; - var page = d.page + dir; - var nextPage = page; - if (page > d.imagenum - 1) nextPage = 0; - if (page < 0) nextPage = d.imagenum - 1; - - canvas.changePage(d.id, nextPage); - }); - sprite.interactive = true; + 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) { + if (drag) return + + s.stopPropagation() + spriteClick = true + var pos = s.data.getLocalPosition(s.currentTarget) + var dir = pos.x > 0 ? 1 : -1 + var page = d.page + dir + var nextPage = page + if (page > d.imagenum - 1) nextPage = 0 + if (page < 0) nextPage = d.imagenum - 1 + + canvas.changePage(d.id, nextPage) + }) + sprite.interactive = true } - sprite.anchor.x = 0.5; - sprite.anchor.y = 0.5; - sprite.position.x = d.x * scale3 + imageSize3 / 2; - sprite.position.y = d.y * scale3 + imageSize3 / 2; - sprite._data = d; - d.big = true; - stage5.addChild(sprite); - sleep = false; + sprite.anchor.x = 0.5 + sprite.anchor.y = 0.5 + sprite.position.x = d.x * scale3 + imageSize3 / 2 + sprite.position.y = d.y * scale3 + imageSize3 / 2 + sprite._data = d + d.big = true + stage5.addChild(sprite) + sleep = false } function clearBigImages() { while (stage5.children[0]) { - stage5.children[0]._data.big = false; - stage5.removeChild(stage5.children[0]); - sleep = false; + stage5.children[0]._data.big = false + stage5.removeChild(stage5.children[0]) + sleep = false } } function loadImages() { - if (zooming) return; - if (zoomedToImage) return; + if (zooming) return + if (zoomedToImage) return if (loadImagesCue.length) { - var d = loadImagesCue.pop(); + var d = loadImagesCue.pop() if (!d.loaded) { - loadMiddleImage(d); + loadMiddleImage(d) } } } @@ -998,8 +1009,8 @@ function Canvas() { var x1 = node.x1, y1 = node.y1, x2 = node.x2, - y2 = node.y2; - node.visited = true; + y2 = node.y2 + node.visited = true //console.log(node, x , x1 , best.d); //return; // exclude node if point is farther away than best distance in either axis @@ -1009,36 +1020,36 @@ function Canvas() { y < y1 - best.d || y > y2 + best.d ) { - return best; + return best } // test point if there is one, potentially updating best - var p = node.point; + var p = node.point if (p) { - p.scanned = true; + p.scanned = true var dx = p.x - x, dy = p.y - y, - d = Math.sqrt(dx * dx + dy * dy); + d = Math.sqrt(dx * dx + dy * dy) if (d < best.d) { - best.d = d; - best.p = p; + best.d = d + best.p = p } } // check if kid is on the right or left, and top or bottom // and then recurse on most likely kids first, so we quickly find a // nearby point and then exclude many larger rectangles later - var kids = node.nodes; + var kids = node.nodes var rl = 2 * x > x1 + x2, - bt = 2 * y > y1 + y2; - if (kids[bt * 2 + rl]) best = nearest(x, y, best, kids[bt * 2 + rl]); + bt = 2 * y > y1 + y2 + if (kids[bt * 2 + rl]) best = nearest(x, y, best, kids[bt * 2 + rl]) if (kids[bt * 2 + (1 - rl)]) - best = nearest(x, y, best, kids[bt * 2 + (1 - rl)]); + best = nearest(x, y, best, kids[bt * 2 + (1 - rl)]) if (kids[(1 - bt) * 2 + rl]) - best = nearest(x, y, best, kids[(1 - bt) * 2 + rl]); + best = nearest(x, y, best, kids[(1 - bt) * 2 + rl]) if (kids[(1 - bt) * 2 + (1 - rl)]) - best = nearest(x, y, best, kids[(1 - bt) * 2 + (1 - rl)]); + best = nearest(x, y, best, kids[(1 - bt) * 2 + (1 - rl)]) - return best; + return best } - return canvas; + return canvas } diff --git a/js/mapbox.js b/js/mapbox.js index 7ff1806fdad5e3d21b445ff70d1c75d107c89354..f6ff5a548663db73e2065623b9b9003500ec32a6 100644 --- a/js/mapbox.js +++ b/js/mapbox.js @@ -1,95 +1,163 @@ -mapboxgl.accessToken = ''; - +mapboxgl.accessToken = + 'pk.eyJ1IjoidGVjaG5vbG9naWVzdGlmdHVuZyIsImEiOiJja2EyODNzenQwMHB0M2xsazd1dXZtOW5tIn0.GxXlHFEWUj_zfgnPAjpX3g' function Mapbox() { - - var state = { - open: false - } - - var map; - var initialZoom; - var initialCenter; - - function mapbox() { } - - mapbox.init = function(data){ - - data.forEach(d => { - d.lat = Number(d._Lat) - d.lng = Number(d._Lon) - }) - - var validData = data.filter(d => !isNaN(d.lat) && !isNaN(d.lng)) - - var extent = [ - d3.extent(validData, function(d){ return d.lng; }) - ,d3.extent(validData, function(d){ return d.lat; }) - ] - - var bounds = [[extent[0][0], extent[1][0]], [extent[0][1], extent[1][1]]] - console.log(bounds, bounds) - - map = new mapboxgl.Map({ - container: 'map', - style: 'mapbox://styles/mapbox/streets-v11', - bounds: bounds, - //fitBoundsOptions: { padding: 200 }, - // causes pan & zoom handlers not to be applied, similar to - // .dragging.disable() and other handler .disable() funtions in Leaflet. - interactive: false - }); - - - - window.mapbox = map - - initialZoom = map.getZoom() - initialCenter = map.getCenter() - - - - map.on('load', function() { - - var projected = validData.map(d => { - var point = map.project([d.lng, d.lat]) - return { - id: d.id, - x: point.x, - y: point.y- canvas.height() - } - }) - - canvas.addMapData(projected) - canvas.projectMap() - canvas.wakeup() - - }) - } - - mapbox.zoom = function(center, scale, translate, scale1){ - if(!map) return - var height = canvas.height() - console.log(scale, translate, scale1) - //map.setZoom(initialZoom + scale) - - var y = (height + translate[1]) * -1 - var x = translate[0] - - map.panTo(initialCenter, {offset: translate, animate:false}) - map.setZoom(initialZoom - (1-Math.sqrt(scale))) - // if(center){ - // var c = [center.lng, center.lat] - // //map.setCenter(c) - // //console.log(c) - // map.flyTo({ - // around: c, - // zoom: initialZoom + Math.sqrt(scale), - // duration: 0 - // }) - // } - - } - - return mapbox; -} \ No newline at end of file + var state = { + open: false, + } + + var map + var initialZoom + var initialCenter + var projected + var validData + var bounds + function mapbox() {} + + mapbox.init = function (data) { + data.forEach((d) => { + d.lat = Number(d._Lat) + d.lng = Number(d._Lon) + }) + + validData = data.filter((d) => !isNaN(d.lat) && !isNaN(d.lng)) + + var extent = [ + d3.extent(validData, function (d) { + return d.lng + }), + d3.extent(validData, function (d) { + return d.lat + }), + ] + + bounds = [ + [extent[0][0], extent[1][0]], + [extent[0][1], extent[1][1]], + ] + console.log(bounds, bounds) + + map = new mapboxgl.Map({ + container: 'map', + style: 'mapbox://styles/mapbox/streets-v11', + bounds: bounds, + //fitBoundsOptions: { padding: 200 }, + // causes pan & zoom handlers not to be applied, similar to + // .dragging.disable() and other handler .disable() funtions in Leaflet. + interactive: false, + }) + + window.mapbox = map + + map.on('load', function () { + console.log('load') + mapbox.project() + }) + // map.on('resize', function () { + // mapbox.project() + // }) + } + + mapbox.project = function () { + console.log('projekt') + map.fitBounds(bounds) + var projected = validData.map((d) => { + var point = map.project([d.lng, d.lat]) + return { + id: d.id, + // x: point.x - 50 - canvas.imgPadding(), + // y: point.y - canvas.imgPadding() - canvas.height(), + x: point.x, + y: point.y, + } + }) + + initialZoom = map.getZoom() + initialCenter = map.getCenter() + initialCenterPos = map.project(initialCenter) + + var aspect = canvas.width() / canvas.height() + // var magic = aspect ? 18.4 : 17.85 + var magic = 17.75 + + console.log(aspect) + + zoomScale.range([initialZoom, magic]) + + canvas.setMapData(projected) + // canvas.projectMap() + // canvas.wakeup() + } + + var zoomScale = d3.scale.log().domain([1, 80]) + mapbox.zoom = function (center, mousePos, scale, translate, imageSize) { + if (!map) return + // console.log('zoom') + + // console.log(map.getZoom(), scale) + // console.log(Math.log(scale)) + + if (initialCenter) { + var x0 = translate[0] + (canvas.width() * scale - canvas.width()) / 2 + var y0 = translate[1] + (canvas.height() * scale - canvas.height()) / 2 + + // console.log(translate, y0) + // console.log(canvas.width() / 2, canvas.height() / 2) + + var x = canvas.width() / 2 + x0 + var y = canvas.height() / 2 + y0 + + var zoom = zoomScale(scale) + + map.setZoom(zoom) + map.transform.setLocationAtPoint(initialCenter, new mapboxgl.Point(x, y)) + } + + if (center) { + // var centerCoord = { lng: center.lng, lat: center.lat } + // var centerPos = [center.x, center.y] + // var projected = map.project(centerCoord) + // // console.log(centerCoord, center, projected, mousePos, centerPos) + // var x0 = translate[0] + (canvas.width() * scale - canvas.width()) / 2 + // var y0 = translate[1] + (canvas.height() * scale - canvas.height()) / 2 + // console.log(translate, y0) + // var x = center.x + x0 + // var y = center.y + canvas.height() + y0 + // var zoom = zoomScale(scale) + // // console.log('zooom', zoom, scale) + // //map.panTo(initialCenter, { offset: translate, animate: false }) + // map.transform.setLocationAtPoint(centerCoord, new mapboxgl.Point(x, y)) + // map.setZoom(zoom) + // --- + // console.log(map.getCenter()) + //initialCenter = centerCoord + //map.setCenter(c) + //console.log(c) + // map.flyTo({ + // around: c, + // zoom: initialZoom - (1 - Math.sqrt(scale)), + // duration: 0, + // }) + } + // } else { + + // map.panTo(initialCenter, { offset: scaledTranslate, animate: false }) + // console.log(map.getCenter()) + // console.log(translate) + // //initialCenter = map.getCenter() + // } + + // if(center){ + // var c = [center.lng, center.lat] + // //map.setCenter(c) + // //console.log(c) + // map.flyTo({ + // around: c, + // zoom: initialZoom + Math.sqrt(scale), + // duration: 0 + // }) + // } + } + + return mapbox +} diff --git a/js/utils.js b/js/utils.js index 5c2ad3d27dc4994f13cd52da4dbf548cd7880ef2..e8eb40833c106a6f3dbdc7374a43e9a8ad2bb0e7 100644 --- a/js/utils.js +++ b/js/utils.js @@ -3,137 +3,196 @@ // @chrispiecom // 2015-2018 - -window.utils = {}; - -utils.isMobile = function(){ - return (window.innerWidth - || document.documentElement.clientWidth - || document.body.clientWidth) < 500; +window.utils = {} + +utils.isMobile = function () { + return ( + (window.innerWidth || + document.documentElement.clientWidth || + document.body.clientWidth) < 500 + ) } -utils.isSafari = function(){ - return /^((?!chrome|android).)*safari/i.test(navigator.userAgent); +utils.isSafari = function () { + return /^((?!chrome|android).)*safari/i.test(navigator.userAgent) } -utils.welcome = function(){ - // who needs this fancy console styles - if (window.console) - { - window.console.log('\n _ ________ ____ ______ \n| | / / _/ //_/ / / / __/ \n| |/ // // ,< / /_/ /\ \ \n|___/___/_/|_|\____/___/_______ \n| | / / _/ __/ | /| / / __/ _ \ \n| |/ // // _/ | |/ |/ / _// , _/ \n|___/___/___/ |__/|__/___/_/|_| \n') - } +utils.welcome = function () { + // who needs this fancy console styles + if (window.console) { + window.console.log( + '\n _ ________ ____ ______ \n| | / / _/ //_/ / / / __/ \n| |/ // // ,< / /_/ / \n|___/___/_/|_|____/___/_______ \n| | / / _/ __/ | /| / / __/ _ \n| |/ // // _/ | |/ |/ / _// , _/ \n|___/___/___/ |__/|__/___/_/|_| \n', + ) + } } -utils.initConfig = function(config){ - - // load infosidebar info.md - d3.text(config.loader.info, function(text){ if(text) infoVue.info = text }) - - // set window title - document.title = config.project.name - - // puh thats kind of nasty, lets call it oldschool... - var length = document.styleSheets[0].cssRules.length - document.styleSheets[0].insertRule('.close::before { background-color: ' + config.style.fontColorActive + '}', length); - document.styleSheets[0].insertRule('.close::after { background-color: ' + config.style.fontColorActive + '}', length); - document.styleSheets[0].insertRule('.tag.active { color: ' + config.style.fontColorActive + '}', length); - document.styleSheets[0].insertRule('.tag.active { background: ' + config.style.fontBackground + '}', length); - document.styleSheets[0].insertRule('.timeline .entry { background: ' + config.style.timelineBackground + '}', length); - document.styleSheets[0].insertRule('.timeline .entry { color: ' + config.style.timelineFontColor + '}', length); - document.styleSheets[0].insertRule('.timeline .year { color: ' + config.style.fontColor + '}', length); - document.styleSheets[0].insertRule('.tagcloud .tag { text-shadow: ' + config.style.textShadow + '}', length); - document.styleSheets[0].insertRule('.infobar .outer { background: ' + config.style.infoBackground + '}', length); - document.styleSheets[0].insertRule('.infobar .outer { color: ' + config.style.infoFontColor + '}', length); - document.styleSheets[0].insertRule('.infobar a { color: ' + config.style.infoFontColor + '}', length); - document.styleSheets[0].insertRule('.infobar .infobutton path { stroke: ' + config.style.infoFontColor + '}', length); - document.styleSheets[0].insertRule('.infobar.sneak .infobutton path { stroke: ' + config.style.fontColor + '}', length); - document.styleSheets[0].insertRule('.sidebar .outer { background: ' + config.style.detailBackground + '}', length); - document.styleSheets[0].insertRule('.searchbar input { background: ' + config.style.searchbarBackground + '}', length); +utils.initConfig = function (config) { + // load infosidebar info.md + d3.text(config.loader.info, function (text) { + if (text) infoVue.info = text + }) + + // set window title + document.title = config.project.name + + // puh thats kind of nasty, lets call it oldschool... + var length = document.styleSheets[0].cssRules.length + document.styleSheets[0].insertRule( + '.close::before { background-color: ' + config.style.fontColorActive + '}', + length, + ) + document.styleSheets[0].insertRule( + '.close::after { background-color: ' + config.style.fontColorActive + '}', + length, + ) + document.styleSheets[0].insertRule( + '.tag.active { color: ' + config.style.fontColorActive + '}', + length, + ) + document.styleSheets[0].insertRule( + '.tag.active { background: ' + config.style.fontBackground + '}', + length, + ) + document.styleSheets[0].insertRule( + '.timeline .entry { background: ' + config.style.timelineBackground + '}', + length, + ) + document.styleSheets[0].insertRule( + '.timeline .entry { color: ' + config.style.timelineFontColor + '}', + length, + ) + document.styleSheets[0].insertRule( + '.timeline .year { color: ' + config.style.fontColor + '}', + length, + ) + document.styleSheets[0].insertRule( + '.tagcloud .tag { text-shadow: ' + config.style.textShadow + '}', + length, + ) + document.styleSheets[0].insertRule( + '.infobar .outer { background: ' + config.style.infoBackground + '}', + length, + ) + document.styleSheets[0].insertRule( + '.infobar .outer { color: ' + config.style.infoFontColor + '}', + length, + ) + document.styleSheets[0].insertRule( + '.infobar a { color: ' + config.style.infoFontColor + '}', + length, + ) + document.styleSheets[0].insertRule( + '.infobar .infobutton path { stroke: ' + config.style.infoFontColor + '}', + length, + ) + document.styleSheets[0].insertRule( + '.infobar.sneak .infobutton path { stroke: ' + config.style.fontColor + '}', + length, + ) + document.styleSheets[0].insertRule( + '.sidebar .outer { background: ' + config.style.detailBackground + '}', + length, + ) + document.styleSheets[0].insertRule( + '.searchbar input { background: ' + config.style.searchbarBackground + '}', + length, + ) + document.styleSheets[0].insertRule( + 'body { background: ' + config.style.canvasBackground + '}', + length, + ) } // exhibition installations, will reinitialize the vis after x seconds -utils.ping = function(){ - var time = +new Date(); - var timeout = 2 * 60 * 1000; - var interval = setInterval(function() { - if(new Date() - time > timeout ){ - //location.reload(); - } - }, 1000); - - return function(){ - time = +new Date(); - } +utils.ping = function () { + var time = +new Date() + var timeout = 2 * 60 * 1000 + var interval = setInterval(function () { + if (new Date() - time > timeout) { + //location.reload(); + } + }, 1000) + + return function () { + time = +new Date() + } } -utils.printkeywords = function(data){ - var keywords = {}; - data.forEach(function(d){ - d.keywords.forEach(function(d){ - keywords[d] = 0; - }) - }) - d3.keys(keywords).forEach(function(d){ - console.log(d); - }) +utils.printkeywords = function (data) { + var keywords = {} + data.forEach(function (d) { + d.keywords.forEach(function (d) { + keywords[d] = 0 + }) + }) + d3.keys(keywords).forEach(function (d) { + console.log(d) + }) } -utils.fullscreen = function(){ - document.fullscreenEnabled = document.fullscreenEnabled || document.mozFullScreenEnabled || document.documentElement.webkitRequestFullScreen; - - function requestFullscreen(element) { - if (element.requestFullscreen) { - element.requestFullscreen(); - } else if (element.mozRequestFullScreen) { - element.mozRequestFullScreen(); - } else if (element.webkitRequestFullScreen) { - element.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); - } - } - - if (document.fullscreenEnabled) { - requestFullscreen(document.documentElement); - } -} - -utils.clean = function(data) { - - data.forEach(function(d,i){ - d.search = Object.keys(d).map(function(e) { return d[e] }).join(' - ').toUpperCase() - d.i = i; - d.keywords = _(d.keywords) - .chain() - .split(",") - .map(_.trim) - .uniq() - .filter(function(d) { return d !== "" }) - .value() - - // for proper sorting - d.keywords = d.keywords.map(function(d){ - return d.charAt(0).toUpperCase() + d.slice(1); - }); - - d._year = d.year - d._keywords = d.keywords - - // internal vars - d.alpha = 1; - d.active = 1; - d.loaded = false; - d.type = "image"; - d.page = 0 - d.scaleFactor = 0.9 - d.x = i; - d.y = i; - d.order = i; - }); - +utils.fullscreen = function () { + document.fullscreenEnabled = + document.fullscreenEnabled || + document.mozFullScreenEnabled || + document.documentElement.webkitRequestFullScreen + + function requestFullscreen(element) { + if (element.requestFullscreen) { + element.requestFullscreen() + } else if (element.mozRequestFullScreen) { + element.mozRequestFullScreen() + } else if (element.webkitRequestFullScreen) { + element.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT) + } + } + + if (document.fullscreenEnabled) { + requestFullscreen(document.documentElement) + } } -utils.simulateLargeDatasets = function(data){ - Array.prototype.push.apply(data, _.clone(data, true)) - Array.prototype.push.apply(data, _.clone(data, true)) - Array.prototype.push.apply(data, _.clone(data, true).slice(0,1036)) +utils.clean = function (data) { + data.forEach(function (d, i) { + d.search = Object.keys(d) + .map(function (e) { + return d[e] + }) + .join(' - ') + .toUpperCase() + d.i = i + d.keywords = _(d.keywords) + .chain() + .split(',') + .map(_.trim) + .uniq() + .filter(function (d) { + return d !== '' + }) + .value() + + // for proper sorting + d.keywords = d.keywords.map(function (d) { + return d.charAt(0).toUpperCase() + d.slice(1) + }) + + d._year = d.year + d._keywords = d.keywords + + // internal vars + d.alpha = 1 + d.active = 1 + d.loaded = false + d.type = 'image' + d.page = 0 + d.scaleFactor = 0.9 + d.x = i + d.y = i + d.order = i + }) } +utils.simulateLargeDatasets = function (data) { + Array.prototype.push.apply(data, _.clone(data, true)) + Array.prototype.push.apply(data, _.clone(data, true)) + Array.prototype.push.apply(data, _.clone(data, true).slice(0, 1036)) +} diff --git a/js/viz.js b/js/viz.js index 235915159b548bca7b010a7d90edb6fe690f56c9..21f548c14b3d0714b10bf68af59cf4bf88b49e09 100644 --- a/js/viz.js +++ b/js/viz.js @@ -1,141 +1,134 @@ -// ,--. -// ,---, ,--/ /| .--.--. -// ,---.,`--.' |,---,': / ' ,--, / / '. -// /__./|| : :: : '/ / ,'_ /|| : /`. / -// ,---.; ; |: | '| ' , .--. | | :; | |--` -// /___/ \ | || : |' | / ,'_ /| : . || : ;_ -// \ ; \ ' |' ' ;| ; ; | ' | | . . \ \ `. -// \ \ \: || | |: ' \ | | ' | | | `----. \ -// ; \ ' .' : ;| | ' : | | : ' ; __ \ \ | -// \ \ '| | '' : |. \| ; ' | | ' / /`--' / -// \ ` ;' : || | '_\.': | : ; ; |'--'. / -// : \ |; |.' ' : | ' : `--' \ `--'---' -// '---" '---' ; |,' : , .-./ -// '---' `--`----' -// ,---, ,---,. .---. ,---,.,-.----. -// ,---.,`--.' | ,' .' | /. ./| ,' .' |\ / \ -// /__./|| : :,---.' | .--'. ' ;,---.' |; : \ -// ,---.; ; |: | '| | .' /__./ \ : || | .'| | .\ : -// /___/ \ | || : |: : |-, .--'. ' \' .: : |-,. : |: | -// \ ; \ ' |' ' ;: | ;/|/___/ \ | ' ': | ;/|| | \ : -// \ \ \: || | || : .'; \ \; :| : .'| : . / -// ; \ ' .' : ;| | |-, \ ; ` || | |-,; | | \ -// \ \ '| | '' : ;/| . \ .\ ;' : ;/|| | ;\ \ -// \ ` ;' : || | \ \ \ ' \ || | \: ' | \.' -// : \ |; |.' | : .' : ' |--" | : .': : :-' -// '---" '---' | | ,' \ \ ; | | ,' | |.' -// `----' '---" `----' `---' - +// ,--. +// ,---, ,--/ /| .--.--. +// ,---.,`--.' |,---,': / ' ,--, / / '. +// /__./|| : :: : '/ / ,'_ /|| : /`. / +// ,---.; ; |: | '| ' , .--. | | :; | |--` +// /___/ \ | || : |' | / ,'_ /| : . || : ;_ +// \ ; \ ' |' ' ;| ; ; | ' | | . . \ \ `. +// \ \ \: || | |: ' \ | | ' | | | `----. \ +// ; \ ' .' : ;| | ' : | | : ' ; __ \ \ | +// \ \ '| | '' : |. \| ; ' | | ' / /`--' / +// \ ` ;' : || | '_\.': | : ; ; |'--'. / +// : \ |; |.' ' : | ' : `--' \ `--'---' +// '---" '---' ; |,' : , .-./ +// '---' `--`----' +// ,---, ,---,. .---. ,---,.,-.----. +// ,---.,`--.' | ,' .' | /. ./| ,' .' |\ / \ +// /__./|| : :,---.' | .--'. ' ;,---.' |; : \ +// ,---.; ; |: | '| | .' /__./ \ : || | .'| | .\ : +// /___/ \ | || : |: : |-, .--'. ' \' .: : |-,. : |: | +// \ ; \ ' |' ' ;: | ;/|/___/ \ | ' ': | ;/|| | \ : +// \ \ \: || | || : .'; \ \; :| : .'| : . / +// ; \ ' .' : ;| | |-, \ ; ` || | |-,; | | \ +// \ \ '| | '' : ;/| . \ .\ ;' : ;/|| | ;\ \ +// \ ` ;' : || | \ \ \ ' \ || | \: ' | \.' +// : \ |; |.' | : .' : ' |--" | : .': : :-' +// '---" '---' | | ,' \ \ ; | | ,' | |.' +// `----' '---" `----' `---' // christopher pietsch // @chrispiecom // 2015-2018 +utils.welcome() -utils.welcome(); - -var data; -var tags; -var canvas; -var search; -var ping; -var map; +var data +var tags +var canvas +var search +var ping +var map if (Modernizr.webgl && !utils.isMobile()) { - init(); + init() } function init() { - - map = Mapbox(); - 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); - map.init(data) - - window.data = data - - 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.selectAll(".navi .button") - .on("click", function () { - var that = this; - var mode = d3.select(this).attr("data"); - canvas.setMode(mode); - timeline.setDisabled(mode != "time"); - - d3.selectAll(".navi .button").classed("active", function () { - return that === this - }); - }) + map = Mapbox() + 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) + map.init(data) + + window.data = data + + 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.selectAll('.navi .button').on('click', function () { + var that = this + var mode = d3.select(this).attr('data') + canvas.setMode(mode) + timeline.setDisabled(mode != 'time') + d3.select('#map').classed('hide', mode != 'map') + + d3.selectAll('.navi .button').classed('active', function () { + return that === this + }) + }) } -d3.select(".browserInfo").classed("show", utils.isMobile()); \ No newline at end of file +d3.select('.browserInfo').classed('show', utils.isMobile())