Renderer
Optimized small library for convenient work with coordinates and render loop. Renderer is written on typescipt. You can use with frontend frameworks or native js. Aimed on creating websites animations
- excellent support projects on native JS or TS
- excellent support React.js
- partable support Vue.js. If you get errors, and use typescript, try import all components from "textura-renderer/src".
- no support for Angular.js. But you are able to copy "textura-renderer" folder from "node_modules/" and put the file directly in your project. If u still get errors, try import all methods from "src" folder.
Current Updates (24.02.2023, v1.0.4)
- "label" & "delay" parameteries now is not required in "setToRender" method.
- Fix "getInterpolated" method. Now it works stable.
- Fix error in "getInterpolated" method example.
Next Update (v1.0.5)
- Add new methods: getMouseVelocity, getMouseVelocityX, getMouseVelocityY.
- Add new methods: getScrollVelocityX, getScrollVelocityY.
Future Updates (v1.0.x)
- Add hooks for React and Vue.
- ...
Quick start
Installation
npm
For module bundlers such as Webpack or Browserify.
npm i textura-renderer
import {
startRender,
stopRender,
...
} from 'textura-renderer'
CDN
Recommended for learning purposes, you can use the latest version:
<script src="https://cdn.jsdelivr.net/npm/textura-renderer/dist/index.js"></script>
All methods are available on the object "Renderer":
<script type="text/javascript">
Renderer.startRender()
Renderer.stopRender()
...
</script>
Docs
- Installation
- All methods
- Core renderer methods
- Mouse methods
- Coordinates methods
- Interpolation
- Tweening
All methods
import {
startRender,
stopRender,
setToRender,
removeFromRender,
getRendering,
subscribeMouse,
unsubscribeMouse,
getMouseCoords,
getMouseCoordsFromElement,
getElementDocumentCoords,
getElementWindowCoords,
getScrollCoordsFromElement,
isElementHovered,
isElementFullyVisibleX,
isElementFullyVisibleY,
isElementFullyVisible,
isElementPartableVisibleX,
isElementPartableVisibleY,
isElementPartableVisible,
getInterpolated,
Tween,
Ease,
lerp
} from 'textura-renderer'
Methods | Props | Return Type | Description |
---|---|---|---|
startRender | -- | void | start global render loop in app |
stopRender | -- | void | stop global render loop in app |
setToRender | { label?: string / number; handler: (time: number) => {}, delay?: number } | void | add handler to global render loop |
removeFromRender | label?: string / number | void | remove handler from global render loop |
getRendering | -- | [] | return array of handlers in rendering |
subscribeMouse | -- | void | start saving mouse position |
unsubscribeMouse | -- | void | stop saving mouse position |
getMouseCoords | domElement: HTMLElement | { document: { x: number / null, y: number / null }, window: { x: number / null, y: number / null } } | return mouse coords relatively document and window |
getMouseCoordsFromElement | domElement: HTMLElement | { top: { left: { x, y }, right: { x, y } }, center: { center: { x, y } }, bottom: { left: { x, y }, right: { x, y } } } | return mouse coords relatively dom element |
isElementHovered | domElement: HTMLElement, additionalRadius: number | boolean | return is element hovered |
getElementDocumentCoords | domElement: HTMLElement | {} | return element coords relativity document |
getElementWindowCoords | domElement: HTMLElement | {} | return element coords relativity window (can be negative) |
getScrollCoordsFromElement | domElement: HTMLElement | {} | return scroll coords relativity dom element (can be negative) |
isElementFullyVisibleX | domElement: HTMLElement | boolean | return is element fully visible on x axe |
isElementFullyVisibleY | domElement: HTMLElement | boolean | return is element fully visible on y axe |
isElementFullyVisible | domElement: HTMLElement | boolean | return is element fully visible (true if fully visible on x and y axes) |
isElementPartableVisibleX | domElement: HTMLElement | boolean | return is element partable visible on x axe |
isElementPartableVisibleY | domElement: HTMLElement | boolean | return is element partable visible on y axe |
isElementPartableVisible | domElement: HTMLElement | boolean | return is element partable visible (true if partable visible on x or y axes) |
getInterpolated | config: { timeline: timelineType, interface: InterfaceType }, time: number | { [key] : { [innerKey]: number }, ... } | return object of keys which contains keys with number values in current time. this version uses only piecewise function for interpolation |
Tween.to | {}: TweenPropsType | void | -- |
Ease.Line | time: number | number | Bezier Linear |
Ease.In | time: number | number | Bezier In |
Ease.InCubic | t:ime number | number | Bezier In (pow 3) |
Ease.InQuartic | t:ime number | number | Bezier In (pow 4) |
Ease.InQuintic | time: number | number | Bezier In (pow 5) |
Ease.InCustom | time: number, strength?: number | number | Bezier In |
Ease.Out | time: number | number | Bezier Out |
Ease.OutCubic | time: number | number | Bezier Out (pow 3) |
Ease.OutQuartic | time: number | number | Bezier Out (pow 4) |
Ease.OutQuintic | time: number | number | Bezier Out (pow 5) |
Ease.OutCustom | time: number, strength?: number | number | Bezier Out |
Ease.InOut | time: number | number | Bezier InOut |
Ease.InOutCubic | time: number | number | Bezier InOut (pow 3) |
Ease.InOutQuartic | time: number | number | Bezier InOut (pow 4) |
Ease.InOutQuintic | time: number | number | Bezier InOut (pow 5) |
Ease.InOutCustom | time: number, strengthIn?: number, strengthOut?: number | number | Bezier InOut |
lerp | start: number, end: number, t?: number | number | -- |
Core renderer methods
Add "startRender()" at the top level of the app to use renderer. Then to add code to render loop use "setToRender()" where you want
Example
//App.tsx
useEffect(() => {
startRender()
return () => stopRender()
}, [])
// component.tsx
useEffect(() => {
const label = 'myCustomAnimation'
setToRender({
label,
handler: ( time: number ) => { /* your code */ },
delay: 10 //ms
})
return () => removeFromRender( label )
}, [])
Methods | Props | Return Type | Description |
---|---|---|---|
startRender | -- | void | start global render loop in app |
stopRender | -- | void | stop global render loop in app |
setToRender | { label?: string / number; handler: (time: number) => {}, delay?: number } | void | add handler to global render loop |
removeFromRender | label?: string / number | void | remove handler from global render loop |
getRendering | -- | [] | return array of handlers in rendering |
Mouse methods
Add "subscribeMouse()" at the top level of the app to use mouse methods.
Example using with renderer
//App.tsx
useEffect(() => {
subscribeMouse()
startRender()
return () => {
unsubscribeMouse()
stopRender()
}
}, [])
// component.tsx
function myAnimation() {
if ( !myRef.current ) { return }
const isHovered: boolean = isElementHovered(myRef.current)
if ( isHovered ) {
console.log( 'Hovered!' )
}
}
useEffect(() => {
const label = 'myCustomAnimation'
setToRender({
label,
handler: ( time: number ) => myAnimation(),
delay: 10 //ms
})
return () => removeFromRender( label )
}, [])
Methods | Props | Return Type | Description |
---|---|---|---|
subscribeMouse | -- | void | start saving mouse position |
unsubscribeMouse | -- | void | stop saving mouse position |
getMouseCoords | domElement: HTMLElement | { document: { x: number / null, y: number / null }, window: { x: number / null, y: number / null } } | return mouse coords relatively document and window |
getMouseCoordsFromElement | domElement: HTMLElement | { top: { left: { x, y }, right: { x, y } }, center: { center: { x, y } }, bottom: { left: { x, y }, right: { x, y } } } | return mouse coords relatively dom element |
isElementHovered | domElement: HTMLElement, additionalRadius: number | boolean | return is element hovered |
Coordinates methods
Convinient functions for dom elements coords. Use this methods anywhere.
Example
const isVisible = isElementPartableVisibleY(myRef.current)
Methods | Props | Return Type | Description |
---|---|---|---|
getElementDocumentCoords | domElement: HTMLElement | {} | return element coords relativity document |
getElementWindowCoords | domElement: HTMLElement | {} | return element coords relativity window (can be negative) |
getScrollCoordsFromElement | domElement: HTMLElement | {} | return scroll coords relativity dom element (can be negative) |
isElementFullyVisibleX | domElement: HTMLElement | boolean | return is element fully visible on x axe |
isElementFullyVisibleY | domElement: HTMLElement | boolean | return is element fully visible on y axe |
isElementFullyVisible | domElement: HTMLElement | boolean | return is element fully visible (true if fully visible on x and y axes) |
isElementPartableVisibleX | domElement: HTMLElement | boolean | return is element partable visible on x axe |
isElementPartableVisibleY | domElement: HTMLElement | boolean | return is element partable visible on y axe |
isElementPartableVisible | domElement: HTMLElement | boolean | return is element partable visible (true if partable visible on x or y axes) |
Interpolation
Use "getInterpolated(config, time)" to create frameByFrame animation. For example on scroll. Or animate any looped object in render loop. U able to scroll video, transform any html content and so on
Example
const Timeline = ( scrollContainer ) => {
const dist = scrollContainer.getBoundingClientRect().height
const START = 0
const MIDDLE = dist / 2
const END = dist
const timelineInterface = {
header: {
opacity: 0,
translateY: 0,
$TIME: [ START, MIDDLE, END ]
},
svg: {
rotate: 0,
$TIME: [ MIDDLE, END ]
}
}
const timeline = [
{
$TIME: START,
header: {
opacity: 0,
translateY: 0
}
},
{
$TIME: MIDDLE,
header: {
opacity: 1,
translateY: 100
},
svg: {
rotate: 30
}
},
{
$TIME: END,
header: {
opacity: .5,
translateY: -50
},
svg: {
rotate: -180
}
}
]
return { timeline, interface: timelineInterface }
}
useEffect(() => {
const label = 'myScrollAnimation'
setToRender({
label,
handler: ( time ) => {
if (!scrollContainer.current || !header.current || !svg.current) { return }
const config = Timeline( scrollContainer.current )
const t = getInterpolated( config, window.scrollY )
header.current.style.cssText = `
opacity: ${t.header.opacity};
transform: translateY(t.header.translateY);
`
svg.current.style.cssText = `
transform: rotate(t.svg.rotate);
`
},
})
return () => removeFromRender( label )
}, [])
Methods | Props | Return Type | Description |
---|---|---|---|
getInterpolated | config: { timeline: timelineType, interface: InterfaceType }, time: number | { [key] : { [innerKey]: number }, ... } | return object of keys which contains keys with number values in current time. this version uses only piecwise function for interpolation |
Tweening
Light tween and easing functions for interpolating between two values.
TweenPropsType = {
from: number / {},
to: number / {},
{
duration?: number,
renderDelay?: number,
delay?: number,
onChange?: Function,
onComplete?: Functions
ease?: Function //Ease.InOut by default
}
}
Methods | Props | Return Type | Description |
---|---|---|---|
Tween.to | {}: TweenPropsType | void | -- |
Ease.Line | time: number | number | Bezier Linear |
Ease.In | time: number | number | Bezier In |
Ease.InCubic | t:ime number | number | Bezier In (pow 3) |
Ease.InQuartic | t:ime number | number | Bezier In (pow 4) |
Ease.InQuintic | time: number | number | Bezier In (pow 5) |
Ease.InCustom | time: number, strength?: number | number | Bezier In |
Ease.Out | time: number | number | Bezier Out |
Ease.OutCubic | time: number | number | Bezier Out (pow 3) |
Ease.OutQuartic | time: number | number | Bezier Out (pow 4) |
Ease.OutQuintic | time: number | number | Bezier Out (pow 5) |
Ease.OutCustom | time: number, strength?: number | number | Bezier Out |
Ease.InOut | time: number | number | Bezier InOut |
Ease.InOutCubic | time: number | number | Bezier InOut (pow 3) |
Ease.InOutQuartic | time: number | number | Bezier InOut (pow 4) |
Ease.InOutQuintic | time: number | number | Bezier InOut (pow 5) |
Ease.InOutCustom | time: number, strengthIn?: number, strengthOut?: number | number | Bezier InOut |
Methods | Props | Return Type | Description |
---|---|---|---|
lerp | start: number, end: number, t?: number | number | -- |
@author: denkravchu@gmail.com