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"
|
version="1.1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
@click="renderMessage"
|
||||||
>
|
>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient
|
<linearGradient
|
||||||
|
|
@ -40,6 +41,7 @@
|
||||||
<g
|
<g
|
||||||
v-for="(item, index) in renderArr"
|
v-for="(item, index) in renderArr"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
:id="index"
|
||||||
class="test"
|
class="test"
|
||||||
transform="translate(0, 0)"
|
transform="translate(0, 0)"
|
||||||
>
|
>
|
||||||
|
|
@ -83,7 +85,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<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 MessageItem from './UIDetails/messageItem.vue';
|
||||||
import InputItem from "./UIDetails/inputItem.vue";
|
import InputItem from "./UIDetails/inputItem.vue";
|
||||||
import Messages from "./UIDetails/messages";
|
import Messages from "./UIDetails/messages";
|
||||||
|
|
@ -94,30 +96,24 @@ export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
const renderArr: Message[] = reactive([])
|
const renderArr: Message[] = reactive([])
|
||||||
const messages = Messages;
|
const messages = Messages;
|
||||||
|
const count = ref(0);
|
||||||
|
|
||||||
const { beforeEnter, enter, msgOffset } = useUIindexAnims();
|
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
|
// TODO implemeant Undo animation
|
||||||
function leave() {
|
function leave() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
const renderMessage = () => {
|
||||||
|
if (count.value < messages.length) {
|
||||||
|
renderArr.push(messages[count.value])
|
||||||
|
count.value++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
runAnim();
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
|
renderMessage,
|
||||||
renderArr,
|
renderArr,
|
||||||
msgOffset,
|
msgOffset,
|
||||||
beforeEnter,
|
beforeEnter,
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,28 @@
|
||||||
import { inject, onMounted } from "vue";
|
import { inject, onMounted, ref } from "vue";
|
||||||
export default function useUIindexAnims() {
|
export default function useUIindexAnims() {
|
||||||
const anime: any = inject("animejs");
|
const anime: any = inject("animejs");
|
||||||
const timeline = anime.timeline({ loop: true });
|
|
||||||
const msgOffset = {
|
const msgOffset = {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0
|
y: 0
|
||||||
};
|
};
|
||||||
let winW: number;
|
let winW: number;
|
||||||
let modifier: string;
|
let modifier: string;
|
||||||
let msg: any;
|
let msg: HTMLElement | null;
|
||||||
let cardsDiv: any;
|
|
||||||
let prevCardH = 0;
|
let prevCardH = 0;
|
||||||
let totalHeight = 0;
|
let totalHeight = 0;
|
||||||
let messenger: any;
|
let messenger: HTMLElement | null;
|
||||||
let currentCard: Element;
|
|
||||||
let renderList: NodeList;
|
let renderList: NodeList;
|
||||||
|
let scrollAnim = false;
|
||||||
|
let scroll = 0;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
messenger = document.getElementById("messenger");
|
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;
|
const cardHeight = el.getBBox().height;
|
||||||
return cardHeight;
|
return cardHeight;
|
||||||
}
|
}
|
||||||
|
|
@ -30,93 +31,119 @@ export default function useUIindexAnims() {
|
||||||
const cards = document.querySelectorAll(".test");
|
const cards = document.querySelectorAll(".test");
|
||||||
if (cards.length) {
|
if (cards.length) {
|
||||||
renderList = cards;
|
renderList = cards;
|
||||||
currentCard = cards.item(cards.length - 1);
|
|
||||||
for (const card of cards) {
|
for (const card of cards) {
|
||||||
const height = getCardHeight(card);
|
const el = card as SVGGElement;
|
||||||
|
const height = getSVGElHeight(el);
|
||||||
totalHeight += height;
|
totalHeight += height;
|
||||||
}
|
}
|
||||||
|
scrollAnim = totalHeight > 500 ? true : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function beforeEnter(el: SVGGElement) {
|
async function beforeEnter(el: SVGGElement) {
|
||||||
modifier = el.className.baseVal.substring(0, 2);
|
modifier = el.className.baseVal.substring(0, 2);
|
||||||
calculateAllCardsHeight();
|
if (!scrollAnim) calculateAllCardsHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function stackAnimate(el: any, done: any) {
|
function scrollOffset(l: NodeList, height: number) {
|
||||||
const paddingLeft = 40;
|
for (const card of l) {
|
||||||
msg = await document.getElementById(el.id);
|
const c = card.parentNode as HTMLElement;
|
||||||
const rect = msg.getBoundingClientRect();
|
anime({
|
||||||
const msgW = rect.width;
|
targets: c,
|
||||||
const msgH = rect.height;
|
transform: `translate(0 ${height})`,
|
||||||
cardsDiv = document.getElementById("cardsDiv");
|
easing: "easeInOutQuad",
|
||||||
const cdBox = cardsDiv.getBBox();
|
duration: 500,
|
||||||
|
})
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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) {
|
switch (modifier) {
|
||||||
case "sf":
|
case "sf":
|
||||||
msgOffset.x = winW - msgW;
|
msgOffset.x = winW - messageWidth;
|
||||||
break;
|
break;
|
||||||
case "ai":
|
case "ai":
|
||||||
msgOffset.x = (winW - msgW) / 2;
|
msgOffset.x = (winW - messageWidth) / 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
msgOffset.x = paddingLeft;
|
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() {
|
function setYoffset(messageHeight: number) {
|
||||||
// TODO implement individual offset function
|
if (prevCardH === 0) {
|
||||||
|
msgOffset.y += messageHeight;
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
} else {
|
} 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 {
|
return {
|
||||||
beforeEnter,
|
beforeEnter,
|
||||||
enter,
|
enter,
|
||||||
msgOffset
|
msgOffset,
|
||||||
|
addMessage
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue