AnimeStars Lootbox Card ID Overlay

Show data-id on lootbox cards (updates live) and color by highest/middle/lowest

目前為 2025-08-24 提交的版本,檢視 最新版本

// ==UserScript==
// @name         AnimeStars Lootbox Card ID Overlay
// @namespace    Violentmonkey
// @version      1.0
// @description  Show data-id on lootbox cards (updates live) and color by highest/middle/lowest
// @match        https://astars.club/cards/pack
// @match        https://asstars.club/cards/pack
// @match        https://asstars1.astars.club/cards/pack
// @match        https://animestars.org/cards/pack
// @match        https://as1.astars.club/cards/pack
// @match        https://asstars.tv/cards/pack
// @match        https://ass.astars.club/cards/pack
// @match        https://as2.asstars.tv/cards/pack
// @grant        none
// @license MIT
// ==/UserScript==

(function () {
  'use strict';

  const COLORS = {
    high:  '#16a34a', // green
    mid:   '#ca8a04', // yellow
    low:   '#dc2626'  // red
  };

  const BADGE_CLASS = 'lb-id-badge';

  // Create/update a badge in the top-right of a .lootbox__card
  function setBadge(cardEl, text, color) {
    let b = cardEl.querySelector(`.${BADGE_CLASS}`);
    if (!b) {
      b = document.createElement('div');
      b.className = BADGE_CLASS;
      Object.assign(b.style, {
        position: 'absolute',
        top: '6px',
        right: '6px',
        padding: '2px 6px',
        borderRadius: '10px',
        background: color,
        color: '#fff',
        font: 'bold 12px/1.2 -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Arial, sans-serif',
        boxShadow: '0 1px 3px rgba(0,0,0,.25)',
        zIndex: 10,
        pointerEvents: 'none'
      });
      // ensure the card is positioned so the absolute badge anchors correctly
      const cs = getComputedStyle(cardEl);
      if (cs.position === 'static') cardEl.style.position = 'relative';
      cardEl.appendChild(b);
    }
    b.textContent = text;
    b.style.background = color;
  }

  function update() {
    const cards = Array.from(document.querySelectorAll('.lootbox__card[data-id][data-rank]'));
    if (cards.length === 0) return;

    // Extract numeric ids
    const data = cards.map(el => ({
      el,
      id: Number(el.getAttribute('data-id')) || 0
    }));

    // Determine ordering (highest = green, middle = yellow, lowest = red)
    const sorted = [...data].sort((a, b) => b.id - a.id);

    // Handle ties by assigning same color to equal values
    const idsSorted = sorted.map(x => x.id);
    const max = idsSorted[0];
    const min = idsSorted[idsSorted.length - 1];

    data.forEach(item => {
      const label = String(item.id);
      let color = COLORS.mid; // default

      if (item.id === max && idsSorted.filter(v => v === max).length >= 1) {
        color = COLORS.high;
      }
      if (item.id === min && idsSorted.filter(v => v === min).length >= 1) {
        color = COLORS.low;
      }

      // Special case: only 1 or 2 cards visible
      if (data.length === 1) color = COLORS.high;
      if (data.length === 2) {
        color = (item.id === max) ? COLORS.high : COLORS.low;
      }

      setBadge(item.el, label, color);
    });
  }

  // Debounce helper to avoid thrashing on rapid DOM changes
  let rafPending = false;
  function scheduleUpdate() {
    if (rafPending) return;
    rafPending = true;
    requestAnimationFrame(() => {
      rafPending = false;
      update();
    });
  }

  // Observe DOM changes (cards swap without full reload)
  const mo = new MutationObserver(scheduleUpdate);
  mo.observe(document.body, { childList: true, subtree: true });

  // Also run periodically as a safety net (1s)
  setInterval(update, 1000);

  // Initial run
  update();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址