add bottom bound to message visualizer
This commit is contained in:
parent
f0a89bd5e4
commit
2831c11de3
6 changed files with 66 additions and 106 deletions
|
|
@ -19,8 +19,8 @@ export async function main() {
|
|||
});
|
||||
|
||||
// Instantiate socket session with crimata-platorm.
|
||||
// if (!socket) initSession();
|
||||
// socket = true;
|
||||
if (!socket) initSession();
|
||||
socket = true;
|
||||
|
||||
// Begin audio stream.
|
||||
// initRecorder();
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
:viewBox="scrollView"
|
||||
id="test"
|
||||
>
|
||||
<g id="messageView" transform="translate(0, 5)">
|
||||
<g id="messageView" transform="translate(0, 20)">
|
||||
<g
|
||||
v-for="(item, index) in renderArr"
|
||||
:key="index"
|
||||
class="messageList"
|
||||
transform="translate(0, 25)"
|
||||
preserverAspectRatio="none"
|
||||
>
|
||||
<transition
|
||||
|
|
@ -31,7 +30,7 @@ import useMessageView from "./viewDetails/visualizer";
|
|||
import useScrollView from "@/modules/scrollView";
|
||||
import TextBubble from "@/components/textBubble/index.vue";
|
||||
import { Message } from "@/types/message/index";
|
||||
import { defineComponent, reactive, onMounted, onUnmounted } from "vue";
|
||||
import { defineComponent, reactive, onMounted, onUnmounted, watch, ref, computed } from "vue";
|
||||
import useMitt from "@/modules/mitt";
|
||||
import { useIpc } from "@/modules/ipc";
|
||||
|
||||
|
|
@ -51,9 +50,9 @@ export default defineComponent({
|
|||
|
||||
emitter.on("animateSend", async (message) => {
|
||||
try {
|
||||
renderArr.push(message)
|
||||
// await invoke(message);
|
||||
// renderArr.push(data.value);
|
||||
// renderArr.push(message)
|
||||
await invoke(message);
|
||||
renderArr.push(data.value);
|
||||
} catch (e) {
|
||||
console.log("No response. Do not render.");
|
||||
}
|
||||
|
|
@ -80,13 +79,3 @@ export default defineComponent({
|
|||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
svg {
|
||||
height: 1%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#messageRenderer {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -5,76 +5,47 @@ import { MessageAnimeFunc } from '@/types/message/index';
|
|||
/**
|
||||
* anime js animations used by message renderer
|
||||
*/
|
||||
export default function useMessageViewAnims(): {
|
||||
shiftAnimate: MessageAnimeFunc;
|
||||
stackAnimate: MessageAnimeFunc;
|
||||
} {
|
||||
export default function useMessageViewAnims() {
|
||||
// imports animejs safely
|
||||
let anime: AnimeFunc;
|
||||
const animeInject: AnimeFunc | undefined = inject("animejs");
|
||||
if (animeInject) anime = animeInject;
|
||||
|
||||
// shifts message list by a given value
|
||||
function shiftList({ targetList, sv }: { targetList: NodeList | undefined; sv: number | undefined }) {
|
||||
if (targetList) {
|
||||
for (const element of targetList) {
|
||||
const el = element.parentNode as HTMLElement;
|
||||
anime({
|
||||
targets: el,
|
||||
transform: `translate(0 ${sv})`,
|
||||
easing: "easeInOutQuad",
|
||||
duration: 500,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adds new message at the bottom of the list and shifts existing message list
|
||||
const shiftAnimate: MessageAnimeFunc = (el, transform, shiftValue, targetList) => {
|
||||
const shiftAnimate = (el: Element, transform: string, view: SVGGElement, viewTransform: string) => {
|
||||
anime({
|
||||
targets: el,
|
||||
transform: transform.initialTranslate,
|
||||
transform: transform,
|
||||
easing: "easeInOutQuad",
|
||||
duration: 500,
|
||||
duration: 800,
|
||||
begin: function() {
|
||||
shiftList({
|
||||
targetList,
|
||||
sv: shiftValue
|
||||
});
|
||||
shiftView(view, viewTransform);
|
||||
},
|
||||
complete: function() {
|
||||
anime({
|
||||
targets: el,
|
||||
transform: transform.finalTranslate,
|
||||
easing: "easeInOutQuad",
|
||||
duration: 500,
|
||||
offset: 1000
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// stacks message from top to bottom
|
||||
const stackAnimate: MessageAnimeFunc = (el, transform) => {
|
||||
const stackAnimate = (el: Element, transform: string) => {
|
||||
anime({
|
||||
targets: el,
|
||||
transform: transform.initialTranslate,
|
||||
transform: transform,
|
||||
easing: "easeInOutQuad",
|
||||
duration: 1000,
|
||||
complete: function() {
|
||||
anime({
|
||||
targets: el,
|
||||
transform: transform.finalTranslate,
|
||||
easing: "easeInOutQuad",
|
||||
duration: 500,
|
||||
offset: 1000
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// update message View bottom bound
|
||||
const shiftView = (el: SVGGElement, transform: string) => {
|
||||
anime({
|
||||
targets: el,
|
||||
transform: transform,
|
||||
easing: "easeInOutQuad",
|
||||
duration: 500,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
shiftAnimate,
|
||||
stackAnimate
|
||||
stackAnimate,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export default function useOffsetCalculator() {
|
|||
let previousMessageHeight = 0;
|
||||
const messagePadding = 15;
|
||||
|
||||
function calculateX(message: HTMLElement): void {
|
||||
function calculateX(message: HTMLElement| SVGGElement): void {
|
||||
const computedQuery = window.getComputedStyle(message);
|
||||
const matrix = new WebKitCSSMatrix(computedQuery.webkitTransform);
|
||||
xOffset.value = matrix.m41;
|
||||
|
|
|
|||
|
|
@ -7,60 +7,62 @@ import { VueTransitionCallback } from '@/types/vue3/vueTransitionCallback/index'
|
|||
import useMessageViewAnims from "./anime";
|
||||
import useOffsetCalculator from './offsetCalculator';
|
||||
|
||||
export default function useMessageView(): {
|
||||
beforeEnter: VueTransitionCallback;
|
||||
enter: VueTransitionCallback;
|
||||
afterEnter: VueTransitionCallback;
|
||||
} {
|
||||
// uses offsetCalculator logic and renderer animations
|
||||
const wH = 500; // window Height
|
||||
const vP = 10; // view padding
|
||||
const mP = 15; // message padding
|
||||
let mH: number; // message Height
|
||||
let vH: number; // view Height
|
||||
let vB: number; // view Bottom Bound
|
||||
let message: HTMLElement | null;
|
||||
let messageOffset = { x: 0, y: 0 };
|
||||
let shift = false;
|
||||
let beforeEnterVH: number;
|
||||
let messageView: SVGGElement;
|
||||
|
||||
export default function useMessageView() {
|
||||
const { calculateMessageOffsets } = useOffsetCalculator();
|
||||
const { shiftAnimate, stackAnimate } = useMessageViewAnims();
|
||||
|
||||
const messagePadding = 15;
|
||||
let messageList: NodeList;
|
||||
let message: HTMLElement | null;
|
||||
let messageOffset = { x: 0, y: 0 };
|
||||
let shift = false;
|
||||
let shiftOffset = 0;
|
||||
|
||||
// animates message item to 'enter' renderView
|
||||
const animateMessage = (el: SVGGElement): void => {
|
||||
|
||||
const transform = {
|
||||
initialTranslate: `translate(${messageOffset.x} ${messageOffset.y})`,
|
||||
finalTranslate: `translate(${messageOffset.x} ${messageOffset.y})`
|
||||
const elTransform = `translate(${messageOffset.x} ${messageOffset.y})`;
|
||||
const viewTransform = `translate(0 ${-vB})`;
|
||||
|
||||
if (shift) {
|
||||
shiftAnimate(el, elTransform, messageView, viewTransform);
|
||||
} else {
|
||||
stackAnimate(el, elTransform)
|
||||
}
|
||||
shift ? shiftAnimate(el, transform, shiftOffset, messageList) : stackAnimate(el, transform);
|
||||
|
||||
}
|
||||
|
||||
const beforeEnter: VueTransitionCallback = () => {
|
||||
const queryResult = document.querySelectorAll(".messageList");
|
||||
console.log(queryResult)
|
||||
if (queryResult.length) messageList = queryResult;
|
||||
// query DOM for messageView element
|
||||
const messageViewQuery = document.querySelectorAll("#messageView");
|
||||
messageView = messageViewQuery[0] as SVGGElement;
|
||||
if (messageViewQuery){
|
||||
beforeEnterVH = messageView.getBBox().height;
|
||||
}
|
||||
}
|
||||
|
||||
const enter: VueTransitionCallback = (el) => {
|
||||
// query DOM for latest message as soon as it enters
|
||||
// query DOM for latest message
|
||||
if (el) {
|
||||
message = document.getElementById(el.id);
|
||||
}
|
||||
}
|
||||
|
||||
const afterEnter: VueTransitionCallback = (el) => {
|
||||
// get message positioning & shift state before animating
|
||||
if (message) {
|
||||
messageOffset = calculateMessageOffsets(message);
|
||||
shift = messageOffset.y > 400 ? true : false;
|
||||
}
|
||||
const afterEnter: VueTransitionCallback = async (el) => {
|
||||
|
||||
if (message) messageOffset = calculateMessageOffsets(message);
|
||||
|
||||
if (el) {
|
||||
if (shift) {
|
||||
shiftOffset -= el.getBBox().height + messagePadding;
|
||||
// if (messageOffset.y < 445) {
|
||||
// shiftOffset -= 15;
|
||||
// } else {
|
||||
// shiftOffset -= el.getBBox().height + messagePadding;
|
||||
// }
|
||||
}
|
||||
// calculate message & view heights, as well as view bottom bound
|
||||
mH = el.getBoundingClientRect().height;
|
||||
vH = mH + beforeEnterVH + mP;
|
||||
vB = Math.abs(vH - wH) + vP;
|
||||
|
||||
shift = vH > wH ? true : false;
|
||||
animateMessage(el);
|
||||
}
|
||||
}
|
||||
|
|
@ -68,6 +70,6 @@ export default function useMessageView(): {
|
|||
return {
|
||||
beforeEnter,
|
||||
enter,
|
||||
afterEnter
|
||||
afterEnter,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
@click="emittMessage"
|
||||
>
|
||||
<MessageView />
|
||||
<TextAudioInput />
|
||||
|
|
@ -26,7 +25,6 @@ export default defineComponent({
|
|||
const counter = ref(0);
|
||||
|
||||
const emittMessage = () => {
|
||||
console.log('testing')
|
||||
emitter.emit('animateSend', Messages[counter.value])
|
||||
counter.value++;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue