Before Width: | Height: | Size: 559 KiB |
Before Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 367 KiB |
Before Width: | Height: | Size: 24 KiB |
@ -0,0 +1,134 @@ |
|||
import { Ray } from '../math/Ray.js'; |
|||
|
|||
/** |
|||
* @author mrdoob / http://mrdoob.com/
|
|||
* @author bhouston / http://clara.io/
|
|||
* @author stephomi / http://stephaneginier.com/
|
|||
*/ |
|||
|
|||
function Raycaster( origin, direction, near, far ) { |
|||
|
|||
this.ray = new Ray( origin, direction ); |
|||
// direction is assumed to be normalized (for accurate distance calculations)
|
|||
|
|||
this.near = near || 0; |
|||
this.far = far || Infinity; |
|||
|
|||
this.params = { |
|||
Mesh: {}, |
|||
Line: {}, |
|||
LOD: {}, |
|||
Points: { threshold: 1 }, |
|||
Sprite: {} |
|||
}; |
|||
|
|||
Object.defineProperties( this.params, { |
|||
PointCloud: { |
|||
get: function () { |
|||
|
|||
console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' ); |
|||
return this.Points; |
|||
|
|||
} |
|||
} |
|||
} ); |
|||
|
|||
} |
|||
|
|||
function ascSort( a, b ) { |
|||
|
|||
return a.distance - b.distance; |
|||
|
|||
} |
|||
|
|||
function intersectObject( object, raycaster, intersects, recursive ) { |
|||
|
|||
if ( object.visible === false ) return; |
|||
|
|||
object.raycast( raycaster, intersects ); |
|||
|
|||
if ( recursive === true ) { |
|||
|
|||
var children = object.children; |
|||
|
|||
for ( var i = 0, l = children.length; i < l; i ++ ) { |
|||
|
|||
intersectObject( children[ i ], raycaster, intersects, true ); |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
Object.assign( Raycaster.prototype, { |
|||
|
|||
linePrecision: 1, |
|||
|
|||
set: function ( origin, direction ) { |
|||
|
|||
// direction is assumed to be normalized (for accurate distance calculations)
|
|||
|
|||
this.ray.set( origin, direction ); |
|||
|
|||
}, |
|||
|
|||
setFromCamera: function ( coords, camera ) { |
|||
|
|||
if ( ( camera && camera.isPerspectiveCamera ) ) { |
|||
|
|||
this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); |
|||
this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); |
|||
|
|||
} else if ( ( camera && camera.isOrthographicCamera ) ) { |
|||
|
|||
this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
|
|||
this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); |
|||
|
|||
} else { |
|||
|
|||
console.error( 'THREE.Raycaster: Unsupported camera type.' ); |
|||
|
|||
} |
|||
|
|||
}, |
|||
|
|||
intersectObject: function ( object, recursive, optionalTarget ) { |
|||
|
|||
var intersects = optionalTarget || []; |
|||
|
|||
intersectObject( object, this, intersects, recursive ); |
|||
|
|||
intersects.sort( ascSort ); |
|||
|
|||
return intersects; |
|||
|
|||
}, |
|||
|
|||
intersectObjects: function ( objects, recursive, optionalTarget ) { |
|||
|
|||
var intersects = optionalTarget || []; |
|||
|
|||
if ( Array.isArray( objects ) === false ) { |
|||
|
|||
console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' ); |
|||
return intersects; |
|||
|
|||
} |
|||
|
|||
for ( var i = 0, l = objects.length; i < l; i ++ ) { |
|||
|
|||
intersectObject( objects[ i ], this, intersects, recursive ); |
|||
|
|||
} |
|||
|
|||
intersects.sort( ascSort ); |
|||
|
|||
return intersects; |
|||
|
|||
} |
|||
|
|||
} ); |
|||
|
|||
|
|||
export { Raycaster }; |
@ -0,0 +1,81 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<title>Collection</title> |
|||
<script> |
|||
var booktitles = [ |
|||
{ |
|||
title: "Mac OS X Leopard Edition", |
|||
id: "1", |
|||
|
|||
}, |
|||
{ |
|||
title: "The Qmail Handbook", |
|||
id: "2", |
|||
|
|||
}, |
|||
{ |
|||
title: "Hardening Network Infrastructure: Bulletproof Your Systems Before You Are Hacked!", |
|||
id: "3", |
|||
|
|||
}, |
|||
{ |
|||
title: "Cocoa Programming for Mac OS X Second Edition", |
|||
id: "4", |
|||
|
|||
}, |
|||
{ |
|||
title: "LDAP System Administration", |
|||
id: "5", |
|||
|
|||
} |
|||
|
|||
]; |
|||
|
|||
|
|||
</script> |
|||
|
|||
</head> |
|||
<body> |
|||
<ul> |
|||
<script> |
|||
for(i =0; i < booktitles.length;i++){ |
|||
document.write('<h4>'+booktitles[i].title+'</h4>'); |
|||
|
|||
var myCoords = xyzGen(booktitles[i].title) |
|||
console.log("Coordinates of " + booktitles[i].title) |
|||
console.log("x : " + myCoords.x) |
|||
console.log("y : " + myCoords.y) |
|||
console.log("z : " + myCoords.z) |
|||
|
|||
} |
|||
// console.log(booktitles); |
|||
|
|||
var x,y,z |
|||
|
|||
function xyzGen(string) { |
|||
let coords = { |
|||
x: 0, |
|||
y: 0, |
|||
z: 0, |
|||
} |
|||
string = string.split(' ') |
|||
|
|||
for (var i = 0; i < 3; i++) { |
|||
for (c in string[i]) { |
|||
if (i == 0) { |
|||
coords.x += string[i].charCodeAt(c) |
|||
} else if (i == 1) { |
|||
coords.y += string[i].charCodeAt(c) |
|||
} else if (i == 2) { |
|||
coords.z += string[i].charCodeAt(c) |
|||
} |
|||
} |
|||
} |
|||
return coords |
|||
} |
|||
</script> |
|||
</ul> |
|||
|
|||
</body> |
|||
</html> |
@ -0,0 +1,382 @@ |
|||
<!DOCTYPE html> |
|||
|
|||
<html> |
|||
<head> |
|||
<title>XPPL VOLUMETRIC CATALOGUE </title> |
|||
<meta charset="utf-8"> |
|||
<link href="https://fonts.googleapis.com/css?family=Karla" rel="stylesheet"> |
|||
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> |
|||
<style> |
|||
body{ |
|||
cccccc; |
|||
font-family: 'Karla', sans-serif; |
|||
font-size:15px; |
|||
|
|||
text-align:left; |
|||
background-color: #140b33; |
|||
margin: 0px; |
|||
overflow: hidden; |
|||
} |
|||
#info { |
|||
position: absolute; |
|||
top: 0px; width: 10%; |
|||
padding: 10px; |
|||
} |
|||
a { |
|||
color: #444b7c; |
|||
} |
|||
|
|||
.swal-button { |
|||
padding: 7px 19px; |
|||
|
|||
background-color: #aca4c1; |
|||
font-size: 12px; |
|||
|
|||
|
|||
} |
|||
|
|||
.swal-title { |
|||
margin: 0px; |
|||
font-size: 16px; |
|||
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.21); |
|||
margin-bottom: 28px; |
|||
} |
|||
|
|||
.swal-overlay { |
|||
background-color: rgba(20, 13, 50, 0.6); |
|||
} |
|||
.swal-modal { |
|||
background-color: rgba(172, 164, 193, 1); |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
</style> |
|||
</head> |
|||
<body> |
|||
<div id="info"><a target="_blank" rel="noopener">XPPL VOLUMETRIC CATALOGUE <br> <br> Feel free to move around and explore the content of the library by clicking on the volumetric shapes</div> |
|||
<div id="container"></div> |
|||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> |
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script> |
|||
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script> |
|||
|
|||
<script src="three.min.js"></script> |
|||
<script src="OrbitControls.js"></script> |
|||
|
|||
<script> |
|||
|
|||
|
|||
var category2color = new Object(); |
|||
category2color["Technical"] = "#003d5d"; |
|||
category2color["Science/History"] = "#f23d5d"; |
|||
category2color["Media studies"] = "#8c3d5d"; |
|||
category2color["Philosophy"] = "#723d5d"; |
|||
category2color["Computer culture"] = "#423d5d"; |
|||
category2color["Design / writing / publishing"] = "#ff0000"; |
|||
category2color["Desk"] = "#09edff"; |
|||
category2color["Art"] = "#ffedff"; |
|||
category2color["Digital (Steve Trim 2 reading)"] = "#ffe1cc"; |
|||
category2color["Media Studies (Femke Trim 3)"] = "#00e1cc"; |
|||
category2color["Literature, Culture, Theory"] = "#00a1d4"; |
|||
|
|||
category2color["default"] = "#cdc1ec"; |
|||
|
|||
|
|||
|
|||
|
|||
console.clear(); |
|||
|
|||
const MAX_DISTANCE = 13000; |
|||
// |
|||
const MIN_DISTANCE = 200; |
|||
|
|||
const MAX_SPHERE_RADIUS = 700; |
|||
|
|||
var bookTitles; |
|||
var request = new XMLHttpRequest(); |
|||
request.open('GET', 'export.json', true); |
|||
|
|||
request.onload = function() { |
|||
if (request.status >= 200 && request.status < 400) { |
|||
var data = JSON.parse(request.responseText); |
|||
//bookTitles = data; |
|||
bookTitles = data.books[0]; |
|||
|
|||
bookTitles.forEach(function(book) { |
|||
book.type = "sphere"; |
|||
console.log('BOOK:', book); |
|||
|
|||
|
|||
|
|||
}); |
|||
console.log("got books", bookTitles) |
|||
// loaded data, start |
|||
init(); |
|||
animate(); |
|||
} else { |
|||
// We reached our target server, but it returned an error |
|||
|
|||
} |
|||
}; |
|||
|
|||
request.onerror = function() { |
|||
// There was a connection error of some sort |
|||
}; |
|||
|
|||
request.send(); |
|||
|
|||
|
|||
// --- threeJS --- // |
|||
var renderer, scene, camera, distance, raycaster, projector; |
|||
|
|||
var container = document.getElementById('container'); |
|||
var raycaster = new THREE.Raycaster(),INTERSECTED; |
|||
var mouse = new THREE.Vector2(); |
|||
var distance = 400; |
|||
|
|||
// -- basic initialization -- // |
|||
function init() { |
|||
renderer = new THREE.WebGLRenderer({ |
|||
antialias: true |
|||
}); |
|||
renderer.setSize(window.innerWidth, window.innerHeight); |
|||
renderer.setClearColor(0x140b33, 1); |
|||
container.appendChild(renderer.domElement); |
|||
|
|||
scene = new THREE.Scene(); |
|||
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.2, 25000); |
|||
controls = new THREE.OrbitControls(camera); |
|||
/* |
|||
controls = new THREE.OrbitControls(camera, renderer.domElement); |
|||
controls.maxDistance = MAX_DISTANCE * 3; |
|||
controls.target = new THREE.Vector3(0, 0, 0); |
|||
controls.rotateSpeed = .2; |
|||
controls.enableDamping = true; |
|||
console.log(controls.enableDamping); |
|||
controls.dampingFactor = .15; |
|||
controls.panSpeed = .15; |
|||
controls.screenSpacePanning = true;*/ |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
camera.position.set(100, 100, 2000); |
|||
controls.update(); |
|||
scene.add(camera); |
|||
|
|||
light = new THREE.PointLight(0xffffff, 1, 4000); |
|||
light.position.set(50, 0, 0); |
|||
light_two = new THREE.PointLight(0xffffff, 1, 4000); |
|||
light_two.position.set(-100, 800, 800); |
|||
lightAmbient = new THREE.AmbientLight(0x404040); |
|||
scene.add(light, light_two, lightAmbient); |
|||
|
|||
// createSpheres(); |
|||
|
|||
createDiamond(); |
|||
|
|||
createSpace(); |
|||
|
|||
renderer.render(scene, camera); |
|||
|
|||
document.addEventListener('mousemove', onMouseMove, false); |
|||
document.addEventListener('mousedown', onDocumentMouseDown, false); |
|||
window.addEventListener('resize', onWindowResize, false); |
|||
} |
|||
|
|||
// -- diamonds -- // |
|||
|
|||
|
|||
function catInobject(obj, category){ //checks if category is in object, if so return corresponding color |
|||
if (obj.hasOwnProperty(category)) { |
|||
var color = obj[category]; |
|||
} else { var color = obj["default"]; |
|||
} |
|||
return color; |
|||
} |
|||
|
|||
function createDiamond() { |
|||
|
|||
diamondsGroup = new THREE.Object3D(); |
|||
|
|||
|
|||
console.log(); |
|||
|
|||
bookTitles.forEach(function (book) { |
|||
var chosencolor = catInobject(category2color, book.category); |
|||
var sphere = new THREE.SphereGeometry(1, Math.random() * 100, Math.random() * 100); |
|||
var material = new THREE.MeshPhongMaterial({ |
|||
color: chosencolor,//Math.random() * 0xff00000 - 0xff00000, |
|||
shading: THREE.FlatShading |
|||
}); |
|||
var sphere = new THREE.Mesh(sphere, material); |
|||
sphere.position.x = Math.random() * -distance * 6; |
|||
sphere.position.y = Math.random() * -distance * 2; |
|||
sphere.position.z = Math.random() * distance * 3; |
|||
sphere.rotation.y = Math.random() * 2 * Math.PI; |
|||
sphere.scale.x = sphere.scale.y = sphere.scale.z = Math.random() * 50 + 10; |
|||
|
|||
sphere.userData = book; |
|||
diamondsGroup.add(sphere); |
|||
|
|||
}) |
|||
diamondsGroup.position.x = 1400; |
|||
scene.add(diamondsGroup); |
|||
|
|||
}; |
|||
|
|||
// -- dots on the back -- // |
|||
function createSpace() { |
|||
|
|||
dots = new THREE.Object3D(); |
|||
|
|||
for (var i = 0; i < 1000; i++) { |
|||
var circleGeometry = new THREE.SphereGeometry(2, Math.random() * 5, Math.random() * 5); |
|||
var color; |
|||
if (Math.round(Math.random()) === 0) |
|||
color = new THREE.Color('#003d5d'); |
|||
else |
|||
//color = new THREE.Color('#f23d5d'); |
|||
color = new THREE.Color('#4f2939'); |
|||
|
|||
var material = new THREE.MeshBasicMaterial({ |
|||
color: color |
|||
}); |
|||
material.flatShading = true; |
|||
|
|||
//var material = new THREE.MeshBasicMaterial({ |
|||
//color : new THREE.Color(Math.floor(Math.random() * 1) === 1), |
|||
//color : new THREE.Color(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 0), |
|||
//shading: THREE.FlatShading, |
|||
//}) |
|||
var circle = new THREE.Mesh(circleGeometry, material); |
|||
material.side = THREE.DoubleSide; |
|||
|
|||
circle.position.x = Math.random() * -distance * 50; |
|||
circle.position.y = Math.random() * -distance * 8; |
|||
circle.position.z = Math.random() * distance * 5; |
|||
circle.rotation.y = Math.random() * 2 * Math.PI; |
|||
circle.scale.x = circle.scale.y = circle.scale.z = Math.random() * 6 + 5; |
|||
dots.add(circle); |
|||
} |
|||
|
|||
dots.position.x = 14000; |
|||
dots.position.y = 1500; |
|||
dots.position.z = -4000; |
|||
dots.rotation.y = Math.PI * 600; |
|||
dots.rotation.z = Math.PI * 500; |
|||
|
|||
scene.add(dots); |
|||
}; |
|||
|
|||
|
|||
|
|||
// -- events -- // |
|||
function onMouseMove(event) { |
|||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; |
|||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; |
|||
mouseX = event.clientX - window.innerWidth / 2; |
|||
mouseY = event.clientY - window.innerHeight / 2; |
|||
camera.position.x += (mouseX - camera.position.x) * 0.01; |
|||
controls.update(); |
|||
camera.position.y += (mouseY - camera.position.y) * 0.01; |
|||
controls.update(); |
|||
camera.lookAt(scene.position); |
|||
controls.update(); |
|||
}; |
|||
|
|||
function onDocumentMouseDown(event) { |
|||
|
|||
event.preventDefault(); |
|||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; |
|||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; |
|||
|
|||
raycaster.setFromCamera(mouse, camera); |
|||
|
|||
var intersects = raycaster.intersectObjects(diamondsGroup.children); |
|||
if (intersects.length > 0) { |
|||
var book = intersects[0].object.userData; |
|||
console.log("click", book); |
|||
//alert("book" + book.title); |
|||
|
|||
//swal(book.title + book.authors); |
|||
|
|||
swal(book.title + " \n " + " " + book.authors[0].author_name + " \n" + book.category, { |
|||
button: { |
|||
text: "Open", |
|||
} |
|||
|
|||
|
|||
}). then (function() { |
|||
window.location = "/books/"+book.id |
|||
}); |
|||
|
|||
|
|||
} |
|||
|
|||
}; |
|||
|
|||
function onDocumentMouseWheel( event ) { |
|||
|
|||
fov -= event.wheelDeltaY * 0.05; |
|||
camera.projectionMatrix = THREE.Matrix4.makePerspective( fov, window.innerWidth / window.innerHeight, 1, 1100 ); |
|||
|
|||
} |
|||
|
|||
|
|||
function onWindowResize() { |
|||
camera.aspect = window.innerWidth / window.innerHeight; |
|||
renderer.setSize(window.innerWidth, window.innerHeight); |
|||
camera.updateProjectionMatrix(); |
|||
controls.update(); |
|||
}; |
|||
|
|||
// ---- // |
|||
function animate() { |
|||
requestAnimationFrame(animate); |
|||
controls.update(); |
|||
render(); |
|||
}; |
|||
|
|||
// -- render all -- // |
|||
function render() { |
|||
|
|||
var timer = 0.00001 * Date.now(); |
|||
|
|||
for (var i = 0, l = diamondsGroup.children.length; i < l; i++) { |
|||
var object = diamondsGroup.children[i]; |
|||
object.position.y = 500 * Math.cos(timer + i); |
|||
object.rotation.y += Math.PI / 500; |
|||
} |
|||
|
|||
// update the picking ray with the camera and mouse position |
|||
raycaster.setFromCamera(mouse, camera); |
|||
|
|||
// calculate objects intersecting the picking ray |
|||
var intersects = raycaster.intersectObjects(diamondsGroup.children); |
|||
|
|||
if (intersects.length > 0) { |
|||
if (INTERSECTED != intersects[0].object) { |
|||
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex); |
|||
INTERSECTED = intersects[0].object; |
|||
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex(); |
|||
INTERSECTED.material.emissive.setHex(Math.random() * 0xff00000 - 0xff00000); |
|||
} |
|||
} else { |
|||
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex); |
|||
INTERSECTED = null; |
|||
} |
|||
|
|||
renderer.render(scene, camera); |
|||
}; |
|||
|
|||
// -- run functions -- // |
|||
//init(); |
|||
//animate(); |
|||
|
|||
</script> |
|||
|
|||
</body> |
|||
</html> |
@ -0,0 +1,458 @@ |
|||
<!DOCTYPE html> |
|||
|
|||
<html> |
|||
<head> |
|||
<title>XPPL VOLUMETRIC CATALOGUE </title> |
|||
<meta charset="utf-8"> |
|||
<link href="https://fonts.googleapis.com/css?family=Karla" rel="stylesheet"> |
|||
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> |
|||
<style> |
|||
body{ |
|||
cccccc; |
|||
font-family: 'Karla', sans-serif; |
|||
font-size:15px; |
|||
|
|||
text-align:left; |
|||
background-color: #140b33; |
|||
margin: 0px; |
|||
overflow: hidden; |
|||
} |
|||
#info { |
|||
position: absolute; |
|||
top: 0px; width: 10%; |
|||
padding: 10px; |
|||
} |
|||
a { |
|||
color: #444b7c; |
|||
} |
|||
|
|||
.swal-button { |
|||
padding: 7px 19px; |
|||
|
|||
background-color: #aca4c1; |
|||
font-size: 12px; |
|||
|
|||
|
|||
} |
|||
|
|||
.swal-title { |
|||
margin: 0px; |
|||
font-size: 16px; |
|||
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.21); |
|||
margin-bottom: 28px; |
|||
} |
|||
|
|||
.swal-overlay { |
|||
background-color: rgba(20, 13, 50, 0.6); |
|||
} |
|||
.swal-modal { |
|||
background-color: rgba(172, 164, 193, 1); |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
</style> |
|||
</head> |
|||
<body> |
|||
|
|||
<div id="container"></div> |
|||
<canvas id="viewer"></canvas> |
|||
<script src="https://rawgit.com/mrdoob/three.js/dev/build/three.min.js"></script> |
|||
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script> |
|||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> |
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script> |
|||
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script> |
|||
<script> |
|||
|
|||
|
|||
var category2color = new Object(); |
|||
category2color["Technical"] = "#003d5d"; |
|||
category2color["Science/History"] = "#f23d5d"; |
|||
category2color["Media studies"] = "#8c3d5d"; |
|||
category2color["Philosophy"] = "#723d5d"; |
|||
category2color["Computer culture"] = "#423d5d"; |
|||
category2color["Design / writing / publishing"] = "#ff0000"; |
|||
category2color["Desk"] = "#09edff"; |
|||
category2color["Art"] = "#ffedff"; |
|||
category2color["Digital (Steve Trim 2 reading)"] = "#ffe1cc"; |
|||
category2color["Media Studies (Femke Trim 3)"] = "#00e1cc"; |
|||
category2color["Literature, Culture, Theory"] = "#00a1d4"; |
|||
|
|||
category2color["default"] = "#cdc1ec"; |
|||
|
|||
|
|||
|
|||
|
|||
console.clear(); |
|||
|
|||
const MAX_DISTANCE = 1000; |
|||
// |
|||
const MIN_DISTANCE = 200; |
|||
|
|||
const MAX_SPHERE_RADIUS = 700; |
|||
|
|||
var bookTitles; |
|||
var request = new XMLHttpRequest(); |
|||
request.open('GET', 'export.json', true); |
|||
|
|||
request.onload = function() { |
|||
if (request.status >= 200 && request.status < 400) { |
|||
var data = JSON.parse(request.responseText); |
|||
//bookTitles = data; |
|||
bookTitles = data.books[0]; |
|||
|
|||
bookTitles.forEach(function(book) { |
|||
book.type = "sphere"; |
|||
console.log('BOOK:', book); |
|||
|
|||
|
|||
|
|||
}); |
|||
console.log("got books", bookTitles) |
|||
// loaded data, start |
|||
init(); |
|||
animate(); |
|||
} else { |
|||
// We reached our target server, but it returned an error |
|||
|
|||
} |
|||
}; |
|||
|
|||
request.onerror = function() { |
|||
// There was a connection error of some sort |
|||
}; |
|||
|
|||
request.send(); |
|||
|
|||
|
|||
// --- threeJS --- // |
|||
var renderer, scene, camera, distance, raycaster, projector; |
|||
|
|||
var container = document.getElementById('container'); |
|||
var raycaster = new THREE.Raycaster(),INTERSECTED; |
|||
var mouse = new THREE.Vector2(); |
|||
var distance = 600; |
|||
|
|||
// -- basic initialization -- // |
|||
function init() { |
|||
renderer = new THREE.WebGLRenderer({ |
|||
antialias: true |
|||
}); |
|||
|
|||
renderer.setSize(window.innerWidth, window.innerHeight); |
|||
renderer.setClearColor(0x140b33, 1); |
|||
container.appendChild(renderer.domElement); |
|||
|
|||
scene = new THREE.Scene(); |
|||
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.01, 300000); |
|||
// controls = new THREE.OrbitControls(camera); |
|||
//camera.position.set(1, 1, -5); |
|||
camera.position.set(MAX_DISTANCE/2, MAX_DISTANCE/20, MAX_DISTANCE/20); |
|||
|
|||
camera.updateProjectionMatrix(); |
|||
|
|||
controls = new THREE.OrbitControls(camera, renderer.domElement); |
|||
// controls.maxDistance = MAX_DISTANCE * 3; |
|||
controls.target = new THREE.Vector3(0, 0, 0); |
|||
controls.rotateSpeed = .2; |
|||
controls.enableDamping = true; |
|||
console.log(controls.enableDamping); |
|||
controls.dampingFactor = .15; |
|||
controls.panSpeed = .15; |
|||
controls.screenSpacePanning = true; |
|||
// to disable zoom |
|||
controls.enableZoom = true; |
|||
// to disable rotation |
|||
controls.enableRotate = true; |
|||
// to disable pan |
|||
controls.enablePan = true; |
|||
scene.add(camera); |
|||
|
|||
//camera.position.set(-150, 10, 1); |
|||
//controls.update(); |
|||
// scene.add(camera); |
|||
/* |
|||
light = new THREE.PointLight(0xffffff, 1, 4000); |
|||
light.position.set(50, 0, 0); |
|||
light_two = new THREE.PointLight(0xffffff, 1, 4000); |
|||
light_two.position.set(-100, 800, 800); |
|||
lightAmbient = new THREE.AmbientLight(0x404040); |
|||
scene.add(light, light_two, lightAmbient);*/ |
|||
|
|||
// createSpheres(); |
|||
|
|||
scene.add(new THREE.DirectionalLight(0xffffff)); |
|||
scene.add(new THREE.AmbientLight(0x222222)); |
|||
|
|||
renderer.setPixelRatio(window.devicePixelRatio); |
|||
|
|||
let viewer = document.querySelector('#viewer'); |
|||
viewer.parentNode.replaceChild(renderer.domElement, viewer); |
|||
|
|||
createDiamond(); |
|||
|
|||
createSpace(); |
|||
|
|||
renderer.render(scene, camera); |
|||
|
|||
document.addEventListener('mousemove', onMouseMove, false); |
|||
document.addEventListener('mousedown', onDocumentMouseDown, false); |
|||
window.addEventListener('resize', onWindowResize, false); |
|||
|
|||
|
|||
} |
|||
|
|||
// -- diamonds -- // |
|||
|
|||
|
|||
function catInobject(obj, category){ //checks if category is in object, if so return corresponding color |
|||
if (obj.hasOwnProperty(category)) { |
|||
var color = obj[category]; |
|||
} else { var color = obj["default"]; |
|||
} |
|||
return color; |
|||
} |
|||
|
|||
function createDiamond() { |
|||
|
|||
diamondsGroup = new THREE.Object3D(); |
|||
|
|||
|
|||
console.log(); |
|||
|
|||
bookTitles.forEach(function (book) { |
|||
var chosencolor = catInobject(category2color, book.category); |
|||
var sphere = new THREE.SphereGeometry(50, Math.random() * 1, Math.random() * 1); |
|||
var material = new THREE.MeshPhongMaterial({ |
|||
color: chosencolor,//Math.random() * 0xff00000 - 0xff00000, |
|||
shading: THREE.FlatShading |
|||
}); |
|||
var sphere = new THREE.Mesh(sphere, material); |
|||
sphere.position.x = get_x(book.title) * Math.random() * 100 - 1000; |
|||
sphere.position.z = get_z(book.category) * Math.random() * 100 - 1000; |
|||
sphere.rotation.y =get_y(book.fileformat) * Math.random() * 100 - 1000; |
|||
//sphere.scale.x = sphere.scale.y = sphere.scale.z = Math.random() * 50 + 10; |
|||
sphere.scale.x = sphere.scale.y = sphere.scale.z = get_size(book.title); |
|||
|
|||
sphere.userData = book; |
|||
diamondsGroup.add(sphere); |
|||
|
|||
}) |
|||
diamondsGroup.position.x = 500; |
|||
scene.add(diamondsGroup); |
|||
|
|||
}; |
|||
|
|||
function get_size(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
|
|||
function get_x(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
function get_y(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
function get_z(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
|
|||
// -- dots on the back -- // |
|||
function createSpace() { |
|||
|
|||
let dots = new THREE.Object3D(); |
|||
|
|||
for (let i = 0; i < 1000; i++) { |
|||
let circleGeometry = new THREE.SphereGeometry(2, Math.random() * 5, Math.random() * 5); |
|||
let color; |
|||
if (Math.round(Math.random()) === 0) |
|||
color = new THREE.Color('#003d5d'); |
|||
else |
|||
//color = new THREE.Color('#f23d5d'); |
|||
color = new THREE.Color('#4f2939'); |
|||
|
|||
let material = new THREE.MeshPhongMaterial({ |
|||
color: color |
|||
//side: THREE.DoubleSide |
|||
}); |
|||
|
|||
material.flatShading = true; |
|||
|
|||
//var material = new THREE.MeshBasicMaterial({ |
|||
//color : new THREE.Color(Math.floor(Math.random() * 1) === 1), |
|||
//color : new THREE.Color(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 0), |
|||
//shading: THREE.FlatShading, |
|||
//}) |
|||
var circle = new THREE.Mesh(circleGeometry, material); |
|||
material.side = THREE.DoubleSide; |
|||
|
|||
circle.position.x = Math.random() * -distance * 50; |
|||
circle.position.y = Math.random() * -distance * 8; |
|||
circle.position.z = Math.random() * distance * 5; |
|||
circle.rotation.y = Math.random() * 2 * Math.PI; |
|||
circle.scale.x = circle.scale.y = circle.scale.z = Math.random() * 6 + 5; |
|||
dots.add(circle); |
|||
} |
|||
|
|||
dots.position.x = 14000; |
|||
dots.position.y = 1500; |
|||
dots.position.z = -4000; |
|||
dots.rotation.y = Math.PI * 600; |
|||
dots.rotation.z = Math.PI * 500; |
|||
|
|||
scene.add(dots); |
|||
}; |
|||
|
|||
|
|||
/* let circle = new THREE.Mesh(circleGeometry, material); |
|||
|
|||
let direction = getRandomVector().normalize(); |
|||
let minDistance = MAX_DISTANCE * 8; |
|||
let maxDistance = minDistance + 0.5; |
|||
direction.multiplyScalar(Math.random() * (maxDistance - minDistance) + minDistance); |
|||
|
|||
circle.position.add(direction); |
|||
|
|||
dots.add(circle); |
|||
} |
|||
scene.add(dots); |
|||
} */ |
|||
|
|||
function getRandomVector(max_distance) { |
|||
if (max_distance === undefined) |
|||
max_distance = 1; |
|||
return new THREE.Vector3(getRandom(max_distance), getRandom(max_distance), getRandom(max_distance)); |
|||
} |
|||
|
|||
function getRandom(max_distance) { |
|||
let random = Math.random() * max_distance; |
|||
random *= Math.floor(Math.random() * 2) === 1 ? 1 : -1; |
|||
return random; |
|||
} |
|||
|
|||
|
|||
|
|||
// -- events -- // |
|||
function onMouseMove(event) { |
|||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; |
|||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; |
|||
mouseX = event.clientX - window.innerWidth / 2 ; |
|||
mouseY = event.clientY - window.innerHeight / 2 ; |
|||
camera.position.x += (mouseX - camera.position.x) * 0.01; |
|||
camera.position.y += (mouseY - camera.position.y) * 0.01; |
|||
camera.lookAt(scene.position); |
|||
}; |
|||
|
|||
function onDocumentMouseDown(event) { |
|||
|
|||
event.preventDefault(); |
|||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; |
|||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; |
|||
|
|||
raycaster.setFromCamera(mouse, camera); |
|||
|
|||
var intersects = raycaster.intersectObjects(diamondsGroup.children); |
|||
if (intersects.length > 0) { |
|||
var book = intersects[0].object.userData; |
|||
console.log("click", book); |
|||
//alert("book" + book.title); |
|||
|
|||
//swal(book.title + book.authors); |
|||
|
|||
swal(book.title + " \n " + " " + book.authors[0].author_name + " \n" + book.category, { |
|||
button: { |
|||
text: "Open", |
|||
} |
|||
}).then (function(){ |
|||
window.location = "/books/"+book.id |
|||
}); |
|||
|
|||
|
|||
|
|||
} |
|||
|
|||
}; |
|||
|
|||
function onDocumentMouseWheel( event ) { |
|||
|
|||
fov -= event.wheelDeltaY * 0.05; |
|||
camera.projectionMatrix = THREE.Matrix4.makePerspective( fov, window.innerWidth / window.innerHeight, 1, 1100 ); |
|||
|
|||
} |
|||
|
|||
|
|||
function onWindowResize() { |
|||
camera.aspect = window.innerWidth / window.innerHeight; |
|||
renderer.setSize(window.innerWidth, window.innerHeight); |
|||
camera.updateProjectionMatrix(); |
|||
controls.update(); |
|||
}; |
|||
|
|||
// ---- // |
|||
function animate() { |
|||
requestAnimationFrame(animate); |
|||
controls.update(); |
|||
render(); |
|||
}; |
|||
|
|||
// -- render all -- // |
|||
function render() { |
|||
|
|||
var timer = 0.00001 * Date.now(); |
|||
|
|||
for (var i = 0, l = diamondsGroup.children.length; i < l; i++) { |
|||
var object = diamondsGroup.children[i]; |
|||
object.position.y = 500 * Math.cos(timer + i); |
|||
object.rotation.y += Math.PI / 500; |
|||
} |
|||
|
|||
// update the picking ray with the camera and mouse position |
|||
raycaster.setFromCamera(mouse, camera); |
|||
|
|||
// calculate objects intersecting the picking ray |
|||
var intersects = raycaster.intersectObjects(diamondsGroup.children); |
|||
|
|||
if (intersects.length > 0) { |
|||
if (INTERSECTED != intersects[0].object) { |
|||
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex); |
|||
INTERSECTED = intersects[0].object; |
|||
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex(); |
|||
INTERSECTED.material.emissive.setHex(Math.random() * 0xff00000 - 0xff00000); |
|||
} |
|||
} else { |
|||
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex); |
|||
INTERSECTED = null; |
|||
} |
|||
|
|||
renderer.render(scene, camera); |
|||
}; |
|||
|
|||
// -- run functions -- // |
|||
//init(); |
|||
//animate(); |
|||
|
|||
</script> |
|||
|
|||
</body> |
|||
</html> |
@ -0,0 +1,459 @@ |
|||
<!DOCTYPE html> |
|||
|
|||
<html> |
|||
<head> |
|||
<title>XPPL VOLUMETRIC CATALOGUE </title> |
|||
<meta charset="utf-8"> |
|||
<link href="https://fonts.googleapis.com/css?family=Karla" rel="stylesheet"> |
|||
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> |
|||
<style> |
|||
body{ |
|||
cccccc; |
|||
font-family: 'Karla', sans-serif; |
|||
font-size:15px; |
|||
|
|||
text-align:left; |
|||
background-color: #140b33; |
|||
margin: 0px; |
|||
overflow: hidden; |
|||
} |
|||
#info { |
|||
position: absolute; |
|||
top: 0px; width: 10%; |
|||
padding: 10px; |
|||
} |
|||
a { |
|||
color: #444b7c; |
|||
} |
|||
|
|||
.swal-button { |
|||
padding: 7px 19px; |
|||
|
|||
background-color: #aca4c1; |
|||
font-size: 12px; |
|||
|
|||
|
|||
} |
|||
|
|||
.swal-title { |
|||
margin: 0px; |
|||
font-size: 16px; |
|||
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.21); |
|||
margin-bottom: 28px; |
|||
} |
|||
|
|||
.swal-overlay { |
|||
background-color: rgba(20, 13, 50, 0.6); |
|||
} |
|||
.swal-modal { |
|||
background-color: rgba(172, 164, 193, 1); |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
</style> |
|||
</head> |
|||
<body> |
|||
<div id="info"><a target="_blank" rel="noopener">XPPL VOLUMETRIC CATALOGUE <br> <br> Feel free to move around and explore the content of the library by clicking on the volumetric shapes</div> |
|||
<div id="container"></div> |
|||
<canvas id="viewer"></canvas> |
|||
<script src="https://rawgit.com/mrdoob/three.js/dev/build/three.min.js"></script> |
|||
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script> |
|||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> |
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script> |
|||
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script> |
|||
<script> |
|||
|
|||
|
|||
var category2color = new Object(); |
|||
category2color["Technical"] = "#003d5d"; |
|||
category2color["Science/History"] = "#f23d5d"; |
|||
category2color["Media studies"] = "#8c3d5d"; |
|||
category2color["Philosophy"] = "#723d5d"; |
|||
category2color["Computer culture"] = "#423d5d"; |
|||
category2color["Design / writing / publishing"] = "#ff0000"; |
|||
category2color["Desk"] = "#09edff"; |
|||
category2color["Art"] = "#ffedff"; |
|||
category2color["Digital (Steve Trim 2 reading)"] = "#ffe1cc"; |
|||
category2color["Media Studies (Femke Trim 3)"] = "#00e1cc"; |
|||
category2color["Literature, Culture, Theory"] = "#00a1d4"; |
|||
|
|||
category2color["default"] = "#cdc1ec"; |
|||
|
|||
|
|||
|
|||
|
|||
console.clear(); |
|||
|
|||
const MAX_DISTANCE = 1000; |
|||
// |
|||
const MIN_DISTANCE = 200; |
|||
|
|||
const MAX_SPHERE_RADIUS = 700; |
|||
|
|||
var bookTitles; |
|||
var request = new XMLHttpRequest(); |
|||
request.open('GET', 'export.json', true); |
|||
|
|||
request.onload = function() { |
|||
if (request.status >= 200 && request.status < 400) { |
|||
var data = JSON.parse(request.responseText); |
|||
//bookTitles = data; |
|||
bookTitles = data.books[0]; |
|||
|
|||
bookTitles.forEach(function(book) { |
|||
book.type = "sphere"; |
|||
console.log('BOOK:', book); |
|||
|
|||
|
|||
|
|||
}); |
|||
console.log("got books", bookTitles) |
|||
// loaded data, start |
|||
init(); |
|||
animate(); |
|||
} else { |
|||
// We reached our target server, but it returned an error |
|||
|
|||
} |
|||
}; |
|||
|
|||
request.onerror = function() { |
|||
// There was a connection error of some sort |
|||
}; |
|||
|
|||
request.send(); |
|||
|
|||
|
|||
// --- threeJS --- // |
|||
var renderer, scene, camera, distance, raycaster, projector; |
|||
|
|||
var container = document.getElementById('container'); |
|||
var raycaster = new THREE.Raycaster(),INTERSECTED; |
|||
var mouse = new THREE.Vector2(); |
|||
var distance = 600; |
|||
|
|||
// -- basic initialization -- // |
|||
function init() { |
|||
renderer = new THREE.WebGLRenderer({ |
|||
antialias: true |
|||
}); |
|||
|
|||
renderer.setSize(window.innerWidth, window.innerHeight); |
|||
renderer.setClearColor(0x140b33, 1); |
|||
container.appendChild(renderer.domElement); |
|||
|
|||
scene = new THREE.Scene(); |
|||
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.01, 300000); |
|||
// controls = new THREE.OrbitControls(camera); |
|||
//camera.position.set(1, 1, -5); |
|||
camera.position.set(MAX_DISTANCE/2, MAX_DISTANCE/20, MAX_DISTANCE/20); |
|||
|
|||
camera.updateProjectionMatrix(); |
|||
|
|||
controls = new THREE.OrbitControls(camera, renderer.domElement); |
|||
// controls.maxDistance = MAX_DISTANCE * 3; |
|||
controls.target = new THREE.Vector3(0, 0, 0); |
|||
controls.rotateSpeed = .2; |
|||
controls.enableDamping = true; |
|||
console.log(controls.enableDamping); |
|||
controls.dampingFactor = .15; |
|||
controls.panSpeed = .15; |
|||
controls.screenSpacePanning = true; |
|||
// to disable zoom |
|||
controls.enableZoom = true; |
|||
// to disable rotation |
|||
controls.enableRotate = true; |
|||
// to disable pan |
|||
controls.enablePan = true; |
|||
scene.add(camera); |
|||
|
|||
//camera.position.set(-150, 10, 1); |
|||
//controls.update(); |
|||
// scene.add(camera); |
|||
|
|||
light = new THREE.PointLight(0x404040); |
|||
light.position.set(50, 0, 0); |
|||
scene.add(light); |
|||
/* light_two = new THREE.PointLight(0xffffff, 1, 4000); |
|||
light_two.position.set(-100, 800, 800); |
|||
lightAmbient = new THREE.AmbientLight(0x404040); |
|||
scene.add(light, light_two, lightAmbient);*/ |
|||
|
|||
// createSpheres(); |
|||
|
|||
scene.add(new THREE.DirectionalLight(0xffffff)); |
|||
scene.add(new THREE.AmbientLight(0x222222)); |
|||
|
|||
renderer.setPixelRatio(window.devicePixelRatio); |
|||
|
|||
let viewer = document.querySelector('#viewer'); |
|||
viewer.parentNode.replaceChild(renderer.domElement, viewer); |
|||
|
|||
createDiamond(); |
|||
|
|||
createSpace(); |
|||
|
|||
renderer.render(scene, camera); |
|||
|
|||
document.addEventListener('mousemove', onMouseMove, false); |
|||
document.addEventListener('mousedown', onDocumentMouseDown, false); |
|||
window.addEventListener('resize', onWindowResize, false); |
|||
|
|||
|
|||
} |
|||
|
|||
// -- diamonds -- // |
|||
|
|||
|
|||
function catInobject(obj, category){ //checks if category is in object, if so return corresponding color |
|||
if (obj.hasOwnProperty(category)) { |
|||
var color = obj[category]; |
|||
} else { var color = obj["default"]; |
|||
} |
|||
return color; |
|||
} |
|||
|
|||
function createDiamond() { |
|||
|
|||
diamondsGroup = new THREE.Object3D(); |
|||
|
|||
|
|||
console.log(); |
|||
|
|||
bookTitles.forEach(function (book) { |
|||
var chosencolor = catInobject(category2color, book.category); |
|||
var sphere = new THREE.SphereGeometry(1.3, Math.random() * 50, Math.random() * 50); |
|||
var material = new THREE.MeshPhongMaterial({ |
|||
color: chosencolor,//Math.random() * 0xff00000 - 0xff00000, |
|||
shading: THREE.FlatShading |
|||
}); |
|||
var sphere = new THREE.Mesh(sphere, material); |
|||
sphere.position.x = get_x(book.title) * Math.random() * 100 - 1000; |
|||
sphere.position.z = get_z(book.category) * Math.random() * 100 - 1000; |
|||
sphere.rotation.y =get_y(book.fileformat) * Math.random() * 100 - 1000; |
|||
//sphere.scale.x = sphere.scale.y = sphere.scale.z = Math.random() * 50 + 10; |
|||
sphere.scale.x = sphere.scale.y = sphere.scale.z = get_size(book.title); |
|||
|
|||
sphere.userData = book; |
|||
diamondsGroup.add(sphere); |
|||
|
|||
}) |
|||
diamondsGroup.position.x = 500; |
|||
scene.add(diamondsGroup); |
|||
|
|||
}; |
|||
|
|||
function get_size(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
|
|||
function get_x(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
function get_y(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
function get_z(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
|
|||
// -- dots on the back -- // |
|||
function createSpace() { |
|||
|
|||
let dots = new THREE.Object3D(); |
|||
|
|||
for (let i = 0; i < 1000; i++) { |
|||
let circleGeometry = new THREE.SphereGeometry(2, Math.random() * 5, Math.random() * 5); |
|||
let color; |
|||
if (Math.round(Math.random()) === 0) |
|||
color = new THREE.Color('#003d5d'); |
|||
else |
|||
//color = new THREE.Color('#f23d5d'); |
|||
color = new THREE.Color('#f23d5d'); |
|||
|
|||
let material = new THREE.MeshPhongMaterial({ |
|||
color: color |
|||
//side: THREE.DoubleSide |
|||
}); |
|||
|
|||
material.flatShading = true; |
|||
|
|||
//var material = new THREE.MeshBasicMaterial({ |
|||
//color : new THREE.Color(Math.floor(Math.random() * 1) === 1), |
|||
//color : new THREE.Color(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 0), |
|||
//shading: THREE.FlatShading, |
|||
//}) |
|||
var circle = new THREE.Mesh(circleGeometry, material); |
|||
material.side = THREE.DoubleSide; |
|||
|
|||
circle.position.x = Math.random() * -distance * 100; |
|||
circle.position.y = Math.random() * -distance * 8; |
|||
circle.position.z = Math.random() * distance * 5; |
|||
circle.rotation.y = Math.random() * 2 * Math.PI; |
|||
circle.scale.x = circle.scale.y = circle.scale.z = Math.random() * 6 + 5; |
|||
dots.add(circle); |
|||
} |
|||
|
|||
dots.position.x = 14000; |
|||
dots.position.y = 1500; |
|||
dots.position.z = 4000; |
|||
dots.rotation.y = Math.PI * 600; |
|||
dots.rotation.z = Math.PI * 500; |
|||
|
|||
scene.add(dots); |
|||
}; |
|||
|
|||
|
|||
/* let circle = new THREE.Mesh(circleGeometry, material); |
|||
|
|||
let direction = getRandomVector().normalize(); |
|||
let minDistance = MAX_DISTANCE * 8; |
|||
let maxDistance = minDistance + 0.5; |
|||
direction.multiplyScalar(Math.random() * (maxDistance - minDistance) + minDistance); |
|||
|
|||
circle.position.add(direction); |
|||
|
|||
dots.add(circle); |
|||
} |
|||
scene.add(dots); |
|||
} */ |
|||
|
|||
function getRandomVector(max_distance) { |
|||
if (max_distance === undefined) |
|||
max_distance = 1; |
|||
return new THREE.Vector3(getRandom(max_distance), getRandom(max_distance), getRandom(max_distance)); |
|||
} |
|||
|
|||
function getRandom(max_distance) { |
|||
let random = Math.random() * max_distance; |
|||
random *= Math.floor(Math.random() * 2) === 1 ? 1 : -1; |
|||
return random; |
|||
} |
|||
|
|||
|
|||
|
|||
// -- events -- // |
|||
function onMouseMove(event) { |
|||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; |
|||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; |
|||
mouseX = event.clientX - window.innerWidth / 2 ; |
|||
mouseY = event.clientY - window.innerHeight / 2 ; |
|||
camera.position.x += (mouseX - camera.position.x) * 0.01; |
|||
camera.position.y += (mouseY - camera.position.y) * 0.01; |
|||
camera.lookAt(scene.position); |
|||
}; |
|||
|
|||
function onDocumentMouseDown(event) { |
|||
|
|||
event.preventDefault(); |
|||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; |
|||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; |
|||
|
|||
raycaster.setFromCamera(mouse, camera); |
|||
|
|||
var intersects = raycaster.intersectObjects(diamondsGroup.children); |
|||
if (intersects.length > 0) { |
|||
var book = intersects[0].object.userData; |
|||
console.log("click", book); |
|||
//alert("book" + book.title); |
|||
|
|||
//swal(book.title + book.authors); |
|||
|
|||
swal(book.title + " \n " + " " + book.authors[0].author_name + " \n" + book.category, { |
|||
button: { |
|||
text: "Open", |
|||
} |
|||
}).then (function(){ |
|||
window.location = "/books/"+book.id |
|||
}); |
|||
|
|||
|
|||
|
|||
} |
|||
|
|||
}; |
|||
|
|||
function onDocumentMouseWheel( event ) { |
|||
|
|||
fov -= event.wheelDeltaY * 0.05; |
|||
camera.projectionMatrix = THREE.Matrix4.makePerspective( fov, window.innerWidth / window.innerHeight, 1, 1100 ); |
|||
|
|||
} |
|||
|
|||
|
|||
function onWindowResize() { |
|||
camera.aspect = window.innerWidth / window.innerHeight; |
|||
renderer.setSize(window.innerWidth, window.innerHeight); |
|||
camera.updateProjectionMatrix(); |
|||
controls.update(); |
|||
}; |
|||
|
|||
// ---- // |
|||
function animate() { |
|||
requestAnimationFrame(animate); |
|||
controls.update(); |
|||
render(); |
|||
}; |
|||
|
|||
// -- render all -- // |
|||
function render() { |
|||
|
|||
var timer = 0.00001 * Date.now(); |
|||
|
|||
for (var i = 0, l = diamondsGroup.children.length; i < l; i++) { |
|||
var object = diamondsGroup.children[i]; |
|||
object.position.y = 500 * Math.cos(timer + i); |
|||
object.rotation.y += Math.PI / 500; |
|||
} |
|||
|
|||
// update the picking ray with the camera and mouse position |
|||
raycaster.setFromCamera(mouse, camera); |
|||
|
|||
// calculate objects intersecting the picking ray |
|||
var intersects = raycaster.intersectObjects(diamondsGroup.children); |
|||
|
|||
if (intersects.length > 0) { |
|||
if (INTERSECTED != intersects[0].object) { |
|||
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex); |
|||
INTERSECTED = intersects[0].object; |
|||
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex(); |
|||
INTERSECTED.material.emissive.setHex(Math.random() * 0xff00000 - 0xff00000); |
|||
} |
|||
} else { |
|||
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex); |
|||
INTERSECTED = null; |
|||
} |
|||
|
|||
renderer.render(scene, camera); |
|||
}; |
|||
|
|||
// -- run functions -- // |
|||
//init(); |
|||
//animate(); |
|||
|
|||
</script> |
|||
|
|||
</body> |
|||
</html> |
@ -0,0 +1,474 @@ |
|||
<!DOCTYPE html> |
|||
|
|||
<html> |
|||
<head> |
|||
<title>XPPL VOLUMETRIC CATALOGUE </title> |
|||
<meta charset="utf-8"> |
|||
<link href="https://fonts.googleapis.com/css?family=Karla" rel="stylesheet"> |
|||
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> |
|||
<style> |
|||
body{ |
|||
|
|||
font-family: 'Karla', sans-serif; |
|||
font-size:15px; |
|||
|
|||
text-align:left; |
|||
background: #140b33; |
|||
margin: 0px; |
|||
overflow: hidden; |
|||
} |
|||
#info { |
|||
position: absolute; |
|||
top: 0px; width: 10%; |
|||
padding: 10px; |
|||
} |
|||
a { |
|||
color: #444b7c; |
|||
} |
|||
|
|||
.swal-button { |
|||
padding: 7px 19px; |
|||
|
|||
background-color: #aca4c1; |
|||
font-size: 12px; |
|||
|
|||
|
|||
} |
|||
|
|||
.swal-title { |
|||
margin: 0px; |
|||
font-size: 16px; |
|||
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.21); |
|||
margin-bottom: 28px; |
|||
} |
|||
|
|||
.swal-overlay { |
|||
background-color: rgba(20, 13, 50, 0.6); |
|||
} |
|||
.swal-modal { |
|||
background-color: rgba(172, 164, 193, 1); |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
</style> |
|||
</head> |
|||
<body> |
|||
<div id="info"><a href ="/">back to library</a> <br><br><a target="_blank" rel="noopener"> <b> <font size="5"> XPPL VOLUMETRIC CATALOGUE </font> </b> <br> <br> Feel free to move around and explore the content of the library by clicking on the volumetric shapes</div> |
|||
<div id="container"></div> |
|||
<canvas id="viewer"></canvas> |
|||
<script src="https://rawgit.com/mrdoob/three.js/dev/build/three.min.js"></script> |
|||
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script> |
|||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> |
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script> |
|||
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script> |
|||
<script> |
|||
|
|||
|
|||
var category2color = new Object(); |
|||
category2color["Technical"] = "#003d5d"; |
|||
category2color["Science/History"] = "#f23d5d"; |
|||
category2color["Media studies"] = "#8c3d5d"; |
|||
category2color["Philosophy"] = "#723d5d"; |
|||
category2color["Computer culture"] = "#423d5d"; |
|||
category2color["Design / writing / publishing"] = "#ff0000"; |
|||
category2color["Desk"] = "#09edff"; |
|||
category2color["Art"] = "#ffedff"; |
|||
category2color["Digital (Steve Trim 2 reading)"] = "#ffe1cc"; |
|||
category2color["Media Studies (Femke Trim 3)"] = "#00e1cc"; |
|||
category2color["Literature, Culture, Theory"] = "#00a1d4"; |
|||
|
|||
category2color["default"] = "#cdc1ec"; |
|||
|
|||
|
|||
|
|||
|
|||
console.clear(); |
|||
|
|||
const MAX_DISTANCE = 1000; |
|||
// |
|||
const MIN_DISTANCE = 200; |
|||
|
|||
const MAX_SPHERE_RADIUS = 700; |
|||
|
|||
var bookTitles; |
|||
var request = new XMLHttpRequest(); |
|||
request.open('GET', '/api/books', true); |
|||
|
|||
request.onload = function() { |
|||
if (request.status >= 200 && request.status < 400) { |
|||
var data = JSON.parse(request.responseText); |
|||
//bookTitles = data; |
|||
bookTitles = data.books; |
|||
|
|||
bookTitles.forEach(function(book) { |
|||
book.type = "sphere"; |
|||
console.log('BOOK:', book); |
|||
|
|||
|
|||
|
|||
}); |
|||
console.log("got books", bookTitles) |
|||
// loaded data, start |
|||
init(); |
|||
animate(); |
|||
|
|||
} else { |
|||
// We reached our target server, but it returned an error |
|||
|
|||
} |
|||
}; |
|||
|
|||
request.onerror = function() { |
|||
// There was a connection error of some sort |
|||
}; |
|||
|
|||
request.send(); |
|||
|
|||
|
|||
// --- threeJS --- // |
|||
var renderer, scene, camera, distance, raycaster, projector; |
|||
|
|||
var container = document.getElementById('container'); |
|||
var raycaster = new THREE.Raycaster(),INTERSECTED; |
|||
var mouse = new THREE.Vector2(); |
|||
var distance = 600; |
|||
|
|||
// -- basic initialization -- // |
|||
function init() { |
|||
renderer = new THREE.WebGLRenderer({ |
|||
antialias: true |
|||
}); |
|||
|
|||
|
|||
renderer.setClearColor(0x140b33, 1); |
|||
//renderer.setClearColor(0xFF00FF, 1.0); |
|||
renderer.setSize(window.innerWidth, window.innerHeight); |
|||
container.appendChild(renderer.domElement); |
|||
renderer.clear(); |
|||
scene = new THREE.Scene(); |
|||
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.01, 300000); |
|||
// controls = new THREE.OrbitControls(camera); |
|||
//camera.position.set(1, 1, -5); |
|||
camera.position.set(MAX_DISTANCE/2, MAX_DISTANCE/20, MAX_DISTANCE/20); |
|||
|
|||
camera.updateProjectionMatrix(); |
|||
|
|||
controls = new THREE.OrbitControls(camera, renderer.domElement); |
|||
// controls.maxDistance = MAX_DISTANCE * 3; |
|||
controls.target = new THREE.Vector3(0, 0, 0); |
|||
controls.rotateSpeed = .2; |
|||
controls.enableDamping = true; |
|||
console.log(controls.enableDamping); |
|||
controls.dampingFactor = .15; |
|||
controls.panSpeed = .15; |
|||
controls.screenSpacePanning = true; |
|||
// to disable zoom |
|||
controls.enableZoom = true; |
|||
// to disable rotation |
|||
controls.enableRotate = true; |
|||
// to disable pan |
|||
controls.enablePan = true; |
|||
scene.add(camera); |
|||
|
|||
//camera.position.set(-150, 10, 1); |
|||
//controls.update(); |
|||
// scene.add(camera); |
|||
|
|||
light = new THREE.PointLight(0x404040); |
|||
light.position.set(50, 0, 0); |
|||
scene.add(light); |
|||
/* light_two = new THREE.PointLight(0xffffff, 1, 4000); |
|||
light_two.position.set(-100, 800, 800); |
|||
lightAmbient = new THREE.AmbientLight(0x404040); |
|||
scene.add(light, light_two, lightAmbient);*/ |
|||
|
|||
// createSpheres(); |
|||
scene.add(new THREE.DirectionalLight(0xffffff)); |
|||
scene.add(new THREE.AmbientLight(0x222222)); |
|||
|
|||
renderer.setPixelRatio(window.devicePixelRatio); |
|||
renderer.clear(); |
|||
|
|||
let viewer = document.querySelector('#viewer'); |
|||
viewer.parentNode.replaceChild(renderer.domElement, viewer); |
|||
|
|||
|
|||
|
|||
|
|||
window.onload = function () { |
|||
|
|||
createDiamond(); |
|||
createSpace(); |
|||
|
|||
|
|||
document.addEventListener('mousemove', onMouseMove, false); |
|||
document.addEventListener('mousedown', onDocumentMouseDown, false); |
|||
window.addEventListener('resize', onWindowResize, false); |
|||
}; |
|||
|
|||
|
|||
} |
|||
|
|||
// -- diamonds -- // |
|||
|
|||
|
|||
function catInobject(obj, category){ //checks if category is in object, if so return corresponding color |
|||
if (obj.hasOwnProperty(category)) { |
|||
var color = obj[category]; |
|||
} else { var color = obj["default"]; |
|||
} |
|||
return color; |
|||
} |
|||
|
|||
function createDiamond() { |
|||
|
|||
diamondsGroup = new THREE.Object3D(); |
|||
|
|||
|
|||
console.log(); |
|||
|
|||
bookTitles.forEach(function (book) { |
|||
var chosencolor = catInobject(category2color, book.category); |
|||
var sphere = new THREE.SphereGeometry(1.3, Math.random() * 50, Math.random() * 50); |
|||
var material = new THREE.MeshPhongMaterial({ |
|||
color: chosencolor,//Math.random() * 0xff00000 - 0xff00000, |
|||
shading: THREE.FlatShading |
|||
}); |
|||
var sphere = new THREE.Mesh(sphere, material); |
|||
sphere.position.x = get_x(book.title) * Math.random() * 100 - 1000; |
|||
sphere.position.z = get_z(book.category) * Math.random() * 100 - 1000; |
|||
sphere.rotation.y =get_y(book.fileformat) * Math.random() * 100 - 1000; |
|||
//sphere.scale.x = sphere.scale.y = sphere.scale.z = Math.random() * 50 + 10; |
|||
sphere.scale.x = sphere.scale.y = sphere.scale.z = get_size(book.title); |
|||
|
|||
sphere.userData = book; |
|||
diamondsGroup.add(sphere); |
|||
|
|||
}) |
|||
diamondsGroup.position.x = 500; |
|||
scene.add(diamondsGroup); |
|||
|
|||
}; |
|||
|
|||
function get_size(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
|
|||
function get_x(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
function get_y(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
function get_z(title){ |
|||
radius = 0; |
|||
for (var i = 0; i < title.length; i++) { |
|||
radius = radius + title.charCodeAt(i) |
|||
} |
|||
console.log(radius) |
|||
return radius/100; |
|||
} |
|||
|
|||
// -- dots on the back -- // |
|||
function createSpace() { |
|||
|
|||
let dots = new THREE.Object3D(); |
|||
|
|||
for (let i = 0; i < 1000; i++) { |
|||
let circleGeometry = new THREE.SphereGeometry(2, Math.random() * 5, Math.random() * 5); |
|||
let color; |
|||
if (Math.round(Math.random()) === 0) |
|||
color = new THREE.Color('#003d5d'); |
|||
else |
|||
//color = new THREE.Color('#f23d5d'); |
|||
color = new THREE.Color('#f23d5d'); |
|||
|
|||
let material = new THREE.MeshPhongMaterial({ |
|||
color: color |
|||
//side: THREE.DoubleSide |
|||
}); |
|||
|
|||
material.flatShading = true; |
|||
|
|||
//var material = new THREE.MeshBasicMaterial({ |
|||
//color : new THREE.Color(Math.floor(Math.random() * 1) === 1), |
|||
//color : new THREE.Color(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 0), |
|||
//shading: THREE.FlatShading, |
|||
//}) |
|||
|
|||
|
|||
var circle = new THREE.Mesh(circleGeometry, material); |
|||
material.side = THREE.DoubleSide; |
|||
|
|||
circle.position.x = Math.random() * -distance * 100; |
|||
circle.position.y = Math.random() * -distance * 8; |
|||
circle.position.z = Math.random() * distance * 5; |
|||
circle.rotation.y = Math.random() * 2 * Math.PI; |
|||
circle.scale.x = circle.scale.y = circle.scale.z = Math.random() * 8 + 5; |
|||
dots.add(circle); |
|||
} |
|||
|
|||
dots.position.x = 14000; |
|||
dots.position.y = 1500; |
|||
dots.position.z = 4000; |
|||
dots.rotation.y = Math.PI * 600; |
|||
dots.rotation.z = Math.PI * 500; |
|||
|
|||
scene.add(dots); |
|||
}; |
|||
/* |
|||
|
|||
|
|||
let circle = new THREE.Mesh(circleGeometry, material); |
|||
|
|||
let direction = getRandomVector().normalize(); |
|||
let minDistance = MAX_DISTANCE * 8; |
|||
let maxDistance = minDistance + 0.5; |
|||
direction.multiplyScalar(Math.random() * (maxDistance - minDistance) + minDistance); |
|||
|
|||
circle.position.add(direction); |
|||
|
|||
dots.add(circle); |
|||
} |
|||
scene.add(dots); |
|||
} |
|||
*/ |
|||
|
|||
|
|||
function getRandomVector(max_distance) { |
|||
if (max_distance === undefined) |
|||
max_distance = 1; |
|||
return new THREE.Vector3(getRandom(max_distance), getRandom(max_distance), getRandom(max_distance)); |
|||
} |
|||
|
|||
function getRandom(max_distance) { |
|||
let random = Math.random() * max_distance; |
|||
random *= Math.floor(Math.random() * 2) === 1 ? 1 : -1; |
|||
return random; |
|||
} |
|||
|
|||
|
|||
|
|||
// -- events -- // |
|||
function onMouseMove(event) { |
|||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; |
|||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; |
|||
mouseX = event.clientX - window.innerWidth / 2 ; |
|||
mouseY = event.clientY - window.innerHeight / 2 ; |
|||
//camera.position.x += (mouseX - camera.position.x) * 0.01; |
|||
//camera.position.y += (mouseY - camera.position.y) * 0.01; |
|||
// camera.lookAt(scene.position); |
|||
}; |
|||
|
|||
function onDocumentMouseDown(event) { |
|||
|
|||
event.preventDefault(); |
|||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; |
|||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; |
|||
|
|||
raycaster.setFromCamera(mouse, camera); |
|||
|
|||
var intersects = raycaster.intersectObjects(diamondsGroup.children); |
|||
if (intersects.length > 0) { |
|||
var book = intersects[0].object.userData; |
|||
console.log("click", book); |
|||
//alert("book" + book.title); |
|||
|
|||
//swal(book.title + book.authors); |
|||
|
|||
|
|||
swal(book.title + " \n " + " " + book.authors.map(function(x){return x.author_name}).join(", ") + " \n" + book.category, { |
|||
buttons: ["return", "open" ], |
|||
}).then (function(button){ |
|||
console.log("button", button) |
|||
if (button) { |
|||
window.location = "/books/"+book.id |
|||
} |
|||
|
|||
}); |
|||
|
|||
|
|||
|
|||
} |
|||
|
|||
}; |
|||
|
|||
function onDocumentMouseWheel( event ) { |
|||
|
|||
fov -= event.wheelDeltaY * 0.05; |
|||
camera.projectionMatrix = THREE.Matrix4.makePerspective( fov, window.innerWidth / window.innerHeight, 1, 1100 ); |
|||
|
|||
} |
|||
|
|||
|
|||
function onWindowResize() { |
|||
camera.aspect = window.innerWidth / window.innerHeight; |
|||
renderer.setSize(window.innerWidth, window.innerHeight); |
|||
camera.updateProjectionMatrix(); |
|||
controls.update(); |
|||
}; |
|||
|
|||
// ---- // |
|||
function animate() { |
|||
requestAnimationFrame(animate); |
|||
controls.update(); |
|||
render(); |
|||
}; |
|||
|
|||
// -- render all -- // |
|||
function render() { |
|||
|
|||
var timer = 0.00001 * Date.now(); |
|||
|
|||
for (var i = 0, l = diamondsGroup.children.length; i < l; i++) { |
|||
var object = diamondsGroup.children[i]; |
|||
object.position.y = 500 * Math.cos(timer + i); |
|||
object.rotation.y += Math.PI / 500; |
|||
} |
|||
|
|||
// update the picking ray with the camera and mouse position |
|||
raycaster.setFromCamera(mouse, camera); |
|||
|
|||
// calculate objects intersecting the picking ray |
|||
var intersects = raycaster.intersectObjects(diamondsGroup.children); |
|||
|
|||
if (intersects.length > 0) { |
|||
if (INTERSECTED != intersects[0].object) { |
|||
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex); |
|||
INTERSECTED = intersects[0].object; |
|||
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex(); |
|||
INTERSECTED.material.emissive.setHex(Math.random() * 0xff00000 - 0xff00000); |
|||
} |
|||
} else { |
|||
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex); |
|||
INTERSECTED = null; |
|||
} |
|||
|
|||
renderer.render(scene, camera); |
|||
}; |
|||
|
|||
// -- run functions -- // |
|||
//init(); |
|||
//animate(); |
|||
|
|||
</script> |
|||
|
|||
</body> |
|||
</html> |