Files
RGKT/rg-09112127/js/courseHomeStyle.js
2025-10-10 19:44:14 +08:00

531 lines
18 KiB
JavaScript

(function (win) {
// 初始化样式和方法
console.log("courseHomeStyle init", win, win.location.href,);
if (win.location.href.indexOf("courseHome.html") !== -1) {
// 1、导航条切换
initNav();
// 2、左 侧边栏
initSidebar();
// 3、按钮样式
// 初始化增强的按钮效果
initEnhancedButtonEffects();
// 简化问题文本动画
simplifyQuestionAnimation();
} else if (win.location.href.indexOf("courseHomeBarrierFree.html") !== -1) {
// 1、导航条切换
initNav();
// 2、左 侧边栏
initSidebarBarrier();
}
})(window);
// 1、导航条切换
function initNav() {
$(".container-header-nav > div").each(function (index) {
$(this).on("click", function () {
$(".container-header-nav > div").removeClass("active");
$(this).addClass("active");
window.open(`./${$(this).data("url")}.html`);
// console.log("this", this, $(this));
// $(".container-header-nav > div").eq(index).addClass("active");
});
});
}
// 2、侧边栏
function initSidebar() {
if (
window &&
window.GLOBAL_CONFIG &&
window.GLOBAL_CONFIG.courseList
) {
// 从路由获取当前课程信息 courseHome.html?id=l01
const id = window.location.search.replace("?id=", "") || "m2x04";
const type = {
l: "live",
c: "language",
m: "math",
}[id[0]];
const courseList = window.GLOBAL_CONFIG.courseList[type];
const iconList = {
"course": "📺",
"video": "🤼‍♂️",
"play": "🎮",
};
// console.log("initSidebar", id, type, courseList);
$(".container-main-sidebar .directory-list").empty();
let dom = `<ul class="directory-list">`;
courseList.map((grade, gradeI) => {
grade.map((progress, progressI) => {
dom = `${dom}
<li class="grade-item">
<div class="grade-title">
<span>${gradeI + 1}年级 <span>${"上下"[progressI]}册</span></span>
<span class="arrow">▶</span>
</div>
`;
if (progress) {
dom = `${dom} <ul class="chapter-list">`;
progress.map((chapter, chapterI) => {
dom = `${dom}
<li class="chapter-item">
<div class="chapter-title" data-id="${chapter.id}" >
<span>第${chapterI + 1}${chapter.name}</span>
<span class="arrow">▶</span>
</div>
`;
if (chapter.list) {
dom = `${dom} <ul class="section-list">`;
chapter.list.map((section, sectionI) => {
if (sectionI == 0) {
dom = `${dom}
<div>- 课堂教学 -</div>
`;
}
else if (
sectionI > 0 &&
chapter.list[sectionI - 1].type == "course" &&
section.type == "video"
) {
dom = `${dom}
<div>- 课堂互动 -</div>
`;
}
else if (
sectionI > 0 &&
(chapter.list[sectionI - 1].type == "video" || sectionI == 1) &&
section.type == "play"
) {
dom = `${dom}
<div>- 趣味游戏 -</div>
`;
}
dom = `${dom}
<li class="section-item">
<div
class="section-title"
onclick="sectionClick(event)"
data-info='${JSON.stringify(section)}'
>
<span>${iconList[section.type]}</span>
${section.title}
</div>
</li>
`;
});
dom = `${dom} </ul>`;
};
dom = `${dom} </li>`;
});
dom = `${dom} </ul>`;
}
dom = `${dom} </li>`;
})
});
dom = `${dom} </ul>`;
$(".container-main-sidebar .directory-list").append(dom);
initSidebarEvent();
}
}
// 2、侧边栏 无障碍版本
function initSidebarBarrier() {
if (
window &&
window.GLOBAL_CONFIG &&
window.GLOBAL_CONFIG.playList
) {
let playList = window.GLOBAL_CONFIG.playList;
const typeName = {
"live": "生活",
"language": "语文",
"math": "数学",
};
$(".container-main-sidebar .directory-list").empty();
let dom = `<ul class="directory-list">`;
Object.entries(playList).map((value, valueI) => {
// console.log("initSidebarBarrier", value);
dom = `${dom}
<div
class="type-item"
aria-label="${typeName[value[0]]}课程"
onmouseenter="debouncedSpeechDomTextBarrier(event)"
onmouseout="debouncedSpeechDomTextBarrier(event)"
>
- ${typeName[value[0]]} -
</div>`;
value[1].map((play, playI) => {
dom = `${dom}
<li class="grade-item">
<div
class="grade-title"
aria-label="${typeName[value[0]]}课程中的${play.title}游戏"
onmouseenter="debouncedSpeechDomTextBarrierGame(event)"
onmouseout="debouncedSpeechDomTextBarrierGame(event)"
data-info='${JSON.stringify(play)}'
>
${play.title}
</div>
</li>
`;
});
});
dom = `${dom} </ul>`;
$(".container-main-sidebar .directory-list").append(dom);
// 年级点击事件
$(".container-main-sidebar .grade-title").click(function (event) {
// console.log(".container-main-sidebar .grade-title click", this, event);
if (
event &&
event.target &&
event.target.dataset &&
event.target.dataset.info
) {
const info = JSON.parse(event.target.dataset.info);
let mainPlay = document.getElementById("mainPlay");
mainPlay.src = info.url;
}
// 移除所有active类
$(".container-main-sidebar .grade-title").removeClass("active");
// 为当前点击的添加active类
$(this).addClass("active");
});
}
}
// 2、侧边栏 事件
function initSidebarEvent() {
// 年级点击事件
$(".container-main-sidebar .grade-title").click(function () {
$(this).parent().toggleClass("active");
});
// 章节点击事件
$(".container-main-sidebar .chapter-title").click(function (e) {
e.stopPropagation(); // 阻止事件冒泡到年级标题
$(this).parent().toggleClass("active");
});
// 小节点击事件
$(".container-main-sidebar .section-title").click(function (e) {
e.stopPropagation();
// 移除所有active类
$(".container-main-sidebar .section-title").removeClass("active");
// 为当前点击的添加active类
$(this).addClass("active");
});
$(".container-main .sidebar-circle").click(function (e) {
// 是否隐藏了
const isShow = !$(".container-main-sidebar").hasClass("hidden");
// console.log(".sidebar-circle", e, this, isShow);
$(".container-main-sidebar").toggleClass("hidden");
if (isShow) {
$(".container-main-sidebar").css("width", "0px");
$(this).css("left", "0px");
$(this).text("▶");
$(".container-main-course").css("width", "100%");
} else {
$(".container-main-sidebar").css("width", "var(--sidebar-width)");
$(this).css("left", "var(--sidebar-width)");
$(this).text("◀");
$(".container-main-course").css("width", "calc(100vw - var(--sidebar-width) - 30px)");
}
});
}
// 控制功能按钮的展示隐藏 course-operation
function showOperationDom() {
$(".course-operation").toggleClass("show");
}
// 初始化所有增强的按钮效果
function initEnhancedButtonEffects() {
// 首先解除所有现有的事件绑定,避免重复
$('.box-btn-left, .box-btn-right').off();
// 按钮悬停基本效果
$('.box-btn-left, .box-btn-right').hover(
function () {
const button = $(this);
// 添加文字缩放动画
button.find('.btn-text').css({
'animation': 'text-pop 0.8s ease infinite alternate'
});
// 添加粒子效果
addButtonParticles(button);
// 添加3D变换效果
button.addClass('btn-hover-active');
},
function () {
const button = $(this);
// 移除文字动画
button.find('.btn-text').css({
'animation': 'none'
});
// 移除粒子
removeButtonParticles();
// 移除3D效果
button.removeClass('btn-hover-active');
}
);
// 添加3D移动效果
$('.box-btn-left, .box-btn-right').on('mousemove', function (e) {
const button = $(this);
// 只有在悬停状态才应用3D效果
if (button.hasClass('btn-hover-active')) {
const buttonRect = button[0].getBoundingClientRect();
// 计算鼠标在按钮上的相对位置 (-1 到 1 的范围)
const x = ((e.clientX - buttonRect.left) / buttonRect.width) * 2 - 1;
const y = ((e.clientY - buttonRect.top) / buttonRect.height) * 2 - 1;
// 根据鼠标位置应用3D旋转
button.css({
'transform': `translateY(-50%) scale(1.15) rotateX(${-y * 15}deg) rotateY(${x * 15}deg)`,
'transition': 'transform 0.1s ease'
});
}
});
// 鼠标离开时恢复原始状态
$('.box-btn-left, .box-btn-right').on('mouseleave', function () {
$(this).css({
'transform': 'translateY(-50%)',
'transition': 'transform 0.5s ease'
});
});
// 添加按钮动画样式
addButtonAnimationStyles();
}
// 简化问题文本动画
function simplifyQuestionAnimation() {
// DOMSubtreeModified MutationObserver
$('.box-btn-question').on('MutationObserver', function () {
const question = $(this);
const text = question.text().trim();
if (text.length > 0 && !question.hasClass('animated-question')) {
question.addClass('animated-question');
question.css('opacity', '0');
setTimeout(function () {
// 添加有趣的表情符号
if (!text.includes('🤔')) {
question.html('🤔 ' + text);
}
question.css({
'opacity': '1',
'transform': 'translate(-50%, -65%) scale(1.1)',
'transition': 'all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275)'
});
setTimeout(function () {
question.css({
'transform': 'translate(-50%, -50%) scale(1)',
'transition': 'all 0.4s ease'
});
}, 500);
}, 100);
}
});
}
// 添加按钮动画样式
function addButtonAnimationStyles() {
// 移除现有的样式元素,避免重复
$('#button-animation-styles').remove();
// 创建新的样式元素
const styleElement = document.createElement('style');
styleElement.id = 'button-animation-styles';
styleElement.innerHTML = `
@keyframes text-pop {
0% { transform: scale(1); }
100% { transform: scale(1.1); color: #ff6b6b; }
}
@keyframes shadow-dance {
0% { box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3); }
50% { box-shadow: 0 20px 45px rgba(74, 223, 218, 0.4); }
100% { box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3); }
}
@keyframes particle-float {
0% { transform: translate(-50%, -50%) translateY(0) rotate(0deg); opacity: 0.7; }
100% { transform: translate(-50%, -50%) translateY(-50px) rotate(360deg); opacity: 0; }
}
@keyframes sparkle-float {
0% { transform: scale(0); opacity: 0; }
50% { transform: scale(1); opacity: 0.8; }
100% { transform: scale(0); opacity: 0; }
}
/* 按钮颜色变化动画 */
@keyframes color-shift-left {
0% { background: linear-gradient(145deg, #4adfda, #1bb5ad); }
50% { background: linear-gradient(145deg, #ffa3b7, #ff6b93); }
100% { background: linear-gradient(145deg, #a694ff, #7e64ff); }
}
@keyframes color-shift-right {
0% { background: linear-gradient(145deg, #9bea72, #5cc332); }
50% { background: linear-gradient(145deg, #ffb347, #ffcc33); }
100% { background: linear-gradient(145deg, #66a6ff, #3d7edb); }
}
/* 应用颜色变化动画 */
.box-btn-left.btn-hover-active {
animation: border-dance 3s ease infinite, color-shift-left 6s infinite alternate !important;
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35) !important;
}
.box-btn-right.btn-hover-active {
animation: border-dance 3s ease infinite, color-shift-right 6s infinite alternate !important;
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35) !important;
}
/* 3D文本效果 */
.btn-text {
transition: all 0.3s ease;
}
.btn-hover-active .btn-text {
text-shadow: 2px 2px 0 #ff6b93, 4px 4px 0 rgba(0, 0, 0, 0.2);
letter-spacing: 1px;
}
/* 修复冲突 */
.box-btn-left:hover, .box-btn-right:hover {
animation: none !important;
}
`;
document.head.appendChild(styleElement);
}
// 添加按钮粒子效果
function addButtonParticles(button) {
// 移除已有粒子
removeButtonParticles();
// 获取按钮位置
const buttonPos = button.offset();
const buttonWidth = button.outerWidth();
const buttonHeight = button.outerHeight();
// 创建粒子容器
const particleContainer = $('<div class="button-particles"></div>');
particleContainer.css({
'position': 'absolute',
'left': buttonPos.left + 'px',
'top': buttonPos.top + 'px',
'width': buttonWidth + 'px',
'height': buttonHeight + 'px',
'pointer-events': 'none',
'z-index': 1000
});
// 添加粒子
const colors = ['#ffde59', '#ff914d', '#ff66c4', '#5ce1e6'];
for (let i = 0; i < 12; i++) {
const particle = $('<div class="particle"></div>');
const size = Math.random() * 8 + 4;
const color = colors[Math.floor(Math.random() * colors.length)];
particle.css({
'position': 'absolute',
'width': size + 'px',
'height': size + 'px',
'background-color': color,
'border-radius': '50%',
'left': (Math.random() * 100) + '%',
'top': (Math.random() * 100) + '%',
'opacity': 0.7,
'animation': `particle-float ${Math.random() * 2 + 1}s ease-out infinite`,
'transform': 'translate(-50%, -50%)'
});
particleContainer.append(particle);
}
// 添加闪烁效果
for (let i = 0; i < 5; i++) {
const sparkle = $('<div class="sparkle"></div>');
const size = Math.random() * 6 + 2;
sparkle.css({
'position': 'absolute',
'width': size + 'px',
'height': size + 'px',
'background-color': '#fff',
'border-radius': '50%',
'left': (Math.random() * 100) + '%',
'top': (Math.random() * 100) + '%',
'box-shadow': '0 0 10px 2px rgba(255, 255, 255, 0.8)',
'opacity': 0.8,
'animation': `sparkle-float ${Math.random() * 1.5 + 0.5}s ease-out infinite`
});
particleContainer.append(sparkle);
}
// 添加粒子容器到body
$('body').append(particleContainer);
}
// 移除按钮粒子效果
function removeButtonParticles() {
$('.button-particles').remove();
}