message positioning for svgs
This commit is contained in:
parent
2d0292fea5
commit
a9fdf8f1b2
6 changed files with 172 additions and 104 deletions
33
src/components/messageView/message/calcPosition.ts
Normal file
33
src/components/messageView/message/calcPosition.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import {computed} from "vue";
|
||||
|
||||
// Size of "side-gutters" of message window.
|
||||
const margin = 20;
|
||||
const messagePadding = 15;
|
||||
const firstChildMargin = 45;
|
||||
|
||||
|
||||
function calcXPosition(messageWidth: number, windowWidth: number, modifier: string) {
|
||||
let offset = margin;
|
||||
|
||||
if (modifier == "sf") {
|
||||
offset = windowWidth - messageWidth - margin;
|
||||
}
|
||||
|
||||
return offset
|
||||
}
|
||||
|
||||
function calcMessagePosition(modifier: string, messageWidth: number,
|
||||
windowWidth: number, anchorPosition: any) {
|
||||
|
||||
const X = calcXPosition(messageWidth, windowWidth, modifier);
|
||||
|
||||
// Depends on if first child.
|
||||
let Y = firstChildMargin;
|
||||
if (anchorPosition != "none") {
|
||||
Y = anchorPosition + messagePadding;
|
||||
}
|
||||
|
||||
return `translate(${X} ${Y})`;
|
||||
}
|
||||
|
||||
export default calcMessagePosition;
|
||||
101
src/components/messageView/message/message.vue
Normal file
101
src/components/messageView/message/message.vue
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
<template>
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="100"
|
||||
height="46"
|
||||
:transform="position"
|
||||
>
|
||||
|
||||
<rect
|
||||
:id="message.id"
|
||||
:class="message.modifier"
|
||||
|
||||
width="100" height="46" rx="10" fill="#58c4fd"
|
||||
/>
|
||||
|
||||
</svg>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import { defineComponent, computed, onMounted, ref, reactive } from "vue";
|
||||
|
||||
import calcMessagePosition from "./calcPosition";
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
name: "MessageBubble",
|
||||
|
||||
props: {
|
||||
|
||||
// DOM ID of the previous message.
|
||||
// Null if message is first child.
|
||||
anchor: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
|
||||
// Passing in the message contents.
|
||||
message: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
|
||||
// e.g. "translate(20 200)"
|
||||
const position = ref("");
|
||||
let anchorPosition: any;
|
||||
|
||||
// Call to update the position variable.
|
||||
const updatePosition = () => {
|
||||
|
||||
// First get anchor's position.
|
||||
if (props.anchor == "none") {
|
||||
anchorPosition = "none";
|
||||
}
|
||||
|
||||
const m = document.getElementById(props.anchor)
|
||||
if (m) {
|
||||
anchorPosition = m.getBoundingClientRect().bottom
|
||||
}
|
||||
|
||||
position.value = calcMessagePosition(
|
||||
props.message.modifier,
|
||||
100,
|
||||
window.innerWidth,
|
||||
anchorPosition
|
||||
);
|
||||
|
||||
console.log(
|
||||
`Message: ${props.message.id}: \n
|
||||
Anchor: ${props.anchor}: ${anchorPosition} \n
|
||||
Position: ${position.value}`
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
// Assign initial position.
|
||||
updatePosition();
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
// We gotta know when the message above us changes position.
|
||||
|
||||
// Add listener for window resize.
|
||||
window.addEventListener("resize", updatePosition);
|
||||
|
||||
})
|
||||
|
||||
return {
|
||||
position
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
});
|
||||
</script>
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
<template>
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="width"
|
||||
height="height"
|
||||
viewBox="0 0 100 46"
|
||||
>
|
||||
|
||||
<rect
|
||||
:id="item.id"
|
||||
:class="item.modifier"
|
||||
:transform="position"
|
||||
|
||||
width="width" height="height" rx="10" fill="#58c4fd"
|
||||
/>
|
||||
|
||||
</svg>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import { defineComponent, computed, onMounted, ref, reactive } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "TextBubble",
|
||||
|
||||
props: {
|
||||
|
||||
// Passing in the message contents.
|
||||
message: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
|
||||
// The position of the bubble.
|
||||
const position = ref()
|
||||
|
||||
// Calculate the position.
|
||||
computed(() => {
|
||||
|
||||
const calculateX = () => {
|
||||
let x = 20 // side-padding
|
||||
|
||||
if (props.message.modifier == 'sf') {
|
||||
x = window.innerWidth - 100 - 20
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
const calculateY = () => {
|
||||
let y = 45 // top-padding
|
||||
|
||||
if (previousMessage) {
|
||||
prev = document.getElementById(previousMessage)
|
||||
prevPosition = prev.getBoundingClientRect().height
|
||||
|
||||
y = prevPosition + 15 // message-message padding
|
||||
}
|
||||
|
||||
return y
|
||||
}
|
||||
|
||||
let X = calculateX();
|
||||
let Y = calculateY();
|
||||
|
||||
position.value = `translate(${X} ${Y})`;
|
||||
|
||||
})
|
||||
|
||||
return {
|
||||
position
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
</script>
|
||||
|
|
@ -65,8 +65,8 @@ export default function useComputedBubble(m: string, id: string) {
|
|||
if (parentView) {
|
||||
const dimensions = parentView.getBoundingClientRect();
|
||||
|
||||
let X = calculateXoffset(dimensions.width);
|
||||
let Y = calculateYoffset(dimensions.height);
|
||||
const X = calculateXoffset(dimensions.width);
|
||||
const Y = calculateYoffset(dimensions.height);
|
||||
|
||||
return `translate(${X} ${Y})`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ export default function useInputController() {
|
|||
audio: 0,
|
||||
text: input
|
||||
};
|
||||
<<<<<<< Updated upstream
|
||||
|
||||
// trigger send animation
|
||||
emitter.emit("animate-send");
|
||||
|
|
@ -40,13 +39,6 @@ export default function useInputController() {
|
|||
|
||||
const {
|
||||
visualizeStreamAsPaths,
|
||||
=======
|
||||
emitter.emit("animate-send", message);
|
||||
}
|
||||
|
||||
const {
|
||||
visualizeStreamAsPaths,
|
||||
>>>>>>> Stashed changes
|
||||
expandBubble
|
||||
} = useAudioVisualizer(visualizeStream);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,38 +2,56 @@
|
|||
|
||||
<TextAudioInput />
|
||||
|
||||
<!-- List of text bubbles. -->
|
||||
<div id="messenger" v-for="message in messages">
|
||||
<!-- <TextBubble :message="message"/> -->
|
||||
<div>Hello</div>
|
||||
<!-- List of message bubbles. -->
|
||||
<div id="messenger">
|
||||
|
||||
<MessageBubble id="message" v-for="(message, index) in messages"
|
||||
:message="message"
|
||||
:anchor="getAnchor(index)"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import { defineComponent, reactive, onMounted } from "vue";
|
||||
import { defineComponent, computed, reactive, onMounted, ref } from "vue";
|
||||
|
||||
import TextAudioInput from "@/components/taInput/index.vue";
|
||||
// import TextBubble from "@/components/messageView/textBubble.vue";
|
||||
import MessageBubble from "@/components/messageView/message/message.vue";
|
||||
import { Message } from "@/types/message/index";
|
||||
|
||||
export default defineComponent({
|
||||
name: "Messenger",
|
||||
|
||||
components: {
|
||||
// TextBubble
|
||||
components: {
|
||||
MessageBubble,
|
||||
TextAudioInput
|
||||
},
|
||||
|
||||
setup() {
|
||||
setup(props) {
|
||||
|
||||
// List of messages in the view.
|
||||
// Oldest message first.
|
||||
const messages: Message[] = reactive([])
|
||||
|
||||
// Render a message.
|
||||
const render = (message: Message) => {
|
||||
messages.push(message)
|
||||
console.log(`Pushing: ${message.modifier}: ${message.content}`)
|
||||
}
|
||||
|
||||
// Get the "anchor" message for a given message.
|
||||
const getAnchor = (index: number) => {
|
||||
let anchor = "none";
|
||||
|
||||
// If not the first message.
|
||||
if (index > 0) {
|
||||
anchor = messages[index - 1].id
|
||||
}
|
||||
|
||||
return anchor
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
|
@ -46,7 +64,8 @@ export default defineComponent({
|
|||
})
|
||||
|
||||
return {
|
||||
messages
|
||||
messages,
|
||||
getAnchor
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -59,9 +78,15 @@ export default defineComponent({
|
|||
|
||||
#messenger {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
min-height: 100vh;
|
||||
|
||||
overflow: scroll;
|
||||
|
||||
background-color: #EBEBEB;
|
||||
}
|
||||
|
||||
#message {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue