Problem with code

Problem with code

Amel05
Visitor
2 0 0

 

<div class="container">
  <div class="flag-customizer">
   <h1 style="color: black; font-weight: bold">Anpassa din flagga</h1>
   <h5 style="color: black; font-weight: bold">Funktionen tillåter dig både att zooma och justera placeringen på länderna</h5>
   <h6 style="color: black; font-weight: bold">(Obs, det kan ibland ta en stund innan länderna visas när du väljer dem. Starta om sidan om tekniska fel uppstår)</h6>

<label for="flag1" style="color: black; font-weight: bold">Land 1:</label>
<select id="flag1" style="color: black; font-weight: bold">
  <option>Välj</option>
</select>

<br>

<label for="flag2" style="color: black; font-weight: bold">Land 2:</label>
<select id="flag2" style="color: black; font-weight: bold">
  <option>Välj</option>
</select>
  
  <div class="flag-container">
    <canvas id="flagCanvas1" width="5906" height="3544"></canvas>
    <canvas id="flagCanvas2" width="5906" height="3544"></canvas>
  </div>
  
  <button id="uploadFlagBtn">Spara</button>

</div>

<style>

  #flagCanvas1, #flagCanvas2 {
    position: absolute;
    width: 100%;
    height: 100%;
  }

  #flagCanvas1 {
    clip-path: polygon(100% 0, 0 0, 0 100%);
  }

  #flagCanvas2 {
    clip-path: polygon(0 100%, 100% 0, 100% 100%);
  }
</style>

<script>
  // Funktion för att skapa alternativ
  function populateSelect(selectId) {
    const selectElement = document.getElementById(selectId);

    countries.forEach(country => {
      const option = document.createElement("option");
      option.value = country.value;
      option.textContent = country.label;
      selectElement.appendChild(option);
    });
  }

  // När sidan har laddats
  document.addEventListener("DOMContentLoaded", function () {
    populateSelect("flag1"); // Fyll första dropdown
    populateSelect("flag2"); // Fyll andra dropdown
  });
</script>


<script>
  fetch('{{ "flags.json" | asset_url }}?v={{ settings.theme_version }}')
    .then(response => response.json())
    .then(flags => {
      // Exempel: använd flaggorna
      console.log(flags);

      // Ladda flaggor i select-element
      const flag1Select = document.getElementById("flag1");
      const flag2Select = document.getElementById("flag2");

      for (const [key, url] of Object.entries(flags)) {
        const option1 = document.createElement("option");
        option1.value = key;
        option1.textContent = key.replace(/_/g, " ");
        flag1Select.appendChild(option1);

        const option2 = document.createElement("option");
        option2.value = key;
        option2.textContent = key.replace(/_/g, " ");
        flag2Select.appendChild(option2);
      }
    })
    .catch(error => console.error("Kunde inte läsa flaggdata:", error));
</script>





<script>


  document.addEventListener("DOMContentLoaded", function() {
  const canvas1 = document.getElementById("flagCanvas1");
  const ctx1 = canvas1.getContext("2d");
  const canvas2 = document.getElementById("flagCanvas2");
  const ctx2 = canvas2.getContext("2d");

  const flag1Select = document.getElementById("flag1");
  const flag2Select = document.getElementById("flag2");


  let flag1Image = new Image();
  flag1Image.crossOrigin = "anonymous";
  let flag2Image = new Image();
  flag2Image.crossOrigin = "anonymous";

  let flag1Zoom = 3, flag1OffsetX = -5906, flag1OffsetY = -3544;
  let flag2Zoom = 3, flag2OffsetX = -5906, flag2OffsetY = -3544;

  // Load selected flags
  flag1Select.addEventListener("change", function() {
    flag1Image.src=flags[flag1Select.value];
  });
  flag2Select.addEventListener("change", function() {
    flag2Image.src=flags[flag2Select.value];
  });

  // Set initial flags
  flag1Image.src=flags[flag1Select.value];
  flag2Image.src=flags[flag2Select.value];

  function drawFlag1() {
    ctx1.clearRect(0, 0, canvas1.width, canvas1.height);
    ctx1.save();
    ctx1.translate(flag1OffsetX, flag1OffsetY);
    ctx1.scale(flag1Zoom, flag1Zoom);
    ctx1.drawImage(flag1Image, 0, 0, canvas1.width, canvas1.height);
    ctx1.restore();
  }

  function drawFlag2() {
    ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
    ctx2.save();
    ctx2.translate(flag2OffsetX, flag2OffsetY);
    ctx2.scale(flag2Zoom, flag2Zoom);
    ctx2.drawImage(flag2Image, 0, 0, canvas2.width, canvas2.height);
    ctx2.restore();
  }

  flag1Image.onload = drawFlag1;
  flag2Image.onload = drawFlag2;

  // Check if flags are selected
  function isFlagSelected() {
    return (
      flag1Select.value !== "Välj" &&
      flag2Select.value !== "Välj" &&
      flag1Select.value &&
      flag2Select.value
    );
  }

  // Zoom and move functionality for desktop
  canvas1.addEventListener("wheel", function(e) {
    e.preventDefault();
    flag1Zoom += e.deltaY * -0.005;
    drawFlag1();
  });
  canvas2.addEventListener("wheel", function(e) {
    e.preventDefault();
    flag2Zoom += e.deltaY * -0.005;
    drawFlag2();
  });

  // Drag and zoom functionality for canvas1
  let isDragging1 = false, startX1, startY1;
  canvas1.addEventListener("mousedown", function(e) {
    if (!isFlagSelected()) return; // Disable movement if no flags are selected
    isDragging1 = true;
    startX1 = e.offsetX*5 - flag1OffsetX;
    startY1 = e.offsetY*5 - flag1OffsetY;
  });
  canvas1.addEventListener("mousemove", function(e) {
    if (isDragging1) {
      flag1OffsetX = e.offsetX*5 - startX1;
      flag1OffsetY = e.offsetY*5 - startY1;
      drawFlag1();
    }
  });
  canvas1.addEventListener("mouseup", function() { isDragging1 = false; });
  canvas1.addEventListener("mouseleave", function() { isDragging1 = false; });

  // Touch events for drag and zoom on canvas1
  let initialTouchDistance1 = 0;
  canvas1.addEventListener("touchstart", function(e) {
    if (!isFlagSelected()) return; // Disable movement if no flags are selected
    if (e.touches.length === 1) { // Single finger touch for dragging
      isDragging1 = true;
      startX1 = e.touches[0].clientX*5 - flag1OffsetX;
      startY1 = e.touches[0].clientY*5 - flag1OffsetY;
    } else if (e.touches.length === 2) { // Two finger touch for zooming
      isDragging1 = false;
      initialTouchDistance1 = Math.hypot(
        e.touches[0].clientX - e.touches[1].clientX,
        e.touches[0].clientY - e.touches[1].clientY
      );
    }
  });
  canvas1.addEventListener("touchmove", function(e) {
    if (isDragging1 && e.touches.length === 1) {
      flag1OffsetX = e.touches[0].clientX*5 - startX1;
      flag1OffsetY = e.touches[0].clientY*5 - startY1;
      drawFlag1();
    } else if (e.touches.length === 2) {
      const currentTouchDistance1 = Math.hypot(
        e.touches[0].clientX - e.touches[1].clientX,
        e.touches[0].clientY - e.touches[1].clientY
      );
      const zoomFactor = 0.2;
      flag1Zoom *= 1 + (zoomFactor * (currentTouchDistance1 / initialTouchDistance1 - 1));
      initialTouchDistance1 = currentTouchDistance1;
      drawFlag1();
    }
  });
  canvas1.addEventListener("touchend", function() { isDragging1 = false; });

  // Drag and zoom functionality for canvas2
  let isDragging2 = false, startX2, startY2;
  canvas2.addEventListener("mousedown", function(e) {
    if (!isFlagSelected()) return; // Disable movement if no flags are selected
    isDragging2 = true;
    startX2 = e.offsetX*5 - flag2OffsetX;
    startY2 = e.offsetY*5 - flag2OffsetY;
  });
  canvas2.addEventListener("mousemove", function(e) {
    if (isDragging2) {
      flag2OffsetX = e.offsetX*5 - startX2;
      flag2OffsetY = e.offsetY*5 - startY2;
      drawFlag2();
    }
  });
  canvas2.addEventListener("mouseup", function() { isDragging2 = false; });
  canvas2.addEventListener("mouseleave", function() { isDragging2 = false; });

  // Touch events for drag and zoom on canvas2
  let initialTouchDistance2 = 0;
  canvas2.addEventListener("touchstart", function(e) {
    if (!isFlagSelected()) return; // Disable movement if no flags are selected
    if (e.touches.length === 1) {
      isDragging2 = true;
      startX2 = e.touches[0].clientX*5 - flag2OffsetX;
      startY2 = e.touches[0].clientY*5 - flag2OffsetY;
    } else if (e.touches.length === 2) {
      isDragging2 = false;
      initialTouchDistance2 = Math.hypot(
        e.touches[0].clientX - e.touches[1].clientX,
        e.touches[0].clientY - e.touches[1].clientY
      );
    }
  });
  canvas2.addEventListener("touchmove", function(e) {
    if (isDragging2 && e.touches.length === 1) {
      flag2OffsetX = e.touches[0].clientX*5 - startX2;
      flag2OffsetY = e.touches[0].clientY*5 - startY2;
      drawFlag2();
    } else if (e.touches.length === 2) {
      const currentTouchDistance2 = Math.hypot(
        e.touches[0].clientX - e.touches[1].clientX,
        e.touches[0].clientY - e.touches[1].clientY
      );
      const zoomFactor = 0.2;
      flag2Zoom *= 1 + (zoomFactor * (currentTouchDistance2 / initialTouchDistance2 - 1));
      initialTouchDistance2 = currentTouchDistance2;
      drawFlag2();
    }
  });
  canvas2.addEventListener("touchend", function() { isDragging2 = false; });

  // Prevent page movement during touch interactions
  document.addEventListener("touchmove", function(e) {
    if (e.target.closest(".flag-container")) {
      e.preventDefault();
    }
  }, { passive: false });


  // Funktionen som sparar flagganpassningen
  document.getElementById("uploadFlagBtn").addEventListener("click", function () {

  const flag1Value = flag1Select.value;
  const flag2Value = flag2Select.value;

  if (!flag1Value || flag1Value === "Välj" || !flag2Value || flag2Value === "Välj") {
    alert("Du måste välja två flaggor innan du sparar!"); // Visa ett meddelande
    return; // Stoppa funktionen
  }
    
  const combinedCanvas = document.createElement("canvas");
  combinedCanvas.width = 5906; // Match canvas dimensions
  combinedCanvas.height = 3544;
  const combinedCtx = combinedCanvas.getContext("2d");

  // Combine the two canvases
  combinedCtx.save();
  combinedCtx.beginPath();
  combinedCtx.moveTo(0, combinedCanvas.height);
  combinedCtx.lineTo(combinedCanvas.width, 0);
  combinedCtx.lineTo(0, 0);
  combinedCtx.closePath();
  combinedCtx.clip();
  combinedCtx.drawImage(document.getElementById("flagCanvas1"), 0, 0, combinedCanvas.width, combinedCanvas.height);
  combinedCtx.restore();

  combinedCtx.save();
  combinedCtx.beginPath();
  combinedCtx.moveTo(combinedCanvas.width, 0);
  combinedCtx.lineTo(0, combinedCanvas.height);
  combinedCtx.lineTo(combinedCanvas.width, combinedCanvas.height);
  combinedCtx.closePath();
  combinedCtx.clip();
  combinedCtx.drawImage(document.getElementById("flagCanvas2"), 0, 0, combinedCanvas.width, combinedCanvas.height);
  combinedCtx.restore();

  // Convert the canvas to a Blob
  combinedCanvas.toBlob(function (blob) {
    // Prepare the file for upload
    const file = new File([blob], "customized_flag.png", { type: "image/png" });

    // Find the Upload Lift input element (FilePond)
    const uploadInput = document.querySelector('input[type="file"].filepond--browser');

    if (uploadInput) {
      // Use FilePond's File API to add the file programmatically
      const dataTransfer = new DataTransfer();
      dataTransfer.items.add(file);
      uploadInput.files = dataTransfer.files;

      // Trigger the change event to start the upload process
      const event = new Event("change", { bubbles: true });
      uploadInput.dispatchEvent(event);

        alert("Din flagga har sparats! Scrolla nedåt för att slutföra din beställning.");
    } else {
      alert("Kunde inte hitta uppladdningsfältet. Kontrollera din konfiguration.");
    }
  }, "image/png");
});

});

</script>

 

 

What is wrong with my code, the function is to allow the customer to choose 2 countries and make 1 flag out of it. For some customers the function works but for others it doesn't work, they don't get the flag images visible and they can't do anything. How do I fix this problem, please help.

Replies 4 (4)

mane
Shopify Partner
7 0 1

@Amel05 HI,

 

Here's a cleaned-up and fixed version of your code that:

  1. Ensures flags are fully loaded before any dropdowns or canvas logic runs.
  2. Avoids timing issues by initializing everything after the fetch.
  3. Adds fallback error handling and loading text visibility.

<!-- Optional: Loading message -->
<p id="loadingMsg">Laddar flaggor...</p>

<select id="flag1"></select>
<select id="flag2"></select>
<br><br>
<canvas id="canvas" width="400" height="300"></canvas>
<br>
<button id="saveButton">Spara flagga</button>

<script>
fetch('{{ "flags.json" | asset_url }}?v={{ settings.theme_version }}')
.then(response => response.json())
.then(flags => {
const flag1Select = document.getElementById("flag1");
const flag2Select = document.getElementById("flag2");

for (const [key, url] of Object.entries(flags)) {
const option1 = document.createElement("option");
option1.value = key;
option1.textContent = key.replace(/_/g, " ");
flag1Select.appendChild(option1);

const option2 = document.createElement("option");
option2.value = key;
option2.textContent = key.replace(/_/g, " ");
flag2Select.appendChild(option2);
}

document.getElementById("loadingMsg").style.display = "none";

initializeCanvasLogic(flags);
})
.catch(error => {
console.error("Kunde inte läsa flaggdata:", error);
alert("Kunde inte ladda flaggdata. Vänligen försök igen senare.");
});

function initializeCanvasLogic(flags) {
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

let scale = 1, offsetX = 0, offsetY = 0, isDragging = false, startX, startY;
const flag1Image = new Image();
const flag2Image = new Image();

const flag1Select = document.getElementById("flag1");
const flag2Select = document.getElementById("flag2");

flag1Select.addEventListener("change", () => loadImage(flag1Image, flags[flag1Select.value]));
flag2Select.addEventListener("change", () => loadImage(flag2Image, flags[flag2Select.value]));

function loadImage(image, src) {
image.crossOrigin = "anonymous";
image.src=src;
image.onerror = () => alert("Kunde inte ladda en flagga. Välj ett annat land eller kontrollera din internetanslutning.");
image.onload = draw;
}

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(offsetX, offsetY);
ctx.scale(scale, scale);

// Draw flag1 on left diagonal
ctx.save();
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(canvas.width, 0);
ctx.lineTo(0, canvas.height);
ctx.closePath();
ctx.clip();
ctx.drawImage(flag1Image, 0, 0, canvas.width, canvas.height);
ctx.restore();

// Draw flag2 on right diagonal
ctx.save();
ctx.beginPath();
ctx.moveTo(canvas.width, 0);
ctx.lineTo(canvas.width, canvas.height);
ctx.lineTo(0, canvas.height);
ctx.closePath();
ctx.clip();
ctx.drawImage(flag2Image, 0, 0, canvas.width, canvas.height);
ctx.restore();

ctx.restore();
}

canvas.addEventListener("wheel", (e) => {
e.preventDefault();
const delta = e.deltaY < 0 ? 0.1 : -0.1;
scale = Math.max(0.1, scale + delta);
draw();
});

canvas.addEventListener("mousedown", (e) => {
isDragging = true;
startX = e.offsetX;
startY = e.offsetY;
});

canvas.addEventListener("mousemove", (e) => {
if (isDragging) {
offsetX += (e.offsetX - startX);
offsetY += (e.offsetY - startY);
startX = e.offsetX;
startY = e.offsetY;
draw();
}
});

canvas.addEventListener("mouseup", () => isDragging = false);
canvas.addEventListener("mouseout", () => isDragging = false);

document.getElementById("saveButton").addEventListener("click", () => {
const link = document.createElement("a");
link.download = "kombinerad_flagga.png";
link.href = canvas.toDataURL("image/png");
link.click();
});
}
</script>

Warm Regards,
Ankit Mane
Support Specialist | 5+ Years of Experience with Shopify

https://thaliatechnologies.com

TheScriptFlow
Shopify Partner
709 49 95

Please replace the previous code with this one.

<div class="container">
  <div class="flag-customizer">
    <h1 style="color: black; font-weight: bold">Anpassa din flagga</h1>
    <h5 style="color: black; font-weight: bold">Funktionen tillåter dig både att zooma och justera placeringen på länderna</h5>
    <h6 style="color: black; font-weight: bold">(Obs, det kan ibland ta en stund innan länderna visas när du väljer dem. Starta om sidan om tekniska fel uppstår)</h6>

    <label for="flag1" style="color: black; font-weight: bold">Land 1:</label>
    <select id="flag1" style="color: black; font-weight: bold">
      <option value="">Välj</option>
    </select>

    <br>

    <label for="flag2" style="color: black; font-weight: bold">Land 2:</label>
    <select id="flag2" style="color: black; font-weight: bold">
      <option value="">Välj</option>
    </select>
  
    <div class="flag-container">
      <canvas id="flagCanvas1" width="5906" height="3544"></canvas>
      <canvas id="flagCanvas2" width="5906" height="3544"></canvas>
      <div id="loadingMessage" style="display: none; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: black; font-weight: bold;">
        Laddar flagga...
      </div>
    </div>
  
    <button id="uploadFlagBtn">Spara</button>
  </div>
</div>

<style>
  .flag-container {
    position: relative;
    width: 100%;
    height: 400px; /* Fixed height for better control */
    border: 1px solid #ccc;
    overflow: hidden;
    margin-top: 20px;
  }

  #flagCanvas1, #flagCanvas2 {
    position: absolute;
    width: 100%;
    height: 100%;
  }

  #flagCanvas1 {
    clip-path: polygon(100% 0, 0 0, 0 100%);
  }

  #flagCanvas2 {
    clip-path: polygon(0 100%, 100% 0, 100% 100%);
  }
</style>

<script>
// Global flags object
let flags = {};

// Function to load flags JSON
function loadFlags() {
  return fetch('{{ "flags.json" | asset_url }}?v={{ settings.theme_version }}')
    .then(response => {
      if (!response.ok) throw new Error('Network response was not ok');
      return response.json();
    })
    .then(loadedFlags => {
      flags = loadedFlags;
      return flags;
    });
}

// Function to populate select dropdowns
function populateSelects() {
  const flag1Select = document.getElementById("flag1");
  const flag2Select = document.getElementById("flag2");
  
  // Clear existing options except first
  while (flag1Select.options.length > 1) flag1Select.remove(1);
  while (flag2Select.options.length > 1) flag2Select.remove(1);

  for (const [key, url] of Object.entries(flags)) {
    const option1 = document.createElement("option");
    option1.value = key;
    option1.textContent = key.replace(/_/g, " ");
    flag1Select.appendChild(option1);

    const option2 = document.createElement("option");
    option2.value = key;
    option2.textContent = key.replace(/_/g, " ");
    flag2Select.appendChild(option2);
  }
}

// Function to load an image with error handling
function loadImage(src) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.crossOrigin = "anonymous";
    img.onload = () => resolve(img);
    img.onerror = () => reject(new Error(`Failed to load image: ${src}`));
    img.src=src;
  });
}

// Main function when DOM is loaded
document.addEventListener("DOMContentLoaded", async function() {
  try {
    // Show loading state
    const loadingMessage = document.getElementById("loadingMessage");
    
    // Load flags data
    await loadFlags();
    populateSelects();
    
    const canvas1 = document.getElementById("flagCanvas1");
    const ctx1 = canvas1.getContext("2d");
    const canvas2 = document.getElementById("flagCanvas2");
    const ctx2 = canvas2.getContext("2d");

    const flag1Select = document.getElementById("flag1");
    const flag2Select = document.getElementById("flag2");

    let flag1Image = null;
    let flag2Image = null;

    let flag1Zoom = 1, flag1OffsetX = 0, flag1OffsetY = 0;
    let flag2Zoom = 1, flag2OffsetX = 0, flag2OffsetY = 0;

    // Draw flag with current settings
    function drawFlag1() {
      if (!flag1Image) return;
      
      ctx1.clearRect(0, 0, canvas1.width, canvas1.height);
      ctx1.save();
      ctx1.translate(flag1OffsetX, flag1OffsetY);
      ctx1.scale(flag1Zoom, flag1Zoom);
      ctx1.drawImage(flag1Image, 0, 0, canvas1.width, canvas1.height);
      ctx1.restore();
    }

    function drawFlag2() {
      if (!flag2Image) return;
      
      ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
      ctx2.save();
      ctx2.translate(flag2OffsetX, flag2OffsetY);
      ctx2.scale(flag2Zoom, flag2Zoom);
      ctx2.drawImage(flag2Image, 0, 0, canvas2.width, canvas2.height);
      ctx2.restore();
    }

    // Load selected flags with error handling
    flag1Select.addEventListener("change", async function() {
      if (!this.value) return;
      
      try {
        loadingMessage.style.display = 'block';
        flag1Image = await loadImage(flags[this.value]);
        // Reset position and zoom for new flag
        flag1Zoom = 1;
        flag1OffsetX = 0;
        flag1OffsetY = 0;
        drawFlag1();
      } catch (error) {
        console.error("Error loading flag 1:", error);
        alert("Kunde inte ladda flaggan. Försök igen.");
      } finally {
        loadingMessage.style.display = 'none';
      }
    });

    flag2Select.addEventListener("change", async function() {
      if (!this.value) return;
      
      try {
        loadingMessage.style.display = 'block';
        flag2Image = await loadImage(flags[this.value]);
        // Reset position and zoom for new flag
        flag2Zoom = 1;
        flag2OffsetX = 0;
        flag2OffsetY = 0;
        drawFlag2();
      } catch (error) {
        console.error("Error loading flag 2:", error);
        alert("Kunde inte ladda flaggan. Försök igen.");
      } finally {
        loadingMessage.style.display = 'none';
      }
    });

    // Check if flags are selected
    function isFlagSelected() {
      return flag1Image && flag2Image;
    }

    // Zoom with limits
    function applyZoom(zoom, delta, currentZoom) {
      const newZoom = currentZoom + delta * -0.005;
      return Math.max(0.1, Math.min(10, newZoom)); // Limit zoom between 0.1 and 10
    }

    // Zoom functionality for desktop
    canvas1.addEventListener("wheel", function(e) {
      e.preventDefault();
      if (!isFlagSelected()) return;
      flag1Zoom = applyZoom(flag1Zoom, e.deltaY, flag1Zoom);
      drawFlag1();
    });
    
    canvas2.addEventListener("wheel", function(e) {
      e.preventDefault();
      if (!isFlagSelected()) return;
      flag2Zoom = applyZoom(flag2Zoom, e.deltaY, flag2Zoom);
      drawFlag2();
    });

    // Drag functionality for canvas1
    let isDragging1 = false, startX1, startY1;
    canvas1.addEventListener("mousedown", function(e) {
      if (!isFlagSelected()) return;
      isDragging1 = true;
      startX1 = e.offsetX - flag1OffsetX;
      startY1 = e.offsetY - flag1OffsetY;
    });
    
    canvas1.addEventListener("mousemove", function(e) {
      if (isDragging1) {
        flag1OffsetX = e.offsetX - startX1;
        flag1OffsetY = e.offsetY - startY1;
        drawFlag1();
      }
    });
    
    canvas1.addEventListener("mouseup", function() { isDragging1 = false; });
    canvas1.addEventListener("mouseleave", function() { isDragging1 = false; });

    // Touch events for canvas1
    let initialTouchDistance1 = 0;
    canvas1.addEventListener("touchstart", function(e) {
      if (!isFlagSelected()) return;
      if (e.touches.length === 1) {
        isDragging1 = true;
        const touch = e.touches[0];
        const rect = canvas1.getBoundingClientRect();
        startX1 = touch.clientX - rect.left - flag1OffsetX;
        startY1 = touch.clientY - rect.top - flag1OffsetY;
      } else if (e.touches.length === 2) {
        isDragging1 = false;
        initialTouchDistance1 = Math.hypot(
          e.touches[0].clientX - e.touches[1].clientX,
          e.touches[0].clientY - e.touches[1].clientY
        );
      }
    });
    
    canvas1.addEventListener("touchmove", function(e) {
      if (!isFlagSelected()) return;
      e.preventDefault();
      
      if (isDragging1 && e.touches.length === 1) {
        const touch = e.touches[0];
        const rect = canvas1.getBoundingClientRect();
        flag1OffsetX = touch.clientX - rect.left - startX1;
        flag1OffsetY = touch.clientY - rect.top - startY1;
        drawFlag1();
      } else if (e.touches.length === 2) {
        const currentTouchDistance1 = Math.hypot(
          e.touches[0].clientX - e.touches[1].clientX,
          e.touches[0].clientY - e.touches[1].clientY
        );
        const zoomFactor = 0.01; // More subtle zoom
        flag1Zoom = applyZoom(flag1Zoom, (currentTouchDistance1 / initialTouchDistance1 - 1) * 100, flag1Zoom);
        initialTouchDistance1 = currentTouchDistance1;
        drawFlag1();
      }
    });
    
    canvas1.addEventListener("touchend", function() { isDragging1 = false; });

    // Drag functionality for canvas2
    let isDragging2 = false, startX2, startY2;
    canvas2.addEventListener("mousedown", function(e) {
      if (!isFlagSelected()) return;
      isDragging2 = true;
      startX2 = e.offsetX - flag2OffsetX;
      startY2 = e.offsetY - flag2OffsetY;
    });
    
    canvas2.addEventListener("mousemove", function(e) {
      if (isDragging2) {
        flag2OffsetX = e.offsetX - startX2;
        flag2OffsetY = e.offsetY - startY2;
        drawFlag2();
      }
    });
    
    canvas2.addEventListener("mouseup", function() { isDragging2 = false; });
    canvas2.addEventListener("mouseleave", function() { isDragging2 = false; });

    // Touch events for canvas2
    let initialTouchDistance2 = 0;
    canvas2.addEventListener("touchstart", function(e) {
      if (!isFlagSelected()) return;
      if (e.touches.length === 1) {
        isDragging2 = true;
        const touch = e.touches[0];
        const rect = canvas2.getBoundingClientRect();
        startX2 = touch.clientX - rect.left - flag2OffsetX;
        startY2 = touch.clientY - rect.top - flag2OffsetY;
      } else if (e.touches.length === 2) {
        isDragging2 = false;
        initialTouchDistance2 = Math.hypot(
          e.touches[0].clientX - e.touches[1].clientX,
          e.touches[0].clientY - e.touches[1].clientY
        );
      }
    });
    
    canvas2.addEventListener("touchmove", function(e) {
      if (!isFlagSelected()) return;
      e.preventDefault();
      
      if (isDragging2 && e.touches.length === 1) {
        const touch = e.touches[0];
        const rect = canvas2.getBoundingClientRect();
        flag2OffsetX = touch.clientX - rect.left - startX2;
        flag2OffsetY = touch.clientY - rect.top - startY2;
        drawFlag2();
      } else if (e.touches.length === 2) {
        const currentTouchDistance2 = Math.hypot(
          e.touches[0].clientX - e.touches[1].clientX,
          e.touches[0].clientY - e.touches[1].clientY
        );
        const zoomFactor = 0.01; // More subtle zoom
        flag2Zoom = applyZoom(flag2Zoom, (currentTouchDistance2 / initialTouchDistance2 - 1) * 100, flag2Zoom);
        initialTouchDistance2 = currentTouchDistance2;
        drawFlag2();
      }
    });
    
    canvas2.addEventListener("touchend", function() { isDragging2 = false; });

    // Save flag function
    document.getElementById("uploadFlagBtn").addEventListener("click", function() {
      if (!isFlagSelected()) {
        alert("Du måste välja två flaggor innan du sparar!");
        return;
      }
      
      const combinedCanvas = document.createElement("canvas");
      combinedCanvas.width = 5906;
      combinedCanvas.height = 3544;
      const combinedCtx = combinedCanvas.getContext("2d");

      // Combine the two canvases
      combinedCtx.save();
      combinedCtx.beginPath();
      combinedCtx.moveTo(0, combinedCanvas.height);
      combinedCtx.lineTo(combinedCanvas.width, 0);
      combinedCtx.lineTo(0, 0);
      combinedCtx.closePath();
      combinedCtx.clip();
      combinedCtx.drawImage(canvas1, 0, 0, combinedCanvas.width, combinedCanvas.height);
      combinedCtx.restore();

      combinedCtx.save();
      combinedCtx.beginPath();
      combinedCtx.moveTo(combinedCanvas.width, 0);
      combinedCtx.lineTo(0, combinedCanvas.height);
      combinedCtx.lineTo(combinedCanvas.width, combinedCanvas.height);
      combinedCtx.closePath();
      combinedCtx.clip();
      combinedCtx.drawImage(canvas2, 0, 0, combinedCanvas.width, combinedCanvas.height);
      combinedCtx.restore();

      // Convert to Blob
      combinedCanvas.toBlob(function(blob) {
        const file = new File([blob], "customized_flag.png", { type: "image/png" });
        const uploadInput = document.querySelector('input[type="file"].filepond--browser');

        if (uploadInput) {
          const dataTransfer = new DataTransfer();
          dataTransfer.items.add(file);
          uploadInput.files = dataTransfer.files;
          uploadInput.dispatchEvent(new Event("change", { bubbles: true }));
          alert("Din flagga har sparats! Scrolla nedåt för att slutföra din beställning.");
        } else {
          alert("Kunde inte hitta uppladdningsfältet. Kontrollera din konfiguration.");
        }
      }, "image/png");
    });

  } catch (error) {
    console.error("Initialization error:", error);
    alert("Ett fel uppstod vid initiering av flagganpassaren. Ladda om sidan och försök igen.");
  }
});
</script>

What I did here:

  • I make sure that it initialized in a better way.
  • I improve the srror handling.
  • I fixed the race condition.
  • I enhanced the Mobile Support.
  • I fix the zoom limit.

By applying these changes I make sur eit's work well.

Let me know if it work for you. If not I will provide you anothe rsolution code.

Thanks

- Need a Shopify Specialist? Chat on WhatsApp Or Email at info@thescriptflow.com

- Boost Your Sales with Affiliate Marketing - UpPromote: Affiliate & Referral


- If my solution was helpful, mark it as a solution and hit the like button! And Wait Don't forget to Buy me a Coffee

Amel05
Visitor
2 0 0

Now I can't choose any flag, but it isn't flags.json, it is flags.js. 

TheScriptFlow
Shopify Partner
709 49 95

Could you please share the collab code in the p/m so that I can take a look and fix it.

Thanks

- Need a Shopify Specialist? Chat on WhatsApp Or Email at info@thescriptflow.com

- Boost Your Sales with Affiliate Marketing - UpPromote: Affiliate & Referral


- If my solution was helpful, mark it as a solution and hit the like button! And Wait Don't forget to Buy me a Coffee