Avatar Directive
The v-avatar
directive is used to display an avatar image, It will use the alt
attribute as the fallback text if the image fails to load. You can pass custom classes to apply styles of your choice.
Usage
View Code
vue
<script setup>
const images = [
{
src: "https://images.pexels.com/photos/1123757/pexels-photo-1123757.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
alt: "AD",
},
{
src: "failed",
alt: "FM",
className: "bg-zinc-100 dark:bg-zinc-800 text-zinc-800 dark:text-zinc-100 font-medium text-2xl rounded-full",
},
{
src: "https://images.pexels.com/photos/1081685/pexels-photo-1081685.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
alt: "JL",
},
{
src: "Failed",
alt: "GM",
className: "bg-green-100 dark:bg-green-800 text-green-800 dark:text-green-100 font-medium text-2xl",
},
];
</script>
<template>
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
<img
v-for="(image, index) in images"
:key="index"
v-avatar:[image.className]
:src="image.src"
:alt="image.alt"
:class="image.className"
class="w-32 h-32 rounded-2xl"
/>
</div>
</template>
<style scoped></style>
Arguments
The v-avatar
does not take any arguments.
Modifiers
The v-avatar
does not take any modifiers.
Source Code
js
export const VAvatar = {
mounted(el, binding) {
el.addEventListener("error", () => {
const img = el;
// Get width and height from inline styles
let width = img.style.width;
let height = img.style.height;
let borderRadius = img.style.borderRadius;
// If not set via inline styles, try to get from computed styles
if (!width || !height || !borderRadius || !backgroundColor) {
const computedStyle = window.getComputedStyle(img);
width = computedStyle.getPropertyValue("width");
height = computedStyle.getPropertyValue("height");
borderRadius = computedStyle.getPropertyValue("border-radius");
}
// If still not available, use naturalWidth and naturalHeight properties
if (!width || !height) {
const naturalWidth = img.naturalWidth;
const naturalHeight = img.naturalHeight;
width = naturalWidth ? `${naturalWidth}px` : null;
height = naturalHeight ? `${naturalHeight}px` : null;
}
// Convert width and height to numbers
const parsedWidth = parseFloat(width);
const parsedHeight = parseFloat(height);
// Convert border-radius to a number or percentage to pixels
let parsedRadius;
if (borderRadius.includes("%")) {
console.log("borderRadius:", borderRadius);
parsedRadius =
(parseFloat(borderRadius) / 100) *
Math.min(parsedWidth, parsedHeight);
} else {
parsedRadius = parseFloat(borderRadius);
}
// Check if parsing was successful and the values are valid
if (
!isNaN(parsedWidth) &&
!isNaN(parsedHeight) &&
parsedWidth > 0 &&
parsedHeight > 0 &&
!isNaN(parsedRadius)
) {
// Create a div element to replace the img element
const div = document.createElement("div");
div.style.width = width;
div.style.height = height;
div.style.borderRadius = borderRadius;
div.style.display = "flex";
div.style.justifyContent = "center";
div.style.alignItems = "center";
if (binding.arg) {
let classes = binding.arg.split(" ");
for (let i = 0; i < classes.length; i++) {
div.classList.add(classes[i]);
}
}
// Create text element
const text = document.createElement("span");
text.textContent = img.alt || "Avatar";
text.style.width = "100%";
text.style.height = "100%";
text.style.display = "flex";
text.style.justifyContent = "center";
text.style.alignItems = "center";
text.style.overflow = "hidden";
text.style.userSelect = "none";
// Append text to div
div.appendChild(text);
// Replace img with div
img.parentNode.replaceChild(div, img);
// Remove event listener
el.removeEventListener("error", () => {});
} else {
console.log("Invalid width, height, or radius");
}
});
},
updated(el, binding) {
// watch for color changes
console.log("updated", binding.value);
},
};