add scroll animate

This commit is contained in:
riqo 2020-10-31 17:04:55 -05:00
commit 47025c3ac4
2 changed files with 104 additions and 81 deletions

View file

@ -4,6 +4,7 @@
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
@click="renderMessage"
>
<defs>
<linearGradient
@ -40,6 +41,7 @@
<g
v-for="(item, index) in renderArr"
:key="index"
:id="index"
class="test"
transform="translate(0, 0)"
>
@ -83,7 +85,7 @@
</template>
<script lang="ts">
import { defineComponent, inject, onMounted, reactive } from "vue";
import { defineComponent, ref, inject, onMounted, reactive } from "vue";
import MessageItem from './UIDetails/messageItem.vue';
import InputItem from "./UIDetails/inputItem.vue";
import Messages from "./UIDetails/messages";
@ -94,30 +96,24 @@ export default defineComponent({
setup() {
const renderArr: Message[] = reactive([])
const messages = Messages;
const count = ref(0);
const { beforeEnter, enter, msgOffset } = useUIindexAnims();
function renderMsg(i: number): void {
setTimeout(() => {
renderArr.push(messages[i]);
}, 2000);
}
function runAnim(): void {
for (let i = 0; i < messages.length; i++) {
renderMsg(i);
}
}
// TODO implemeant Undo animation
function leave() {
}
const renderMessage = () => {
if (count.value < messages.length) {
renderArr.push(messages[count.value])
count.value++;
return;
}
}
onMounted(() => {
runAnim();
});
return {
renderMessage,
renderArr,
msgOffset,
beforeEnter,

View file

@ -1,27 +1,28 @@
import { inject, onMounted } from "vue";
import { inject, onMounted, ref } from "vue";
export default function useUIindexAnims() {
const anime: any = inject("animejs");
const timeline = anime.timeline({ loop: true });
const msgOffset = {
x: 0,
y: 0
};
let winW: number;
let modifier: string;
let msg: any;
let cardsDiv: any;
let msg: HTMLElement | null;
let prevCardH = 0;
let totalHeight = 0;
let messenger: any;
let currentCard: Element;
let messenger: HTMLElement | null;
let renderList: NodeList;
let scrollAnim = false;
let scroll = 0;
onMounted(() => {
messenger = document.getElementById("messenger");
winW = messenger.clientWidth;
if (messenger) {
winW = messenger.clientWidth;
}
});
function getCardHeight(el: any) {
function getSVGElHeight(el: SVGGElement) {
const cardHeight = el.getBBox().height;
return cardHeight;
}
@ -30,93 +31,119 @@ export default function useUIindexAnims() {
const cards = document.querySelectorAll(".test");
if (cards.length) {
renderList = cards;
currentCard = cards.item(cards.length - 1);
for (const card of cards) {
const height = getCardHeight(card);
const el = card as SVGGElement;
const height = getSVGElHeight(el);
totalHeight += height;
}
scrollAnim = totalHeight > 500 ? true : false;
}
}
async function beforeEnter(el: SVGGElement) {
modifier = el.className.baseVal.substring(0, 2);
calculateAllCardsHeight();
if (!scrollAnim) calculateAllCardsHeight();
}
async function stackAnimate(el: any, done: any) {
const paddingLeft = 40;
msg = await document.getElementById(el.id);
const rect = msg.getBoundingClientRect();
const msgW = rect.width;
const msgH = rect.height;
cardsDiv = document.getElementById("cardsDiv");
const cdBox = cardsDiv.getBBox();
if (prevCardH === 0) {
msgOffset.y += cdBox.height;
} else if (prevCardH > msgH) {
// cardsDiv is offset by 17.5
msgOffset.y += prevCardH + msgH / 2 + 17.5;
} else {
msgOffset.y += cdBox.height - 20;
function scrollOffset(l: NodeList, height: number) {
for (const card of l) {
const c = card.parentNode as HTMLElement;
anime({
targets: c,
transform: `translate(0 ${height})`,
easing: "easeInOutQuad",
duration: 500,
})
}
prevCardH = msgH;
}
function scrollAnimate(el: SVGGElement) {
anime({
targets: el,
transform: `translate(${msgOffset.x} ${msgOffset.y})`,
easing: "easeInOutQuad",
duration: 500,
begin: function() {
scrollOffset(renderList, scroll);
},
complete: function() {
anime({
targets: el,
transform: `translate(${msgOffset.x} ${msgOffset.y + 5})`,
offset: 1000
});
}
});
}
function stackAnimate(el: SVGGElement) {
const translateUp = `translate(${msgOffset.x} ${msgOffset.y})`;
const translateDown = `translate(${msgOffset.x} ${msgOffset.y + 5})`;
anime({
targets: el,
transform: translateUp,
easing: "easeInOutQuad",
duration: 1000,
complete: function() {
anime({
targets: el,
transform: translateDown,
easing: "easeInOutQuad",
duration: 500,
offset: 1000
});
}
});
}
function addMessage(el: SVGGElement) {
scrollAnim ? scrollAnimate(el) : stackAnimate(el)
}
function setXoffset(messageWidth: number) {
const paddingLeft = 40;
switch (modifier) {
case "sf":
msgOffset.x = winW - msgW;
msgOffset.x = winW - messageWidth;
break;
case "ai":
msgOffset.x = (winW - msgW) / 2;
msgOffset.x = (winW - messageWidth) / 2;
break;
default:
msgOffset.x = paddingLeft;
}
const translateUp = `translate(${msgOffset.x} ${msgOffset.y})`;
const translateDown = `translate(${msgOffset.x} ${msgOffset.y + 5})`;
timeline
.add({
targets: el,
transform: translateUp,
easing: "easeInOutQuad",
duration: 1000
})
.add({
targets: el,
transform: translateDown,
easing: "easeInOutQuad",
duration: 500,
offset: 1000
});
done;
}
function OffsetMessage() {
// TODO implement individual offset function
}
function scrollOffset(l: NodeList) {
}
async function scrollAnimate(el: any, done: any) {
// get incoming card height
const height = getCardHeight(el);
scrollOffset(renderList)
}
async function enter(el: SVGGElement, done: any) {
if (totalHeight < 500) {
stackAnimate(el, done)
function setYoffset(messageHeight: number) {
if (prevCardH === 0) {
msgOffset.y += messageHeight;
} else {
scrollAnimate(el, done);
msgOffset.y += prevCardH + messageHeight / 2 + 17.5;
}
prevCardH = messageHeight;
}
function calculateMessageOffsets(msg: any) {
const msgRect = msg.getBoundingClientRect();
if (scrollAnim) {
// update scroll
scroll -= msgRect.height + msgRect.height / 2;
}
setXoffset(msgRect.width)
setYoffset(msgRect.height)
}
async function enter(el: SVGGElement) {
msg = await document.getElementById(el.id);
calculateMessageOffsets(msg)
addMessage(el);
}
return {
beforeEnter,
enter,
msgOffset
msgOffset,
addMessage
};
}