123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- <template>
- <ui-editor-toolbar toolbar class="animation-toolbar">
- <div class="top-bar">
- <div class="play-bar">
- <ui-icon type="close" ctrl @click="play = !play" />
- </div>
- <div class="scale-bar">
- <ui-icon type="close" class="icon" ctrl />
- <Slider
- class="slider"
- v-model:value="scale"
- :min="0.5"
- :max="8"
- :step="0.01"
- :tooltipOpen="false"
- />
- <ui-icon type="close" class="icon" ctrl />
- </div>
- </div>
- <div class="oper-bar" :class="{ disabled: play }">
- <Renderer v-model:scale="scale">
- <TimeLine
- v-for="prop in tlProps"
- :items="am[prop.attr]"
- :height="prop.height"
- :top="prop.top"
- :itemsRenderer="prop.component"
- @update="({ ndx, time }) => (am[prop.attr][ndx].time = time)"
- @add="
- (item) => {
- am[prop.attr].push(item);
- $emit('update:active', { key: prop.attr, ndx: am[prop.attr].length - 1 });
- }
- "
- @del="(ndx) => am[prop.attr].splice(ndx, 1)"
- :active="prop.attr === active?.key ? am[prop.attr][active.ndx] : undefined"
- @update:active="(active: any) => $emit('update:active', active && { key: prop.attr, ndx: am[prop.attr].indexOf(active) })"
- />
- <Time @update-current-time="(time) => $emit('update:currentTime', time)">
- <TimeCurrent
- :currentTime="currentTime"
- @update:current-time="(time) => $emit('update:currentTime', time)"
- :follow="play"
- />
- </Time>
- </Renderer>
- </div>
- </ui-editor-toolbar>
- </template>
- <script lang="ts" setup>
- import { Slider } from "ant-design-vue";
- import { ref, watch } from "vue";
- import { AnimationModel } from "@/store/animation";
- import Renderer from "@/components/drawing/renderer.vue";
- import Time from "@/components/drawing-time/time.vue";
- import TimeCurrent from "@/components/drawing-time/current.vue";
- import TimeLine from "@/components/drawing-time-line/index.vue";
- import TimeLineFrame from "@/components/drawing-time-line/frame.vue";
- import TimeLineAction from "@/components/drawing-time-line/action.vue";
- import { Active } from "./type";
- const props = defineProps<{ am: AnimationModel; active?: Active; currentTime: number }>();
- const emit = defineEmits<{
- (e: "update:active", data: Active | undefined): void;
- (e: "update:currentTime", v: number): void;
- }>();
- const scale = ref(1);
- const tlProps = [
- { attr: "frames", component: TimeLineFrame, height: 30, top: 24 },
- { attr: "actions", component: TimeLineAction, height: 30, top: 65 },
- { attr: "subtitles", component: TimeLineAction, height: 30, top: 105 },
- { attr: "paths", component: TimeLineAction, height: 30, top: 140 },
- ] as const;
- const play = ref(false);
- watch(play, (_a, _b, onCleanup) => {
- let isDes = false;
- let prevNow = Date.now();
- const animation = () => {
- if (play.value && !isDes) {
- const curNow = Date.now();
- emit("update:currentTime", props.currentTime + (curNow - prevNow) * 0.001);
- prevNow = curNow;
- requestAnimationFrame(animation);
- }
- };
- animation();
- onCleanup(() => (isDes = true));
- });
- </script>
- <style scoped lang="scss">
- .top-bar {
- display: flex;
- height: 40px;
- align-items: center;
- border-bottom: 1px solid rgba(255, 255, 255, 0.16);
- .play-bar {
- flex: 1;
- display: flex;
- justify-content: center;
- }
- .scale-bar {
- width: 180px;
- flex: 0 0 auto;
- display: flex;
- align-items: center;
- padding: 0 20px;
- position: relative;
- &::before {
- content: "";
- position: absolute;
- left: 0;
- width: 1px;
- height: 16px;
- background: rgba(255, 255, 255, 0.16);
- }
- .slider {
- flex: 1;
- }
- .icon {
- margin: 0 5px;
- }
- }
- }
- .oper-bar {
- height: calc(100% - 40px);
- }
- </style>
|