/** * Copyright 2016 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const THREE = require('three') var geometry = new THREE.PlaneGeometry( 1, 1, 1 ) var material = new THREE.MeshBasicMaterial( {color: 0x1FB7EC, side: THREE.DoubleSide} ) var aiMaterial = new THREE.MeshBasicMaterial( {color: 0xFFB729, side: THREE.DoubleSide} ) window.zero = new THREE.Vector3(0, 0, 0) function scale(value, inMin, inMax, min, max){ return ((value - inMin) / (inMax - inMin)) * (max - min) + min } class Roll { constructor(container){ this._element = document.createElement('div') this._element.id = 'roll' container.appendChild(this._element) this._camera = new THREE.OrthographicCamera(0, 1, 1, 0, 1, 1000 ) this._camera.position.z = 1 this._camera.lookAt(new THREE.Vector3(0, 0, 0)) this._scene = new THREE.Scene() this._renderer = new THREE.WebGLRenderer({alpha: true}) this._renderer.setClearColor(0x000000, 0) this._renderer.setPixelRatio( window.devicePixelRatio ) this._renderer.sortObjects = false this._element.appendChild(this._renderer.domElement) this._currentNotes = {} window.camera = this._camera //set the size initially this._resize() //start the loop this._boundLoop = this._loop.bind(this) this._boundLoop() window.addEventListener('resize', this._resize.bind(this)) } keyDown(midi, box, ai=false){ const selector = ai ? `ai${midi}` : midi if (midi && box && !this._currentNotes.hasOwnProperty(selector)){ //translate the box coords to this space const initialScaling = 10000 const plane = new THREE.Mesh( geometry, ai ? aiMaterial : material ) const margin = 4 const width = box.width - margin * 2 plane.scale.set(width, initialScaling, 1) plane.position.z = 0 plane.position.x = box.left + margin + width / 2 plane.position.y = this._element.clientHeight + this._camera.position.y + initialScaling / 2 this._scene.add(plane) this._currentNotes[selector] = { plane : plane, position: this._camera.position.y } } } keyUp(midi, ai=false){ const selector = ai ? `ai${midi}` : midi if (this._currentNotes[selector]){ const plane = this._currentNotes[selector].plane const position = this._currentNotes[selector].position delete this._currentNotes[selector] // get the distance covered plane.scale.y = Math.max(this._camera.position.y - position, 5) plane.position.y = this._element.clientHeight + position + plane.scale.y / 2 } } _resize(){ var frustumSize = 1000 var aspect = this._element.clientWidth / this._element.clientHeight //make it match the screen pixesl this._camera.left = 0 this._camera.bottom = this._element.clientHeight this._camera.right = this._element.clientWidth this._camera.top = 0 //update things this._camera.updateProjectionMatrix() this._renderer.setSize( this._element.clientWidth, this._element.clientHeight ) } _loop(){ requestAnimationFrame(this._boundLoop) this._renderer.render( this._scene, this._camera ) this._camera.position.y += 2 } } export {Roll}