MediaWiki:Script/Colorblind.js : Différence entre versions

(Page créée avec « const SPAWN_LAYER_COLOR = "spawnLayerColor"; const OPTION_MAPPING = { 0: "🟥 Rouge", 50: "🟫 Marron", 140: "🟩 Vert", 230: "🟦 Bleu", 290: "🟪 Violet",... »)
 
Ligne 1 : Ligne 1 :
const SPAWN_LAYER_COLOR = "spawnLayerColor";
+
class SpawnLayerManager {
const OPTION_MAPPING = {
+
  static SPAWN_COLOR_KEY = "mt2.spawn.color";
  0: "🟥 Rouge",
+
  static OPTION_MAPPING = {
  50: "🟫 Marron",
+
    0: "🟥 Rouge",
  140: "🟩 Vert",
+
    50: "🟫 Marron",
  230: "🟦 Bleu",
+
    140: "🟩 Vert",
  290: "🟪 Violet",
+
    230: "🟦 Bleu",
  black: "⬛ Noir",
+
    290: "🟪 Violet",
  white: "⬜ Blanc"
+
    black: "⬛ Noir",
}
+
    white: "⬜ Blanc",
const STYLE_MAPPING = {
+
  };
  position: "absolute",
+
  static STYLE_MAPPING = {
  left: "0",
+
    position: "absolute",
  margin: "0",
+
    top: "0",
  background: "#434242b3",
+
    left: "0",
  color: "white",
+
    margin: "4px",
  borderRadius: "5px",
+
    background: "#434242b3",
  cursor: "pointer"
+
    color: "white",
}
+
    borderRadius: "5px",
 +
    cursor: "pointer",
 +
    border: "1px white solid",
 +
  };
 +
 
 +
  constructor(containerSelector = ".spawn-map-container") {
 +
    this.containerSelector = containerSelector;
 +
    this.currentFilter = null;
 +
    this.selects = [];
 +
    this.spawnLayers = [];
 +
    this.isClipboardImageSupported = this._isClipboardImageSupported();
 +
    this._initialize();
 +
  }
 +
 
 +
  _isClipboardImageSupported() {
 +
    return !!(navigator.clipboard?.write && window.ClipboardItem);
 +
  }
 +
 
 +
  _initialize() {
 +
    const containers = this._getContainers();
 +
    if (!containers.length) return;
 +
 
 +
    containers.forEach((container) => this._setupContainer(container));
 +
 
 +
    const savedColor = this._getSavedColor();
 +
    if (savedColor) this._applyColor(savedColor);
 +
  }
 +
 
 +
  _getContainers() {
 +
    return document.querySelectorAll(this.containerSelector);
 +
  }
 +
 
 +
  _getSavedColor() {
 +
    return localStorage.getItem(SpawnLayerManager.SPAWN_COLOR_KEY);
 +
  }
 +
 
 +
  _saveColor(value) {
 +
    localStorage.setItem(SpawnLayerManager.SPAWN_COLOR_KEY, value);
 +
  }
 +
 
 +
  _setupContainer(container) {
 +
    const [mapContainer, spawnContainer] = container.children;
  
const spawnLayerContainers = document.querySelectorAll(".spawn-layer");
+
    if (!mapContainer || !spawnContainer) return;
  
if (spawnLayerContainers.length) {
+
    const map = mapContainer.querySelector("img");
  initializeSpawnLayers(spawnLayerContainers);
+
    const spawnLayer = spawnContainer.querySelector("img");
}
 
  
function initializeSpawnLayers(spawnLayerContainers) {
+
     if (!map || !spawnLayer) return;
    const selects = [];
 
    const spawnLayers = [];
 
     const spawnLayerColor = localStorage.getItem(SPAWN_LAYER_COLOR);
 
  
     spawnLayerContainers.forEach((spawnLayerContainer) => {
+
     const select = this._createColorSelect();
        const spawnLayer = spawnLayerContainer.querySelector("img");
+
    spawnContainer.appendChild(select);
       
 
        if (spawnLayer) {
 
            const selectColor = createSelectColor();
 
            spawnLayerContainer.appendChild(selectColor);
 
            selects.push(selectColor);
 
            spawnLayers.push(spawnLayer);
 
        }
 
    });
 
  
     function handleChange(event) {
+
     this.selects.push(select);
        changeSpawnLayerColor(event.target.value, selects, spawnLayers);
+
    this.spawnLayers.push(spawnLayer);
    };
 
  
     selects.forEach(select => {
+
     select.addEventListener("change", (e) => this._onColorChange(e));
        select.addEventListener("change", handleChange);
 
    });
 
  
     if (spawnLayerColor) {
+
     if (this.isClipboardImageSupported) {
        changeSpawnLayerColor(spawnLayerColor, selects, spawnLayers);
+
      this._setupCopyButton(spawnContainer, map, spawnLayer);
 
     }
 
     }
}
+
  }
  
function createSelectColor() {
+
  _createColorSelect() {
 
     const select = document.createElement("select");
 
     const select = document.createElement("select");
    Object.entries(OPTION_MAPPING).forEach(([key, value]) => {
 
        const option = document.createElement("option");
 
        option.value = key;
 
        option.textContent = value;
 
        select.appendChild(option);
 
    });
 
    Object.entries(STYLE_MAPPING).forEach(([property, value]) => {
 
        select.style[property] = value;
 
    });
 
  
 +
    for (const [value, label] of Object.entries(
 +
      SpawnLayerManager.OPTION_MAPPING
 +
    )) {
 +
      const option = document.createElement("option");
 +
      option.value = value;
 +
      option.textContent = label;
 +
      select.appendChild(option);
 +
    }
 +
 +
    Object.assign(select.style, SpawnLayerManager.STYLE_MAPPING);
 
     return select;
 
     return select;
}
+
  }
 +
 
 +
  _onColorChange(event) {
 +
    const value = event.target.value;
 +
    this._applyColor(value);
 +
  }
 +
 
 +
  _applyColor(value) {
 +
    if (!SpawnLayerManager.OPTION_MAPPING.hasOwnProperty(value)) return;
 +
 
 +
    const filter = this._getFilterForValue(value);
 +
    this.currentFilter = filter;
 +
 
 +
    this.selects.forEach((select) => (select.value = value));
 +
    this.spawnLayers.forEach((layer) => (layer.style.filter = filter));
 +
    this._saveColor(value);
 +
  }
  
function changeSpawnLayerColor(value, selects, spawnLayers) {
+
  _getFilterForValue(value) {
     if (!OPTION_MAPPING.hasOwnProperty(value)) {
+
     switch (value) {
         return;
+
      case "black":
 +
        return "invert(1) brightness(0) contrast(100%)";
 +
      case "white":
 +
        return "invert(1) sepia(1) saturate(100%) brightness(3)";
 +
      default:
 +
         return `hue-rotate(${value}deg)`;
 
     }
 
     }
 +
  }
  
     let filter;
+
  _setupCopyButton(spawnContainer, map, spawnLayer) {
 +
     const copyButton = spawnContainer.querySelector(".copy-to-clipboard");
  
     if (value === "black") {
+
     if (!copyButton) return;
        filter = "invert(1) brightness(0) contrast(100%)";
+
 
     } else if (value === "white") {
+
    const defaultEmoji = copyButton.querySelector("[data-default]");
        filter = "invert(1) sepia(1) saturate(100%) brightness(3)";
+
    const clickedEmoji = copyButton.querySelector("[data-clicked]");
     } else {
+
 
        filter = `hue-rotate(${value}deg)`;
+
    if (!defaultEmoji || !clickedEmoji) return;
 +
 
 +
    showElement(copyButton);
 +
 
 +
    copyButton.addEventListener("click", () => {
 +
      this._copyCombinedImageToClipboard(map, spawnLayer);
 +
      this._copyAnimation(defaultEmoji, clickedEmoji);
 +
    });
 +
  }
 +
 
 +
  _copyCombinedImageToClipboard(map, spawnLayer) {
 +
    const canvas = document.createElement("canvas");
 +
    canvas.width = Math.max(map.width, spawnLayer.width);
 +
    canvas.height = Math.max(map.height, spawnLayer.height);
 +
 
 +
    const ctx = canvas.getContext("2d");
 +
    ctx.drawImage(map, 0, 0);
 +
 
 +
    const filteredLayer = this._drawFilteredLayer(spawnLayer);
 +
    ctx.drawImage(filteredLayer, 0, 0);
 +
 
 +
     this._copyCanvasContentsToClipboard(canvas);
 +
  }
 +
 
 +
  _drawFilteredLayer(layer) {
 +
    const canvas = document.createElement("canvas");
 +
    canvas.width = layer.width;
 +
    canvas.height = layer.height;
 +
 
 +
    const ctx = canvas.getContext("2d");
 +
    ctx.filter = this.currentFilter || "none";
 +
    ctx.drawImage(layer, 0, 0);
 +
 
 +
    return canvas;
 +
  }
 +
 
 +
  async _getBlobFromCanvas(canvas) {
 +
    return new Promise((resolve, reject) => {
 +
      canvas.toBlob((blob) => {
 +
        if (blob) {
 +
          resolve(blob);
 +
        } else {
 +
          reject(new Error("Canvas toBlob failed"));
 +
        }
 +
      });
 +
     });
 +
  }
 +
 
 +
  async _copyCanvasContentsToClipboard(canvas) {
 +
    try {
 +
      const blob = await this._getBlobFromCanvas(canvas);
 +
      const data = [new ClipboardItem({ [blob.type]: blob })];
 +
      await navigator.clipboard.write(data);
 +
    } catch (error) {
 +
      console.error(error);
 
     }
 
     }
 +
  }
  
     selects.forEach(select => select.value = value);
+
  _copyAnimation(defaultEmoji, clickedEmoji) {
     spawnLayers.forEach(spawnLayer => spawnLayer.style.filter = filter);
+
     hideElement(defaultEmoji);
 +
     showElement(clickedEmoji);
  
     localStorage.setItem(SPAWN_LAYER_COLOR, value);
+
     setTimeout(() => {
 +
      hideElement(clickedEmoji);
 +
      showElement(defaultEmoji);
 +
    }, 1500);
 +
  }
 
}
 
}
 +
 +
new SpawnLayerManager();

Version du 8 mai 2025 à 05:42

class SpawnLayerManager {
  static SPAWN_COLOR_KEY = "mt2.spawn.color";
  static OPTION_MAPPING = {
    0: "🟥 Rouge",
    50: "🟫 Marron",
    140: "🟩 Vert",
    230: "🟦 Bleu",
    290: "🟪 Violet",
    black: "⬛ Noir",
    white: "⬜ Blanc",
  };
  static STYLE_MAPPING = {
    position: "absolute",
    top: "0",
    left: "0",
    margin: "4px",
    background: "#434242b3",
    color: "white",
    borderRadius: "5px",
    cursor: "pointer",
    border: "1px white solid",
  };

  constructor(containerSelector = ".spawn-map-container") {
    this.containerSelector = containerSelector;
    this.currentFilter = null;
    this.selects = [];
    this.spawnLayers = [];
    this.isClipboardImageSupported = this._isClipboardImageSupported();
    this._initialize();
  }

  _isClipboardImageSupported() {
    return !!(navigator.clipboard?.write && window.ClipboardItem);
  }

  _initialize() {
    const containers = this._getContainers();
    if (!containers.length) return;

    containers.forEach((container) => this._setupContainer(container));

    const savedColor = this._getSavedColor();
    if (savedColor) this._applyColor(savedColor);
  }

  _getContainers() {
    return document.querySelectorAll(this.containerSelector);
  }

  _getSavedColor() {
    return localStorage.getItem(SpawnLayerManager.SPAWN_COLOR_KEY);
  }

  _saveColor(value) {
    localStorage.setItem(SpawnLayerManager.SPAWN_COLOR_KEY, value);
  }

  _setupContainer(container) {
    const [mapContainer, spawnContainer] = container.children;

    if (!mapContainer || !spawnContainer) return;

    const map = mapContainer.querySelector("img");
    const spawnLayer = spawnContainer.querySelector("img");

    if (!map || !spawnLayer) return;

    const select = this._createColorSelect();
    spawnContainer.appendChild(select);

    this.selects.push(select);
    this.spawnLayers.push(spawnLayer);

    select.addEventListener("change", (e) => this._onColorChange(e));

    if (this.isClipboardImageSupported) {
      this._setupCopyButton(spawnContainer, map, spawnLayer);
    }
  }

  _createColorSelect() {
    const select = document.createElement("select");

    for (const [value, label] of Object.entries(
      SpawnLayerManager.OPTION_MAPPING
    )) {
      const option = document.createElement("option");
      option.value = value;
      option.textContent = label;
      select.appendChild(option);
    }

    Object.assign(select.style, SpawnLayerManager.STYLE_MAPPING);
    return select;
  }

  _onColorChange(event) {
    const value = event.target.value;
    this._applyColor(value);
  }

  _applyColor(value) {
    if (!SpawnLayerManager.OPTION_MAPPING.hasOwnProperty(value)) return;

    const filter = this._getFilterForValue(value);
    this.currentFilter = filter;

    this.selects.forEach((select) => (select.value = value));
    this.spawnLayers.forEach((layer) => (layer.style.filter = filter));
    this._saveColor(value);
  }

  _getFilterForValue(value) {
    switch (value) {
      case "black":
        return "invert(1) brightness(0) contrast(100%)";
      case "white":
        return "invert(1) sepia(1) saturate(100%) brightness(3)";
      default:
        return `hue-rotate(${value}deg)`;
    }
  }

  _setupCopyButton(spawnContainer, map, spawnLayer) {
    const copyButton = spawnContainer.querySelector(".copy-to-clipboard");

    if (!copyButton) return;

    const defaultEmoji = copyButton.querySelector("[data-default]");
    const clickedEmoji = copyButton.querySelector("[data-clicked]");

    if (!defaultEmoji || !clickedEmoji) return;

    showElement(copyButton);

    copyButton.addEventListener("click", () => {
      this._copyCombinedImageToClipboard(map, spawnLayer);
      this._copyAnimation(defaultEmoji, clickedEmoji);
    });
  }

  _copyCombinedImageToClipboard(map, spawnLayer) {
    const canvas = document.createElement("canvas");
    canvas.width = Math.max(map.width, spawnLayer.width);
    canvas.height = Math.max(map.height, spawnLayer.height);

    const ctx = canvas.getContext("2d");
    ctx.drawImage(map, 0, 0);

    const filteredLayer = this._drawFilteredLayer(spawnLayer);
    ctx.drawImage(filteredLayer, 0, 0);

    this._copyCanvasContentsToClipboard(canvas);
  }

  _drawFilteredLayer(layer) {
    const canvas = document.createElement("canvas");
    canvas.width = layer.width;
    canvas.height = layer.height;

    const ctx = canvas.getContext("2d");
    ctx.filter = this.currentFilter || "none";
    ctx.drawImage(layer, 0, 0);

    return canvas;
  }

  async _getBlobFromCanvas(canvas) {
    return new Promise((resolve, reject) => {
      canvas.toBlob((blob) => {
        if (blob) {
          resolve(blob);
        } else {
          reject(new Error("Canvas toBlob failed"));
        }
      });
    });
  }

  async _copyCanvasContentsToClipboard(canvas) {
    try {
      const blob = await this._getBlobFromCanvas(canvas);
      const data = [new ClipboardItem({ [blob.type]: blob })];
      await navigator.clipboard.write(data);
    } catch (error) {
      console.error(error);
    }
  }

  _copyAnimation(defaultEmoji, clickedEmoji) {
    hideElement(defaultEmoji);
    showElement(clickedEmoji);

    setTimeout(() => {
      hideElement(clickedEmoji);
      showElement(defaultEmoji);
    }, 1500);
  }
}

new SpawnLayerManager();