diff --git a/package.json b/package.json
index d7f498fbc..cf86bc266 100644
--- a/package.json
+++ b/package.json
@@ -16,9 +16,7 @@
"classnames": "2.3.2",
"dayjs": "1.11.9",
"default-passive-events": "2.0.0",
- "detect-gpu": "5.0.37",
"echarts": "4.9.0",
- "gsap": "3.12.2",
"history": "5.3.0",
"i18next": "20.6.1",
"js-base64": "^3.7.5",
@@ -35,8 +33,7 @@
"react-router-dom": "5.3.4",
"react-scripts": "5.0.1",
"sass": "1.66.1",
- "styled-components": "5.3.11",
- "three": "0.149.0"
+ "styled-components": "5.3.11"
},
"devDependencies": {
"@sentry/webpack-plugin": "2.7.1",
diff --git a/src/components/BannerFallback/index.module.scss b/src/components/BannerFallback/index.module.scss
deleted file mode 100644
index e98dc92b9..000000000
--- a/src/components/BannerFallback/index.module.scss
+++ /dev/null
@@ -1,15 +0,0 @@
-$backgroudColor: #232323;
-
-.Root {
- width: 100%;
- background-color: $backgroudColor;
- height: 200px;
- position: relative;
- background-image: url('../../assets/ckb_explorer_banner.svg');
- background-repeat: no-repeat;
- background-position: center center;
- background-size: auto 100%;
- @media (max-width: 750px) {
- background-image: url('../../assets/ckb_explorer_banner_phone.svg');
- }
-}
diff --git a/src/components/BannerFallback/index.tsx b/src/components/BannerFallback/index.tsx
deleted file mode 100644
index f4272ebf7..000000000
--- a/src/components/BannerFallback/index.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-import styles from './index.module.scss'
-
-export default () =>
diff --git a/src/pages/Home/Banner/anime.ts b/src/pages/Home/Banner/anime.ts
deleted file mode 100644
index 74261ac8b..000000000
--- a/src/pages/Home/Banner/anime.ts
+++ /dev/null
@@ -1,163 +0,0 @@
-import { Mesh } from 'three'
-import { gsap } from 'gsap'
-import { singleton } from '../../../utils/util'
-import { assert } from '../../../utils/error'
-import { CubeOffset, InstancedCubeUnitControl } from './renderUtils'
-
-export const playNewBlockAnime = singleton(_playNewBlockAnime)
-
-const DURATION_TO_PROTRUDE = 5 // duration to protrude
-const DELAY_OF_RIPPLE = 10 // change the distance between edges of a ripple
-
-// eslint-disable-next-line no-underscore-dangle
-function _playNewBlockAnime(
- cubeOffsets: CubeOffset[],
- getCubeControl: (
- x: number,
- z: number,
- ) =>
- | (InstancedCubeUnitControl & {
- isTextCube: boolean
- isDataCube: boolean
- isFloatCubeCreator: boolean
- })
- | null,
- createFloatCube: () => Mesh,
-) {
- return Promise.all(cubeOffsets.map(startCubeAnime))
-
- function startCubeAnime(offset: CubeOffset): gsap.core.Animation | null {
- const control = getCubeControl(offset.x, offset.z)
- if (control == null) return null
- const { position, onUpdate, isTextCube, isDataCube, isFloatCubeCreator } = control
-
- const textCubeFirstUpDistance = 40
- const ySpeedPerSecond = 75
- const getMoveTime = (distance: number, multiply = 1) => distance / ySpeedPerSecond / multiply
-
- if (isTextCube) {
- return gsap
- .timeline()
- .to(position, {
- y: position.y + textCubeFirstUpDistance * 2,
- duration: getMoveTime(DURATION_TO_PROTRUDE * 4),
- onUpdate,
- })
- .to(position, {
- y: -40,
- duration: getMoveTime(DURATION_TO_PROTRUDE * 3),
- onUpdate,
- })
- .to(position, {
- y: position.y + textCubeFirstUpDistance,
- duration: getMoveTime(DURATION_TO_PROTRUDE * 4),
- onUpdate,
- })
- .to(position, {
- y: position.y,
- duration: getMoveTime(DURATION_TO_PROTRUDE * 5),
- onUpdate,
- })
- }
-
- const distance = Math.sqrt(position.x ** 2 + position.z ** 2)
- const maxDistanceWithReduction = 1000
- const reductionRatio = distance > maxDistanceWithReduction ? 0 : 1 - distance / maxDistanceWithReduction
- const textCubeFirstUpDuration = getMoveTime(textCubeFirstUpDistance, 2) * 4e3
-
- const timeline = gsap
- .timeline()
- .to(position, {
- delay: (distance + textCubeFirstUpDuration - 500 * reductionRatio) / 2000,
- y: position.y + 40,
- duration: getMoveTime(DURATION_TO_PROTRUDE),
- onUpdate,
- })
- .to(position, {
- delay: getMoveTime(DELAY_OF_RIPPLE),
- y: position.y,
- duration: getMoveTime(DURATION_TO_PROTRUDE),
- onUpdate,
- })
-
- if (!isDataCube) return timeline
-
- const createFloatCubeTimeline = () => {
- const moveLength = 1500
- const moveTime = getMoveTime(moveLength, 5)
- const floatCube = createFloatCube()
- assert(!Array.isArray(floatCube.material))
- floatCube.material.opacity = 0
- floatCube.position.copy(position)
-
- return gsap
- .timeline()
- .addLabel('start')
- .to(
- floatCube.material,
- {
- opacity: 1,
- duration: moveTime * 0.4,
- },
- 'start',
- )
- .to(
- floatCube.material,
- {
- opacity: 0,
- delay: moveTime * 0.6,
- duration: moveTime * 0.4,
- },
- 'start',
- )
- .to(
- floatCube.position,
- {
- y: moveLength,
- duration: moveTime,
- onComplete() {
- floatCube.removeFromParent()
- floatCube.geometry.dispose()
- assert(!Array.isArray(floatCube.material))
- floatCube.material.dispose()
- },
- },
- 'start',
- )
- .to(
- floatCube.rotation,
- {
- x: 2.42 / 8,
- y: 3.21 / 8,
- z: 14 / 8,
- duration: moveTime,
- },
- 'start',
- )
- }
-
- const dataCubeProtrudingHeight = 40
- timeline
- .to(position, {
- y: position.y + dataCubeProtrudingHeight,
- duration: getMoveTime(dataCubeProtrudingHeight),
- onUpdate,
- })
- // ">" The end of the previous animation, "<" The start of previous animation
- .addLabel('onDataCubeScaleEnd', '>')
- .addLabel('onDataCubeScaleStart', '<')
- .add(isFloatCubeCreator ? createFloatCubeTimeline() : [], 'onDataCubeScaleStart')
- .to(
- position,
- {
- delay: getMoveTime(150),
- y: position.y,
- duration: getMoveTime(dataCubeProtrudingHeight),
- onUpdate,
- },
- 'onDataCubeScaleEnd',
- )
-
- return timeline
- }
-}
diff --git a/src/pages/Home/Banner/index.module.scss b/src/pages/Home/Banner/index.module.scss
deleted file mode 100644
index 86da74ad5..000000000
--- a/src/pages/Home/Banner/index.module.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-.banner {
- background: #000;
- --rendererWidth: 1200px;
-
- &.mobile {
- --rendererWidth: 600px;
- }
-
- .renderer {
- position: relative;
- left: calc(50% - var(--rendererWidth) / 2);
- width: var(--rendererWidth);
- height: calc(var(--rendererWidth) / 4);
- }
-
- canvas {
- filter: drop-shadow(2px 4px 6px #000);
- }
-}
diff --git a/src/pages/Home/Banner/index.tsx b/src/pages/Home/Banner/index.tsx
deleted file mode 100644
index 0a8be3f72..000000000
--- a/src/pages/Home/Banner/index.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import { FC, memo, useEffect, useRef, useState } from 'react'
-import classNames from 'classnames'
-import { getGPUTier } from 'detect-gpu'
-import { BannerRender, createBannerRender } from './render'
-import styles from './index.module.scss'
-import { useIsMobile, usePrevious } from '../../../utils/hook'
-import { isMainnet as isMainnetFunc } from '../../../utils/chain'
-import BannerFallback from '../../../components/BannerFallback'
-
-const GPUTier = {
- MIN_TIER: 2,
- key: 'gpu-info',
- get(): number | null {
- try {
- const cache = localStorage.getItem(this.key)
- return cache ? JSON.parse(cache).tier : null
- } catch {
- return null
- }
- },
- async update() {
- const info = await getGPUTier()
- localStorage.setItem(this.key, JSON.stringify(info))
- return info.tier
- },
-}
-
-// eslint-disable-next-line no-underscore-dangle
-const _Banner: FC<{ latestBlock?: State.Block }> = ({ latestBlock }) => {
- const isMobile = useIsMobile()
- const ref = useRef(null)
- const [render, setRender] = useState()
- const [gpuTier, setGPUTier] = useState(GPUTier.get())
-
- const isFallbackDisplayed = gpuTier === null || gpuTier < GPUTier.MIN_TIER
-
- useEffect(() => {
- GPUTier.update().then(setGPUTier).catch(console.error)
- }, [setGPUTier])
-
- useEffect(() => {
- if (isFallbackDisplayed) return
-
- const container = ref.current
- if (!container) return
- try {
- const r = createBannerRender(container)
- setRender(r)
- return () => r.destroy()
- } catch (e) {
- if (e instanceof Error) {
- console.error(e.message)
- }
- // ignore
- }
- }, [setRender, isFallbackDisplayed])
-
- const prevLatestBlock = usePrevious(latestBlock)
- useEffect(() => {
- if (!latestBlock || !prevLatestBlock) return
- render?.onNewBlock(latestBlock)
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [latestBlock])
-
- // eslint-disable-next-line react-hooks/exhaustive-deps
- useEffect(() => render?.onResize(), [isMobile])
-
- if (isFallbackDisplayed) {
- return
- }
-
- return (
-
- )
-}
-
-/*
- * FIXME: this is a fallback for https://github.com/Magickbase/ckb-explorer-public-issues/issues/218 and should be restored once performance issue is fixed
- */
-const isMainnet = isMainnetFunc()
-export const Banner = isMainnet
- ? BannerFallback
- : memo(_Banner, (a, b) => a.latestBlock?.number === b.latestBlock?.number)
diff --git a/src/pages/Home/Banner/render.ts b/src/pages/Home/Banner/render.ts
deleted file mode 100644
index 6d25f7cd7..000000000
--- a/src/pages/Home/Banner/render.ts
+++ /dev/null
@@ -1,342 +0,0 @@
-import {
- Camera,
- DirectionalLight,
- Frustum,
- Matrix4,
- Mesh,
- MeshPhysicalMaterial,
- OrthographicCamera,
- Scene,
- Vector3,
- WebGLRenderer,
- sRGBEncoding,
- MeshLambertMaterial,
-} from 'three'
-import { RoundedBoxGeometry } from 'three/examples/jsm/geometries/RoundedBoxGeometry'
-import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
-import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'
-import { playNewBlockAnime } from './anime'
-import { isMainnet } from '../../../utils/chain'
-import { createSideFadeOutPass } from './shaderPass/sideFadeOutPass'
-import { createTextureOverlapPass } from './shaderPass/textureOverlapPass'
-import {
- containsPoint,
- createBloomComposerController,
- createInstancedCubeMesh,
- CubeOffset,
- InstancedCubeUnitControl,
-} from './renderUtils'
-import { assert } from '../../../utils/error'
-import { randomInt } from '../../../utils/util'
-import { getPrimaryColor } from '../../../constants/common'
-
-const COLORS = {
- primary: getPrimaryColor(),
- float: isMainnet() ? 0x00330b : 0x4d1676,
-}
-
-export interface BannerRender {
- onNewBlock: (block: State.Block) => void
- onResize: () => void
- destroy: () => void
-}
-
-export function createBannerRender(container: HTMLElement) {
- const width = container.clientWidth
- const height = container.clientHeight
- const aspect = width / height
- const scene = new Scene()
- // The following number constants are from the design draft.
- const camera = new OrthographicCamera(-700 * aspect, 700 * aspect, 150 * aspect, -150 * aspect, -100000, 100000)
- const renderer = new WebGLRenderer({ antialias: true, alpha: true })
- renderer.setPixelRatio(window.devicePixelRatio)
- renderer.outputEncoding = sRGBEncoding
- renderer.setSize(width, height)
- container.appendChild(renderer.domElement)
-
- // Fixed a viewing angle.
- camera.rotation.x = Math.PI / (180 / -37.46)
- camera.rotation.y = Math.PI / (180 / -33.83)
- camera.rotation.z = Math.PI / (180 / -28)
- camera.position.x = -540
- camera.position.z = 880
- camera.position.y = 720
- camera.updateWorldMatrix(true, false)
-
- const cubeSize = new Vector3(100, 200, 100)
- const gap = 10
- const {
- mesh: textCubes,
- cubeOffsets: textCubeOffsets,
- getCubeControl: getTextCubeControl,
- } = createTextCubes(cubeSize, gap)
- const {
- mesh: normalCubes,
- cubeOffsets: normalCubeOffsets,
- getCubeControl: getNormalCubeControl,
- } = createNormalCubes(cubeSize, gap, camera, textCubeOffsets)
- scene.add(normalCubes)
- scene.add(textCubes)
-
- const highlight1 = new DirectionalLight(0x999999, 12)
- highlight1.position.set(1, 1, 0)
- scene.add(highlight1)
-
- const highlight2 = new DirectionalLight(COLORS.primary, 600)
- highlight2.position.set(1, -80, 1)
- scene.add(highlight2)
-
- const highlight3 = new DirectionalLight(0xffffff, 20)
- highlight3.position.set(-1, -5, 0)
- scene.add(highlight3)
-
- const renderPass = new RenderPass(scene, camera)
- const sideFadeOutPass = createSideFadeOutPass()
- const bloomComposerCtl = createBloomComposerController(renderer, scene, width, height, [renderPass])
- const bloomTextureOverlapPass = createTextureOverlapPass(bloomComposerCtl.composer.renderTarget2.texture)
-
- const finalComposer = new EffectComposer(renderer)
- finalComposer.addPass(renderPass)
- finalComposer.addPass(bloomTextureOverlapPass)
- finalComposer.addPass(sideFadeOutPass)
-
- let stopRenderLoop: (() => void) | null = null
- function render() {
- const handle = requestAnimationFrame(render)
- stopRenderLoop = () => cancelAnimationFrame(handle)
-
- bloomComposerCtl.render()
- finalComposer.render()
- }
- render()
-
- function createFloatCube() {
- const boxGeometry = new RoundedBoxGeometry(100, 100, 100, 6, 6)
- const boxMaterial = new MeshLambertMaterial({
- color: COLORS.float,
- emissive: COLORS.float,
- emissiveIntensity: 0.001,
- transparent: true,
- opacity: 0.8,
- })
- const cube = new Mesh(boxGeometry, boxMaterial)
- bloomComposerCtl.toggleBloom(cube)
- scene.add(cube)
- return cube
- }
-
- return {
- onNewBlock(block: State.Block) {
- const dataCubeOffsets = getDataCubeOffsets(camera, getNormalCubeControl, textCubeOffsets, block.transactionsCount)
- const combinedGetCubeControl = (x: number, z: number) => {
- const control = getNormalCubeControl(x, z) ?? getTextCubeControl(x, z)
- if (control == null) return null
-
- const isTextCube = textCubeOffsets.some(offset => CubeOffset.isEqual(offset, { x, z }))
- const isDataCube = dataCubeOffsets.some(offset => CubeOffset.isEqual(offset, { x, z }))
- const isFloatCubeCreator = isDataCube && CubeOffset.isEqual(dataCubeOffsets[0], { x, z })
- return { ...control, isTextCube, isDataCube, isFloatCubeCreator }
- }
-
- playNewBlockAnime([...normalCubeOffsets, ...textCubeOffsets], combinedGetCubeControl, createFloatCube)
- },
- onResize() {
- renderer.setSize(container.clientWidth, container.clientHeight)
- },
- destroy() {
- stopRenderLoop?.()
-
- // It is expected that the rest of the resources will be automatically reclaimed by GC.
- finalComposer.dispose()
- renderer.dispose()
-
- renderPass.dispose()
- sideFadeOutPass.dispose()
- bloomComposerCtl.dispose()
- bloomTextureOverlapPass.dispose()
-
- highlight1.dispose()
- highlight2.dispose()
- highlight3.dispose()
-
- const meshes = [normalCubes, textCubes]
- meshes.forEach(mesh => {
- mesh.removeFromParent()
- mesh.geometry.dispose()
- assert(!Array.isArray(mesh.material))
- mesh.material.dispose()
- })
-
- renderer.domElement.remove()
- },
- }
-}
-
-function createNormalCubes(
- cubeSize: Vector3,
- spacingBetweenCubes: number,
- camera: Camera,
- disabledOffsets: CubeOffset[],
- centerPos: Vector3 = new Vector3(0, 0, 0),
-) {
- const cubeCanvasRangeLimit = { minX: -25, maxX: 25, minZ: -30, maxZ: 25 }
- const cubeWidth = cubeSize.x
- const cubeHeight = cubeSize.y
- const cubeLong = cubeSize.z
-
- const frustum = new Frustum()
- frustum.setFromProjectionMatrix(new Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse))
- const isVisibleToCamera = (pos: Vector3) => containsPoint(frustum, pos, Math.max(cubeWidth, cubeLong))
-
- const cubes: { x: number; z: number; initPosition: Vector3 }[] = []
- const cubeIndexMap: Record> = {}
- for (let x = cubeCanvasRangeLimit.minX; x < cubeCanvasRangeLimit.maxX; x++) {
- for (let z = cubeCanvasRangeLimit.minZ; z < cubeCanvasRangeLimit.maxZ; z++) {
- const xOffset = x * (cubeWidth + spacingBetweenCubes)
- const zOffset = z * (cubeLong + spacingBetweenCubes)
- const position = new Vector3(
- centerPos.x + (xOffset + spacingBetweenCubes / 2 + cubeWidth),
- centerPos.y + 0,
- centerPos.z + (zOffset + spacingBetweenCubes / 2 + cubeLong),
- )
- const disabled = disabledOffsets.some(offset => CubeOffset.isEqual(offset, { x, z }))
- if (!disabled && isVisibleToCamera(position)) {
- const index = cubes.push({ x, z, initPosition: position }) - 1
- const mapWithColumn = cubeIndexMap[x] ?? (cubeIndexMap[x] = {})
- mapWithColumn[z] = index
- }
- }
- }
-
- const boxGeometry = new RoundedBoxGeometry(cubeWidth, cubeHeight, cubeLong, 5, 8)
- const boxMaterial = new MeshPhysicalMaterial({
- metalness: 0.01,
- roughness: 0.9,
- clearcoatRoughness: 1,
- transmission: 1,
- })
-
- return createInstancedCubeMesh(cubes, cubeIndexMap, boxGeometry, boxMaterial)
-}
-
-function createTextCubes(cubeSize: Vector3, spacingBetweenCubes: number, centerPos: Vector3 = new Vector3(0, 0, 0)) {
- const cubeWidth = cubeSize.x
- const cubeHeight = cubeSize.y
- const cubeLong = cubeSize.z
-
- const textCubePoints = getTextPoints('C K B')
- const cubes: { x: number; z: number; initPosition: Vector3 }[] = []
- const cubeIndexMap: Record> = {}
- textCubePoints.forEach(({ x, z }) => {
- const xOffset = x * (cubeWidth + spacingBetweenCubes)
- const zOffset = z * (cubeLong + spacingBetweenCubes)
- const position = new Vector3(
- centerPos.x + (xOffset + spacingBetweenCubes / 2 + cubeWidth),
- centerPos.y + 40,
- centerPos.z + (zOffset + spacingBetweenCubes / 2 + cubeLong),
- )
- const index = cubes.push({ x, z, initPosition: position }) - 1
- const mapWithColumn = cubeIndexMap[x] ?? (cubeIndexMap[x] = {})
- mapWithColumn[z] = index
- })
-
- const boxGeometry = new RoundedBoxGeometry(cubeWidth, cubeHeight, cubeLong, 5, 8)
- const boxMaterial = new MeshPhysicalMaterial({
- clearcoatRoughness: 1,
- metalness: 0.08,
- roughness: 0.95,
- transmission: 1,
- color: 0xcccccc,
- })
-
- return createInstancedCubeMesh(cubes, cubeIndexMap, boxGeometry, boxMaterial)
-}
-
-function getDataCubeOffsets(
- camera: OrthographicCamera,
- getCubeControl: (x: number, z: number) => InstancedCubeUnitControl | null,
- textCubeOffsets: CubeOffset[],
- count: number,
-) {
- const smallVisionCamera = camera.clone()
- smallVisionCamera.left *= 0.7
- smallVisionCamera.right *= 0.7
- smallVisionCamera.updateProjectionMatrix()
- const frustum = new Frustum()
- frustum.setFromProjectionMatrix(
- new Matrix4().multiplyMatrices(smallVisionCamera.projectionMatrix, smallVisionCamera.matrixWorldInverse),
- )
- const isNearToViewport = (pos: Vector3) => containsPoint(frustum, pos, -100)
-
- const textRect = { x1: 0, z1: 0, x2: 0, z2: 0 }
- textCubeOffsets.forEach(({ x, z }) => {
- textRect.x1 = Math.min(textRect.x1, x)
- textRect.z1 = Math.min(textRect.z1, z)
- textRect.x2 = Math.max(textRect.x2, x)
- textRect.z2 = Math.max(textRect.z2, z)
- })
- const isInTextRect = ({ x, z }: CubeOffset) =>
- x >= textRect.x1 && x <= textRect.x2 && z >= textRect.z1 && z <= textRect.z2
-
- const offsets: CubeOffset[] = []
- while (count > offsets.length) {
- const offset: CubeOffset = { x: randomInt(-25, 25), z: randomInt(-30, 25) }
- const info = getCubeControl(offset.x, offset.z)
- if (
- info == null ||
- offsets.some(existed => CubeOffset.isEqual(existed, offset)) ||
- isInTextRect(offset) ||
- !isNearToViewport(info.position)
- )
- continue
- offsets.push(offset)
- }
-
- return offsets
-}
-
-function getTextPoints(text: string, font = '100 8px Arial') {
- if (text !== 'C K B' || font !== '100 8px Arial') {
- throw new Error(
- 'This function is not fully implemented, you need to refactor this function to pass in parameters freely',
- )
- }
-
- return [
- // C
- [-7, -1],
- [-7, 0],
- [-6, -2],
- [-6, 1],
- [-5, -3],
- [-5, 2],
- [-4, -3],
- [-4, 2],
- // K
- [-1, -3],
- [-1, -2],
- [-1, -1],
- [-1, 0],
- [-1, 1],
- [-1, 2],
- [0, -1],
- [0, 0],
- [1, -2],
- [1, 1],
- [2, -3],
- [2, 2],
- // B
- [5, -3],
- [5, -2],
- [5, -1],
- [5, 0],
- [5, 1],
- [5, 2],
- [6, -3],
- [6, -1],
- [6, 2],
- [7, -2],
- [7, 0],
- [7, 1],
- ].map(([x, z]) => ({ x, z }))
-}
diff --git a/src/pages/Home/Banner/renderUtils.ts b/src/pages/Home/Banner/renderUtils.ts
deleted file mode 100644
index 49082ce81..000000000
--- a/src/pages/Home/Banner/renderUtils.ts
+++ /dev/null
@@ -1,149 +0,0 @@
-import {
- Mesh,
- Frustum,
- Vector3,
- Layers,
- Object3D,
- Vector2,
- Scene,
- WebGLRenderer,
- Quaternion,
- BoxGeometry,
- InstancedMesh,
- Material,
- Matrix4,
-} from 'three'
-import { EffectComposer, Pass } from 'three/examples/jsm/postprocessing/EffectComposer'
-import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass'
-import { pick } from '../../../utils/object'
-
-export type CubeMap = Partial<{
- [x: number]: Partial<{
- [z: number]: Mesh
- }>
-}>
-
-export interface CubeOffset {
- x: number
- z: number
-}
-
-// eslint-disable-next-line no-redeclare
-export namespace CubeOffset {
- export function isEqual(a: CubeOffset, b: CubeOffset) {
- return a.x === b.x && a.z === b.z
- }
-}
-
-export interface InstancedCubeUnitControl {
- position: Vector3
- quaternion: Quaternion
- scale: Vector3
- onUpdate: () => void
-}
-
-// `frustum.containsPoint` of the variation
-export function containsPoint(frustum: Frustum, point: Vector3, tolerance = 0) {
- const { planes } = frustum
-
- for (let i = 0; i < 6; i++) {
- if (planes[i].distanceToPoint(point) < -tolerance) {
- return false
- }
- }
-
- return true
-}
-
-// Reference from:
-// https://github.com/mrdoob/three.js/blob/master/examples/webgl_postprocessing_unreal_bloom_selective.html
-export function createBloomComposerController(
- renderer: WebGLRenderer,
- scene: Scene,
- width: number,
- height: number,
- beforePasses: Pass[],
-): {
- composer: EffectComposer
- toggleBloom: (mesh: Mesh) => void
- render: (delta?: number) => void
- dispose: () => void
-} {
- const BLOOM_SCENE = 1
- const bloomLayer = new Layers()
- bloomLayer.set(BLOOM_SCENE)
-
- function setNoRenderIfNonBloomed() {
- const objs: Object3D[] = []
- scene.traverse((obj: Object3D | Mesh) => {
- if ('isMesh' in obj && obj.isMesh && bloomLayer.test(obj.layers) === false) {
- objs.push(obj)
- }
- })
-
- objs.forEach(obj => scene.remove(obj))
- return () => objs.forEach(obj => scene.add(obj))
- }
-
- const bloomPass = new UnrealBloomPass(new Vector2(width, height), 1.5, 0.5, 0)
-
- const composer = new EffectComposer(renderer)
- composer.renderToScreen = false
- beforePasses.forEach(p => composer.addPass(p))
- composer.addPass(bloomPass)
-
- return {
- composer,
- toggleBloom(mesh) {
- mesh.layers.toggle(BLOOM_SCENE)
- },
- render(delta) {
- const restore = setNoRenderIfNonBloomed()
- composer.render(delta)
- restore()
- },
- dispose() {
- composer.dispose()
- bloomPass.dispose()
- },
- }
-}
-
-export function createInstancedCubeMesh(
- cubes: { x: number; z: number; initPosition: Vector3 }[],
- cubeIndexMap: Record>,
- geometry: BoxGeometry,
- material: Material,
-) {
- const mesh = new InstancedMesh(geometry, material, cubes.length)
- const matrix = new Matrix4()
- cubes.forEach(({ initPosition }, idx) => {
- matrix.setPosition(initPosition)
- mesh.setMatrixAt(idx, matrix)
- })
-
- return {
- mesh,
- cubeOffsets: cubes.map(cube => pick(cube, ['x', 'z'])),
- getCubeControl(xOrIndex: number, z?: number): InstancedCubeUnitControl | null {
- const idx = z == null ? xOrIndex : cubeIndexMap[xOrIndex]?.[z]
- if (idx == null) return null
-
- mesh.getMatrixAt(idx, matrix)
- const position = new Vector3()
- const quaternion = new Quaternion()
- const scale = new Vector3()
- matrix.decompose(position, quaternion, scale)
-
- return {
- position,
- quaternion,
- scale,
- onUpdate() {
- mesh.setMatrixAt(idx, new Matrix4().compose(position, quaternion, scale))
- mesh.instanceMatrix.needsUpdate = true
- },
- }
- },
- }
-}
diff --git a/src/pages/Home/Banner/shaderPass/sideFadeOutPass.ts b/src/pages/Home/Banner/shaderPass/sideFadeOutPass.ts
deleted file mode 100644
index 5d1a31898..000000000
--- a/src/pages/Home/Banner/shaderPass/sideFadeOutPass.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass'
-
-export function createSideFadeOutPass() {
- const pass = new ShaderPass({
- uniforms: {
- tDiffuse: { value: null },
- },
-
- vertexShader: /* glsl */ `
- varying vec2 vUv;
- varying float x;
- void main() {
- vUv = uv;
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
- x = (gl_Position.x + 1.0) * 0.5;
- }`,
-
- fragmentShader: /* glsl */ `
- uniform sampler2D tDiffuse;
- varying vec2 vUv;
- varying float x;
- void main() {
- gl_FragColor = texture2D( tDiffuse, vUv );
- float edgeDist = (0.5 - abs(x - 0.5));
- gl_FragColor.a = edgeDist * 2.0;
- }`,
- })
-
- pass.material.transparent = true
-
- return pass
-}
diff --git a/src/pages/Home/Banner/shaderPass/textureOverlapPass.ts b/src/pages/Home/Banner/shaderPass/textureOverlapPass.ts
deleted file mode 100644
index d0ac7b790..000000000
--- a/src/pages/Home/Banner/shaderPass/textureOverlapPass.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { ShaderMaterial, Texture } from 'three'
-import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass'
-
-export function createTextureOverlapPass(texture: Texture) {
- const pass = new ShaderPass(
- new ShaderMaterial({
- uniforms: {
- baseTexture: { value: null },
- overlapTexture: { value: texture },
- },
-
- vertexShader: /* glsl */ `
- varying vec2 vUv;
- void main() {
- vUv = uv;
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
- }`,
-
- fragmentShader: /* glsl */ `
- uniform sampler2D baseTexture;
- uniform sampler2D overlapTexture;
- varying vec2 vUv;
- void main() {
- gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( overlapTexture, vUv ) );
- }`,
-
- defines: {},
- }),
- 'baseTexture',
- )
- pass.needsSwap = true
-
- return pass
-}
diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx
index b2ec4c870..b07e9f2f8 100644
--- a/src/pages/Home/index.tsx
+++ b/src/pages/Home/index.tsx
@@ -30,7 +30,7 @@ import { BlockCardItem, TransactionCardItem } from './TableCard'
import { getTipBlockNumber } from '../../service/app/address'
import Loading from '../../components/Loading/SmallLoading'
import { useElementIntersecting, useInterval, useIsLGScreen, useIsMobile } from '../../utils/hook'
-import { Banner } from './Banner'
+import Banner from '../../components/Banner'
import { handleBlockchainAlert } from '../../service/app/blockchain'
import Search from '../../components/Search'
import AverageBlockTimeChart from './AverageBlockTimeChart'
@@ -262,7 +262,7 @@ export default () => {
return (
-
+
diff --git a/yarn.lock b/yarn.lock
index e93819e30..a77565d7f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5108,13 +5108,6 @@ destroy@1.2.0:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
-detect-gpu@5.0.37:
- version "5.0.37"
- resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.37.tgz#27febe44d478ef4d35cd38007355da795ba075d5"
- integrity sha512-EraWs84faI4iskB4qvE39bevMIazEvd1RpoyGLOBesRLbiz6eMeJqqRPHjEFClfRByYZzi9IzU35rBXIO76oDw==
- dependencies:
- webgl-constants "^1.1.1"
-
detect-newline@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
@@ -6692,11 +6685,6 @@ grapheme-splitter@^1.0.4:
resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
-gsap@3.12.2:
- version "3.12.2"
- resolved "https://registry.yarnpkg.com/gsap/-/gsap-3.12.2.tgz#6e88203eed360761cbf2a2cb3a8d702aa87f3f6d"
- integrity sha512-EkYnpG8qHgYBFAwsgsGEqvT1WUidX0tt/ijepx7z8EUJHElykg91RvW1XbkT59T0gZzzszOpjQv7SE41XuIXyQ==
-
gzip-size@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
@@ -12102,11 +12090,6 @@ text-table@^0.2.0:
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
-three@0.149.0:
- version "0.149.0"
- resolved "https://registry.yarnpkg.com/three/-/three-0.149.0.tgz#a9cf78b17d02f063ffe6dfca1e300eff2eab2927"
- integrity sha512-tohpUxPDht0qExRLDTM8sjRLc5d9STURNrdnK3w9A+V4pxaTBfKWWT/IqtiLfg23Vfc3Z+ImNfvRw1/0CtxrkQ==
-
throat@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375"
@@ -12613,11 +12596,6 @@ wbuf@^1.1.0, wbuf@^1.7.3:
dependencies:
minimalistic-assert "^1.0.0"
-webgl-constants@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/webgl-constants/-/webgl-constants-1.1.1.tgz#f9633ee87fea56647a60b9ce735cbdfb891c6855"
- integrity sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg==
-
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"