-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
157 lines (137 loc) · 5.4 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
var camera, scene, renderer;
var speechRecognizer, filterDate = '2017-01-01'
const fontLoader = new THREE.FontLoader();
function generateChart(data, dataVars, colorVar, minVals, maxVals, header, zOffset) {
var geometry = new THREE.BufferGeometry();
var positions = [];
var colors = [];
// offsets help make the cube visible when entering the world
const yOffset = 1.6
// const n = 1, n2 = n / 2; // particles spread in the cube
data.forEach(point => {
// scale points down, then set them spatially
// normalization function x-min(x))/(max(x)-min(x)
const x = ((+point[dataVars[0]]-minVals[0])/(maxVals[0]-minVals[0])) - 0.5
const y = ((+point[dataVars[1]]-minVals[1])/(maxVals[1]-minVals[1])) - 0.5
const z = ((+point[dataVars[2]]-minVals[2])/(maxVals[2]-minVals[2])) - 0.5
positions.push( x, y+yOffset, z+zOffset );
const color = new THREE.Color(point[colorVar])
colors.push(color.r, color.g, color.b)
})
geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
geometry.computeBoundingSphere();
//
const sprite = new THREE.TextureLoader().load( 'assets/disc.png' );
const material = new THREE.PointsMaterial({
size: 0.4,
vertexColors: THREE.VertexColors,
map: sprite,
transparent: true,
alphaTest: 0.5
});
const points = new THREE.Points( geometry, material );
scene.add( points );
var geometryCube = cube( 1, yOffset, zOffset );
var lineSegments = new THREE.LineSegments( geometryCube, new THREE.LineDashedMaterial({
color: 0xffaa00, dashSize: .06, gapSize: .02
}) );
lineSegments.computeLineDistances();
scene.add( lineSegments );
fontLoader.load( 'assets/helvetiker_regular.typeface.json', function ( font ) {
// x-axis label, font size is 0.1
const xLabelNear = addText(font, header[dataVars[0]], 0.1)
// offset by chart size (1) divided by 2, and then add the font size, yielding 0.6
xLabelNear.position.set(0, yOffset-0.6, zOffset+0.5)
scene.add(xLabelNear)
const xLabelFar = addText(font, '-' + header[dataVars[0]], 0.1)
xLabelFar.position.set(0, yOffset-0.6, zOffset-0.5)
// rotate the far axis label
xLabelFar.rotation.set(0, Math.PI, 0)
scene.add(xLabelFar)
// y-axis label
const yLabelNear = addText(font, header[dataVars[1]], 0.1)
yLabelNear.position.set(-0.5, yOffset, zOffset+0.5)
yLabelNear.rotation.set(0, Math.PI/4, Math.PI/2)
scene.add(yLabelNear)
const yLabelFar = addText(font, header[dataVars[1]], 0.1)
yLabelFar.position.set(0.5, yOffset, zOffset-0.5)
yLabelFar.rotation.set(Math.PI, -Math.PI/4, -Math.PI/2)
scene.add(yLabelFar)
// z-axis label
const zLabelLeft = addText(font, header[dataVars[2]], 0.1)
zLabelLeft.position.set(-0.5, yOffset-0.6, zOffset)
zLabelLeft.rotation.set(0, -Math.PI/2, 0)
scene.add(zLabelLeft)
const zLabelRight = addText(font, '-' + header[dataVars[2]], 0.1)
zLabelRight.position.set(0.5, yOffset-0.6, zOffset)
zLabelRight.rotation.set(0, Math.PI/2, 0)
scene.add(zLabelRight)
} );
}
async function init() {
const canvas = document.createElement('canvasvr');
const csv = await request({url: "data/creditDensity.csv"})
let data = csv.split(/\r?\n/)
.map(row => row.split(','))
const header = data.shift()
// remove last element if csv has trailing line feed
if (data[data.length-1].length < 4) data.pop()
const dataVars = [2, 3, 1]
const filterVar = 0
const colorVar = 4
// find min/max of values for normalization
var values, minVals = [], maxVals = [];
dataVars.forEach(i => {
values = data.map(d => +d[i])
minVals.push(Math.min.apply(null, values))
maxVals.push(Math.max.apply(null, values))
})
delete values
// filter to jan 2017, just for now
const jan2017 = data.filter(d => d[filterVar] === '2017-01-01')
const jan2018 = data.filter(d => d[filterVar] === '2018-01-01')
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.2, 1000 );
camera.position.set(0.5, 0.5, 0.5);
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x050505 );
scene.fog = new THREE.Fog( 0x050505, 0.2, 1000 );
generateChart(jan2017, dataVars, colorVar, minVals, maxVals, header, -1.5)
generateChart(jan2018, dataVars, colorVar, minVals, maxVals, header, -3.5)
const yoy = [
...jan2017.map(d => {
d[colorVar] = d[5] //greens
return d
}),
...jan2018.map(d => {
d[colorVar] = d[6] //reds
return d
})
]
generateChart(yoy, dataVars, colorVar, minVals, maxVals, header, -5.5)
//
renderer = new THREE.WebGLRenderer({ canvas });
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop(render);
window.addEventListener('resize', onWindowResize, false);
// Enter immersive mode if available
navigator.getVRDisplays().then(
function (value) {
if (value.length > 0) {
renderer.vr.enabled = true;
renderer.vr.setDevice(value[0]);
value[0].requestPresent([{ source: renderer.domElement }]);
}
});
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function render() {
renderer.render(scene, camera);
}
init();
initSpeech();