微件

ScrollText:修订间差异

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献
创建页面,内容为“<style> .scroll-text { position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center; } .scroll-text .scroll-text-content { word-wrap: break-word; word-break: break-all; position: relative; width: 100%; text-align: center; } .scroll-text.has-scroll { align-items: flex-start; } .scroll-text.has-scroll .scroll-text-content { text-align: center; } .scroll-text .scroll-text-content.enable-scroll { a…”
 
律Rhyme留言 | 贡献
无编辑摘要
 
(未显示同一用户的5个中间版本)
第1行: 第1行:
<!-- ScrollText.html -->
<style>
<style>
.scroll-text {
.scroll-text {
第4行: 第5行:
   overflow: hidden;
   overflow: hidden;
   display: flex;
   display: flex;
   align-items: center;
   align-items: flex-start;
  justify-content: center;
}
}


/* 动画由 JS 动态设置 */
.scroll-text .scroll-text-content {
.scroll-text .scroll-text-content {
   word-wrap: break-word;
   word-wrap: break-word;
第13行: 第14行:
   position: relative;
   position: relative;
   width: 100%;
   width: 100%;
  text-align: center;
}
.scroll-text.has-scroll {
  align-items: flex-start;
}
.scroll-text.has-scroll .scroll-text-content {
   text-align: center;
   text-align: center;
  will-change: transform;
}
}


.scroll-text .scroll-text-content.enable-scroll {
.scroll-text .scroll-text-content:hover {
  animation: scrollText linear infinite;
}
 
.scroll-text .scroll-text-content.enable-scroll:hover {
   animation-play-state: paused;
   animation-play-state: paused;
}
@keyframes scrollText-default {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(calc(-100% + 110px));
  }
}
}
</style>
</style>
第44行: 第25行:
<script>
<script>
(function() {
(function() {
  var processedElements = new WeakSet();
   function initScroll() {
   function initScroll() {
    // 使用 class 选择器获取所有滚动文本容器
     var wrappers = document.querySelectorAll('.scroll-text');
     var wrappers = document.querySelectorAll('.scroll-text');
   
 
    if (!wrappers.length) {
      setTimeout(initScroll, 100);
      return;
    }
   
    // 遍历每个容器并初始化
     wrappers.forEach(function(wrapper, index) {
     wrappers.forEach(function(wrapper, index) {
      // 已完成动画绑定的元素跳过
      if (processedElements.has(wrapper)) return;
       var content = wrapper.querySelector('.scroll-text-content');
       var content = wrapper.querySelector('.scroll-text-content');
       if (!content || content.classList.contains('scroll-initialized')) {
       if (!content) return;
         return;
 
      // 不可见容器跳过(等待视图显示时再初始化)
      var rect = wrapper.getBoundingClientRect();
      if (rect.width === 0 || rect.height === 0) return;
 
      var speed = parseFloat(content.getAttribute('data-speed')) || 10;
      var animationName = 'scrollText-' + index + '-' + Date.now();
 
      setTimeout(function() {
        var contentHeight = content.scrollHeight;
        var wrapperHeight = wrapper.offsetHeight;
        var scrollDistance = contentHeight - wrapperHeight;
 
        // 内容未溢出,不绑定动画,也不标记为 processed,给后续机会
        if (scrollDistance <= 0) return;
 
        // 动态注入 keyframes
        var style = document.createElement('style');
        style.textContent =
          '@keyframes ' + animationName + ' {' +
            '0%{transform:translateY(0)}' +
            '100%{transform:translateY(-' + scrollDistance + 'px)}' +
          '}';
 
        document.head.appendChild(style);
 
        // 根据字数/速度估算时长
        var text = content.textContent || content.innerText || '';
        var charCount = text.replace(/\s+/g, '').length;
        var duration = Math.max(speed, charCount / 8);
 
        // 设置动画属性
        content.style.animationName = animationName;
        content.style.animationDuration = duration + 's';
        content.style.animationTimingFunction = 'linear';
        content.style.animationIterationCount = 'infinite';
        content.style.animationPlayState = 'running';
 
        // 仅在成功绑定动画后标记为已处理
        processedElements.add(wrapper);
      }, 50);
    });
  }
 
  // 监听自定义事件(视图显示后主动触发初始化)
  document.addEventListener('scrolltext:init', function () {
    setTimeout(initScroll, 50);
  });
 
  // 监听 DOM 变化(模态和各子视图从隐藏到显示时触发)
  var observer = new MutationObserver(function(mutations) {
    var shouldInit = false;
    mutations.forEach(function(mutation) {
      if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
        var el = mutation.target;
        var visible = el.style && el.style.display && el.style.display !== 'none';
        if (visible && (
          el.classList.contains('card-modal') ||
          el.classList.contains('original-card-view') ||
          el.classList.contains('inspiration-view') ||
          el.classList.contains('god-inspiration-view') ||
          el.classList.contains('subcards-view') ||
          el.classList.contains('nested-subcards-view') ||
          el.classList.contains('inspiration-subcards-view') ||
          el.classList.contains('inspiration-nested-subcards-view')
        )) {
          shouldInit = true;
         }
       }
       }
        
       if (mutation.addedNodes && mutation.addedNodes.length > 0) {
      // 标记已初始化,避免重复处理
         shouldInit = true;
      content.classList.add('scroll-initialized');
     
      var text = content.textContent || content.innerText;
      var charCount = text.replace(/\s+/g, '').length;
      var threshold = parseInt(content.getAttribute('data-threshold')) || 50;
      var speed = parseFloat(content.getAttribute('data-speed')) || 10;
     
      if (charCount > threshold) {
         // 为父容器添加标识类,表示需要滚动
        wrapper.classList.add('has-scroll');
       
        // 为每个实例创建唯一的动画名称
        var animationName = 'scrollText-' + index + '-' + Date.now();
        content.classList.add('enable-scroll');
       
        // 等待DOM更新后计算实际高度
        setTimeout(function() {
          var contentHeight = content.scrollHeight;
          var wrapperHeight = wrapper.offsetHeight;
          var scrollDistance = contentHeight - wrapperHeight;
         
          // 动态设置滚动距离
          if (scrollDistance > 0) {
            // 为当前实例创建独立的动画样式
            var styleId = 'scroll-text-animation-' + index;
            var existingStyle = document.getElementById(styleId);
            if (existingStyle) {
              existingStyle.remove();
            }
           
            var style = document.createElement('style');
            style.id = styleId;
            style.textContent = `
              @keyframes ${animationName} {
                0% {
                  transform: translateY(0);
                }
                100% {
                  transform: translateY(-${scrollDistance}px);
                }
              }
            `;
            document.head.appendChild(style);
           
            // 计算动画时长并应用动画
            var duration = Math.max(speed, charCount / 8);
            content.style.animationName = animationName;
            content.style.animationDuration = duration + 's';
          } else {
            // 如果实际上不需要滚动,移除滚动类
            wrapper.classList.remove('has-scroll');
            content.classList.remove('enable-scroll');
          }
        }, 10);
      } else {
        // 字符数未达到阈值,确保没有滚动类
        wrapper.classList.remove('has-scroll');
       }
       }
     });
     });
   }
 
    
    if (shouldInit) {
      setTimeout(initScroll, 100);
    }
  });
 
  observer.observe(document.body, {
    childList: true,
    subtree: true,
    attributes: true,
    attributeFilter: ['style']
   });
 
   // 初始加载
   if (document.readyState === 'loading') {
   if (document.readyState === 'loading') {
     document.addEventListener('DOMContentLoaded', initScroll);
     document.addEventListener('DOMContentLoaded', function() {
      setTimeout(initScroll, 100);
    });
   } else {
   } else {
     initScroll();
     setTimeout(initScroll, 100);
  }
 
  // MediaWiki 钩子
  if (typeof mw !== 'undefined' && mw.hook) {
    mw.hook('wikipage.content').add(function() {
      setTimeout(initScroll, 100);
    });
   }
   }
})();
})();
</script>
</script>

2025年10月16日 (四) 22:34的最新版本

<style> .scroll-text {

 position: relative;
 overflow: hidden;
 display: flex;
 align-items: flex-start;

}

/* 动画由 JS 动态设置 */ .scroll-text .scroll-text-content {

 word-wrap: break-word;
 word-break: break-all;
 position: relative;
 width: 100%;
 text-align: center;
 will-change: transform;

}

.scroll-text .scroll-text-content:hover {

 animation-play-state: paused;

} </style>

<script> (function() {

 var processedElements = new WeakSet();
 function initScroll() {
   var wrappers = document.querySelectorAll('.scroll-text');
   wrappers.forEach(function(wrapper, index) {
     // 已完成动画绑定的元素跳过
     if (processedElements.has(wrapper)) return;
     var content = wrapper.querySelector('.scroll-text-content');
     if (!content) return;
     // 不可见容器跳过(等待视图显示时再初始化)
     var rect = wrapper.getBoundingClientRect();
     if (rect.width === 0 || rect.height === 0) return;
     var speed = parseFloat(content.getAttribute('data-speed')) || 10;
     var animationName = 'scrollText-' + index + '-' + Date.now();
     setTimeout(function() {
       var contentHeight = content.scrollHeight;
       var wrapperHeight = wrapper.offsetHeight;
       var scrollDistance = contentHeight - wrapperHeight;
       // 内容未溢出,不绑定动画,也不标记为 processed,给后续机会
       if (scrollDistance <= 0) return;
       // 动态注入 keyframes
       var style = document.createElement('style');
       style.textContent =
         '@keyframes ' + animationName + ' {' +
           '0%{transform:translateY(0)}' +
           '100%{transform:translateY(-' + scrollDistance + 'px)}' +
         '}';
       document.head.appendChild(style);
       // 根据字数/速度估算时长
       var text = content.textContent || content.innerText || ;
       var charCount = text.replace(/\s+/g, ).length;
       var duration = Math.max(speed, charCount / 8);
       // 设置动画属性
       content.style.animationName = animationName;
       content.style.animationDuration = duration + 's';
       content.style.animationTimingFunction = 'linear';
       content.style.animationIterationCount = 'infinite';
       content.style.animationPlayState = 'running';
       // 仅在成功绑定动画后标记为已处理
       processedElements.add(wrapper);
     }, 50);
   });
 }
 // 监听自定义事件(视图显示后主动触发初始化)
 document.addEventListener('scrolltext:init', function () {
   setTimeout(initScroll, 50);
 });
 // 监听 DOM 变化(模态和各子视图从隐藏到显示时触发)
 var observer = new MutationObserver(function(mutations) {
   var shouldInit = false;
   mutations.forEach(function(mutation) {
     if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
       var el = mutation.target;
       var visible = el.style && el.style.display && el.style.display !== 'none';
       if (visible && (
         el.classList.contains('card-modal') ||
         el.classList.contains('original-card-view') ||
         el.classList.contains('inspiration-view') ||
         el.classList.contains('god-inspiration-view') ||
         el.classList.contains('subcards-view') ||
         el.classList.contains('nested-subcards-view') ||
         el.classList.contains('inspiration-subcards-view') ||
         el.classList.contains('inspiration-nested-subcards-view')
       )) {
         shouldInit = true;
       }
     }
     if (mutation.addedNodes && mutation.addedNodes.length > 0) {
       shouldInit = true;
     }
   });
   if (shouldInit) {
     setTimeout(initScroll, 100);
   }
 });
 observer.observe(document.body, {
   childList: true,
   subtree: true,
   attributes: true,
   attributeFilter: ['style']
 });
 // 初始加载
 if (document.readyState === 'loading') {
   document.addEventListener('DOMContentLoaded', function() {
     setTimeout(initScroll, 100);
   });
 } else {
   setTimeout(initScroll, 100);
 }
 // MediaWiki 钩子
 if (typeof mw !== 'undefined' && mw.hook) {
   mw.hook('wikipage.content').add(function() {
     setTimeout(initScroll, 100);
   });
 }

})(); </script>