text.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <template>
  2. <div class="text-stage">
  3. <div class="wrapper">
  4. <div class="slash"></div>
  5. <div class="sides">
  6. <div class="side"></div>
  7. <div class="side"></div>
  8. <div class="side"></div>
  9. <div class="side"></div>
  10. </div>
  11. <div class="text">
  12. <div class="text--backing">{{ modelValue }}</div>
  13. <div class="text--left">
  14. <div class="inner">{{ modelValue }}</div>
  15. </div>
  16. <div class="text--right">
  17. <div class="inner">{{ modelValue }}</div>
  18. </div>
  19. </div>
  20. </div>
  21. </div>
  22. </template>
  23. <script lang="ts" setup>
  24. defineProps({
  25. fontSize: {
  26. type: String,
  27. default: "30px"
  28. },
  29. color: {
  30. type: String,
  31. default: "#000000"
  32. },
  33. modelValue: String
  34. });
  35. </script>
  36. <style lang="scss" scoped>
  37. $color: var(--el-text-color-primary);
  38. .text-stage {
  39. display: flex;
  40. align-items: center;
  41. justify-content: center;
  42. }
  43. .wrapper {
  44. position: relative;
  45. font-size: v-bind(fontSize);
  46. color: $color;
  47. padding: 10px;
  48. }
  49. .slash {
  50. position: absolute;
  51. top: 50%;
  52. left: 50%;
  53. transform: translate(-50%, -50%) rotate(-24deg) scaleY(0);
  54. transform-origin: center center;
  55. width: 0.15rem;
  56. height: 145%;
  57. background-color: $color;
  58. z-index: 4;
  59. animation: slash 6s ease-in forwards;
  60. &:before {
  61. content: "";
  62. display: block;
  63. position: absolute;
  64. top: 50%;
  65. left: 50%;
  66. transform: translate(-50%, -50%);
  67. width: 0.75rem;
  68. height: 120%;
  69. background-color: $color;
  70. z-index: -1;
  71. opacity: 0.2;
  72. }
  73. &:after {
  74. content: "";
  75. display: block;
  76. position: absolute;
  77. top: 0;
  78. left: 0;
  79. width: 100%;
  80. height: 100%;
  81. background-color: $color;
  82. }
  83. }
  84. .sides {
  85. position: absolute;
  86. width: 100%;
  87. height: 100%;
  88. top: 0;
  89. left: 0;
  90. overflow: hidden;
  91. .side {
  92. position: absolute;
  93. background-color: $color;
  94. }
  95. .side:nth-child(1) {
  96. top: 0;
  97. left: 0;
  98. width: 100%;
  99. height: 0.15rem;
  100. transform: translateX(-101%);
  101. animation: side-top ease 6s forwards;
  102. }
  103. .side:nth-child(2) {
  104. top: 0;
  105. right: 0;
  106. width: 0.15rem;
  107. height: 100%;
  108. transform: translateY(-101%);
  109. animation: side-right ease 6s forwards;
  110. }
  111. .side:nth-child(3) {
  112. left: 0;
  113. bottom: 0;
  114. width: 100%;
  115. height: 0.15rem;
  116. transform: translateX(101%);
  117. animation: side-bottom ease 6s forwards;
  118. }
  119. .side:nth-child(4) {
  120. top: 0;
  121. left: 0;
  122. width: 0.15rem;
  123. height: 100%;
  124. transform: translateY(101%);
  125. animation: side-left ease 6s forwards;
  126. }
  127. }
  128. .text {
  129. position: relative;
  130. * {
  131. white-space: nowrap;
  132. }
  133. }
  134. .text--backing {
  135. opacity: 0;
  136. }
  137. .text--left {
  138. position: absolute;
  139. top: 0;
  140. left: 0;
  141. width: 51%;
  142. height: 100%;
  143. overflow: hidden;
  144. .inner {
  145. transform: translateX(100%);
  146. animation: text-left 6s ease-in-out forwards;
  147. }
  148. }
  149. .text--right {
  150. position: absolute;
  151. top: 0;
  152. right: 0;
  153. width: 50%;
  154. height: 100%;
  155. overflow: hidden;
  156. .inner {
  157. transform: translateX(-200%);
  158. animation: text-right 6s ease-in-out forwards;
  159. }
  160. }
  161. @keyframes slash {
  162. 0% {
  163. transform: translate(-50%, -50%) rotate(-24deg) scaleY(0);
  164. }
  165. 6% {
  166. transform: translate(-50%, -50%) rotate(-24deg) scaleY(1);
  167. }
  168. 13% {
  169. transform: translate(-50%, -50%) rotate(-24deg) scaleY(1);
  170. }
  171. 16.6% {
  172. transform: translate(-50%, -50%) rotate(-24deg) scaleY(0);
  173. }
  174. 100% {
  175. transform: translate(-50%, -50%) rotate(-24deg) scaleY(0);
  176. }
  177. }
  178. @keyframes text-left {
  179. 0% {
  180. transform: translateX(100%);
  181. }
  182. 10% {
  183. transform: translateX(0);
  184. }
  185. 100% {
  186. transform: translateX(0);
  187. }
  188. }
  189. @keyframes text-right {
  190. 0% {
  191. transform: translateX(-200%);
  192. }
  193. 10% {
  194. transform: translateX(-100%);
  195. }
  196. 100% {
  197. transform: translateX(-100%);
  198. }
  199. }
  200. @keyframes side-top {
  201. 0%,
  202. 14% {
  203. transform: translateX(-101%);
  204. }
  205. 24%,
  206. 100% {
  207. transform: translateX(0);
  208. }
  209. }
  210. @keyframes side-right {
  211. 0%,
  212. 14%,
  213. 23% {
  214. transform: translateY(-101%);
  215. }
  216. 30%,
  217. 100% {
  218. transform: translateY(0);
  219. }
  220. }
  221. @keyframes side-bottom {
  222. 0%,
  223. 14%,
  224. 24%,
  225. 28% {
  226. transform: translateX(101%);
  227. }
  228. 37%,
  229. 100% {
  230. transform: translateX(0);
  231. }
  232. }
  233. @keyframes side-left {
  234. 0%,
  235. 14%,
  236. 24%,
  237. 34%,
  238. 35% {
  239. transform: translateY(101%);
  240. }
  241. 44%,
  242. 100% {
  243. transform: translateY(0);
  244. }
  245. }
  246. </style>