mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-04-18 17:48:52 +08:00
feat: 滚动条渐变
This commit is contained in:
parent
6e990fa926
commit
c5101c9b29
@ -19,9 +19,10 @@ import {
|
|||||||
Transform
|
Transform
|
||||||
} from '@/core/render';
|
} from '@/core/render';
|
||||||
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
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 { clamp } from 'lodash-es';
|
||||||
import { IActionEvent, IWheelEvent, MouseType } from '@/core/render/event';
|
import { IActionEvent, IWheelEvent, MouseType } from '@/core/render/event';
|
||||||
|
import { transitioned } from '../use';
|
||||||
|
|
||||||
export const enum ScrollDirection {
|
export const enum ScrollDirection {
|
||||||
Horizontal,
|
Horizontal,
|
||||||
@ -61,7 +62,7 @@ const SCROLL_MIN_LENGTH = 20;
|
|||||||
/** 滚动条图示的宽度 */
|
/** 滚动条图示的宽度 */
|
||||||
const SCROLL_WIDTH = 10;
|
const SCROLL_WIDTH = 10;
|
||||||
/** 滚动条的颜色 */
|
/** 滚动条的颜色 */
|
||||||
const SCROLL_COLOR = '#ddd';
|
const SCROLL_COLOR = '255,255,255';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 滚动条组件,具有虚拟滚动功能,即在画面外的不渲染。参数参考 {@link ScrollProps},暴露接口参考 {@link ScrollExpose}
|
* 滚动条组件,具有虚拟滚动功能,即在画面外的不渲染。参数参考 {@link ScrollProps},暴露接口参考 {@link ScrollExpose}
|
||||||
@ -100,11 +101,20 @@ export const Scroll = defineComponent<ScrollProps, {}, string, ScrollSlots>(
|
|||||||
const content = ref<Container>();
|
const content = ref<Container>();
|
||||||
const scroll = ref<Sprite>();
|
const scroll = ref<Sprite>();
|
||||||
|
|
||||||
|
const scrollAlpha = transitioned(0.5, 100, linear())!;
|
||||||
|
|
||||||
const width = computed(() => props.loc[2] ?? 200);
|
const width = computed(() => props.loc[2] ?? 200);
|
||||||
const height = computed(() => props.loc[3] ?? 200);
|
const height = computed(() => props.loc[3] ?? 200);
|
||||||
const direction = computed(() =>
|
const direction = computed(() =>
|
||||||
props.hor ? ScrollDirection.Horizontal : ScrollDirection.Vertical
|
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;
|
let contentPos = 0;
|
||||||
@ -301,7 +311,7 @@ export const Scroll = defineComponent<ScrollProps, {}, string, ScrollSlots>(
|
|||||||
const ctx = canvas.ctx;
|
const ctx = canvas.ctx;
|
||||||
ctx.lineCap = 'round';
|
ctx.lineCap = 'round';
|
||||||
ctx.lineWidth = 3;
|
ctx.lineWidth = 3;
|
||||||
ctx.strokeStyle = SCROLL_COLOR;
|
ctx.strokeStyle = scrollColor.value;
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
const scroll = transition.value.scroll;
|
const scroll = transition.value.scroll;
|
||||||
if (direction.value === ScrollDirection.Horizontal) {
|
if (direction.value === ScrollDirection.Horizontal) {
|
||||||
@ -435,6 +445,7 @@ export const Scroll = defineComponent<ScrollProps, {}, string, ScrollSlots>(
|
|||||||
} else {
|
} else {
|
||||||
scrollMutate = true;
|
scrollMutate = true;
|
||||||
}
|
}
|
||||||
|
scrollAlpha.set(0.9);
|
||||||
};
|
};
|
||||||
|
|
||||||
const moveScroll = (ev: IActionEvent) => {
|
const moveScroll = (ev: IActionEvent) => {
|
||||||
@ -461,6 +472,7 @@ export const Scroll = defineComponent<ScrollProps, {}, string, ScrollSlots>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const upScroll = (ev: IActionEvent) => {
|
const upScroll = (ev: IActionEvent) => {
|
||||||
|
scrollAlpha.set(0.7);
|
||||||
if (!scrollMutate) return;
|
if (!scrollMutate) return;
|
||||||
const pos = getPos(ev);
|
const pos = getPos(ev);
|
||||||
if (pos < scrollPos) {
|
if (pos < scrollPos) {
|
||||||
@ -470,6 +482,14 @@ export const Scroll = defineComponent<ScrollProps, {}, string, ScrollSlots>(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const enter = () => {
|
||||||
|
scrollAlpha.set(0.7);
|
||||||
|
};
|
||||||
|
|
||||||
|
const leave = () => {
|
||||||
|
scrollAlpha.set(0.5);
|
||||||
|
};
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -508,6 +528,8 @@ export const Scroll = defineComponent<ScrollProps, {}, string, ScrollSlots>(
|
|||||||
onDown={downScroll}
|
onDown={downScroll}
|
||||||
onUp={upScroll}
|
onUp={upScroll}
|
||||||
zIndex={10}
|
zIndex={10}
|
||||||
|
onEnter={enter}
|
||||||
|
onLeave={leave}
|
||||||
></sprite>
|
></sprite>
|
||||||
</container>
|
</container>
|
||||||
);
|
);
|
||||||
|
@ -3,7 +3,6 @@ import { defineComponent } from 'vue';
|
|||||||
import { SetupComponentOptions } from '../components';
|
import { SetupComponentOptions } from '../components';
|
||||||
import { ElementLocator } from '@/core/render';
|
import { ElementLocator } from '@/core/render';
|
||||||
import { Scroll } from '../components/scroll';
|
import { Scroll } from '../components/scroll';
|
||||||
import { Page } from '../components/page';
|
|
||||||
|
|
||||||
export interface ILeftHeroStatus {
|
export interface ILeftHeroStatus {
|
||||||
hp: number;
|
hp: number;
|
||||||
@ -171,21 +170,6 @@ export const RightStatusBar = defineComponent<StatusBarProps<IRightHeroStatus>>(
|
|||||||
<container loc={p.loc}>
|
<container loc={p.loc}>
|
||||||
<g-rect loc={[0, 0, p.loc[2], p.loc[3]]} stroke></g-rect>
|
<g-rect loc={[0, 0, p.loc[2], p.loc[3]]} stroke></g-rect>
|
||||||
<Scroll loc={[0, 0, 180, 100]}></Scroll>
|
<Scroll loc={[0, 0, 180, 100]}></Scroll>
|
||||||
<Page loc={[0, 200, 180, 100]} pages={3}>
|
|
||||||
{(page: number) => {
|
|
||||||
switch (page) {
|
|
||||||
case 1: {
|
|
||||||
return <text text="测试"></text>;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
return <text text="测试2"></text>;
|
|
||||||
}
|
|
||||||
case 3: {
|
|
||||||
return <text text="测试3"></text>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
</Page>
|
|
||||||
</container>
|
</container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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 {
|
export const enum Orientation {
|
||||||
/** 横屏 */
|
/** 横屏 */
|
||||||
@ -58,3 +66,65 @@ export function onLoaded(hook: () => void) {
|
|||||||
hook();
|
hook();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ITransitionedController {
|
||||||
|
readonly ref: Ref<number>;
|
||||||
|
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<number>;
|
||||||
|
|
||||||
|
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<ComponentInternalInstance, Transition>();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user