|
@@ -5,11 +5,15 @@
|
|
|
:style="{'background': 'url('+curMenu.img+') top no-repeat','background-size': 'cover'}"></div>
|
|
|
|
|
|
<!-- 新增浮动图表 -->
|
|
|
- <div class="fixed-chart" @click="toAi">
|
|
|
+ <div class="fixed-chart"
|
|
|
+ @click="toAi"
|
|
|
+ @mouseenter="isHovering = true"
|
|
|
+ @mouseleave="isHovering = false">
|
|
|
<div class="chart-content">
|
|
|
- <img src="/images/home/fixedAi.png" alt="动态图表">
|
|
|
+ <img src="/images/home/fixedAi.png" alt="动态图表">
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
</div>
|
|
|
<div class="content-bg pt10 pb80">
|
|
|
<div class="main pt50">
|
|
@@ -189,11 +193,12 @@ export default {
|
|
|
}],
|
|
|
isTeacher:false,
|
|
|
zpList:[],
|
|
|
- // 新增拖拽相关数据
|
|
|
- dragPosition: { x: 200, y: 300 }, // 初始位置
|
|
|
- dragging: false,
|
|
|
- startX: 0,
|
|
|
- startY: 0
|
|
|
+ // 新增漂浮动画相关数据
|
|
|
+ floatPosition: { x: 0, y: 0 }, // 漂浮位置偏移量
|
|
|
+ floatVelocity: { x: 1, y: 1 }, // 漂浮速度
|
|
|
+ isHovering: false, // 是否鼠标悬停
|
|
|
+ animationFrameId: null, // 动画帧ID
|
|
|
+
|
|
|
}
|
|
|
|
|
|
},
|
|
@@ -359,67 +364,123 @@ export default {
|
|
|
this.liveData[1].bgImg = bgImg2;
|
|
|
}
|
|
|
},
|
|
|
- // 新增拖拽方法
|
|
|
- startDrag(e) {
|
|
|
- this.dragging = true
|
|
|
- const clientX = e.clientX || e.touches[0].clientX
|
|
|
- const clientY = e.clientY || e.touches[0].clientY
|
|
|
+ // 漂浮动画方法
|
|
|
+ startFloating() {
|
|
|
+ const floatElement = document.querySelector('.fixed-chart');
|
|
|
|
|
|
- this.startX = clientX - this.dragPosition.x
|
|
|
- this.startY = clientY - this.dragPosition.y
|
|
|
+ // 初始化位置为元素当前位置
|
|
|
+ const initialRect = floatElement.getBoundingClientRect();
|
|
|
+ this.floatPosition = {
|
|
|
+ x: initialRect.left,
|
|
|
+ y: initialRect.top
|
|
|
+ };
|
|
|
|
|
|
- document.addEventListener('mousemove', this.onDrag)
|
|
|
- document.addEventListener('touchmove', this.onDrag)
|
|
|
- document.addEventListener('mouseup', this.stopDrag)
|
|
|
- document.addEventListener('touchend', this.stopDrag)
|
|
|
- },
|
|
|
- onDrag(e) {
|
|
|
- if (!this.dragging) return
|
|
|
- const clientX = e.clientX || e.touches[0].clientX
|
|
|
- const clientY = e.clientY || e.touches[0].clientY
|
|
|
+ const updatePosition = () => {
|
|
|
+ if (!this.isHovering && !this.dragging) {
|
|
|
+ // 获取窗口尺寸和元素尺寸
|
|
|
+ const windowWidth = window.innerWidth;
|
|
|
+ const windowHeight = window.innerHeight;
|
|
|
+ const elementRect = floatElement.getBoundingClientRect();
|
|
|
+
|
|
|
+ // 更新位置
|
|
|
+ this.floatPosition.x += this.floatVelocity.x;
|
|
|
+ this.floatPosition.y += this.floatVelocity.y;
|
|
|
+
|
|
|
+ // 检测边界碰撞并反弹 - 修正边界检测逻辑
|
|
|
+ if (this.floatPosition.x <= 0 || this.floatPosition.x >= windowWidth - elementRect.width) {
|
|
|
+ this.floatVelocity.x = -this.floatVelocity.x;
|
|
|
+ // 确保不会卡在边界
|
|
|
+ if (this.floatPosition.x <= 0) {
|
|
|
+ this.floatPosition.x = 1;
|
|
|
+ } else {
|
|
|
+ this.floatPosition.x = windowWidth - elementRect.width - 1;
|
|
|
+ }
|
|
|
+ // 添加一点随机性使运动更自然
|
|
|
+ this.floatVelocity.x += (Math.random() - 0.5) * 0.2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.floatPosition.y <= 0 || this.floatPosition.y >= windowHeight - elementRect.height) {
|
|
|
+ this.floatVelocity.y = -this.floatVelocity.y;
|
|
|
+ // 确保不会卡在边界
|
|
|
+ if (this.floatPosition.y <= 0) {
|
|
|
+ this.floatPosition.y = 1;
|
|
|
+ } else {
|
|
|
+ this.floatPosition.y = windowHeight - elementRect.height - 1;
|
|
|
+ }
|
|
|
+ // 添加一点随机性使运动更自然
|
|
|
+ this.floatVelocity.y += (Math.random() - 0.5) * 0.2;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 控制速度在合理范围内
|
|
|
+ this.floatVelocity.x = Math.max(-1.5, Math.min(1.5, this.floatVelocity.x));
|
|
|
+ this.floatVelocity.y = Math.max(-1.5, Math.min(1.5, this.floatVelocity.y));
|
|
|
+
|
|
|
+ // 应用位置 - 使用绝对定位而不是transform
|
|
|
+ floatElement.style.left = `${this.floatPosition.x}px`;
|
|
|
+ floatElement.style.top = `${this.floatPosition.y}px`;
|
|
|
+ floatElement.style.bottom = 'auto';
|
|
|
+ floatElement.style.right = 'auto';
|
|
|
+ }
|
|
|
+
|
|
|
+ this.animationFrameId = requestAnimationFrame(updatePosition);
|
|
|
+ };
|
|
|
|
|
|
- this.dragPosition.x = clientX - this.startX
|
|
|
- this.dragPosition.y = clientY - this.startY
|
|
|
- e.preventDefault()
|
|
|
- },
|
|
|
- stopDrag() {
|
|
|
- this.dragging = false
|
|
|
- document.removeEventListener('mousemove', this.onDrag)
|
|
|
- document.removeEventListener('touchmove', this.onDrag)
|
|
|
+ // 设置初始样式
|
|
|
+ floatElement.style.transition = 'left 0.05s linear, top 0.05s linear';
|
|
|
+
|
|
|
+ updatePosition();
|
|
|
},
|
|
|
|
|
|
+ stopFloating() {
|
|
|
+ if (this.animationFrameId) {
|
|
|
+ cancelAnimationFrame(this.animationFrameId);
|
|
|
+ this.animationFrameId = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
},
|
|
|
mounted() {
|
|
|
this.initZpData(1);
|
|
|
+ // 启动漂浮动画
|
|
|
+ this.startFloating();
|
|
|
+ },
|
|
|
+ beforeUnmount() {
|
|
|
+ // 清理动画
|
|
|
+ this.stopFloating();
|
|
|
},
|
|
|
-
|
|
|
}
|
|
|
</script>
|
|
|
<style lang="scss" scoped>
|
|
|
@import "@/styles/mixin.scss";
|
|
|
</style>
|
|
|
<style lang="scss" scoped>
|
|
|
-// ::v-deep .el-carousel__mask{
|
|
|
-// opacity: 0!important;
|
|
|
-// }
|
|
|
:deep(.el-carousel__mask){
|
|
|
opacity: 0!important;
|
|
|
}
|
|
|
.fixed-chart {
|
|
|
- position: fixed;
|
|
|
- bottom: 10%;
|
|
|
- right: 4%;
|
|
|
+ position: fixed; /* 保持fixed定位,但位置将由JS控制 */
|
|
|
+ bottom: auto; /* 初始值,会被JS覆盖 */
|
|
|
+ right: auto; /* 初始值,会被JS覆盖 */
|
|
|
z-index: 1000;
|
|
|
- width: 250px !important; // 改为固定宽度
|
|
|
- text-align: right; // 新增文本右对齐
|
|
|
- cursor: move; // 添加拖拽光标
|
|
|
- user-select: none; // 防止选中文本
|
|
|
- touch-action: none; // 禁用默认触控行为
|
|
|
+ width: 200px !important;
|
|
|
+ text-align: left;
|
|
|
+ cursor: pointer;
|
|
|
+ user-select: none;
|
|
|
+ touch-action: none;
|
|
|
+ transition: left 0.05s linear, top 0.05s linear; /* 修改过渡效果 */
|
|
|
|
|
|
.chart-content {
|
|
|
- width: 40% !important; // 改为100%宽度
|
|
|
- margin-left: auto; // 新增右对齐关键属性
|
|
|
+ margin-left: auto;
|
|
|
cursor: pointer;
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 100%;
|
|
|
+ height: auto;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ transition-duration: 0.2s; /* 悬停时过渡效果更明显 */
|
|
|
}
|
|
|
}
|
|
|
.main {
|