微件:Card:修订间差异

来自卡厄思梦境WIKI
跳转到导航 跳转到搜索
律Rhyme留言 | 贡献
创建页面,内容为“<noinclude> 此Widget为卡牌显示添加交互效果: * 鼠标悬停时的动画效果 * 点击后显示放大的模态框 * 支持点击遮罩或关闭按钮关闭模态框 使用方法:在页面中添加 {{#widget:Card}} </noinclude><includeonly> <style> 卡牌悬停动画:​ .card-deck-trans { cursor: pointer; transition: transform 0.3s ease, box-shadow 0.3s ease; } .card-deck-trans:hover { transform: translateY(-8px); filter: brig…”
 
律Rhyme留言 | 贡献
功能测试
第3行: 第3行:
* 鼠标悬停时的动画效果
* 鼠标悬停时的动画效果
* 点击后显示放大的模态框
* 点击后显示放大的模态框
* 支持点击遮罩或关闭按钮关闭模态框
* 自动检测spark_enable属性显示闪光按钮
* 支持闪光卡牌列表显示


使用方法:在页面中添加 {{#widget:Card}}
使用方法:在页面底部添加 <code>{{#widget:Card}}</code>
</noinclude><includeonly>
</noinclude><includeonly>
<style>
<style>
/* 卡牌容器 */
.card-wrapper {
    display: inline-block;
}
/* 卡牌悬停动画 */
/* 卡牌悬停动画 */
.card-deck-trans {
.card-deck-trans {
     cursor: pointer;
     cursor: pointer;
     transition: transform 0.3s ease, box-shadow 0.3s ease;
     transition: transform 0.3s ease, box-shadow 0.3s ease, filter 0.3s ease;
}
}


第23行: 第29行:
}
}


/* 模态框样式 */
/* 模态框通用样式 */
.card-modal-overlay {
.card-modal-overlay,
.spark-modal-overlay {
     display: none;
     display: none;
     position: fixed;
     position: fixed;
第39行: 第46行:
}
}


.card-modal-overlay.active {
.spark-modal-overlay {
    z-index: 10010;
    background-color: rgba(0, 0, 0, 0.9);
}
 
.card-modal-overlay.active,
.spark-modal-overlay.active {
     display: flex;
     display: flex;
     opacity: 1;
     opacity: 1;
}
}


.card-modal-overlay.fade-in {
.card-modal-overlay.fade-in,
.spark-modal-overlay.fade-in {
     opacity: 1;
     opacity: 1;
}
}


.card-modal-overlay.fade-out {
.card-modal-overlay.fade-out,
.spark-modal-overlay.fade-out {
     opacity: 0;
     opacity: 0;
}
}


/* 关闭按钮 */
/* 关闭按钮 */
.card-modal-close {
.card-modal-close,
.spark-modal-close {
     position: fixed;
     position: fixed;
     top: 20px;
     top: 20px;
第67行: 第83行:
}
}


.card-modal-close:hover {
.spark-modal-close {
    z-index: 10012;
}
 
.card-modal-close:hover,
.spark-modal-close:hover {
     color: #ff6b6b;
     color: #ff6b6b;
     transform: scale(1.1);
     transform: scale(1.1);
第76行: 第97行:
     position: relative;
     position: relative;
     z-index: 10000;
     z-index: 10000;
    display: flex;
    flex-direction: column;
    align-items: center;
    animation: cardZoomIn 0.3s ease;
}
.spark-modal-content {
    position: relative;
    z-index: 10011;
    max-width: 90vw;
    max-height: 85vh;
    overflow-y: auto;
    padding: 20px;
     animation: cardZoomIn 0.3s ease;
     animation: cardZoomIn 0.3s ease;
}
}
第91行: 第125行:


/* 放大后的卡牌样式 */
/* 放大后的卡牌样式 */
.card-modal-content .card-deck-trans {
.card-modal-content > .card-deck-trans,
.card-modal-content > .card-wrapper > .card-deck-trans {
    width: 270px !important;
    height: 384px !important;
    transform: none !important;
    filter: none !important;
    cursor: default;
}
 
.card-modal-content > .card-deck-trans:hover,
.card-modal-content > .card-wrapper > .card-deck-trans:hover {
    transform: none !important;
    filter: none !important;
}
 
.card-modal-content > .card-deck-trans > .card-deck,
.card-modal-content > .card-wrapper > .card-deck-trans > .card-deck {
    transform: scale(0.6) !important;
}
 
/* 闪光按钮 */
.spark-button {
    margin-top: 20px;
    padding: 12px 36px;
    font-size: 18px;
    font-weight: bold;
    color: #fff;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border: 2px solid #a78bfa;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.3s ease;
    box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
 
.spark-button:hover {
    background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
    box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
    transform: translateY(-2px);
}
 
.spark-button:active {
    transform: translateY(0);
    box-shadow: 0 2px 10px rgba(102, 126, 234, 0.4);
}
 
/* 闪光图标动画 */
.spark-button::before {
    content: "✦ ";
    animation: sparkle 1.5s ease-in-out infinite;
}
 
.spark-button::after {
    content: " ✦";
    animation: sparkle 1.5s ease-in-out infinite 0.75s;
}
 
@keyframes sparkle {
    0%, 100% { opacity: 0.5; }
    50% { opacity: 1; }
}
 
/* 闪光卡牌列表样式 */
.spark-modal-title {
    text-align: center;
    color: #fff;
    font-size: 24px;
    font-weight: bold;
    margin-bottom: 20px;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
}
 
.spark-modal-title::before {
    content: "✦ ";
    color: #a78bfa;
}
 
.spark-modal-title::after {
    content: " ✦";
    color: #a78bfa;
}
 
.spark-card-list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 15px;
}
 
.spark-card-list .card-wrapper {
    display: inline-block;
}
 
.spark-card-list .card-deck-trans {
    cursor: pointer;
}
 
.spark-card-list .card-deck-trans:hover {
    transform: translateY(-8px);
    filter: brightness(1.1);
}
 
/* 加载提示 */
.spark-loading {
    color: #fff;
    font-size: 18px;
    text-align: center;
    padding: 40px;
}
 
.spark-loading::after {
    content: "";
    animation: loadingDots 1.5s infinite;
}
 
@keyframes loadingDots {
    0% { content: ""; }
    25% { content: "."; }
    50% { content: ".."; }
    75% { content: "..."; }
}
 
/* 空列表提示 */
.spark-empty {
    color: #999;
    font-size: 16px;
    text-align: center;
    padding: 40px;
}
 
/* 放大的闪光卡牌 */
.spark-enlarged-container {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    background: rgba(0, 0, 0, 0.95);
    z-index: 10015;
    animation: cardZoomIn 0.3s ease;
}
 
.spark-enlarged-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
}
 
.spark-enlarged-card .card-deck-trans {
     width: 270px !important;
     width: 270px !important;
     height: 384px !important;
     height: 384px !important;
     transform: none !important;
     transform: none !important;
     filter: none !important;
     filter: none !important;
    cursor: default;
}
}


.card-modal-content .card-deck-trans:hover {
.spark-enlarged-card .card-deck-trans:hover {
     transform: none !important;
     transform: none !important;
     filter: none !important;
     filter: none !important;
}
}


.card-modal-content .card-deck {
.spark-enlarged-card .card-deck {
     transform: scale(0.6) !important;
     transform: scale(0.6) !important;
}
.spark-enlarged-close {
    position: fixed;
    top: 20px;
    right: 30px;
    font-size: 48px;
    font-weight: bold;
    color: #ffffff;
    cursor: pointer;
    z-index: 10016;
    line-height: 1;
    transition: color 0.2s ease, transform 0.2s ease;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
}
.spark-enlarged-close:hover {
    color: #ff6b6b;
    transform: scale(1.1);
}
}


第110行: 第317行:
body.card-modal-open {
body.card-modal-open {
     overflow: hidden;
     overflow: hidden;
}
/* 滚动条样式 */
.spark-modal-content::-webkit-scrollbar {
    width: 8px;
}
.spark-modal-content::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.1);
    border-radius: 4px;
}
.spark-modal-content::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.3);
    border-radius: 4px;
}
.spark-modal-content::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.5);
}
}
</style>
</style>
第125行: 第351行:
      
      
     function initCardWidget() {
     function initCardWidget() {
         // 创建模态框元素(如果不存在)
         // 创建主模态框元素(如果不存在)
         let modalOverlay = document.querySelector('.card-modal-overlay');
         var modalOverlay = document.querySelector('.card-modal-overlay');
          
          
         if (!modalOverlay) {
         if (!modalOverlay) {
第135行: 第361行:
         }
         }
          
          
         const modalContent = modalOverlay.querySelector('.card-modal-content');
         // 创建闪光卡牌模态框(如果不存在)
         const closeButton = modalOverlay.querySelector('.card-modal-close');
        var sparkModalOverlay = document.querySelector('.spark-modal-overlay');
          
        if (!sparkModalOverlay) {
            sparkModalOverlay = document.createElement('div');
            sparkModalOverlay.className = 'spark-modal-overlay';
            sparkModalOverlay.innerHTML = '<span class="spark-modal-close">&times;</span><div class="spark-modal-content"></div>';
            document.body.appendChild(sparkModalOverlay);
        }
          
          
         // 关闭模态框函数
        var modalContent = modalOverlay.querySelector('.card-modal-content');
        var closeButton = modalOverlay.querySelector('.card-modal-close');
        var sparkModalContent = sparkModalOverlay.querySelector('.spark-modal-content');
        var sparkCloseButton = sparkModalOverlay.querySelector('.spark-modal-close');
       
         // 当前放大的闪光卡牌容器
        var currentEnlargedContainer = null;
       
        // 关闭主模态框函数
         function closeModal() {
         function closeModal() {
             modalOverlay.classList.add('fade-out');
             modalOverlay.classList.add('fade-out');
第148行: 第389行:
         }
         }
          
          
         // 打开模态框函数
         // 关闭闪光模态框函数
         function openModal(cardElement) {
        function closeSparkModal() {
             const cardClone = cardElement.cloneNode(true);
            // 先关闭放大的卡牌
            if (currentEnlargedContainer) {
                currentEnlargedContainer.remove();
                currentEnlargedContainer = null;
            }
           
            sparkModalOverlay.classList.add('fade-out');
            setTimeout(function() {
                sparkModalOverlay.classList.remove('active', 'fade-in', 'fade-out');
                sparkModalContent.innerHTML = '';
            }, 300);
        }
       
        // 关闭放大的闪光卡牌
        function closeEnlargedCard() {
            if (currentEnlargedContainer) {
                currentEnlargedContainer.remove();
                currentEnlargedContainer = null;
            }
        }
       
        // 打开主模态框函数
         function openModal(cardElement, cardId, sparkEnable) {
             var cardClone = cardElement.cloneNode(true);
            // 移除克隆卡牌的点击事件标记
            delete cardClone.dataset.cardBound;
           
             modalContent.innerHTML = '';
             modalContent.innerHTML = '';
             modalContent.appendChild(cardClone);
             modalContent.appendChild(cardClone);
           
            // 如果启用了闪光功能,添加闪光按钮
            if (sparkEnable && sparkEnable.trim() !== '') {
                var sparkButton = document.createElement('button');
                sparkButton.className = 'spark-button';
                sparkButton.textContent = '闪光';
                sparkButton.dataset.cardId = cardId;
                sparkButton.addEventListener('click', function() {
                    openSparkModal(cardId);
                });
                modalContent.appendChild(sparkButton);
            }
              
              
             modalOverlay.classList.add('active');
             modalOverlay.classList.add('active');
第160行: 第439行:
             requestAnimationFrame(function() {
             requestAnimationFrame(function() {
                 modalOverlay.classList.add('fade-in');
                 modalOverlay.classList.add('fade-in');
            });
        }
       
        // 打开闪光卡牌模态框
        function openSparkModal(cardId) {
            sparkModalContent.innerHTML = '<div class="spark-modal-title">闪光卡牌列表</div><div class="spark-loading">加载中</div>';
           
            sparkModalOverlay.classList.add('active');
            requestAnimationFrame(function() {
                sparkModalOverlay.classList.add('fade-in');
            });
           
            // 通过API获取闪光卡牌列表
            var api = new mw.Api();
            api.get({
                action: 'parse',
                text: '{{Card/spark/list|' + cardId + '}}',
                prop: 'text',
                disablelimitreport: true,
                format: 'json'
            }).done(function(data) {
                if (data.parse && data.parse.text) {
                    var html = data.parse.text['*'];
                   
                    // 检查是否有卡牌
                    var tempDiv = document.createElement('div');
                    tempDiv.innerHTML = html;
                    var cards = tempDiv.querySelectorAll('.card-deck-trans');
                   
                    if (cards.length > 0) {
                        sparkModalContent.innerHTML = '<div class="spark-modal-title">闪光卡牌列表</div>' + html;
                        // 为闪光列表中的卡牌绑定事件
                        bindSparkListCardEvents();
                    } else {
                        sparkModalContent.innerHTML = '<div class="spark-modal-title">闪光卡牌列表</div><div class="spark-empty">暂无闪光卡牌</div>';
                    }
                }
            }).fail(function() {
                sparkModalContent.innerHTML = '<div class="spark-modal-title">闪光卡牌列表</div><div class="spark-empty">加载失败,请重试</div>';
            });
        }
       
        // 为闪光列表中的卡牌绑定点击事件
        function bindSparkListCardEvents() {
            var sparkCards = sparkModalContent.querySelectorAll('.card-deck-trans');
            sparkCards.forEach(function(card) {
                if (card.dataset.sparkBound) return;
                card.dataset.sparkBound = 'true';
               
                card.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                   
                    // 关闭之前放大的卡牌
                    closeEnlargedCard();
                   
                    // 创建放大容器
                    var enlargedContainer = document.createElement('div');
                    enlargedContainer.className = 'spark-enlarged-container';
                   
                    // 添加关闭按钮
                    var closeBtn = document.createElement('span');
                    closeBtn.className = 'spark-enlarged-close';
                    closeBtn.innerHTML = '&times;';
                    closeBtn.addEventListener('click', function(e) {
                        e.stopPropagation();
                        closeEnlargedCard();
                    });
                    enlargedContainer.appendChild(closeBtn);
                   
                    // 创建卡牌内容区
                    var cardContent = document.createElement('div');
                    cardContent.className = 'spark-enlarged-card';
                   
                    var cardClone = this.cloneNode(true);
                    delete cardClone.dataset.sparkBound;
                    cardContent.appendChild(cardClone);
                   
                    enlargedContainer.appendChild(cardContent);
                   
                    // 点击背景关闭
                    enlargedContainer.addEventListener('click', function(e) {
                        if (e.target === enlargedContainer) {
                            closeEnlargedCard();
                        }
                    });
                   
                    document.body.appendChild(enlargedContainer);
                    currentEnlargedContainer = enlargedContainer;
                });
             });
             });
         }
         }
第167行: 第536行:
             e.stopPropagation();
             e.stopPropagation();
             closeModal();
             closeModal();
        });
       
        sparkCloseButton.addEventListener('click', function(e) {
            e.stopPropagation();
            closeSparkModal();
         });
         });
          
          
第173行: 第547行:
             if (e.target === modalOverlay) {
             if (e.target === modalOverlay) {
                 closeModal();
                 closeModal();
            }
        });
       
        sparkModalOverlay.addEventListener('click', function(e) {
            if (e.target === sparkModalOverlay) {
                closeSparkModal();
             }
             }
         });
         });
第178行: 第558行:
         // ESC键关闭
         // ESC键关闭
         document.addEventListener('keydown', function(e) {
         document.addEventListener('keydown', function(e) {
             if (e.key === 'Escape' && modalOverlay.classList.contains('active')) {
             if (e.key === 'Escape') {
                closeModal();
                // 优先关闭放大的闪光卡牌
                if (currentEnlargedContainer) {
                    closeEnlargedCard();
                } else if (sparkModalOverlay.classList.contains('active')) {
                    closeSparkModal();
                } else if (modalOverlay.classList.contains('active')) {
                    closeModal();
                }
             }
             }
         });
         });
第185行: 第572行:
         // 为所有卡牌绑定点击事件
         // 为所有卡牌绑定点击事件
         function bindCardEvents() {
         function bindCardEvents() {
             const cards = document.querySelectorAll('.card-deck-trans');
             var cards = document.querySelectorAll('.card-deck-trans');
              
              
             cards.forEach(function(card) {
             cards.forEach(function(card) {
第193行: 第580行:
                  
                  
                 // 排除模态框内的卡牌
                 // 排除模态框内的卡牌
                 if (card.closest('.card-modal-overlay')) return;
                 if (card.closest('.card-modal-overlay') || card.closest('.spark-modal-overlay') || card.closest('.spark-enlarged-container')) return;
                  
                  
                 card.addEventListener('click', function(e) {
                 card.addEventListener('click', function(e) {
                     e.preventDefault();
                     e.preventDefault();
                     openModal(this);
                   
                    // 从card-deck-trans元素获取spark_enable
                    var sparkEnable = this.dataset.sparkEnable || '';
                   
                    // 获取card-id从父级card-wrapper
                    var wrapper = this.closest('.card-wrapper');
                    var cardId = wrapper ? wrapper.dataset.cardId : '';
                   
                     openModal(this, cardId, sparkEnable);
                 });
                 });
             });
             });
第206行: 第601行:
          
          
         // 监听DOM变化,为动态加载的卡牌绑定事件
         // 监听DOM变化,为动态加载的卡牌绑定事件
         const observer = new MutationObserver(function(mutations) {
         var observer = new MutationObserver(function(mutations) {
             let shouldBind = false;
             var shouldBind = false;
             mutations.forEach(function(mutation) {
             mutations.forEach(function(mutation) {
                 if (mutation.addedNodes.length > 0) {
                 if (mutation.addedNodes.length > 0) {

2026年1月17日 (六) 09:53的版本

此Widget为卡牌显示添加交互效果:

  • 鼠标悬停时的动画效果
  • 点击后显示放大的模态框
  • 自动检测spark_enable属性显示闪光按钮
  • 支持闪光卡牌列表显示

使用方法:在页面底部添加

×
×