From: Robert Kaiser Date: Fri, 14 Sep 2018 12:35:25 +0000 (+0200) Subject: add Tech Speaker Meetup 2018 X-Git-Url: https://git-public.kairo.at/?p=slides.git;a=commitdiff_plain;h=1b4d668b7313974cf919d2385abc478c84f74988;hp=229421f8cfe17d731eadfe5686154588b9c4509e add Tech Speaker Meetup 2018 --- diff --git a/tsmeetup201809/aframe-sticker.png b/tsmeetup201809/aframe-sticker.png new file mode 100644 index 0000000..19a0c18 Binary files /dev/null and b/tsmeetup201809/aframe-sticker.png differ diff --git a/tsmeetup201809/cc-by-sa.svg b/tsmeetup201809/cc-by-sa.svg new file mode 100644 index 0000000..085c5b5 --- /dev/null +++ b/tsmeetup201809/cc-by-sa.svg @@ -0,0 +1,9 @@ + + + + Creative Commons “Attribution-Share Alike” license icon + + + + + \ No newline at end of file diff --git a/tsmeetup201809/index.html b/tsmeetup201809/index.html new file mode 100755 index 0000000..e36f402 --- /dev/null +++ b/tsmeetup201809/index.html @@ -0,0 +1,189 @@ + + + + + + VR Map - OpenStreetMap goes WebVR + + + + + + + + + + +
+

Table of Contents

+

VR Map: Using OpenStreetMap Data in WebVR

+ +
+

The following slides are available in this presentation:

+
+
    +
+
+ +
+

VR Map: Using OpenStreetMap Data in WebVR

+

Simple GeoData Visualization with A-Frame

+ +
+Robert Kaiser, +"KaiRo" <kairo@kairo.at> +
Mozilla Tech Speaker +
+ +
+

Slides: + https://slides.kairo.at/tsmeetup201809/

+
+
    +
  • Created for a presentation at the Mozilla Tech Speakers Meetup 2018 in Paris.
  • +
  • Written in HTML 5 with CSS 3 and JavaScript.
  • +
  • Navigation via links on all slides, via access keys + (e.g. "n"/Alt+Shift+N for "next") or back/forward arrow keys
  • +
  • Contents
  • +
  • Lizenziert unter CC-BY-SA, + 09/2018 Robert Kaiser - + "Mozilla", "Firefox" and their logos are + trademarks + of Mozilla Foundation.
  • +
+
+
+
+ +
+

WebVR & WebXR

+ +
+VR headset user +
    +
  • WebVR: Virtual Reality + powered by Web technologies
  • +
  • Part of WebXR Device API + - Mixed Reality (Virtual + Augmented Reality)
  • +
  • Open Standard (proposal), in concert with WebGL, WebAudio + and Gamepad APIs
  • +
  • Windows: Firefox release, Mac: Nightly/Beta, Linux: in development
  • +
+

+
+
+ +
+

VR Map

+ +
+VR Map in 2D +
    +
  • Demo for WebVR with live + OpenStreetMap data
  • +
  • Usable in 2D mode on any modern browser
  • +
  • Supports headset + controller where WebVR is supported
  • +
  • Using Mozilla A-Frame (see later)
  • +
  • Simple: Currently ~80 lines HTML, ~600 lines JS
  • +
+

+
+
+ +
+

Code Basics

+ +
+VR Headset user with Mozilla logos +
    +
  • The world is flat (in two ways)!
  • +
  • Ground tiles using + Mercator projection, + "Mapnik" rendering from OSM + via KaiRo's tile caching server
  • +
  • Trees and buildings: live OSM data via + Overpass API
  • +
  • Camera/controller setup to support multiple devices for navigating the scene
  • +
  • Built with Mozilla A-Frame library
  • +
+

+
+
+ +
+

A-Frame - XR Made Simple

+ +
+A-Frame - aframe-io +Example: +
+<a-scene>
+  <a-sphere position="0 1.25 -1" radius="1.25" color="#EF2D5E"></a-sphere>
+  <a-cube position="-1 0.5 1" rotation="0 0 0" …>
+    <a-animation attribute="rotation" … to="0 360 0"></a-animation>
+  </a-cube>
+  <a-cylinder position="1 0.75 1" …></a-cylinder>
+  <a-plane …></a-plane>
+  <a-sky color="#ECECEC"></a-sky>
+</a-scene>
+
+

edit/view +- More at aframe.io +

+
+
+ +
+

Code Details

+ +
+VR Headset user with Mozilla logos +
    +
  • index.html: JS includes, start dialog, scene, camera/controller rig
  • +
  • map.js: variables, load handler, fetch from Overpass API
  • +
  • conversions.js: coordinate conversions
  • +
  • position-limit.js: A-Frame component for keeping position above ground
  • +
  • tiles.js, trees.js, buildings.js: load/draw the 3 types of objects
  • +
  • KaiRo-at/vrmap + at GitHub
  • +
+

+
+
+ +
+

vrmap.kairo.at

+ +
+VR Map in 2D +
+
+ +
+ + +
+ + + diff --git a/tsmeetup201809/mister_tricorder.jpg b/tsmeetup201809/mister_tricorder.jpg new file mode 100644 index 0000000..0ee9687 Binary files /dev/null and b/tsmeetup201809/mister_tricorder.jpg differ diff --git a/tsmeetup201809/slides.css b/tsmeetup201809/slides.css new file mode 100644 index 0000000..8f8d05f --- /dev/null +++ b/tsmeetup201809/slides.css @@ -0,0 +1,448 @@ +/************************** + * styles for talk slides * + * by Robert Kaiser * + * * + * (for FOSDEM 2013) * + **************************/ + + +/***** base style *****/ + +@font-face { + font-family: 'Open Sans'; + src: url('template/OpenSans-Regular-webfont.woff'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Open Sans'; + src: url('template/OpenSans-Semibold-webfont.woff'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'Open Sans'; + src: url('template/OpenSans-Italic-webfont.woff'); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: 'Zilla Slab'; + src: url('template/ZillaSlab-Regular.woff2'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Zilla Slab'; + src: url('template/ZillaSlab-Bold.woff2'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'Zilla Slab Highlight'; + src: url('template/ZillaSlabHighlight-Regular.woff2'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Zilla Slab Highlight'; + src: url('template/ZillaSlabHighlight-Bold.woff2'); + font-weight: bold; + font-style: normal; +} + +html { + overflow: hidden; /* to make translations not paint scrollbars */ + background: white; + height: 100%; +} + +body { + margin: 0px; + padding: 0px; + border: 0px; + font-family: "Open Sans", sans-serif; + font-size: 2em; + color: black; + height: 100%; +} + +ul { + padding-left: 1.2em; + margin-bottom: 0.5em; +} + +ul:first-child, +ul:last-child { + margin-top: 0; +} + +#header { + height: 44px; + position: relative; + font-family: "Zilla Slab", monospace; + border-bottom: 3px solid black; +} + +#headerlogo { + position: absolute; + display: block; + right: 2px; + top: 2px; + text-indent: -2000px; + font-size: 1px; + overflow: hidden; + height: 40px; + width: 140px; + background: url("template/mozilla_logo2017.svg") no-repeat; +} + +#header-text { + position: relative; + top: 5px; + left: 25px; + width: 200px; + width: -moz-fit-content; + width: -webkit-fit-content; + width: fit-content; + padding: 0 5px; + font-size: 20px; + font-weight: bold; + color: white; + background-color: black; +} + +#header-text.neartime { + color: #00FFFF; +} + +#header-text.ontime { + color: #54FFBD; +} + +#header-text.overtime { + color: #FF4F5E; +} + +#subheader-text { + color: black; + position: relative; + top: 3px; + left: 25px; + width: calc(100% - 50px); + padding: 0 5px; + font-size: 10px; +} + +#slidenav { + position: absolute; + right: 200px; + top: 15px; + font-family: "Zilla Slab", monospace; + font-size: 10px; +} + +#slidenav a:link, +#slidenav a:visited { + color: black; +} + +#slidenav a:hover, +#slidenav a:active { + color: #959595; +} + +#slidenav .nolink { + color: #E7E5E2; +} + +article { + position: absolute; + width: 100%; + /* header is 40px, 7px to have a bit of distance, + * 3px height-reducing on the bottom for safety */ + top: 47px; + height: calc(100% - 50px); + overflow: auto; + + transition-property: transform, opacity; + transition-duration: 3s; + transition-timing-function: ease; + transform-origin: center 5em; + + opacity: 0; +/* + transform: translate(-100%, 0); +*/ +/* + transform: scale(0.1) rotate(360deg) translate(-200%, 0); +*/ + transform: scale(0.1) translate(-400%, 0); +} + +article[aria-selected="true"] { + opacity: 1; + transform: scale(1) rotate(0deg) translate(0, 0); +} + +article[aria-selected="true"] ~ article { + opacity: 0; +/* + transform: translate(100%, 0); +*/ +/* + transform: scale(0.1) rotate(-360deg) translate(200%, 0); +*/ + transform: scale(0.1) translate(400%, 0); +} + +/***** headers *****/ + +h1, h2, h3, h4 { + margin: 0.5em 0; + font-family: "Zilla Slab", monospace; + font-weight: bold; + color: black; + text-align: center; +} + +h1 { + font-family: "Zilla Slab Highlight", "Zilla Slab", monospace; + margin-top: 0.5em; + font-size: 2.2em; +} + +h1 span { + font-family: "Zilla Slab", monospace; + background-color: black; + color: white; + padding: 0 10px; +} + +h2 { + font-size: 1.3em; +} + +h3 { + font-size: 1.1em; +} + +h4 { + font-size: 1em; + text-align: left; +} + +/***** boxes *****/ + +.simplebox { + padding: 0.5em; +} + +.captionedbox { + padding: 0px; +} + +.simplebox, +.captionedbox { + margin: 1em; + background-color: white; + /* box-shadow: 0 0 0 1px black inset; */ + /* border-bottom: 1px solid black; */ +} + +.captionedbox-content { + margin: 0; + padding: 0.5em; + border: 0px; + border-top: 1px solid black; +} + +.captionedbox-caption { + margin: 0; + padding: 0.5em; + font-weight: bold; +} + +.simplebox + .simplebox, +.captionedbox + .simplebox, +.simplebox + .captionedbox, +.captionedbox + .captionedbox { + border-top: 1px solid black; +} + +/***** misc formatting *****/ + +mark { + font-family: "Zilla Slab", monospace; + font-weight: bold; + color: black; + background-color: #FFF44F; +} + +.decofont { + font-family: "Zilla Slab", monospace; +} + +.border { + border: 1px solid black; + padding: 0.5em; +} + +.sshot { + max-width: 100%; + max-height: 20em; + /* box-shadow: black 1px 1px 3px 2px; */ +} + +.slidepic { + float: right; + margin-left: .5em; + max-height: 20em; + max-width: 25%; +} + +.ensurepicinbox { + clear: both; + font-size: 1px; + margin: 0; +} + +.largetext { + font-size: 2em; +} + +ul > li { + margin: 0.5em 0; +} + +.columns2 { + -moz-columns: 2; +} + +ul.nobullets > li { + list-style-type: none; +} + +ul.arrows > li { + list-style-type: none; +} +ul.arrows > li:before { + content: "\21d2\20"; /* \2192 would be single thin arrow, hex 20 is space */ +} + +.cent { + text-align: center; +} + +.topmargin { + margin-top: 0.5em; +} + +.akey { + text-decoration: underline; +} + +a:link, a:visited { color: #00458B; text-decoration: none; } +a:hover, a:active { color: #959595; text-decoration: underline; } + +mark a:link, mark a:visited { color: #005E5E; } +mark a:hover, mark a:active { color: #005E5E; } + +h1 span a:link, h1 span a:visited, +h1 span a:hover, h1 span a:active { color: white; } + +pre { margin: 0; } + +/***** small stuff *****/ + +small, +.small { + font-size: 0.75em; +} + +ul.small, +.small ul { + padding: 0px; + border: 0px; + margin: 0px 0px 0px 1em; +} + +ul.small > li +.small ul > li { + margin: 0px; + padding: 0px; + border: 0px; +} + +/***** specific slides *****/ + +/* start slide */ +.ccinline { + border-width: 0; + vertical-align: bottom; + height: 1.75em; +} + +/* end slide */ +.endslidecontainer { + position: relative; +} + +.endslidepic { + width: 100%; + max-height: initial; + z-index: 1; +} + +.endslidetext { + position: absolute; + width: calc(100% - 2rem); + z-index: 3; +} + +h1.endslidetext { +/* color: white; */ + font-size: 2.5em; +} + +h2.endslidetext, +h3.endslidetext { + font-size: 1.5em; +} + +h2.endslidetext > span, +h3.endslidetext > span { + background-color: white; + padding: 0 10px; +} + +.endslidetext:first-child { + top: 1rem; +} + +.endslidetext:nth-child(2) { + top: 11rem; +} + +.endslidetext:nth-child(3) { + top: 17rem; +} + +@media (min-resolution: 1.3dppx) { + .endslidetext:first-child { + top: .5rem; + } + .endslidetext:nth-child(2) { + top: 9rem; + } + + .endslidetext:nth-child(3) { + top: 14rem; + } +} diff --git a/tsmeetup201809/slides.js b/tsmeetup201809/slides.js new file mode 100644 index 0000000..20a4890 --- /dev/null +++ b/tsmeetup201809/slides.js @@ -0,0 +1,230 @@ +/****************************** + * JavaScript for talk slides * + * by Robert Kaiser * + * * + * (for FOSDEM 2011) * + ******************************/ + +var slides = {}; +var articleNodes; +var currentSlide; +var currentIdx; +var defaultIdx = 1; // set to slide index to show by default +var firstIdx = 2; // set no value if to use first available +var lastIdx; // set no value if to use last available + +var pageTitle, headerText, subHeaderText; +var navPrev, navNext, navPrevNolink, navNextNolink; + +// Slide timer - color variation of headerText +// Time per slide is total presentation length divided by number of slides +// except start and end slide. +var presLengthSeconds = 15 * 60; +var slideStart, timerMSec; + +// Called when the document has been loaded. +function docLoaded() { + pageTitle = document.getElementsByTagName("title")[0]; + headerText = document.getElementById("header-text"); + subHeaderText = document.getElementById("subheader-text"); + navPrev = document.getElementById("nav-prev"); + navNext = document.getElementById("nav-next"); + navPrevNolink = document.getElementById("nav-prev-nolink"); + navNextNolink = document.getElementById("nav-next-nolink"); + articleNodes = document.getElementsByTagName("article"); + + if (!firstIdx) + firstIdx = 0; + if (!lastIdx) + lastIdx = articleNodes.length - 1; + var slideSeconds = presLengthSeconds / (lastIdx - firstIdx); + timerMSec = 1000 * (slideSeconds / 3); + + // Get a list of all slides (articles). + subHeaderText.textContent = articleNodes.length + " slides..."; + for (var i = 0; i < articleNodes.length; ++i) { + subHeaderText.textContent = "Indexing slide " + i + " / " + articleNodes.length; + if (!articleNodes[i].id) + articleNodes[i].id = "slide_" + i; + + slides[articleNodes[i].id] = { + "idx": i, + "name": articleNodes[i].id, + "title": articleNodes[i].dataset.title ? articleNodes[i].dataset.title : articleNodes[i].id, + "obj": articleNodes[i], + "timeSeconds": articleNodes[i].dataset.seconds ? articleNodes[i].dataset.seconds : slideSeconds, + }; + + if (location.hash.length && + (location.hash == "#" + articleNodes[i].id || location.hash == "#" + i)) { + articleNodes[i].setAttribute("aria-selected", "true"); + currentSlide = slides[articleNodes[i].id]; + currentIdx = i; + } + } + + if (!currentSlide) { + currentIdx = defaultIdx; + currentSlide = slides[articleNodes[currentIdx].id]; + currentSlide.obj.setAttribute("aria-selected", "true"); + location.hash = "#" + currentSlide.name; + } + updateDisplay(); +} + +// Called when the hash part of the location changes. +function locationHashChanged() { + if (location.hash.length > 1) { + var hashtag = location.hash.substring(1); + // If not a number, treat as ID + if (isNaN(hashtag) && slides[hashtag]) { + currentSlide.obj.removeAttribute("aria-selected"); + currentSlide = slides[hashtag]; + currentIdx = currentSlide.idx; + currentSlide.obj.setAttribute("aria-selected", "true"); + updateDisplay(); + } + else if (articleNodes[hashtag]) { + currentSlide.obj.removeAttribute("aria-selected"); + currentIdx = hashtag; + currentSlide = slides[articleNodes[currentIdx].id]; + currentSlide.obj.setAttribute("aria-selected", "true"); + updateDisplay(); + } + } +} +window.onhashchange = locationHashChanged; + +// Update the display after we updated what slide is shown. +function updateDisplay() { + if (currentIdx >= firstIdx && currentIdx <= lastIdx && + currentSlide.name != "toc") + subHeaderText.textContent = (currentIdx - firstIdx + 1) + "/" + + (lastIdx - firstIdx + 1) + " - " + + currentSlide.title; + else + subHeaderText.textContent = currentSlide.title; + pageTitle.textContent = headerText.textContent + ": " + currentSlide.title; + if (currentIdx > firstIdx && currentSlide.name != "toc") { + navPrev.hidden = false; + navPrev.href = "#" + articleNodes[currentIdx - 1].id; + navPrevNolink.hidden = true; + } + else { + navPrev.hidden = true; + navPrevNolink.hidden = false; + } + if (currentIdx < lastIdx && currentSlide.name != "toc") { + navNext.hidden = false; + navNext.href = "#" + articleNodes[currentIdx + 1].id; + navNextNolink.hidden = true; + } + else { + navNext.hidden = true; + navNextNolink.hidden = false; + } + headerText.className = ""; + slideStart = new Date(); + timerMSec = 1000 * (currentSlide.timeSeconds / 3); + if (currentSlide.name == "toc") + createTOC(); + else + setTimeout(timerFired, timerMSec); +} + +// Create TOC list. +function createTOC() { + var list = document.getElementById("toc-list"); + if (!list.getElementsByTagName("li").length) { + for (var slide in slides) { + if (slide != "toc") { + var item = document.createElement("li"); + var link = document.createElement("a"); + var slideHeaders = slides[slide].obj.getElementsByTagName("h1"); + if (slideHeaders.length) + link.textContent = slideHeaders[0].textContent; + else + link.textContent = slides[slide].title; + link.href = "#" + slides[slide].name; + item.appendChild(link); + list.appendChild(item); + } + } + } +} + +// Do timed color variation on slides. +function timerFired() { + var slideCurrent = new Date(); + var secondsDiff = Math.round((slideCurrent.getTime() - slideStart.getTime()) / 1000); + if (secondsDiff >= currentSlide.timeSeconds) { + headerText.className = "overtime"; + } + else if (secondsDiff >= Math.round(2 * currentSlide.timeSeconds / 3)) { + headerText.className = "ontime"; + setTimeout(timerFired, timerMSec); + } + else if (secondsDiff >= Math.round(currentSlide.timeSeconds / 3)) { + headerText.className = "neartime"; + setTimeout(timerFired, timerMSec); + } + else { + // We should never come here, but if we do, go into a 100ms loop until we get over the upcoming step. + setTimeout(timerFired, 100); + } +} + +// Keyboard/click nav functionality, mostly inherited from FOSDEM 2007. +(function() { + function go(where) { + where = where || "next"; + var navElem = document.getElementById("nav-" + where); + if (!navElem.hidden) + window.location.href = navElem.href; + } + + function handleClick(e) { + e = e || event; + var target = (window.event) ? e.srcElement : e.target; + if (e.which == 1 && target.nodeName != "A" && target.nodeName != "VIDEO") + go("next"); + } + + function handleKeyPress(e) { + e = e || event; + switch (e.key) { + // See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#Constants_for_keyCode_value + case "ArrowLeft": + case "ArrowDown": + case "Left": // non-standard, old browsers + case "Down": // non-standard, old browsers + case "PageDown": + case "P": + case "p": + case "H": //8bitdo Zero "X" + case "h": //8bitdo Zero "X" + go("prev"); break; + case "ArrowRight": + case "ArrowUp": + case "Right": // non-standard, old browsers + case "Up": // non-standard, old browsers + case "PageUp": + case "N": + case "n": + case "J": //8bitdo Zero "B" + case "j": //8bitdo Zero "B" + go("next"); break; + case "Home": + case "I": //8bitdo Zero "Y" + case "i": //8bitdo Zero "Y" + go("start"); break; + case "End": + case "G": //8bitdo Zero "A" + case "g": //8bitdo Zero "A" + go("toc"); break; + } + } + + window.onclick = handleClick; + window.onkeydown = handleKeyPress; +})(); diff --git a/tsmeetup201809/template/OpenSans-Italic-webfont.woff b/tsmeetup201809/template/OpenSans-Italic-webfont.woff new file mode 100644 index 0000000..1ed8ab9 Binary files /dev/null and b/tsmeetup201809/template/OpenSans-Italic-webfont.woff differ diff --git a/tsmeetup201809/template/OpenSans-Regular-webfont.woff b/tsmeetup201809/template/OpenSans-Regular-webfont.woff new file mode 100644 index 0000000..bd0f824 Binary files /dev/null and b/tsmeetup201809/template/OpenSans-Regular-webfont.woff differ diff --git a/tsmeetup201809/template/OpenSans-Semibold-webfont.woff b/tsmeetup201809/template/OpenSans-Semibold-webfont.woff new file mode 100644 index 0000000..3a78f75 Binary files /dev/null and b/tsmeetup201809/template/OpenSans-Semibold-webfont.woff differ diff --git a/tsmeetup201809/template/ZillaSlab-Bold.woff2 b/tsmeetup201809/template/ZillaSlab-Bold.woff2 new file mode 100644 index 0000000..bf96f4d Binary files /dev/null and b/tsmeetup201809/template/ZillaSlab-Bold.woff2 differ diff --git a/tsmeetup201809/template/ZillaSlab-Regular.woff2 b/tsmeetup201809/template/ZillaSlab-Regular.woff2 new file mode 100644 index 0000000..ed653eb Binary files /dev/null and b/tsmeetup201809/template/ZillaSlab-Regular.woff2 differ diff --git a/tsmeetup201809/template/ZillaSlabHighlight-Bold.woff2 b/tsmeetup201809/template/ZillaSlabHighlight-Bold.woff2 new file mode 100644 index 0000000..8414a16 Binary files /dev/null and b/tsmeetup201809/template/ZillaSlabHighlight-Bold.woff2 differ diff --git a/tsmeetup201809/template/ZillaSlabHighlight-Regular.woff2 b/tsmeetup201809/template/ZillaSlabHighlight-Regular.woff2 new file mode 100644 index 0000000..a166fbe Binary files /dev/null and b/tsmeetup201809/template/ZillaSlabHighlight-Regular.woff2 differ diff --git a/tsmeetup201809/template/mozilla-tab.png b/tsmeetup201809/template/mozilla-tab.png new file mode 100644 index 0000000..87f8ef9 Binary files /dev/null and b/tsmeetup201809/template/mozilla-tab.png differ diff --git a/tsmeetup201809/template/mozilla_logo2017.svg b/tsmeetup201809/template/mozilla_logo2017.svg new file mode 100644 index 0000000..08f06e0 --- /dev/null +++ b/tsmeetup201809/template/mozilla_logo2017.svg @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/tsmeetup201809/vrmap-large.png b/tsmeetup201809/vrmap-large.png new file mode 100644 index 0000000..aa9301e Binary files /dev/null and b/tsmeetup201809/vrmap-large.png differ diff --git a/tsmeetup201809/vrmap-small.png b/tsmeetup201809/vrmap-small.png new file mode 100644 index 0000000..bd2e916 Binary files /dev/null and b/tsmeetup201809/vrmap-small.png differ diff --git a/tsmeetup201809/vruser.jpg b/tsmeetup201809/vruser.jpg new file mode 100644 index 0000000..50b3c0b Binary files /dev/null and b/tsmeetup201809/vruser.jpg differ diff --git a/tsmeetup201809/vrusermoz.jpg b/tsmeetup201809/vrusermoz.jpg new file mode 100644 index 0000000..93862e6 Binary files /dev/null and b/tsmeetup201809/vrusermoz.jpg differ