add input animation + input item rafctor
This commit is contained in:
parent
74d6d45150
commit
3cf07e2b45
7 changed files with 121 additions and 63 deletions
|
|
@ -48,6 +48,7 @@ function createWindow() {
|
||||||
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
||||||
// Load the url of the dev server if in development mode
|
// Load the url of the dev server if in development mode
|
||||||
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string);
|
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string);
|
||||||
|
// NOTE uncomment for dev tools on app launch
|
||||||
// if (!process.env.IS_TEST) win.webContents.openDevTools();
|
// if (!process.env.IS_TEST) win.webContents.openDevTools();
|
||||||
} else {
|
} else {
|
||||||
createProtocol("app");
|
createProtocol("app");
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<foreignObject class="inputContainer" :x="x" y="450" width="55%" height="50%">
|
<foreignObject class="inputContainer" :x="inputXoffset" y="450" width="55%" height="50%">
|
||||||
<div xmlns="http://www.w3.org/1999/xhtml">
|
<div xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<div class="inputBubble" contenteditable v-show="input.length > 0">
|
<div class="inputBubble" contenteditable v-show="input.length > 0">
|
||||||
<p>{{ input }}</p>
|
<p>{{ input }}</p>
|
||||||
|
|
@ -9,72 +9,18 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import useKeyDownHandler from "@/composables/keyDownHandler/useKeyDownHandler";
|
import useInputRenderer from "@/composables/inputItem/useInputRenderer";
|
||||||
import AnimeFunc from "@/types/animejs/index";
|
|
||||||
import {
|
import {
|
||||||
defineComponent,
|
defineComponent,
|
||||||
onUnmounted,
|
|
||||||
computed,
|
|
||||||
ref,
|
|
||||||
onMounted,
|
|
||||||
watch,
|
|
||||||
inject,
|
|
||||||
} from "vue";
|
} from "vue";
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "InputItem",
|
name: "InputItem",
|
||||||
setup() {
|
setup() {
|
||||||
const emitter: any = inject("mitt");
|
const { inputXoffset, input } = useInputRenderer();
|
||||||
emitter.on("newSelfMessage", (payload: any) => console.log("foo", payload));
|
|
||||||
const { keyDownHandler, input } = useKeyDownHandler();
|
|
||||||
const inputHeight = ref(42);
|
|
||||||
let inputBubble: HTMLElement;
|
|
||||||
const inputWidth = ref(0);
|
|
||||||
|
|
||||||
// imports animejs safely
|
return {
|
||||||
let anime: AnimeFunc;
|
|
||||||
const animeInject: AnimeFunc | undefined = inject("animejs");
|
|
||||||
if (animeInject) anime = animeInject;
|
|
||||||
|
|
||||||
// add window event listener
|
|
||||||
window.addEventListener("keydown", keyDownHandler);
|
|
||||||
// remove Event Listener on component unMount
|
|
||||||
onUnmounted(() => {
|
|
||||||
window.removeEventListener("keydown", keyDownHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(input, async (input, prevInput) => {
|
|
||||||
const inputDivs = await document.getElementsByClassName("inputBubble");
|
|
||||||
const height = inputDivs[0].getBoundingClientRect().height;
|
|
||||||
inputWidth.value = inputDivs[0].getBoundingClientRect().width;
|
|
||||||
const foreignObjectDiv = document.getElementsByClassName(
|
|
||||||
"inputContainer"
|
|
||||||
);
|
|
||||||
if (height !== inputHeight.value) {
|
|
||||||
inputHeight.value = height;
|
|
||||||
}
|
|
||||||
const foreignEl = foreignObjectDiv[0] as HTMLElement;
|
|
||||||
if (inputHeight.value === 0) {
|
|
||||||
anime({
|
|
||||||
targets: foreignEl,
|
|
||||||
translateY: -10,
|
|
||||||
});
|
|
||||||
} else if (inputHeight.value > 36) {
|
|
||||||
anime({
|
|
||||||
targets: foreignEl,
|
|
||||||
translateY: -inputHeight.value + 30,
|
|
||||||
easing: "easeOutQuad",
|
|
||||||
duration: 150,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const x = computed(() => {
|
|
||||||
return `calc(50% - ${inputWidth.value / 2})`;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
input,
|
input,
|
||||||
x,
|
inputXoffset,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
53
src/composables/inputItem/useInputAnims.ts
Normal file
53
src/composables/inputItem/useInputAnims.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
import AnimeFunc from "@/types/animejs/index";
|
||||||
|
import {inject} from "vue";
|
||||||
|
import {Ref} from "@/types/vueRef/index";
|
||||||
|
export default function useInputAnims() {
|
||||||
|
|
||||||
|
// imports animejs safely
|
||||||
|
let anime: AnimeFunc;
|
||||||
|
const animeInject: AnimeFunc | undefined = inject("animejs");
|
||||||
|
if (animeInject) anime = animeInject;
|
||||||
|
|
||||||
|
const animateSend = (el: HTMLElement, elHeight: number, input: Ref<string>) => {
|
||||||
|
anime({
|
||||||
|
targets: el,
|
||||||
|
translateY: -elHeight + 15,
|
||||||
|
duration: 200,
|
||||||
|
easing: "easeInQuad",
|
||||||
|
complete: function() {
|
||||||
|
anime({
|
||||||
|
targets: el,
|
||||||
|
translateY: 50,
|
||||||
|
duration: 200,
|
||||||
|
easing: "easeOutQuad",
|
||||||
|
complete: function () {
|
||||||
|
input.value = "";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const inputAppear = (el: HTMLElement) => {
|
||||||
|
anime({
|
||||||
|
targets: el,
|
||||||
|
translateY: -10,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const verticalShiftInput = (el: HTMLElement, yTrans: number) => {
|
||||||
|
anime({
|
||||||
|
targets: el,
|
||||||
|
translateY: yTrans,
|
||||||
|
easing: "easeOutQuad",
|
||||||
|
duration: 150,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
animateSend,
|
||||||
|
verticalShiftInput,
|
||||||
|
inputAppear
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
58
src/composables/inputItem/useInputRenderer.ts
Normal file
58
src/composables/inputItem/useInputRenderer.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
import {ref, computed, inject, watch, onUnmounted} from "vue";
|
||||||
|
import useInputAnims from "./useInputAnims";
|
||||||
|
import useKeyDownHandler from "@/composables/keyDownHandler/useKeyDownHandler";
|
||||||
|
export default function useInputRenderer() {
|
||||||
|
const { keyDownHandler, input } = useKeyDownHandler();
|
||||||
|
|
||||||
|
// add window event listener
|
||||||
|
window.addEventListener("keydown", keyDownHandler);
|
||||||
|
// remove Event Listener on component unMount
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener("keydown", keyDownHandler);
|
||||||
|
});
|
||||||
|
|
||||||
|
const emitter: any = inject("mitt");
|
||||||
|
const {animateSend, verticalShiftInput, inputAppear} = useInputAnims();
|
||||||
|
|
||||||
|
|
||||||
|
const inputHeight = ref(42);
|
||||||
|
const inputWidth = ref(0);
|
||||||
|
const renderInput = async() => {
|
||||||
|
const inputDivs = await document.getElementsByClassName("inputBubble");
|
||||||
|
const height = inputDivs[0].getBoundingClientRect().height;
|
||||||
|
inputWidth.value = inputDivs[0].getBoundingClientRect().width;
|
||||||
|
const foreignObjectDiv = document.getElementsByClassName(
|
||||||
|
"inputContainer"
|
||||||
|
);
|
||||||
|
if (height !== inputHeight.value) {
|
||||||
|
inputHeight.value = height;
|
||||||
|
}
|
||||||
|
const foreignEl = foreignObjectDiv[0] as HTMLElement;
|
||||||
|
if (inputHeight.value === 0) {
|
||||||
|
inputAppear(foreignEl)
|
||||||
|
} else if (inputHeight.value > 36) {
|
||||||
|
const yTrans = -inputHeight.value + 30;
|
||||||
|
verticalShiftInput(foreignEl, yTrans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(input, () => {
|
||||||
|
renderInput();
|
||||||
|
});
|
||||||
|
|
||||||
|
emitter.on("newSelfMessage", async (payload: any) => {
|
||||||
|
const inputEl = document.getElementsByClassName("inputContainer");
|
||||||
|
const foreignEl = inputEl[0] as HTMLElement;
|
||||||
|
animateSend(foreignEl, inputHeight.value, input);
|
||||||
|
});
|
||||||
|
|
||||||
|
const inputXoffset = computed(() => {
|
||||||
|
return `calc(50% - ${inputWidth.value / 2})`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
inputXoffset,
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -28,7 +28,6 @@ export default function useKeyDownHandler() {
|
||||||
};
|
};
|
||||||
// fire event with message payload
|
// fire event with message payload
|
||||||
emitter.emit("newSelfMessage", message);
|
emitter.emit("newSelfMessage", message);
|
||||||
input.value = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function keyDownHandler(e: KeyDownEvent) {
|
function keyDownHandler(e: KeyDownEvent) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
interface Ref<A> {
|
import {Ref} from "@/types/vueRef/index";
|
||||||
value: A;
|
|
||||||
}
|
|
||||||
export default function useMessageItemAnims({
|
export default function useMessageItemAnims({
|
||||||
mr,
|
mr,
|
||||||
tr,
|
tr,
|
||||||
|
|
|
||||||
3
src/types/vueRef/index.ts
Normal file
3
src/types/vueRef/index.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface Ref<A> {
|
||||||
|
value: A;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue