shimmer-js
v2.3.4
Published
Enhanced glitter for webGL purposes
Readme
Shimmer
Shimmer extends Glitter
USE CASE
Shimmer is based on components. To be fully functionnal, it needs to have severals events setup.
import { engine, LoaderManager, GLTFLoader } from 'shimmer'
const assets = [
{
name: "texture",
url: "/textures/uv.jpg",
type: "texture"
},
{
name: "object",
url: "/models/object.glb",
type: "object"
}
]
LoaderManager.config = assets
GLTFLoader.draco = { path: '/draco/' }
GLTFLoader.ktx = { path: '/basis/', renderer: webGL.renderer.renderer }
// when client's window is accessible
engine.ready = true
// the canvas or canvas's wrapper element
engine.el = containerWebGL
// set engine's camera with the main experience cameras
engine.camera = webGL.camera
window.addEventListener('pointerdown', engine.pointerdown)
window.addEventListener('pointermove', engine.pointermove)
const obj = LoaderManager.load('test', true)
scene.add(obj)
obj.on('over', () => {
console.log('hover')
})Component's methods and a few utils, are based on internal mechanism defined thanks to those lines.
NB: utils are originally made to be used as standalones. The only utils that are connected to shimmer's mechanisms are for performance benefits.
FILES STRUCTURE
- cameras Defines THREE herited cameras
- component Defines shimmer Component and setup internal structure that supports Components Lifecycles and methods
- utils Defines shimmer utils. Utils are standalone helper functions.
- config Singleton of data used internally to store applications information
- emitter Singleton implementation of emitter used internally to deal with events (for lifecycle, hooks, etc etc)
API
Engine
import { engine } from 'shimmer'
// when window is accessible
engine.ready = trueA singleton that runs the application. Functions needs to be called to allow every features.
set property ready when object client's window is accessible.
Methods
pointerdown (event: Event)- event: user event Required. Needs to be called on pointerdown events
pointermove (event: Event)- event: user event Required. Needs to be called on pointermove events
set el (el: DOMElement)- el: canvas's container Required. Needs to be set before using shimmer
set camera (camera: THREE.Camera)- camera: Camera used on three application Required. Needs to be set before using shimmer
Component
import { Component } from 'shimmer'
const component = new Component({name: 'test'})Abstarct class that heriting from THREE.object3D. As a consequence, those gets all object3D attributes.
Lifecycle
onResize ()- when window is resized OR body height or width changes (cause of content added for instance)
onScroll ()- when scroll on window
onUpdate ({ delta, elpased })- delta: time elapsed since the last frame
- elpased: time elapsed since the beginning of the experience
Methods
getByName (name: String, isComponent: Boolean)- name: name of the object. Canc match a pattern with * e.g.: 'test*'
- isComponent (optionnal): if result should be transformed into a component. Default is true. Searches through an object and its children
on (event: String, callback: Function, ctx)- event: name of the event. Allowed are
hover,over,enter,outandclick. - callback: callback function to be called
- ctx: an object to listen event to, default is
thisAdd event Listener
- event: name of the event. Allowed are
off (event: String, callback: Function)- event: name of the event. Allowed are
hover,over,enter,outandclick. - callback: callback function to be called Remove event Listener
- event: name of the event. Allowed are
destroy ()To be called before removing the elements or when element is not used anymioreget boundingBox ()Return a dynamicaly calculated Box3 matching the current boundingBox of the objectget size ()Return a dynamicaly calculated Vector3 of the object's sizeget center ()Return a dynamicaly calculated Vector3 of the object's center
Utils
Clock
import { clock } from 'shimmer'
clock.on({delta, elapsed} => {
// code
})A timer function that goes thourgh all the application. Used internally by all components.
Chronometer
import { Chronometer } from 'shimmer'
const chrono = new Chronometer()
chrono.on(({elapsed}) => {
// console.log('plop', elapsed)
})
setTimeout(() => {
chrono.start()
}, 3000)A timer class depending on Clock
Used internally by all components.
Countdown
import { Countdown } from 'shimmer'
const countdown = new Countdown(3000)
countdown.start(() => {
// code
})A Countdown class depending on Clock
OrbitAuto
import { OrbitAuto } from 'shimmer'
const orbit = new OrbitAuto(camera, target, maxPolar, maxAzimuth, accelerometer)
orbit.active = true
orbit.update($device.pointer)camera: THREE.Camera Camera currently used in webGLtarget: Vector3 Point that the camera looks atmaxPolar: Float. Max polar value (horizontal)maxAzimuth: Float. Max azimuth value (vertical)accelerometer: Boolean. If set to true and accelerometer allowed, will automatically use device's accelerometer
An Orbit camera class that can uses accelerometer
authorizeAccelerometer
import { authorizeAccelerometer } from 'shimmer'
authorizeAccelerometer()Request device's permission to use accelerometer
Pointer
import { pointer } from 'shimmer'
const intersection = pointer.getIntersectPosition(myMesh)Get raycast intersection Vector3 between mouse position and mesh.
Is used internally by components for methods on.
Pointer is a singleton wich is constantly updated by Engine.
FitTo
import { FitTo } from 'shimmer'
const { position, look } = FitTo.fit(box, padding, { vector, angles }, fit)box: THREE.Box3. targets boxpadding: Float or Object. { top, right, bottom, left } defining padding relatively to objects' box facevector: THREE.Vector3. Director vector used to define the angle of view. Used if angles is not definedangles: Object {polar, azimuth}. defining angle of view of the camera. Ifvectororanglesare not defined, the default vector director will be defined by delta between the camera and the center of the boxfit: String setting the object fit. Can becoverorcontain. Default iscover.
Return a position and a target (lookAt) for the camera to frame a box. Allows a specific padding for each side if needed.
toScreenPosition
import { toScreenPosition } from 'shimmer'
const pos = toScreenPosition(position)position: THREE.Vector3 Position searched
Return the position of a 3D object on the 2D canvas.
positionPadding
import { positionPadding } from 'shimmer'
const {look, position} = positionPadding(target, director, dist, padding)target: THREE.Vector3. Point to look atdirector: THREE.Vector3. Vector director definied angle of viewdist: Float. Distance to have between the position and the point to look atpadding: Float. Value between -1 and 1 where -1 il full offset to left and 1 is full offset to rightlook: THREE.Vector3. Look to set at the camera (lookAt)position: THREE.Vector3. Position of the camera
Calcule the look and position of the camera with a specific padding left or right. Is used to position the camera accordingly to the UI, with the UI on a side of the screen and the target on the other side.
visibleViewport
import { visibleViewport } from 'shimmer'
const {height, width, box} = visibleViewport(target, position)target: THREE.Vector3 Position of where we want to get visible part of 3d spaceposition: Position of the camera. If not set, default camera's position is usedheight: Float height of the space seenwidth: Float width of the space seenbox: THREE.Box3 box of the space seen
Return the visible part of the 3d seen at a specific point
webglAvailable
import { webglAvailable } from 'shimmer'
const res = visibleViewport(webglAvailable)res: Boolean result value
Get if webGL is available on device
ToCanvas
import { ToCanvas } from 'shimmer'
const toCanvas = new ToCanvas({ image, video, width, height, muted = false, loop = true, fit })
toCanvas.promise.then(() => {
code
// if video
toCanvas.start()
})
toCanvas.canvasimage: String. URL of the source if imagevideo: String. URL of the source if video. If image is also defined, it will be used as poster before video is able to play.width: Int. Width of the generated canvas. If not defined, use source as valueheight: Int. Height of the generated canvas. If not defined, use source as valuemuted: Boolean. If source is video, set it to muted to allow autoplayloop: Boolean. If source is video, set it to loopfit: String. Allowed values are 'cover' or 'contained'. Default value is 'cover'
Generate a canvas with an image or a video sized as cover
Loader
import { Loader } from 'shimmer'
Loader.load(objectUrl)objectUrl: String of object's URL
Return a promise. Uses GLTFLoader and FBXLoader. Load FBX / GLTF / GLB. For Draco or KTX compression, GLTFLoader needs to have decoder set. See GLTFLoader.
FBXLoader
import { FBXLoader } from 'shimmer'
FBXLoader.load(objectUrl)objectUrl: String of object's URL
Return a promise. Load FBX.
GLTFLoader
import { GLTFLoader } from 'shimmer'
GLTFLoader.load(objectUrl)
GLTFLoader.draco = { path: '/draco/' }
GLTFLoader.ktx = { path: '/basis/', renderer: webGLRenderer }objectUrl: String of object's URLwebGLRenderer: The current WebGLRenderer
Return a promise. Load GLTF. For draco compression, draco property needs to be set width the decoder. For a KTX compression, ktx property needs to be set width the transcoder path and the webGL renderer.
OrbitControls
import { OrbitControls } from 'shimmer'
new OrbitControls(camera, element)camera: THREE.Camera. Camera currently used in webGLelement: DOM Element. Element to be used for mouse interactions
A complete copy of the THREE orbit camera with the only specificity to not prevent events propagation.
LoaderManager
import { LoaderManager } from 'shimmer'
const config = [
{
"name": "test",
"url": "/test.glb",
"type": "object",
"children": [
{
"name": "children",
"url": "/test.glb",
"type": "object"
}
]
},
{
"name": "test",
"url": "/test.jpg",
"type": "equirectangular"
}
]
LoaderManager.config = config
Each object in the config define an objet (or group) to load with severak properties
name: the key used to load the objecturl: Url of the file to load (for an hdr, of the folder to load)children: Subelements to load in the same timetype: the type of the element to load, can be of four types:hdr,equirectangular,textureorobject
LoaderManager.load('test', false, setupItem)load('test', asComponent, setupItem): Boolean result valuename: String. If empty, load all assets. If not empty, load mathing asset and its children.asComponent: Boolean. Available for typeobjectonly. If true, automatically build a component as a return. Else, return the result of the loading.setupItem: Callback function that receive as an argument each object of the 3d file loader. Available for typeobjectonly.
Cameras
Perspective Camera
import { PerspectiveCamera } from 'shimmer'
const camera = new PerspectiveCamera(50, 1, 1, 1000)Simple Threejs Perspective Camera that with a lookproperty as a Vector3.
Each time camera.look changes, camera.lookAt is called.
look: Vector3 indicating where the camera looks- Each time
camera.lookchanges,camera.lookAtis called.
- Each time
forceUpdateLook: Boolean set to false at each frame- if true, will force apply
camera.look
- if true, will force apply
computeLook(webGL.Scene): Function that recalculate the look directionnal vector of the camera- raycast from camera to an invisible sphere and apply the intersection to the look
Orthographic Camera
import { OrthographicCamera } from 'shimmer'
const camera = new OrthographicCamera()Same new properties as Perspective Camera.
rollup-starter-lib
This repo contains a bare-bones example of how to create a library using Rollup, including importing a module from node_modules and converting it from CommonJS.
We're creating a library called how-long-till-lunch, which usefully tells us how long we have to wait until lunch, using the ms package:
console.log('it will be lunchtime in ' + howLongTillLunch());Getting started
https://github.com/rollup/rollup-starter-lib
Clone this repository and install its dependencies:
git clone https://github.com/rollup/rollup-starter-lib
cd rollup-starter-lib
npm installnpm run build builds the library to dist, generating three files:
dist/how-long-till-lunch.cjs.jsA CommonJS bundle, suitable for use in Node.js, thatrequires the external dependency. This corresponds to the"main"field in package.jsondist/how-long-till-lunch.esm.jsan ES module bundle, suitable for use in other people's libraries and applications, thatimports the external dependency. This corresponds to the"module"field in package.jsondist/how-long-till-lunch.umd.jsa UMD build, suitable for use in any environment (including the browser, as a<script>tag), that includes the external dependency. This corresponds to the"browser"field in package.json
npm run dev builds the library, then keeps rebuilding it whenever the source files change using rollup-watch.
npm test builds the library, then tests it.
Variations
- babel — illustrates writing the source code in ES2015 and transpiling it for older environments with Babel
- buble — similar, but using Bublé which is a faster alternative with less configuration
- TypeScript — uses TypeScript for type-safe code and transpiling
License
MIT.
