add scroll animate
This commit is contained in:
parent
6757303137
commit
47025c3ac4
2 changed files with 104 additions and 81 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue