From 23fddf382e8ad209968d1afa7ba29cee8613cd00 Mon Sep 17 00:00:00 2001 From: Theo Sanderson Date: Wed, 1 Jun 2022 15:22:47 +0100 Subject: [PATCH] update --- taxonium_web_client/src/Deck.jsx | 12 +++++ taxonium_web_client/src/Taxonium.jsx | 3 +- taxonium_web_client/src/hooks/useView.js | 61 ++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/taxonium_web_client/src/Deck.jsx b/taxonium_web_client/src/Deck.jsx index e22766f5..7080d7cb 100644 --- a/taxonium_web_client/src/Deck.jsx +++ b/taxonium_web_client/src/Deck.jsx @@ -15,6 +15,12 @@ import { DeckButtons } from "./components/DeckButtons"; import DeckSettingsModal from "./components/DeckSettingsModal"; import FirefoxWarning from "./components/FirefoxWarning"; +//create your forceUpdate hook +function useForceUpdate(){ + const [value, setValue] = useState(0); // integer state + return () => setValue(value => value + 1); // update the state to force render +} + function Deck({ data, search, @@ -32,6 +38,12 @@ function Deck({ deckSize, isCurrentlyOutsideBounds, }) { + const zoomAnimation = useRef({ + startTime: null, + endTime: null, + startZoom: null, + endZoom: null, + }); const deckRef = useRef(); const snapshot = useSnapshot(deckRef); const [deckSettingsOpen, setDeckSettingsOpen] = useState(false); diff --git a/taxonium_web_client/src/Taxonium.jsx b/taxonium_web_client/src/Taxonium.jsx index 90a76e12..b9c3a407 100644 --- a/taxonium_web_client/src/Taxonium.jsx +++ b/taxonium_web_client/src/Taxonium.jsx @@ -8,11 +8,12 @@ import useSearch from "./hooks/useSearch"; import useColorBy from "./hooks/useColorBy"; import useNodeDetails from "./hooks/useNodeDetails"; import useHoverDetails from "./hooks/useHoverDetails"; -import { useCallback, useMemo, useState } from "react"; +import { useCallback, useMemo, useState, useRef } from "react"; import useBackend from "./hooks/useBackend"; import useConfig from "./hooks/useConfig"; import { useSettings } from "./hooks/useSettings"; + const URL_ON_FAIL = window.location.hostname.includes(".epicov.org") ? "https://www.epicov.org/epi3/frontend" : process.env.REACT_APP_URL_ON_FAIL; diff --git a/taxonium_web_client/src/hooks/useView.js b/taxonium_web_client/src/hooks/useView.js index f226557a..e11215fa 100644 --- a/taxonium_web_client/src/hooks/useView.js +++ b/taxonium_web_client/src/hooks/useView.js @@ -1,4 +1,4 @@ -import { useState, useMemo, useCallback } from "react"; +import { useState, useMemo, useCallback, useRef, useEffect } from "react"; import {toast} from 'react-hot-toast' import { OrthographicView, @@ -6,6 +6,12 @@ import { //OrthographicViewport, } from "@deck.gl/core"; +function useForceUpdate(){ + const [value, setValue] = useState(0); // integer state + return () => setValue(value => value + 1); // update the state to force render +} + + let globalSetZoomAxis = () => {}; class MyOrthographicController extends OrthographicController { // on construction @@ -96,6 +102,8 @@ class MyOrthographicController extends OrthographicController { } const useView = ({ settings, deckSize }) => { + + const forceUpdate = useForceUpdate(); const [zoomAxis, setZoomAxis] = useState("Y"); const [xzoom, setXzoom] = useState(0); globalSetZoomAxis = setZoomAxis; @@ -107,7 +115,17 @@ const useView = ({ settings, deckSize }) => { bearing: 0, minimap: { zoom: -3, target: [250, 1000] }, }); - //console.log("useView", viewState); + + const zoomAnimation = useRef({ + startTime: null, + endTime: null, + startZoom: null, + endZoom: null, + zooming: null, + zoomAxis: null, + }); + + const views = useMemo(() => { return [ @@ -238,7 +256,7 @@ const useView = ({ settings, deckSize }) => { [zoomAxis, xzoom, deckSize] ); - const zoomIncrement = useCallback( + const zoomIncrementBasic = useCallback( (increment, overrideZoomAxis) => { const newViewState = { ...viewState }; newViewState.zoom += increment; @@ -253,6 +271,43 @@ const useView = ({ settings, deckSize }) => { [viewState, onViewStateChange] ); + const zoomIncrement = useCallback( + (increment, overrideZoomAxis) => { + const finalZoom = viewState.zoom + increment; + zoomAnimation.current.zooming = true; + zoomAnimation.current.zoomAxis = overrideZoomAxis; + zoomAnimation.current.startZoom = viewState.zoom; + zoomAnimation.current.endZoom = finalZoom; + zoomAnimation.current.startTime = Date.now(); + zoomAnimation.current.endTime = zoomAnimation.current.startTime + 1000; + forceUpdate(); + }, + [viewState, onViewStateChange] + ); + + + useEffect(() => { + if(zoomAnimation.current.zooming){ + const {startTime, endTime, startZoom, endZoom, zoomAxis} = zoomAnimation.current; + const now = Date.now(); + if(now > endTime){ + const remaining_difference = endZoom - viewState.zoom; + zoomIncrementBasic(remaining_difference, zoomAxis); + zoomAnimation.current.zooming = false; + } + else{ + const elapsed_time = now - startTime; + const target_zoom = startZoom + elapsed_time * (endZoom - startZoom) / (endTime - startTime); + const difference = target_zoom - viewState.zoom; + zoomIncrementBasic(difference, zoomAxis); + setTimeout(() => { + forceUpdate(); + } + , 10); + } + } + }, [viewState.zoom, zoomAxis, forceUpdate, zoomAnimation.current.zooming, zoomIncrementBasic]); + const output = useMemo(() => { return { viewState,