<template> <div :class="[ `text-[${fontSize}px]`, 'overflow-hidden', 'transition-height duration-500 ease-in-out', (showSuspension && !expanded) ? 'suspension' : '' ]" :style="{ lineHeight: `${fontSize * props.lineHeightScale}px `, maxHeight: !expanded ? `${fontSize * maxLines * props.lineHeightScale}px` : `${height}px`, }" > <div v-resize="getHeight" v-highlight="props.text" ></div> </div> <div class="flex items-center justify-center cursor-pointer" ref="slotRef" v-if="showSuspension"> <a class="mt-2" @click="toggle"> {{ expanded ? closeText : openText }} </a> </div> </template>
<script lang="ts" setup> import { onMounted, ref } from 'vue'; import { vHighlight } from '/@/directives/text';
const props = withDefaults( defineProps<{ text: string; maxLines: number; fontSize: number; lineHeightScale: number; openText: string; closeText: string; }>(), { text: '', maxLines: 3, fontSize: 14, lineHeightScale: 1.5, openText: '查看更多', closeText: '收起', }, );
let expanded = ref<boolean>(false); let slotRef = ref<HTMLElement>(); const showSuspension = ref(false); const height = ref<number>(0); const getHeight = (rect: ClientRect) => { height.value = rect.height; console.log('height: ', rect.height); if (rect.height > props.fontSize * props.maxLines * props.lineHeightScale) { showSuspension.value = true; } else { showSuspension.value = false; } };
const toggle = () => { expanded.value = !expanded.value; }; onMounted(() => {}); </script>
<style scoped lang="less"> .suspension { position: relative; &::after { background: linear-gradient(90deg, hsla(0, 0%, 100%, 0.5), #fff 40%); bottom: 0; content: '...'; padding-left: 30px; position: absolute; right: 0; width: 50px; z-index: 100; } } </style>
|