| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- <template>
- <view class="load-container">
- <view class="loading-card">
- <view class="loading-animation">
- <view class="ring ring-1"></view>
- <view class="ring ring-2"></view>
- <view class="ring ring-3"></view>
- <view class="center-ball">
- <view class="highlight"></view>
- <!-- 核心:绑定计算出的弦长宽度 -->
- <view class="horizontal-highlight"
- :style="{ top: 100 - progress + '%', width: chordWidth + '%', height: chordHeight + '%' }"></view>
- </view>
- <view class="floating-dots">
- <view class="dot dot-green"></view>
- <view class="dot dot-yellow"></view>
- <view class="dot dot-blue"></view>
- </view>
- </view>
- <view class="progress-text">{{ progress }}%</view>
- <view class="status-text">{{ statusText }}</view>
- </view>
- </view>
- </template>
- <script>
- export default {
- props: {
- progress: {
- type: Number,
- default: 50
- },
- statusText: {
- type: String,
- default: '正在分析您的简历...'
- }
- },
- data() {
- return {
- show: true
- }
- },
- computed: {
- // 核心修正:用圆的弦长公式计算宽度
- chordWidth() {
- const ballRadius = 130; // 光球半径(260rpx / 2)
- const ballDiameter = 260; // 光球直径
- // 计算高光带的y坐标(rpx)
- const highlightY = ((100 - this.progress) / 100) * ballDiameter;
- // 计算圆心到高光带的垂直距离d
- const d = Math.abs(highlightY - ballRadius);
- // 当d >= 半径时,弦长为0(高光带在圆外)
- if (d >= ballRadius) return 0;
- // 计算弦长(rpx)
- const chordLength = 2 * Math.sqrt(Math.pow(ballRadius, 2) - Math.pow(d, 2));
- // 转化为百分比
- return (chordLength / ballDiameter) * 100;
- },
- chordHeight() {
- if (this.progress < 20 || this.progress > 80) {
- let height = 0
- if (this.progress < 25) {
- height = this.progress
- } else {
- height = 100 - this.progress
- }
- return height
- } else {
- return 20
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .load-container {
- position: fixed;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- background: rgba(0, 0, 0, 0.5);
- }
-
- /* 原有样式不变,仅保证horizontal-highlight的定位正确 */
- .horizontal-highlight {
- position: absolute;
- top: 0%;
- left: 50%;
- transform: translate(-50%, -50%);
- width: 0%;
- height: 0%;
- border-radius: 50%;
- background: radial-gradient(ellipse at center,
- rgba(255, 255, 255, 0.7) 0%,
- rgba(255, 255, 255, 0.3) 50%,
- transparent 100%);
- pointer-events: none;
- z-index: 100;
- transition: width 0.8s ease, top 0.8s ease;
- }
- /* 其他样式保持不变 */
- .loading-card {
- width: 560rpx;
- padding: 60rpx 40rpx;
- background: #fff;
- border-radius: 24rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.05);
- }
- .loading-animation {
- position: relative;
- width: 320rpx;
- height: 320rpx;
- margin-bottom: 30rpx;
- }
- .ring {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- border-radius: 50%;
- background: rgba(255, 215, 186, 0.3);
- }
- .ring-1 {
- width: 100%;
- height: 100%;
- opacity: 0.8;
- }
- .ring-2 {
- width: 120%;
- height: 120%;
- opacity: 0.5;
- }
- .ring-3 {
- width: 140%;
- height: 140%;
- opacity: 0.3;
- }
- .center-ball {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- width: 260rpx;
- height: 260rpx;
- border-radius: 50%;
- box-shadow: 0px 7px 37px 0px rgba(239, 181, 157, 0.62);
- background: linear-gradient(159.89deg, rgba(236, 241, 252, 1) -2.225%, rgba(255, 249.54, 246.5, 1) 17.355%, rgba(255, 166, 130, 1) 69.089%, rgba(253.94, 184.19, 155.54, 1) 90.285%);
- overflow: hidden;
- }
- .highlight {
- position: absolute;
- top: 10%;
- left: 20%;
- width: 60%;
- height: 60%;
- border-radius: 50%;
- background: radial-gradient(circle at center, rgba(255, 255, 255, 0.8) 0%, transparent 70%);
- pointer-events: none;
- }
- .floating-dots {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- pointer-events: none;
- }
- .dot {
- position: absolute;
- width: 12rpx;
- height: 12rpx;
- border-radius: 50%;
- opacity: 0.8;
- }
- .dot-green {
- background: #4ade80;
- animation: floatGreen 12s ease-in-out infinite;
- }
- .dot-yellow {
- background: #fbbf24;
- animation: floatYellow 15s ease-in-out infinite;
- }
- .dot-blue {
- background: #60a5fa;
- animation: floatBlue 10s ease-in-out infinite;
- }
- @keyframes floatGreen {
- 0% {
- transform: translate(40rpx, 60rpx);
- }
- 50% {
- transform: translate(60rpx, 40rpx);
- }
- 100% {
- transform: translate(40rpx, 60rpx);
- }
- }
- @keyframes floatYellow {
- 0% {
- transform: translate(300rpx, 140rpx);
- }
- 50% {
- transform: translate(280rpx, 80rpx);
- }
- 100% {
- transform: translate(300rpx, 140rpx);
- }
- }
- @keyframes floatBlue {
- 0% {
- transform: translate(280rpx, 240rpx);
- }
- 50% {
- transform: translate(240rpx, 280rpx);
- }
- 100% {
- transform: translate(280rpx, 240rpx);
- }
- }
- .progress-text {
- width: 100%;
- font-size: 48rpx;
- font-weight: bold;
- text-align: center;
- color: #ff7d45;
- margin-bottom: 12rpx;
- }
- .status-text {
- font-size: 28rpx;
- color: #666;
- text-align: center;
- line-height: 1.5;
- }
- </style>
|