-
+
}>
+
+
+
+
= ({
scrollY,
0,
calcScrollThreshold() * RESIZE_SPEED_FACTOR,
- 0,
+ 0.2,
1,
),
}}
@@ -295,3 +130,22 @@ export const HeroModel: React.FC = ({
)
}
+
+function Model({ url, ...props }) {
+ // useGLTF suspends the component, it literally stops processing
+ const { scene } = useGLTF(url) as any
+ // By the time we're here the model is gueranteed to be available
+ return
+}
+
+function Rotate(props) {
+ const ref = useRef()
+ useFrame((state) => {
+ if (ref.current) {
+ // @ts-ignore
+ return (ref.current.rotation.y = state.clock.elapsedTime)
+ }
+ return ref
+ })
+ return
+}
diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.utils.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.utils.ts
new file mode 100644
index 0000000..003ca50
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.utils.ts
@@ -0,0 +1,26 @@
+import { calcScrollThreshold, mapFloat } from '../../../lib/ui.utils'
+import {
+ INITIAL_ZOOM,
+ MAX_ROTATE_SPEED,
+ MIN_ROTATE_SPEED,
+ MIN_ZOOM,
+ RESIZE_SPEED_FACTOR,
+} from './HeroModel.configs'
+
+export const calcRotateSpeed = (scrollY = 0, speed) => {
+ const sFactor = mapFloat(scrollY, 0, window.innerHeight, 1, 10)
+ return Math.max(Math.min(speed * sFactor, MAX_ROTATE_SPEED), MIN_ROTATE_SPEED)
+}
+
+export const calcZoom = (scrollY = 0, initZ = INITIAL_ZOOM) => {
+ return Math.max(
+ mapFloat(
+ scrollY,
+ 0,
+ calcScrollThreshold() * RESIZE_SPEED_FACTOR,
+ initZ,
+ MIN_ZOOM,
+ ),
+ MIN_ZOOM,
+ )
+}
diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/_HeroModel.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/_HeroModel.tsx
new file mode 100644
index 0000000..ab7b907
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/_HeroModel.tsx
@@ -0,0 +1,336 @@
+/*
+import {OrbitControls, useGLTF} from '@react-three/drei'
+import {Canvas, useFrame, useThree} from '@react-three/fiber'
+import clsx from 'clsx'
+import React, {
+ PropsWithChildren,
+ Suspense,
+ useEffect,
+ useLayoutEffect,
+ useMemo,
+ useRef,
+ useState,
+} from 'react'
+import * as THREE from 'three'
+import {AsciiEffect} from 'three-stdlib'
+import './HeroModel.scss'
+import {
+ calcScrollThreshold,
+ isTouchDevice,
+ mapFloat,
+ random,
+} from '../../../lib/ui.utils'
+import {useScrollY} from '../../../lib/useScrollY'
+
+let ROTATE_SPEED = 0.1
+const MIN_ROTATE_SPEED = 0.1
+const MAX_ROTATE_SPEED = 1
+
+const MAX_Z = 20 * 1.4 // or another value that suits your needs
+const MIN_Z = 0.2 * 1.4
+const MIN_Y = -0.25
+const MAX_Y = 0.25
+const MIN_X = -0.25
+const MAX_X = 0.25
+
+const MIN_ZOOM = 0.22
+const RESIZE_SPEED_FACTOR = 0.9
+const INITIAL_ZOOM = 3
+const calcZoom = (scrollY = 0, initZ = INITIAL_ZOOM) => {
+ return Math.max(
+ mapFloat(
+ scrollY,
+ 0,
+ calcScrollThreshold() * RESIZE_SPEED_FACTOR,
+ initZ,
+ MIN_ZOOM,
+ ),
+ MIN_ZOOM,
+ )
+}
+
+const calcRotateSpeed = (scrollY = 0, speed) => {
+ const sFactor = mapFloat(scrollY, 0, window.innerHeight, 1, 10)
+ return Math.max(Math.min(speed * sFactor, MAX_ROTATE_SPEED), MIN_ROTATE_SPEED)
+}
+
+function Model({url, ...props}) {
+ // useGLTF suspends the component, it literally stops processing
+ const {scene} = useGLTF(url) as any
+ // useLayoutEffect(() => {
+ // if (!camera) return
+ // const c = camera as THREE.PerspectiveCamera
+ // const fov = c.fov * (Math.PI / 180)
+ // const distance = Math.abs(Math.max(size.x, size.y) / Math.sin(fov / 2))
+ // c.position.setZ(distance)
+ // }, [size, camera])
+ return (
+
+ )
+}
+
+type RotateProps = PropsWithChildren<{
+ initialZ?: number
+ rotateSpeed?: number
+ enableZoom?: boolean
+ enableRotateOnScroll?: boolean
+}>
+
+function Movements({
+ initialZ,
+ rotateSpeed = ROTATE_SPEED,
+ enableZoom = true,
+ enableRotateOnScroll = true,
+ ...props
+ }: RotateProps) {
+ const ref = useRef
()
+ const scrollY = useScrollY()
+
+ useFrame((state, delta) => {
+ // const f = mapFloat(scrollY, 0, 1000, 1, 2);
+ // ref.current.rotation.x += delta * (ROTATE_SPEED);
+ // ref.current.rotation.y += delta * (ROTATE_SPEED);
+ const speed = enableRotateOnScroll
+ ? calcRotateSpeed(scrollY, rotateSpeed)
+ : rotateSpeed
+ ref.current.rotation.y += delta * speed
+ })
+
+ return (
+
+ )
+}
+
+type AsciiConfigs = {
+ characters?: string
+ invert?: boolean
+ color?: boolean
+ bgColor?: string
+ fgColor?: string
+ resolution?: number
+ renderIndex?: number
+}
+
+const defaultAsciiConfigs = {
+ renderIndex: 1,
+ bgColor: 'rgb(var(--lsd-surface-primary))',
+ fgColor: 'rgb(var(--lsd-text-primary))',
+ characters: ' l.o.g.o.s ',
+ invert: false,
+ color: false,
+ resolution: 0.2,
+}
+
+type AsciiEffectProps = {
+ config?: AsciiConfigs
+ initialZ?: number
+}
+
+function useAsciiEffect({config = {}, initialZ}: AsciiEffectProps) {
+ const {
+ renderIndex = defaultAsciiConfigs.renderIndex,
+ characters = defaultAsciiConfigs.characters,
+ invert = defaultAsciiConfigs.invert,
+ color = defaultAsciiConfigs.color,
+ resolution = defaultAsciiConfigs.resolution,
+ bgColor = defaultAsciiConfigs.bgColor,
+ fgColor = defaultAsciiConfigs.fgColor,
+ } = config
+
+ // Reactive state
+ const {gl, size, scene, camera, viewport} = useThree()
+
+ const effect = useMemo(() => {
+ const effect = new AsciiEffect(gl, " characters ", {
+ invert: true,
+ color: false,
+ resolution: 0.1,
+ })
+ effect.domElement.style.position = 'absolute'
+ effect.domElement.style.top = '0px'
+ effect.domElement.style.left = '0px'
+ effect.domElement.style.pointerEvents = 'none'
+ return effect
+ }, [characters, invert, color, resolution])
+
+ useLayoutEffect(() => {
+ effect.domElement.style.color = fgColor
+ // effect.domElement.style.backgroundColor = bgColor
+ }, [fgColor, bgColor])
+
+ // Append on mount, remove on unmount
+ useEffect(() => {
+ gl.domElement.style.opacity = '0'
+ gl.domElement.parentNode!.appendChild(effect.domElement)
+ return () => {
+ gl.domElement.style.opacity = '1'
+ gl.domElement.parentNode!.removeChild(effect.domElement)
+ }
+ }, [effect])
+
+ // Set size
+ useEffect(() => {
+ effect.setSize(size.width, size.height)
+ }, [effect, size])
+
+ // Take over render-loop (that is what the index is for)
+ useFrame((state) => {
+ effect.render(scene, camera)
+ }, renderIndex)
+}
+
+const AsciiRenderer = (props: AsciiEffectProps) => {
+ useAsciiEffect(props)
+ return <>>
+}
+
+export type HeroModelProps = React.HTMLAttributes & {
+ modelUrl: string
+ layout?: 'floating' | 'cropped'
+ renderer?: '3d' | 'ascii'
+ asciiConfig?: AsciiConfigs
+ initialZ?: number
+ initialX?: number
+ initialY?: number
+ rotateSpeed?: number
+ enableZoom?: boolean
+ enableRotateOnScroll?: boolean
+ withParallelEffect?: boolean
+}
+
+function Box(props) {
+ // This reference will give us direct access to the mesh
+ const mesh = useRef()
+ // Set up state for the hovered and active state
+ const [hovered, setHover] = useState(false)
+ const [active, setActive] = useState(false)
+ // Subscribe this component to the render-loop, rotate the mesh every frame
+ useFrame((state, delta) => {
+ if (mesh && mesh.current){
+ // @ts-ignore
+ return mesh.current.rotation.x += delta
+ }
+ })
+ // Return view, these are regular three.js elements expressed in JSX
+ return (
+ setActive(!active)}
+ onPointerOver={(event) => setHover(true)}
+ onPointerOut={(event) => setHover(false)}>
+
+
+
+ )
+}
+export const HeroModel: React.FC = ({}) => {
+ return (
+
+ )
+}
+
+// export const HeroModel: React.FC = ({
+// layout = 'floating',
+// renderer = '3d',
+// modelUrl,
+// className,
+// children,
+// asciiConfig,
+// initialX,
+// initialY,
+// initialZ,
+// rotateSpeed = ROTATE_SPEED,
+// enableZoom,
+// enableRotateOnScroll,
+// withParallelEffect,
+// ...props
+// }) => {
+ const scrollY = useScrollY()
+ const initialPosition = useMemo(() => {
+ if (typeof window === 'undefined') return new THREE.Vector3(0, 0, 0)
+ if (renderer === 'ascii') {
+ return new THREE.Vector3(
+ initialX || random(MIN_X, MAX_X),
+ initialY || random(MIN_Y, MAX_Y),
+ 0,
+ )
+ }
+ // if not ascii then use the max z
+ return new THREE.Vector3(3.1, initialY || random(MIN_Y, MAX_Y), 0)
+ }, [initialX, initialY, initialZ, renderer])
+// return (
+//
+
+//
+//
+//
+//
+// }>
+//
+//
+//
+
+//
+// )
+// }
+
+ */
+export default {}
diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/index.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/index.tsx
index 7da17d1..8e367da 100644
--- a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/index.tsx
+++ b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/index.tsx
@@ -1,17 +1,20 @@
-import BrowserOnly from '@docusaurus/BrowserOnly'
import React from 'react'
-import { HeroModelProps } from './HeroModel'
+import { HeroModel as Model, HeroModelProps } from './HeroModel'
export const HeroModel: React.FC = (props) => {
- return (
-
- {() => {
- const { HeroModel: Model } = require('./HeroModel')
+ if (typeof window === 'undefined') return null
- return
- }}
-
- )
+ return
+
+ // return (
+ //
+ // {() => {
+ // const { HeroModel: Model } = require('./HeroModel')
+ //
+ // return
+ // }}
+ //
+ // )
}
export type { HeroModelProps } from './HeroModel'
diff --git a/packages/logos-docusaurus-theme/src/client/lib/ui.utils.ts b/packages/logos-docusaurus-theme/src/client/lib/ui.utils.ts
index 5c9a235..b39a78a 100644
--- a/packages/logos-docusaurus-theme/src/client/lib/ui.utils.ts
+++ b/packages/logos-docusaurus-theme/src/client/lib/ui.utils.ts
@@ -19,3 +19,15 @@ export const isTouchDevice = () => {
(navigator.msMaxTouchPoints && navigator.msMaxTouchPoints > 0)
)
}
+
+export const generateTextShadow = (steps: number): string => {
+ let shadows = ''
+ for (let i = 0; i < steps; i++) {
+ let colorValue = Math.floor((i / (steps - 1)) * 255) // Generate a value between 0 and 255
+ let shadow = `${-i * 5}px ${
+ -i * 5
+ }px 0px rgb(${colorValue}, ${colorValue}, ${colorValue})`
+ shadows += (i === 0 ? '' : ', ') + shadow
+ }
+ return shadows
+}
diff --git a/packages/logos-docusaurus-theme/src/client/types/ui.types.ts b/packages/logos-docusaurus-theme/src/client/types/ui.types.ts
index ad53471..11d64c2 100644
--- a/packages/logos-docusaurus-theme/src/client/types/ui.types.ts
+++ b/packages/logos-docusaurus-theme/src/client/types/ui.types.ts
@@ -1,3 +1,5 @@
+import { GroupProps } from '@react-three/fiber/dist/declarations/src/three-types'
+
export enum ECommunityProviders {
'discord' = 'discord',
'twitter' = 'twitter',
@@ -8,3 +10,34 @@ export enum ECommunityProviders {
'telegram' = 'telegram',
'gscholar' = 'gscholar',
}
+
+export type LookPresetItemValues = {
+ cameraPos: [number, number, number]
+ cameraRot: [number, number, number]
+ controlsTarget: [number, number, number]
+}
+
+export type LookPresetItem = {
+ modelId: string
+ simple: LookPresetItemValues
+ abstract: LookPresetItemValues
+}
+
+export type MovementProps = {
+ rotateSpeed?: number
+ enableZoom?: boolean
+ enableRotateOnScroll?: boolean
+ preset: LookPresetItemValues
+} & GroupProps
+
+export type AsciiConfigs = {
+ characters?: string
+ invert?: boolean
+ color?: boolean
+ bgColor?: string
+ fgColor?: string
+ resolution?: number
+ renderIndex?: number
+ textShadowSize?: number
+ withTextShadow?: boolean
+}