diff --git a/src/module/render/components/scroll.tsx b/src/module/render/components/scroll.tsx index 29e6bea..0e18fde 100644 --- a/src/module/render/components/scroll.tsx +++ b/src/module/render/components/scroll.tsx @@ -19,9 +19,10 @@ import { Transform } from '@/core/render'; import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; -import { hyper, Transition } from 'mutate-animate'; +import { hyper, linear, Transition } from 'mutate-animate'; import { clamp } from 'lodash-es'; import { IActionEvent, IWheelEvent, MouseType } from '@/core/render/event'; +import { transitioned } from '../use'; export const enum ScrollDirection { Horizontal, @@ -61,7 +62,7 @@ const SCROLL_MIN_LENGTH = 20; /** 滚动条图示的宽度 */ const SCROLL_WIDTH = 10; /** 滚动条的颜色 */ -const SCROLL_COLOR = '#ddd'; +const SCROLL_COLOR = '255,255,255'; /** * 滚动条组件,具有虚拟滚动功能,即在画面外的不渲染。参数参考 {@link ScrollProps},暴露接口参考 {@link ScrollExpose} @@ -100,11 +101,20 @@ export const Scroll = defineComponent( const content = ref(); const scroll = ref(); + const scrollAlpha = transitioned(0.5, 100, linear())!; + const width = computed(() => props.loc[2] ?? 200); const height = computed(() => props.loc[3] ?? 200); const direction = computed(() => props.hor ? ScrollDirection.Horizontal : ScrollDirection.Vertical ); + const scrollColor = computed( + () => `rgba(${SCROLL_COLOR},${scrollAlpha.ref.value ?? 0.5})` + ); + + watch(scrollColor, () => { + scroll.value?.update(); + }); /** 滚动内容的当前位置 */ let contentPos = 0; @@ -301,7 +311,7 @@ export const Scroll = defineComponent( const ctx = canvas.ctx; ctx.lineCap = 'round'; ctx.lineWidth = 3; - ctx.strokeStyle = SCROLL_COLOR; + ctx.strokeStyle = scrollColor.value; ctx.beginPath(); const scroll = transition.value.scroll; if (direction.value === ScrollDirection.Horizontal) { @@ -435,6 +445,7 @@ export const Scroll = defineComponent( } else { scrollMutate = true; } + scrollAlpha.set(0.9); }; const moveScroll = (ev: IActionEvent) => { @@ -461,6 +472,7 @@ export const Scroll = defineComponent( }; const upScroll = (ev: IActionEvent) => { + scrollAlpha.set(0.7); if (!scrollMutate) return; const pos = getPos(ev); if (pos < scrollPos) { @@ -470,6 +482,14 @@ export const Scroll = defineComponent( } }; + const enter = () => { + scrollAlpha.set(0.7); + }; + + const leave = () => { + scrollAlpha.set(0.5); + }; + //#endregion onMounted(() => { @@ -508,6 +528,8 @@ export const Scroll = defineComponent( onDown={downScroll} onUp={upScroll} zIndex={10} + onEnter={enter} + onLeave={leave} > ); diff --git a/src/module/render/ui/statusBar.tsx b/src/module/render/ui/statusBar.tsx index 4f15a60..2b08506 100644 --- a/src/module/render/ui/statusBar.tsx +++ b/src/module/render/ui/statusBar.tsx @@ -3,7 +3,6 @@ import { defineComponent } from 'vue'; import { SetupComponentOptions } from '../components'; import { ElementLocator } from '@/core/render'; import { Scroll } from '../components/scroll'; -import { Page } from '../components/page'; export interface ILeftHeroStatus { hp: number; @@ -171,21 +170,6 @@ export const RightStatusBar = defineComponent>( - - {(page: number) => { - switch (page) { - case 1: { - return ; - } - case 2: { - return ; - } - case 3: { - return ; - } - } - }} - ); }; diff --git a/src/module/render/use.ts b/src/module/render/use.ts index 60a1623..b82736a 100644 --- a/src/module/render/use.ts +++ b/src/module/render/use.ts @@ -1,4 +1,12 @@ -import { onMounted, onUnmounted } from 'vue'; +import { TimingFn, Transition } from 'mutate-animate'; +import { + ComponentInternalInstance, + getCurrentInstance, + onMounted, + onUnmounted, + ref, + Ref +} from 'vue'; export const enum Orientation { /** 横屏 */ @@ -58,3 +66,65 @@ export function onLoaded(hook: () => void) { hook(); } } + +export interface ITransitionedController { + readonly ref: Ref; + readonly value: number; + set(value: number): void; +} + +class RenderTransition implements ITransitionedController { + private static key: number = 0; + + private readonly key: string = `$${RenderTransition.key++}`; + + public readonly ref: Ref; + + set value(v: number) { + this.transition.transition(this.key, v); + } + get value() { + return this.transition.value[this.key]; + } + + constructor( + value: number, + public readonly transition: Transition, + public readonly time: number, + public readonly curve: TimingFn + ) { + this.ref = ref(value); + transition.ticker.add(() => { + this.ref.value = transition.value[this.key]; + }); + } + + set(value: number): void { + this.transition + .time(this.time) + .mode(this.curve) + .transition(this.key, value); + } +} + +const transitionMap = new Map(); + +export function transitioned( + value: number, + time: number, + curve: TimingFn +): ITransitionedController | null { + const instance = getCurrentInstance(); + if (!instance) return null; + if (!transitionMap.has(instance)) { + const tran = new Transition(); + transitionMap.set(instance, tran); + onUnmounted(() => { + transitionMap.delete(instance); + tran.ticker.destroy(); + }); + } + const tran = transitionMap.get(instance); + if (!tran) return null; + return new RenderTransition(value, tran, time, curve); +}