Widget:Carousel: Difference between revisions
Jump to navigation
Jump to search
Created page with "<div id="carousel-container"></div> <style> →===== 轮播容器 =====: #carousel-container { position: relative; width: 100%; max-width: 960px; margin: 0 auto; overflow: hidden; border-radius: 8px; background: #1a1a1a; } #carousel-container .carousel-wrapper { position: relative; width: 100%; padding-top: 56.25%; →16:9: } #carousel-container .carousel-slide { position: absolute; top: 0; left: 0; width: 10..." |
mNo edit summary |
||
| Line 2: | Line 2: | ||
<style> | <style> | ||
#carousel-container { | #carousel-container { | ||
position: relative; | position: relative; | ||
| Line 9: | Line 8: | ||
margin: 0 auto; | margin: 0 auto; | ||
overflow: hidden; | overflow: hidden; | ||
border-radius: | border-radius: 0; | ||
background: #1a1a1a; | background: #1a1a1a; | ||
} | } | ||
| Line 16: | Line 15: | ||
position: relative; | position: relative; | ||
width: 100%; | width: 100%; | ||
padding-top: 56.25%; | padding-top: 56.25%; | ||
} | } | ||
| Line 102: | Line 101: | ||
} | } | ||
#carousel-container .carousel-indicators { | #carousel-container .carousel-indicators { | ||
display: flex; | display: flex; | ||
| Line 114: | Line 112: | ||
background: rgba(255, 255, 255, 0.35); | background: rgba(255, 255, 255, 0.35); | ||
border: none; | border: none; | ||
border-radius: | border-radius: 0; | ||
cursor: pointer; | cursor: pointer; | ||
padding: 0; | padding: 0; | ||
| Line 130: | Line 128: | ||
width: 0%; | width: 0%; | ||
background: #fb5711; | background: #fb5711; | ||
border-radius: | border-radius: 0; | ||
transition: none; | transition: none; | ||
} | } | ||
| Line 153: | Line 151: | ||
} | } | ||
#carousel-container .carousel-arrow { | #carousel-container .carousel-arrow { | ||
position: absolute; | position: absolute; | ||
| Line 164: | Line 161: | ||
width: 40px; | width: 40px; | ||
height: 40px; | height: 40px; | ||
border-radius: | border-radius: 0; | ||
cursor: pointer; | cursor: pointer; | ||
font-size: 18px; | font-size: 18px; | ||
| Line 190: | Line 187: | ||
} | } | ||
#carousel-container.single-slide .carousel-arrow, | #carousel-container.single-slide .carousel-arrow, | ||
#carousel-container.single-slide .carousel-indicators { | #carousel-container.single-slide .carousel-indicators { | ||
| Line 196: | Line 192: | ||
} | } | ||
@media (max-width: 600px) { | @media (max-width: 600px) { | ||
#carousel-container .slide-content { | #carousel-container .slide-content { | ||
| Line 239: | Line 234: | ||
if (slides.length === 1) container.classList.add('single-slide'); | if (slides.length === 1) container.classList.add('single-slide'); | ||
// | // 构建页面跳转链接,不依赖 mw 对象 | ||
function buildHref(pageName) { | |||
if (!pageName) return '#'; | |||
// 尝试使用 mw.util.getUrl,若不可用则手动拼接 | |||
if (typeof mw !== 'undefined' && mw.util && mw.util.getUrl) { | |||
return mw.util.getUrl(pageName); | |||
} | |||
if (typeof mw !== 'undefined' && mw.config && mw.config.get) { | |||
var path = mw.config.get('wgArticlePath'); | |||
if (path) return path.replace('$1', encodeURIComponent(pageName)); | |||
} | |||
// 最终回退:直接拼 /wiki/ 路径 | |||
return '/wiki/' + encodeURIComponent(pageName.replace(/ /g, '_')); | |||
} | |||
var html = '<div class="carousel-wrapper">'; | var html = '<div class="carousel-wrapper">'; | ||
for (var i = 0; i < slides.length; i++) { | for (var i = 0; i < slides.length; i++) { | ||
var s = slides[i]; | var s = slides[i]; | ||
var href = | var href = buildHref(s.jump); | ||
html += '<a class="carousel-slide' + (i === 0 ? ' active' : '') + '" href="' + href + '">'; | html += '<a class="carousel-slide' + (i === 0 ? ' active' : '') + '" href="' + href + '">'; | ||
html += '<div class="slide-bg" style="background-image:url(\'' + s.image.replace(/'/g, "\\'") + '\')"></div>'; | html += '<div class="slide-bg" style="background-image:url(\'' + s.image.replace(/'/g, "\\'") + '\')"></div>'; | ||
| Line 259: | Line 267: | ||
html += '<p class="slide-desc">' + s.desc + '</p>'; | html += '<p class="slide-desc">' + s.desc + '</p>'; | ||
} | } | ||
if (slides.length > 1) { | if (slides.length > 1) { | ||
html += '<div class="carousel-indicators">'; | html += '<div class="carousel-indicators">'; | ||
| Line 270: | Line 277: | ||
} | } | ||
if (slides.length > 1) { | if (slides.length > 1) { | ||
html += '<button class="carousel-arrow carousel-arrow-left">❮</button>'; | html += '<button class="carousel-arrow carousel-arrow-left">❮</button>'; | ||
| Line 281: | Line 287: | ||
if (slides.length <= 1) return; | if (slides.length <= 1) return; | ||
var current = 0; | var current = 0; | ||
var slideEls = container.querySelectorAll('.carousel-slide'); | var slideEls = container.querySelectorAll('.carousel-slide'); | ||
var timer = null; | var timer = null; | ||
var INTERVAL = 5000; | var INTERVAL = 5000; | ||
function goTo(idx) { | |||
function goTo(idx | |||
if (idx === current) return; | if (idx === current) return; | ||
slideEls[current].classList.remove('active'); | slideEls[current].classList.remove('active'); | ||
| Line 308: | Line 302: | ||
function updateIndicators() { | function updateIndicators() { | ||
var allSets = container.querySelectorAll('.carousel-slide'); | var allSets = container.querySelectorAll('.carousel-slide'); | ||
for (var s = 0; s < allSets.length; s++) { | for (var s = 0; s < allSets.length; s++) { | ||
| Line 317: | Line 310: | ||
inds[j].classList.add('visited'); | inds[j].classList.add('visited'); | ||
} else if (j === current) { | } else if (j === current) { | ||
void inds[j].offsetWidth; | void inds[j].offsetWidth; | ||
} | } | ||
} | } | ||
} | } | ||
setTimeout(function() { | setTimeout(function() { | ||
var | var allSets2 = container.querySelectorAll('.carousel-slide'); | ||
for (var | for (var s = 0; s < allSets2.length; s++) { | ||
var inds = allSets2[s].querySelectorAll('.carousel-indicator'); | |||
if (inds[current]) { | |||
inds[current].classList.add('active'); | |||
} | |||
} | } | ||
}, | }, 20); | ||
} | } | ||
| Line 347: | Line 338: | ||
} | } | ||
container.querySelector('.carousel-arrow-left').addEventListener('click', function(e) { | container.querySelector('.carousel-arrow-left').addEventListener('click', function(e) { | ||
e.preventDefault(); | e.preventDefault(); | ||
| Line 359: | Line 349: | ||
}); | }); | ||
container.addEventListener('click', function(e) { | container.addEventListener('click', function(e) { | ||
var btn = e.target. | var btn = e.target; | ||
while (btn && !btn.classList.contains('carousel-indicator')) { | |||
if (btn === container) { btn = null; break; } | |||
btn = btn.parentElement; | |||
} | |||
if (btn) { | if (btn) { | ||
e.preventDefault(); | e.preventDefault(); | ||
| Line 370: | Line 363: | ||
}); | }); | ||
container.addEventListener('mouseenter', function() { clearInterval(timer); }); | container.addEventListener('mouseenter', function() { clearInterval(timer); }); | ||
container.addEventListener('mouseleave', function() { resetTimer(); }); | container.addEventListener('mouseleave', function() { resetTimer(); }); | ||
Latest revision as of 16:42, 17 April 2026
<style>
- carousel-container {
position: relative; width: 100%; max-width: 960px; margin: 0 auto; overflow: hidden; border-radius: 0; background: #1a1a1a;
}
- carousel-container .carousel-wrapper {
position: relative; width: 100%; padding-top: 56.25%;
}
- carousel-container .carousel-slide {
position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 0.6s ease-in-out; cursor: pointer; display: block; text-decoration: none; color: inherit;
}
- carousel-container .carousel-slide.active {
opacity: 1; z-index: 1;
}
- carousel-container .carousel-slide .slide-bg {
position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-size: cover; background-position: center; background-repeat: no-repeat;
}
- carousel-container .carousel-slide .slide-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(
to top,
rgba(0, 0, 0, 0.85) 0%,
rgba(0, 0, 0, 0.5) 40%,
rgba(0, 0, 0, 0.2) 70%,
rgba(0, 0, 0, 0.1) 100%
);
}
- carousel-container .slide-content {
position: absolute; bottom: 0; left: 0; right: 0; padding: 24px 32px; z-index: 2;
}
- carousel-container .slide-category {
display: inline-block; border: 1.5px solid #ffffff; color: #ffffff; font-size: 11px; font-weight: 700; letter-spacing: 1.5px; padding: 3px 10px; margin-bottom: 16px; text-transform: uppercase; background: transparent;
}
- carousel-container .slide-title {
font-size: 24px; font-weight: 800; color: #ffffff; margin: 0 0 8px 0; line-height: 1.3;
}
- carousel-container .slide-desc {
font-size: 14px; color: rgba(255, 255, 255, 0.85); margin: 0 0 16px 0; font-weight: 500; line-height: 1.5;
}
- carousel-container .carousel-indicators {
display: flex; gap: 6px; align-items: center;
}
- carousel-container .carousel-indicator {
width: 24px; height: 3px; background: rgba(255, 255, 255, 0.35); border: none; border-radius: 0; cursor: pointer; padding: 0; transition: all 0.3s ease; position: relative; overflow: hidden;
}
- carousel-container .carousel-indicator::after {
content: ; position: absolute; top: 0; left: 0; height: 100%; width: 0%; background: #fb5711; border-radius: 0; transition: none;
}
- carousel-container .carousel-indicator.active::after {
width: 100%; transition: width 5s linear;
}
- carousel-container .carousel-indicator.active {
width: 32px; background: rgba(255, 255, 255, 0.2);
}
- carousel-container .carousel-indicator.visited {
background: #fb5711;
}
- carousel-container .carousel-indicator.visited::after {
width: 100%; transition: none;
}
- carousel-container .carousel-arrow {
position: absolute; top: 50%; transform: translateY(-50%); z-index: 10; background: rgba(0, 0, 0, 0.45); border: none; color: #fff; width: 40px; height: 40px; border-radius: 0; cursor: pointer; font-size: 18px; display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.3s ease, background 0.3s ease;
}
- carousel-container:hover .carousel-arrow {
opacity: 1;
}
- carousel-container .carousel-arrow:hover {
background: #fb5711;
}
- carousel-container .carousel-arrow-left {
left: 12px;
}
- carousel-container .carousel-arrow-right {
right: 12px;
}
- carousel-container.single-slide .carousel-arrow,
- carousel-container.single-slide .carousel-indicators {
display: none !important;
}
@media (max-width: 600px) {
#carousel-container .slide-content {
padding: 16px 20px;
}
#carousel-container .slide-title {
font-size: 18px;
}
#carousel-container .slide-desc {
font-size: 12px;
}
#carousel-container .carousel-arrow {
width: 32px;
height: 32px;
font-size: 14px;
}
} </style>
<script> (function() {
function initCarousel() {
var dataEl = document.getElementById('carousel-data');
var container = document.getElementById('carousel-container');
if (!dataEl || !container) return;
var count = parseInt(dataEl.getAttribute('data-count')) || 1;
if (count > 4) count = 4;
var slides = [];
for (var i = 1; i <= count; i++) {
slides.push({
image: dataEl.getAttribute('data-banner' + i) || ,
category: dataEl.getAttribute('data-banner' + i + '-category') || ,
title: dataEl.getAttribute('data-banner' + i + '-title') || ,
desc: dataEl.getAttribute('data-banner' + i + '-desc') || ,
jump: dataEl.getAttribute('data-banner' + i + '-jump') ||
});
}
if (slides.length === 0) return;
if (slides.length === 1) container.classList.add('single-slide');
// 构建页面跳转链接,不依赖 mw 对象
function buildHref(pageName) {
if (!pageName) return '#';
// 尝试使用 mw.util.getUrl,若不可用则手动拼接
if (typeof mw !== 'undefined' && mw.util && mw.util.getUrl) {
return mw.util.getUrl(pageName);
}
if (typeof mw !== 'undefined' && mw.config && mw.config.get) {
var path = mw.config.get('wgArticlePath');
if (path) return path.replace('$1', encodeURIComponent(pageName));
}
// 最终回退:直接拼 /wiki/ 路径
return '/wiki/' + encodeURIComponent(pageName.replace(/ /g, '_'));
}
var html = '
';
for (var i = 0; i < slides.length; i++) {
var s = slides[i];
var href = buildHref(s.jump);
html += '<a class="carousel-slide' + (i === 0 ? ' active' : ) + '" href="' + href + '">';
html += '';
html += '';
html += '</a>';
}
if (slides.length > 1) {
html += '<button class="carousel-arrow carousel-arrow-left">❮</button>';
html += '<button class="carousel-arrow carousel-arrow-right">❯</button>';
}
html += '';
container.innerHTML = html;
if (slides.length <= 1) return;
var current = 0;
var slideEls = container.querySelectorAll('.carousel-slide');
var timer = null;
var INTERVAL = 5000;
function goTo(idx) {
if (idx === current) return;
slideEls[current].classList.remove('active');
current = idx;
slideEls[current].classList.add('active');
updateIndicators();
resetTimer();
}
function updateIndicators() {
var allSets = container.querySelectorAll('.carousel-slide');
for (var s = 0; s < allSets.length; s++) {
var inds = allSets[s].querySelectorAll('.carousel-indicator');
for (var j = 0; j < inds.length; j++) {
inds[j].classList.remove('active', 'visited');
if (j < current) {
inds[j].classList.add('visited');
} else if (j === current) {
void inds[j].offsetWidth;
}
}
}
setTimeout(function() {
var allSets2 = container.querySelectorAll('.carousel-slide');
for (var s = 0; s < allSets2.length; s++) {
var inds = allSets2[s].querySelectorAll('.carousel-indicator');
if (inds[current]) {
inds[current].classList.add('active');
}
}
}, 20);
}
function next() {
goTo((current + 1) % slides.length);
}
function prev() {
goTo((current - 1 + slides.length) % slides.length);
}
function resetTimer() {
clearInterval(timer);
timer = setInterval(next, INTERVAL);
}
container.querySelector('.carousel-arrow-left').addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
prev();
});
container.querySelector('.carousel-arrow-right').addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
next();
});
container.addEventListener('click', function(e) {
var btn = e.target;
while (btn && !btn.classList.contains('carousel-indicator')) {
if (btn === container) { btn = null; break; }
btn = btn.parentElement;
}
if (btn) {
e.preventDefault();
e.stopPropagation();
var idx = parseInt(btn.getAttribute('data-index'));
if (!isNaN(idx)) goTo(idx);
}
});
container.addEventListener('mouseenter', function() { clearInterval(timer); });
container.addEventListener('mouseleave', function() { resetTimer(); });
updateIndicators();
resetTimer();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initCarousel);
} else {
initCarousel();
}
})(); </script>