因为很简单就不介绍了,直接上代码,直接可以用。
<template>
<div class="bubble-box">
<slot></slot>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
const { position, stroke, angle, color } = defineProps({
position: { type: Array, default: ['bottom', '50%'] }, // [位置, 偏移量(百分比)]
stroke: { type: String, default: '0.05' }, // 描边粗细(rem)
angle: { type: String, default: '0.5' }, // 角的大小(rem)
color: { type: Array, default: ['#ffecd0', 'linear-gradient(180deg, #fffdfc 0%, #fffaf0 100%)'] } // [描边颜色, 背景颜色]
});
const getBubbleStyle = () => {
const getCornerStyle = (direction) => {
const styles = {
bottom: `
top: 100%;
left: ${position[1]};
transform: translateX(-50%);
border-color: ${color[0]} transparent transparent transparent;
`,
top: `
bottom: 100%;
left: ${position[1]};
transform: translateX(-50%);
border-color: transparent transparent ${color[0]} transparent;
`,
left: `
right: 100%;
top: ${position[1]};
transform: translateY(-50%);
border-color: transparent ${color[0]} transparent transparent;
`,
right: `
left: 100%;
top: ${position[1]};
transform: translateY(-50%);
border-color: transparent transparent transparent ${color[0]};
`
};
return styles[direction] || '';
};
const getAfterStyle = (direction) => {
const borderColor = color[1].match(/(#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})([0-9A-Fa-f]{2})?|rgb(a?)\(\d{1,3}, \d{1,3}, \d{1,3}(?:, ?\d?(\.\d+)?)?\)|hsl(a?)\(\d{1,3}, \d{1,3}%, \d{1,3}%(?:, ?\d?(\.\d+)?)?\))/i)[0];
const borderWidth = Number(stroke) + 0.03;
const styles = {
bottom: `
margin-top: -${borderWidth}rem;
border-color: ${borderColor} transparent transparent transparent;
`,
top: `
margin-bottom: -${borderWidth}rem;
border-color: transparent transparent ${borderColor} transparent;
`,
left: `
margin-right: -${borderWidth}rem;
border-color: transparent ${borderColor} transparent transparent;
`,
right: `
margin-left: -${borderWidth}rem;
border-color: transparent transparent transparent ${borderColor};
`
};
return styles[direction] || '';
};
return `
.bubble-box {
position: relative;
background: ${color[1]};
border: ${stroke}rem solid ${color[0]};
border-radius: 0.4rem;
}
.bubble-box::before,
.bubble-box::after {
content: '';
position: absolute;
border-width: ${angle}rem;
border-style: solid;
pointer-events: none;
}
.bubble-box::before {
${getCornerStyle(position[0])}
}
.bubble-box::after {
${getCornerStyle(position[0])}
${getAfterStyle(position[0])}
}
`;
};
onMounted(() => {
const style = document.createElement('style');
style.innerHTML = getBubbleStyle();
document.head.appendChild(style);
});
</script>