start
This commit is contained in:
111
flat.html
Normal file
111
flat.html
Normal file
@@ -0,0 +1,111 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
||||
<link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet">
|
||||
|
||||
<script src="setup/upload/server/php/files/usersdb.js"></script>
|
||||
<script src="https://aframe.io/releases/1.0.0/aframe.min.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
body { background-color: transparent; }
|
||||
|
||||
#email, #sms {
|
||||
font-size: xx-large;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
|
||||
<img src="setup/productlogo.png">
|
||||
|
||||
<h3>flat viewer by category sorted by position</h3>
|
||||
|
||||
<div id="spacesholder">Your spaces:
|
||||
<ul id="spaces"></ul>
|
||||
</div>
|
||||
|
||||
<div>Already have an account? <span onclick="login()" style="text-decoration: underline;">Log-in</span>
|
||||
<form>
|
||||
<div id="login" style="display:none"><input id="useremail"/>
|
||||
<button style="margin-top:2px;" type="button" onclick="loginViaEmail()" id="loginemail" class="btn btn-lg btn-primary btn-block">Login</button>
|
||||
</div>
|
||||
</form>
|
||||
<div style="display:none" id="nouser">User not found. Double check your email address then contact fabien@iterative-explorations.com</a></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const email = urlParams.get('email');
|
||||
if (email) loginViaEmail()
|
||||
|
||||
var uploadedURL = "setup/upload/server/php/files/";
|
||||
var images = []
|
||||
var url = "/"
|
||||
var urlParameters = "?customimages="
|
||||
var userspace
|
||||
|
||||
function login(){
|
||||
document.querySelector("#login").style.display = "block"
|
||||
}
|
||||
|
||||
function findCategory(image){
|
||||
if (!userspace) return
|
||||
console.log(image.filename)
|
||||
var imagePos = new THREE.Vector3();
|
||||
imagePos.copy ( AFRAME.utils.coordinates.parse(image.position) )
|
||||
|
||||
var closest
|
||||
var smallestDistance = 1000
|
||||
for (var category of userspace.categories){
|
||||
var categoryPos = new THREE.Vector3();
|
||||
categoryPos.copy ( AFRAME.utils.coordinates.parse(category.position) )
|
||||
var distance = categoryPos.distanceTo( imagePos )
|
||||
if (distance < smallestDistance){
|
||||
smallestDistance = distance
|
||||
closest = category.label
|
||||
}
|
||||
console.log(distance, category.label)
|
||||
}
|
||||
|
||||
return closest
|
||||
}
|
||||
|
||||
function loginViaEmail(){
|
||||
var path = "setup/"
|
||||
if (!email)
|
||||
email = document.querySelector("#useremail").value
|
||||
userspace = database[email]
|
||||
if (!userspace){
|
||||
document.querySelector("#nouser").style.display = "block"
|
||||
return
|
||||
}
|
||||
|
||||
document.querySelector("#spacesholder").style.display = "block"
|
||||
var spaces = document.querySelector("#spaces")
|
||||
var space = document.createElement("li")
|
||||
var spacelink = document.createElement("a")
|
||||
var images = userspace.files
|
||||
spacelink.href = url + urlParameters
|
||||
spacelink.target = "_blank"
|
||||
spacelink.innerHTML = userspace.last_login
|
||||
space.appendChild(spacelink)
|
||||
for (var image of images){
|
||||
urlParameters += image.filename + ","
|
||||
space.innerHTML += path + image.filename + " " + findCategory( image )
|
||||
}
|
||||
console.log(space)
|
||||
spaces.appendChild(space)
|
||||
console.log("userspace", userspace)
|
||||
}
|
||||
</script>
|
||||
|
||||
<h3 style="position:absolute; bottom:0px; right:0px;">A product by <a href="https://iterative-explorations.com"><img width="200px" src="https://iterative-explorations.com/logo.svg"></a>.</h3>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
150
index.html
Normal file
150
index.html
Normal file
@@ -0,0 +1,150 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Think + Relax space by Iterative Explorations</title>
|
||||
<script src="https://aframe.io/releases/1.0.0/aframe.min.js"></script>
|
||||
<script src="https://rawgit.com/feiss/aframe-environment-component/master/dist/aframe-environment-component.min.js"></script>
|
||||
<script src="https://cdn.rawgit.com/donmccurdy/aframe-extras/v4.1.2/dist/aframe-extras.min.js"></script>
|
||||
<script src="https://unpkg.com/super-hands@3.0.0/dist/super-hands.min.js"></script>
|
||||
<script src="pimvrhelpers.js"></script>
|
||||
</head>
|
||||
<script>
|
||||
// could add an in VR edit mode for the categories, to position them, name them, etc
|
||||
// should be mostly for adjustments
|
||||
var timer = AFRAME.utils.getUrlParameter('timer')
|
||||
if (!timer) timer = 300 //5min
|
||||
|
||||
function saveNewItemsPosition(){
|
||||
var selector = ".notes";
|
||||
var pos = ""
|
||||
document.querySelectorAll(selector).forEach(
|
||||
e => pos += "\n" + AFRAME.utils.coordinates.stringify( e.getAttribute("position") )
|
||||
)
|
||||
pimvrSaveRemote("WeWorkTest", pos) // from pimvrhelpers.js
|
||||
// should be saved by username by space
|
||||
// could be pointed at from the database file (thus having multiple storages)
|
||||
}
|
||||
|
||||
AFRAME.registerComponent("watch", {
|
||||
init: function() {
|
||||
document.querySelector("#timer").setAttribute("text","value:"+timer)
|
||||
this.tick = AFRAME.utils.throttleTick(this.tick, 1000, this);
|
||||
// details https://aframe.io/docs/1.0.0/core/utils.html#aframe-utils-throttle-function-minimuminterval-optionalcontext
|
||||
},
|
||||
|
||||
tick: function (t, dt) {
|
||||
var time = Number( document.querySelector("#timer").getAttribute("text").value )
|
||||
time--
|
||||
document.querySelector("#timer").setAttribute("text","value:"+(time))
|
||||
},
|
||||
})
|
||||
|
||||
AFRAME.registerComponent("relaxing-introduction", {
|
||||
init: function() {
|
||||
// get in flow state
|
||||
// for now controlled just with AFrame animation
|
||||
// cf https://aframe.io/docs/1.0.0/components/animation.html
|
||||
|
||||
setTimeout(function(){
|
||||
for (var note of document.querySelectorAll(".notes")){ note.emit("fadein") }
|
||||
}, 10 * 1000) // arbitrary 10s, should be instead after the introduction is finished
|
||||
}
|
||||
})
|
||||
|
||||
AFRAME.registerComponent("decompression-conclusion", {
|
||||
init: function() {
|
||||
// cf PoC at 2017 W3C web authoring workshop with Roland Dubois
|
||||
setTimeout(function(){
|
||||
var intructions = document.querySelector("#instructions")
|
||||
instructions.setAttribute("position", "-1 1.5 -1") // assumes the user is roughtly centered... could force on camera instead
|
||||
instructions.setAttribute("text", "value", "Your session will end soon\n\nVisit https://learnWebVR.xyz/flat.html\n\nto work outside of VR.")
|
||||
instructions.setAttribute("opacity", "1") // could be animated instead
|
||||
|
||||
console.log("X min voice over and notes fade-out with contextual information (time, weather, etc)")
|
||||
|
||||
document.querySelector("[environment]").setAttribute("environment", "preset:checkerboard")
|
||||
}, timer * 1000);
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
AFRAME.registerComponent("environment-by-url", {
|
||||
schema: {},
|
||||
init: function() {
|
||||
var environment = AFRAME.utils.getUrlParameter('environment')
|
||||
if (environment) document.querySelector("[environment]").setAttribute("environment", "preset:" + environment)
|
||||
}
|
||||
})
|
||||
|
||||
AFRAME.registerComponent("photo-importer", {
|
||||
schema: {},
|
||||
init: function() {
|
||||
var baseURL = "setup/"
|
||||
var images = AFRAME.utils.getUrlParameter('customimages').split(',');
|
||||
if (images.length == 1) window.location = baseURL; // no images? must be configured first
|
||||
// could also display a tutorial instead
|
||||
var i=1
|
||||
for (var image of images){
|
||||
if (image){
|
||||
var id = "placeholder"+i
|
||||
var placeholder = document.querySelector("#"+id)
|
||||
if (!placeholder){
|
||||
// TODO somehow not interactable anymore?!
|
||||
// had a similar silly issue before but can't recall how I fixed it :(
|
||||
// something basic about entities or hierarchy...
|
||||
placeholder = document.createElement("a-box")
|
||||
placeholder.id = id
|
||||
placeholder.setAttribute("material", "shader:flat")
|
||||
placeholder.setAttribute("hoverable", "")
|
||||
placeholder.setAttribute("grabbable", "")
|
||||
placeholder.setAttribute("draggable", "")
|
||||
placeholder.setAttribute("dropppable", "")
|
||||
// somehow does appear visually correct but are NOT interactable!
|
||||
placeholder.setAttribute("position", "" + i/1.5-1.5 + " 1.5 -0.7")
|
||||
placeholder.setAttribute("scale", "0.5 0.3 0.01")
|
||||
// assume 1 * 1.5 photo ratio (landscape)
|
||||
AFRAME.scenes[0].appendChild(placeholder)
|
||||
}
|
||||
placeholder.className += "notes"
|
||||
placeholder.setAttribute("opacity", "0")
|
||||
placeholder.setAttribute("animation", "property: components.material.material.opacity; to: 1; dur: 1500; easing: linear; startEvents: fadein;")
|
||||
placeholder.setAttribute("src", baseURL+image)
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
<body>
|
||||
<a-scene photo-importer environment-by-url relaxing-introduction decompression-conclusion>
|
||||
<a-entity environment="preset: forest;"></a-entity>
|
||||
|
||||
<a-entity sphere-collider="objects: a-box" super-hands hand-controls="left"></a-entity>
|
||||
<a-entity sphere-collider="objects: a-box" super-hands hand-controls="right"></a-entity>
|
||||
|
||||
<!-- could be wrist watch as I've done via Twitter years ago -->
|
||||
<a-text watch id="timer" rotation="180 0 180" position="0 1 2" value="time"></a-text>
|
||||
|
||||
<a-text id="instructions" position="-1 1.5 -0.65" value="welcome to your\n\nthink+relax space" opacity="0"
|
||||
animation__fadein="property: components.text.material.uniforms.opacity.value; to: 0.99; dur: 1500; easing: linear"
|
||||
animation__fadeout="property: components.text.material.uniforms.opacity.value; to: 0.01; dur: 1500; easing: linear; startEvents: fadeout;"
|
||||
animation__leave="property: object3D.position.z; to: -100; dur: 15000; easing: linear; delay: 2500;"
|
||||
></a-text>
|
||||
|
||||
|
||||
<a-text rotation="-20 20 0" position="-2 0.2 -2" scale="1 1 1" value="waiting"></a-text>
|
||||
<a-box material="wireframe:true" color="orange" position="-2 1 -2" scale="2 2 2"></a-box>
|
||||
<a-text rotation="-20 0 0" position=" 0 0.2 -2" scale="1 1 1" value="in progress"></a-text>
|
||||
<a-box material="wireframe:true" color="red" position="0 1 -2" scale="2 2 2"></a-box>
|
||||
<a-text rotation="-20 -20 0" position=" 2 0.2 -2" scale="1 1 1" value="completed"></a-text>
|
||||
<a-box material="wireframe:true" color="green" position="2 1 -2" scale="2 2 2"></a-box>
|
||||
|
||||
<a-box material="shader:flat" id="placeholder1" hoverable grabbable stretchable draggable dropppable position="0.5 1.5 -0.5" scale="0.5 0.3 0.01"></a-box>
|
||||
<a-box material="shader:flat" id="placeholder2" hoverable grabbable stretchable draggable dropppable position="0 1.9 -0.7" scale="0.5 0.3 0.01"></a-box>
|
||||
<a-box material="shader:flat" id="placeholder3" hoverable grabbable stretchable draggable dropppable position="-0.5 1.5 -0.7" scale="0.5 0.3 0.01"></a-box>
|
||||
<!-- somehow creating dynamically fails... even though it did (!) work at some point (but wasn't saved via git)-->
|
||||
<!-- until then will rely on a pool of objects -->
|
||||
|
||||
</a-scene>
|
||||
</body>
|
||||
187
setup/index.html
Normal file
187
setup/index.html
Normal file
@@ -0,0 +1,187 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
||||
<link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet">
|
||||
|
||||
<script src="clipboard.min.js"></script>
|
||||
<script src="upload/server/php/files/usersdb.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
body { background-color: transparent; }
|
||||
|
||||
#email, #sms {
|
||||
font-size: xx-large;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
|
||||
<img src="productlogo.png">
|
||||
|
||||
<script>
|
||||
var tickMark = "✔";
|
||||
var uploadedURL = "upload/server/php/files/";
|
||||
var images = []
|
||||
var url = "/"
|
||||
var urlParameters = "?customimages="
|
||||
|
||||
function generateURL(){
|
||||
//var url = "https://learnwebvr.xyz/importer.html"
|
||||
for (var image of images){
|
||||
urlParameters += image + ","
|
||||
}
|
||||
console.log ("URL", urlParameters );
|
||||
|
||||
var encodedURL = url + urlParameters
|
||||
|
||||
encodedURL += "&environment=" + document.querySelector("#environment").value
|
||||
document.querySelector("#link").href = encodedURL
|
||||
document.querySelector("#copyBtn").setAttribute("data-clipboard-text", encodedURL)
|
||||
document.querySelector("#generateURL").style.display = "block"
|
||||
|
||||
document.querySelector("#email").href = "mailto:?&subject=session&body=" + encodeURIComponent( encodedURL )
|
||||
// tested on iPhone 6S and Pixel2 and desktop
|
||||
|
||||
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
|
||||
}
|
||||
else {
|
||||
document.querySelector("#copydiv").className = "cold-md-6"
|
||||
document.querySelector("#emaildiv").className = "cold-md-6"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<div class="container">
|
||||
|
||||
<form class="form-signin">
|
||||
|
||||
Environment:
|
||||
<select id="environment">
|
||||
<option name="contact">contact</option>
|
||||
<option name="egypt">egypt</option>
|
||||
<option name="checkerboard">checkerboard</option>
|
||||
<option name="forest" selected="selected">forest</option>
|
||||
<option name="goaland">goaland</option>
|
||||
<option name="yavapai">yavapai</option>
|
||||
<option name="goldmine">goldmine</option>
|
||||
<option name="threetowers">threetowers</option>
|
||||
<option name="poison">poison</option>
|
||||
<option name="arches">arches</option>
|
||||
<option name="tron">tron</option>
|
||||
<option name="japan">japan</option>
|
||||
<option name="dream">dream</option>
|
||||
<option name="volcano">volcano</option>
|
||||
<option name="starry">starry</option>
|
||||
<option name="osiris">osiris</option>
|
||||
</select>
|
||||
|
||||
<button style="margin-top:2px;" type="button" onclick="unhide('#fileupload2');" class="btn btn-primary btn-block">Upload your office photos<br/>(post-its, white board, etc)</button>
|
||||
|
||||
No content available? Try <a target="_blank" href="https://learnwebvr.xyz/?customimages=upload/server/php/files/photo6035074301452988871.jpg,upload/server/php/files/photo6035074301452988870.jpg,upload/server/php/files/IMG_6496 (1).jpg"> this example instead</a>!
|
||||
|
||||
<input style="display:none;" id="fileupload2" type="file" name="files[]" data-url="upload/server/php/" multiple>
|
||||
<div style="display:none;" id="fileuploaded2">Files uploaded: </div>
|
||||
<div style="opacity:0.7;" id="uploadrate"></div>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script src="upload/js/vendor/jquery.ui.widget.js"></script>
|
||||
<script src="upload/js/jquery.iframe-transport.js"></script>
|
||||
<script src="upload/js/jquery.fileupload.js"></script>
|
||||
<script>
|
||||
|
||||
function unhide( element ){
|
||||
document.querySelector(element).style.display = "block";
|
||||
}
|
||||
|
||||
$(function () {
|
||||
|
||||
$('#fileupload2').fileupload({
|
||||
dataType: 'json',
|
||||
done: function (e, data) {
|
||||
$.each(data.result.files, function (index, file) {
|
||||
var imageURL = uploadedURL + (file.name)
|
||||
images.push(imageURL)
|
||||
var uploaded = document.querySelector("#fileuploaded2");
|
||||
uploaded.style.display = "block";
|
||||
uploaded.innerHTML += tickMark;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<button style="margin-top:2px;" type="button" onclick="generateURL()" id="generate-simulation" class="btn btn-lg btn-primary btn-block">Generate your<br/>relax+think space</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="generateURL" style="display:none; text-align:center;" class="container">
|
||||
<div class="container">
|
||||
<a id="link" target="_blank" href=""><button type="button" class="btn btn-lg btn-primary btn-block">Launch relax+think space</button></a>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-4" id="copydiv">
|
||||
<button class="btn" data-clipboard-text="" id="copyBtn">Copy to clipboard</button>
|
||||
<script>
|
||||
new Clipboard('.btn');
|
||||
</script>
|
||||
</div>
|
||||
<div class="col-md-4" id="emaildiv">
|
||||
<a id="email" href="" target="_blank">email link</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function login(){
|
||||
document.querySelector("#login").style.display = "block"
|
||||
}
|
||||
function loginViaEmail(){
|
||||
var email = document.querySelector("#useremail").value
|
||||
var userspace = database[email]
|
||||
if (!userspace){
|
||||
document.querySelector("#nouser").style.display = "block"
|
||||
return
|
||||
}
|
||||
|
||||
document.querySelector("#spacesholder").style.display = "block"
|
||||
var spaces = document.querySelector("#spaces")
|
||||
var space = document.createElement("li")
|
||||
var spacelink = document.createElement("a")
|
||||
var images = userspace.files
|
||||
for (var image of images){
|
||||
urlParameters += image.filename + ","
|
||||
}
|
||||
spacelink.href = url + urlParameters
|
||||
spacelink.target = "_blank"
|
||||
spacelink.innerHTML = userspace.last_login
|
||||
space.appendChild(spacelink)
|
||||
console.log(space)
|
||||
spaces.appendChild(space)
|
||||
console.log("userspace", userspace)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>Already have an account? <span onclick="login()" style="text-decoration: underline;">Log-in</span>
|
||||
<form>
|
||||
<div id="login" style="display:none"><input id="useremail"/>
|
||||
<button style="margin-top:2px;" type="button" onclick="loginViaEmail()" id="loginemail" class="btn btn-lg btn-primary btn-block">Login</button>
|
||||
</div>
|
||||
</form>
|
||||
<div style="display:none" id="nouser">User not found. Double check your email address then contact fabien@iterative-explorations.com</a></div>
|
||||
<div style="display:none" id="spacesholder">Your spaces:
|
||||
<ul id="spaces"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="position:absolute; bottom:0px; right:0px;">A product by <a href="https://iterative-explorations.com"><img width="200px" src="https://iterative-explorations.com/logo.svg"></a>.</h3>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
18
setup/upload/server/php/files/usersdb.js
Normal file
18
setup/upload/server/php/files/usersdb.js
Normal file
@@ -0,0 +1,18 @@
|
||||
var database = {
|
||||
"fabien@benetou.fr" : {
|
||||
"username": "fabien",
|
||||
"password": "test",
|
||||
"last_login": 1576749381516,
|
||||
"environment": "forest",
|
||||
"files" : [
|
||||
{ "position": "-2 1 -2", "filename" : "upload/server/php/files/C1C4E2F7-865A-4DB4-9274-1EA69B6C4A7E.jpeg" },
|
||||
{ "position": "0 1 -2", "filename" : "upload/server/php/files/4A21A76C-F375-4884-9040-BC51A24057A6.jpeg" },
|
||||
{ "position": "2 1 -2", "filename" : "upload/server/php/files/2CD9932F-891C-4BA5-BDDA-A3B39B39CF09.jpeg" }
|
||||
],
|
||||
"categories" : [
|
||||
{ "position": "-2 1 -2", "color" : "orange", "label" : "waiting" },
|
||||
{ "position": "0 1 -2", "color" : "red", "label" : "in progress" },
|
||||
{ "position": "2 1 -2", "color" : "green", "label" : "completed" }
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user