diff --git a/packages/docusaurus-playground/docusaurus.config.js b/packages/docusaurus-playground/docusaurus.config.js index 6b94846..879e5d2 100644 --- a/packages/docusaurus-playground/docusaurus.config.js +++ b/packages/docusaurus-playground/docusaurus.config.js @@ -56,6 +56,13 @@ const config = { defaultMode: 'dark', disableSwitch: false, }, + navbar: { + // items: [ + // { + // type: 'search', + // } + // ] + }, }), } diff --git a/packages/docusaurus-playground/src/pages/index.mdx b/packages/docusaurus-playground/src/pages/index.mdx index d78fde3..920b8d5 100644 --- a/packages/docusaurus-playground/src/pages/index.mdx +++ b/packages/docusaurus-playground/src/pages/index.mdx @@ -32,14 +32,13 @@ import { diff --git a/packages/docusaurus-playground/static/hero/architecture01/hi.gbl b/packages/docusaurus-playground/static/hero/architecture01/hi.gbl new file mode 100644 index 0000000..b07454d Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture01/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture01/lo.gbl b/packages/docusaurus-playground/static/hero/architecture01/lo.gbl new file mode 100644 index 0000000..b07454d Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture01/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture02/hi.gbl b/packages/docusaurus-playground/static/hero/architecture02/hi.gbl new file mode 100644 index 0000000..77d2ce7 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture02/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture02/lo.gbl b/packages/docusaurus-playground/static/hero/architecture02/lo.gbl new file mode 100644 index 0000000..77d2ce7 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture02/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture03/hi.gbl b/packages/docusaurus-playground/static/hero/architecture03/hi.gbl new file mode 100644 index 0000000..f0cdb2b Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture03/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture03/lo.gbl b/packages/docusaurus-playground/static/hero/architecture03/lo.gbl new file mode 100644 index 0000000..f0cdb2b Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture03/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture04/hi.gbl b/packages/docusaurus-playground/static/hero/architecture04/hi.gbl new file mode 100644 index 0000000..f3139c6 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture04/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture04/lo.gbl b/packages/docusaurus-playground/static/hero/architecture04/lo.gbl new file mode 100644 index 0000000..bebb2e7 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture04/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture05/hi.gbl b/packages/docusaurus-playground/static/hero/architecture05/hi.gbl new file mode 100644 index 0000000..8a925be Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture05/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture05/lo.gbl b/packages/docusaurus-playground/static/hero/architecture05/lo.gbl new file mode 100644 index 0000000..b8b7ddb Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture05/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture06/hi.gbl b/packages/docusaurus-playground/static/hero/architecture06/hi.gbl new file mode 100644 index 0000000..caaefde Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture06/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture06/lo.gbl b/packages/docusaurus-playground/static/hero/architecture06/lo.gbl new file mode 100644 index 0000000..caaefde Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture06/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture07/hi.gbl b/packages/docusaurus-playground/static/hero/architecture07/hi.gbl new file mode 100644 index 0000000..697f119 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture07/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/architecture07/lo.gbl b/packages/docusaurus-playground/static/hero/architecture07/lo.gbl new file mode 100644 index 0000000..697f119 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/architecture07/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/bulanding-generic-atlas-01.glb b/packages/docusaurus-playground/static/hero/atlas/hi.gbl similarity index 100% rename from packages/docusaurus-playground/static/hero/bulanding-generic-atlas-01.glb rename to packages/docusaurus-playground/static/hero/atlas/hi.gbl diff --git a/packages/docusaurus-playground/static/hero/atlas/lo.gbl b/packages/docusaurus-playground/static/hero/atlas/lo.gbl new file mode 100644 index 0000000..0adfed0 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/atlas/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/bust01/hi.gbl b/packages/docusaurus-playground/static/hero/bust01/hi.gbl new file mode 100644 index 0000000..2eedb60 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/bust01/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/bust01/lo.gbl b/packages/docusaurus-playground/static/hero/bust01/lo.gbl new file mode 100644 index 0000000..2eedb60 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/bust01/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/bust02/hi.gbl b/packages/docusaurus-playground/static/hero/bust02/hi.gbl new file mode 100644 index 0000000..00955a2 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/bust02/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/bust02/lo.gbl b/packages/docusaurus-playground/static/hero/bust02/lo.gbl new file mode 100644 index 0000000..e67bfe1 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/bust02/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/bust03/hi.gbl b/packages/docusaurus-playground/static/hero/bust03/hi.gbl new file mode 100644 index 0000000..77b847e Binary files /dev/null and b/packages/docusaurus-playground/static/hero/bust03/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/bust03/lo.gbl b/packages/docusaurus-playground/static/hero/bust03/lo.gbl new file mode 100644 index 0000000..a449f7d Binary files /dev/null and b/packages/docusaurus-playground/static/hero/bust03/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/discobolus/hi.gbl b/packages/docusaurus-playground/static/hero/discobolus/hi.gbl new file mode 100644 index 0000000..ea2ec28 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/discobolus/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/discobolus/lo.gbl b/packages/docusaurus-playground/static/hero/discobolus/lo.gbl new file mode 100644 index 0000000..f3c80c0 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/discobolus/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/bulanding-generic-hand-01.glb b/packages/docusaurus-playground/static/hero/hand/hi.gbl similarity index 100% rename from packages/docusaurus-playground/static/hero/bulanding-generic-hand-01.glb rename to packages/docusaurus-playground/static/hero/hand/hi.gbl diff --git a/packages/docusaurus-playground/static/hero/hand/lo.gbl b/packages/docusaurus-playground/static/hero/hand/lo.gbl new file mode 100644 index 0000000..5492ee5 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/hand/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/bulanding-generic-vase-02.glb b/packages/docusaurus-playground/static/hero/vase01/hi.gbl similarity index 100% rename from packages/docusaurus-playground/static/hero/bulanding-generic-vase-02.glb rename to packages/docusaurus-playground/static/hero/vase01/hi.gbl diff --git a/packages/docusaurus-playground/static/hero/vase01/lo.gbl b/packages/docusaurus-playground/static/hero/vase01/lo.gbl new file mode 100644 index 0000000..30f50f0 Binary files /dev/null and b/packages/docusaurus-playground/static/hero/vase01/lo.gbl differ diff --git a/packages/docusaurus-playground/static/hero/venus/hi.gbl b/packages/docusaurus-playground/static/hero/venus/hi.gbl new file mode 100644 index 0000000..a9fe31e Binary files /dev/null and b/packages/docusaurus-playground/static/hero/venus/hi.gbl differ diff --git a/packages/docusaurus-playground/static/hero/venus/lo.gbl b/packages/docusaurus-playground/static/hero/venus/lo.gbl new file mode 100644 index 0000000..2df429a Binary files /dev/null and b/packages/docusaurus-playground/static/hero/venus/lo.gbl differ diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroDescription/HeroDescription.scss b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroDescription/HeroDescription.scss index a5e6e43..edd47bb 100644 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroDescription/HeroDescription.scss +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroDescription/HeroDescription.scss @@ -1,5 +1,8 @@ .mdx-hero-description { + // we need position relative because we need the z-index to work in order to keep it under the hero model + position: relative; z-index: -2; + font-weight: 100 !important; } .mdx-hero-description--small { diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroInfo/HeroInfo.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroInfo/HeroInfo.tsx index 3d24048..ad77f2d 100644 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroInfo/HeroInfo.tsx +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroInfo/HeroInfo.tsx @@ -12,7 +12,7 @@ export type HeroInfoProps = PropsWithChildren< } const calcMaxOffsetY = () => { - return window.innerHeight * 0.33 + return window.innerHeight * 0.1 } export const HeroInfo: React.FC = ({ size: sizeProp, diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/Ascii.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/Ascii.tsx new file mode 100644 index 0000000..9b2378e --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/Ascii.tsx @@ -0,0 +1,73 @@ +import { AsciiConfigs } from '../../../types/ui.types' +import { defaultAsciiConfigs } from './HeroModel.configs' +import { useFrame, useThree } from '@react-three/fiber' +import React, { useEffect, useLayoutEffect, useMemo } from 'react' +import { AsciiEffect } from 'three-stdlib' +import { generateTextShadow } from '../../../lib/ui.utils' + +function useAsciiEffect(config: AsciiConfigs = {}) { + const { + renderIndex = defaultAsciiConfigs.renderIndex, + characters = defaultAsciiConfigs.characters, + invert = defaultAsciiConfigs.invert, + color = defaultAsciiConfigs.color, + resolution = defaultAsciiConfigs.resolution, + bgColor = defaultAsciiConfigs.bgColor, + fgColor = defaultAsciiConfigs.fgColor, + textShadowSize = defaultAsciiConfigs.textShadowSize, + withTextShadow = false, + } = config + const { gl, size, scene, camera, viewport } = useThree() + + const effect = useMemo(() => { + const effect = new AsciiEffect(gl, characters, { + invert, + color, + resolution, + }) + 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) + + if (withTextShadow) { + const style = document.createElement('style') + style.innerHTML = `table *{text-shadow: ${generateTextShadow( + textShadowSize, + )};` + effect.domElement.appendChild(style) + } + + 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) +} + +export const AsciiRenderer = (configs: AsciiConfigs) => { + useAsciiEffect(configs) + return <> +} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/Controls.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/Controls.tsx new file mode 100644 index 0000000..97f20d6 --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/Controls.tsx @@ -0,0 +1,120 @@ +import { ROTATE_SPEED } from './HeroModel.configs' +import { MovementProps } from '../../../types/ui.types' +import React, { useEffect, useRef } from 'react' +import { useScrollY } from '../../../lib/useScrollY' +import { useFrame, useThree } from '@react-three/fiber' +import { calcRotateSpeed } from './HeroModel.utils' +import { OrbitControls } from '@react-three/drei' + +class Vector3 { + x: number + y: number + z: number + + constructor(x: number, y: number, z: number) { + this.x = x + this.y = y + this.z = z + } + + subtract(v: Vector3) { + return new Vector3(this.x - v.x, this.y - v.y, this.z - v.z) + } + + add(v: Vector3) { + return new Vector3(this.x + v.x, this.y + v.y, this.z + v.z) + } + + multiplyScalar(s: number) { + return new Vector3(this.x * s, this.y * s, this.z * s) + } + + clone() { + return new Vector3(this.x, this.y, this.z) + } + + toArray() { + return [this.x, this.y, this.z] + } +} + +const lerp = (a: number, b: number, t: number) => (1 - t) * a + t * b +let targetPos: [number, number, number] = [0, 0, 0] + +function calculateCameraPosition(scrollY: number): [number, number, number] { + const baseXZ = -1.6 // Base x and z component at scrollY = 0 + const baseY = 4.04 // Base y component at scrollY = 0 + const rateXZ = -0.01 // Rate of change for x and z components + const rateY = 0.00185 // Rate of change for y component + const deltaX = baseXZ + rateXZ * scrollY - baseXZ + const deltaY = baseY + rateY * scrollY - baseY + const deltaZ = baseXZ + rateXZ * scrollY - baseXZ + return [deltaX, deltaY, deltaZ] +} +export const Controls = ({ + rotateSpeed = ROTATE_SPEED, + enableZoom = true, + enableRotateOnScroll = true, + preset, + children, + ...props +}: MovementProps) => { + const ref = useRef() + const scrollY = useScrollY() + const { camera, size } = useThree() + const controls = useRef() + + useFrame((state, delta) => { + const speed = enableRotateOnScroll + ? calcRotateSpeed(scrollY, rotateSpeed) + : rotateSpeed + ref.current.rotation.y += delta * speed + }) + + useEffect(() => { + const onClick = () => { + console.log( + JSON.stringify( + { + cameraPos: camera.position.toArray(), + cameraRot: camera.rotation.toArray().slice(0, 3), + controlsTarget: controls.current.target.toArray(), + }, + null, + 2, + ), + ) + } + + window.addEventListener('click', onClick) + return () => window.removeEventListener('click', onClick) + }, [camera]) + + useEffect(() => { + const [deltaX, deltaY, deltaZ] = calculateCameraPosition(scrollY) + + // Add the deltas to the initial positions + const newPositionX = preset.cameraPos[0] + deltaX + const newPositionY = preset.cameraPos[1] + deltaY + const newPositionZ = preset.cameraPos[2] + deltaZ + + camera.position.set(newPositionX, newPositionY, newPositionZ) + camera.updateProjectionMatrix() + + // const scale = mapFloat(scrollY, 0, calcScrollThreshold(), 1, 0.5); + // const initialPosition = ref.current.position.clone(); + // ref.current.scale.set(scale, scale, scale); + // ref.current.position.y += 0.0001 * scale; + }, [scrollY, camera]) + + return ( + + {children} + + + ) +} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.configs.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.configs.ts new file mode 100644 index 0000000..ce8439e --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.configs.ts @@ -0,0 +1,260 @@ +import { LookPresetItem, LookPresetItemValues } from '../../../types/ui.types' + +export let ROTATE_SPEED = 0.1 +export const MIN_ROTATE_SPEED = 0 +export const MAX_ROTATE_SPEED = 1 +export const MAX_Z = 20 * 1.4 // or another value that suits your needs +export const MIN_Z = 0.2 * 1.4 +export const MIN_Y = -0.25 +export const MAX_Y = 0.25 +export const MIN_X = -0.25 +export const MAX_X = 0.25 +export const MIN_ZOOM = 0.22 +export const RESIZE_SPEED_FACTOR = 0.9 +export const INITIAL_ZOOM = 3 + +export 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.21, + textShadowSize: 15, +} + +export const defaultPresets: { + simple: LookPresetItemValues + abstract: LookPresetItemValues +} = { + simple: { + cameraPos: [6.898858137575106, 4.772099506970454, -3.1821660872368627], + cameraRot: [-2.733342169570335, 1.127956558492365, 2.7690180385429666], + controlsTarget: [ + -0.2185887974027981, 3.4320197290105474, -0.08409377618890646, + ], + }, + abstract: { + cameraPos: [-1.4826176635786852, 4.021180061821954, -1.5929058418153597], + cameraRot: [-2.9244096935808908, -0.8625529112689497, -2.9755407843387185], + controlsTarget: [-0.3236695017538898, 3.8072918272567, -0.6236093222013962], + }, +} + +export const OBJECTS_PRESETS: LookPresetItem[] = [ + { + modelId: 'bust', + simple: { + cameraPos: [6.898858137575106, 4.772099506970454, -3.1821660872368627], + cameraRot: [-2.733342169570335, 1.127956558492365, 2.7690180385429666], + controlsTarget: [ + -0.2185887974027981, 3.4320197290105474, -0.08409377618890646, + ], + }, + abstract: { + cameraPos: [-1.4826176635786852, 4.021180061821954, -1.5929058418153597], + cameraRot: [ + -2.9244096935808908, -0.8625529112689497, -2.9755407843387185, + ], + controlsTarget: [ + -0.3236695017538898, 3.8072918272567, -0.6236093222013962, + ], + }, + }, + { + modelId: 'architecture01', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'architecture02', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'architecture03', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'architecture04', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'architecture05', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'architecture06', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'architecture07', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'atlas', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'bust01', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'bust02', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'bust03', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'discobolus', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'hand', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'vase01', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, + { + modelId: 'venus', + simple: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + abstract: { + cameraPos: [0, 0, 0], + cameraRot: [0, 0, 0], + controlsTarget: [0, 0, 0], + }, + }, +] diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.scss b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.scss index 9d484c0..165c2a8 100644 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.scss +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.scss @@ -5,63 +5,42 @@ ); position: absolute; top: calc(var(--logos-hero-info-height) - 10px); - z-index: -1; + z-index: 0; .mdx-hero-model--inner { position: relative; width: 100%; - height: 1400px; z-index: 0; left: 0; top: 0; - //transition: translate 0.6s ease-in-out; - canvas { - pointer-events: none; - } - } -} - -.mdx-hero-model--cropped { -} - -.mdx-hero-model--floating { - .mdx-hero-model--inner { canvas { pointer-events: unset !important; } } } -.mdx-hero-model--3d { - overflow: visible !important; +.mdx-hero-model--simple { +} - .mdx-hero-model--inner { - position: relative; - } - - .mdx-hero-model--inner { - > div { - position: absolute; - top: 50%; - left: 50%; - transform: scale(1.2) translate(-50%, -50%); - } - } +.mdx-hero-model--abstract { } .mdx-hero-model--ascii { + filter: grayscale(100%); table { &, * { border: none !important; font-family: monospace; + //text-shadow: -5px 5px 0px #d5d5d5, -10px 10px 0px #01cccc, -15px 15px 0px #00bdbd, 2px 2px 2px rgba(206,89,55,0); + color: #ffffff; } } } .mdx-hero-model--shade { width: 100%; - height: 600px; + height: 60vh; position: absolute; background: linear-gradient( 0deg, @@ -69,6 +48,6 @@ rgb(0, 0, 0) 0%, rgba(0, 0, 0, 0) 100% ); - bottom: 500px; + bottom: -0; left: 0; } 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 index 7babd53..e4951c5 100644 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.tsx +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/HeroModel/HeroModel.tsx @@ -1,284 +1,119 @@ -import { OrbitControls, useGLTF } from '@react-three/drei' -import { Canvas, useFrame, useThree } from '@react-three/fiber' +import React, { Suspense, useMemo, useRef } from 'react' +import { Canvas, useFrame } from '@react-three/fiber' +import { useGLTF } from '@react-three/drei' 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' + defaultPresets, + OBJECTS_PRESETS, + RESIZE_SPEED_FACTOR, + ROTATE_SPEED, +} from './HeroModel.configs' +import { AsciiConfigs, LookPresetItemValues } from '../../../types/ui.types' + +import './HeroModel.scss' +import { AsciiRenderer } from './Ascii' +import { Controls } from './Controls' +import { calcScrollThreshold, mapFloat } 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, - color, - resolution, - }) - 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' + modelUrlHi: string + modelUrlLow: string + modelId?: string + preset?: LookPresetItemValues + mode?: 'simple' | 'abstract' asciiConfig?: AsciiConfigs - initialZ?: number - initialX?: number - initialY?: number rotateSpeed?: number + enableZoom?: boolean enableRotateOnScroll?: boolean withParallelEffect?: boolean } -export const HeroModel: React.FC = ({ - layout = 'floating', - renderer = '3d', - modelUrl, - className, - children, - asciiConfig, - initialX, - initialY, - initialZ, - rotateSpeed = ROTATE_SPEED, - enableZoom, - enableRotateOnScroll, - withParallelEffect, - ...props -}) => { +const useLookPreset = ( + mode: 'abstract' | 'simple', + preset?: LookPresetItemValues, + modelId?: string, +): LookPresetItemValues => { + return useMemo(() => { + if (preset) return preset + if (!modelId) return defaultPresets[mode] + const existingPreset = OBJECTS_PRESETS.find((p) => p.modelId === modelId) + return existingPreset ? existingPreset[mode] : defaultPresets[mode] + }, [preset, modelId]) +} + +const getInitialY = (mode: 'abstract' | 'simple'): number => { + return mode === 'abstract' ? 0 : -200 +} + +export const HeroModel = (props: HeroModelProps) => { + const { + modelUrlHi, + modelUrlLow, + modelId, + preset: presetProp, + mode = 'simple', + className, + children, + asciiConfig, + rotateSpeed = ROTATE_SPEED, + enableZoom, + enableRotateOnScroll, + withParallelEffect = true, + ...divProps + } = props + + const preset = useLookPreset(mode, presetProp, modelId) + // const index = 1; + // const preset = OBJECTS_PRESETS[1]? OBJECTS_PRESETS[index][mode] : defaultPresets[mode]; 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 (
- - - - - - }> - - - - - {!isTouchDevice() && } - {renderer === 'ascii' && ( - - )} - + }> + + + + + + + }> + + + + + +
= ({ 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 ( +//
+
+// +// +// +// +// }> +// +// +// }> + + + + +// +// +// +// +// {!isTouchDevice() && } + {renderer === 'ascii' && ( + + )} +// +// +//
+ +//
+// ) +// } + + */ +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 +}