在 Fabric.js Canvas 中选择另一个对象时如何将对象保留在顶层?

问题描述 投票:0回答:1

我正在开发一个项目,其中使用 Fabric.js 库创建带有文本和图像的画布。我有一个要求,即使我主动选择要上传的图像,我也想确保文本始终保留在顶层。

我已经实现了上传图像并将文本添加到画布的功能。但是,当我选择图像时,图像似乎覆盖了文本,这不是我想要的行为。相反,我希望文本保留在顶层,无论是否选择图像。

我尝试使用以下方法来管理分层:

canvas.sendBackwards(myObject)
canvas.sendToBack(myObject)
canvas.bringForward(myObject)
canvas.bringToFront(myObject)

但是,我还没有达到预期的行为。在图像上传过程中,文本仍然被图像遮挡。

   <script>
      // Initialize Firebase with your own config
      const firebaseConfig = {//
      };

      firebase.initializeApp(firebaseConfig);
      const storage = firebase.storage();
      const firestore = firebase.firestore();

      // Update the submit button click event handler
      document
        .getElementById("submit-button")
        .addEventListener("click", async () => {
          const imageFilename = document.getElementById("image-filename").value;

          // Convert the canvas to a PNG data URL
          const pngDataURL = canvas.toDataURL({ format: "png", multiplier: 3 }); // Adjust multiplier as needed for higher resolution

          // Convert the data URL to a Blob
          const pngBlob = await (await fetch(pngDataURL)).blob();

          // Create a reference to Firebase storage
          const storageRef = storage.ref();

          // Define the path for the uploaded PNG
          const pngPath = `designs/${imageFilename}.png`;

          // Upload PNG to Firebase storage
          const pngUploadTask = storageRef.child(pngPath).put(pngBlob);

          pngUploadTask.on(
            "state_changed",
            (snapshot) => {
              // Handle upload progress if needed
              const progress =
                (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
              console.log(`Upload progress: ${progress}%`);
            },
            (error) => {
              // Handle errors
              console.error("Upload error:", error);
            },
            async () => {
              // Get the download URL of the uploaded PNG
              const downloadURL =
                await pngUploadTask.snapshot.ref.getDownloadURL();
              console.log("PNG download URL:", downloadURL);

              const designRef = firestore.collection("designs").doc();
              const timestamp = firebase.firestore.FieldValue.serverTimestamp();

              await designRef.set({
                filename: imageFilename,
                url: downloadURL,
                timestamp: timestamp,
                completed: false,
              });

              // Show a success message
              window.location.href = "thank_you.html";

              // Clear the filename input field
              document.getElementById("image-filename").value = "";
            }
          );
        });

      const canvas = new fabric.Canvas("spacebar-canvas");

      // Load the sample SVG background
      fabric.loadSVGFromURL("sample.svg", function (objects, options) {
        const svg = fabric.util.groupSVGElements(objects, options);
        svg.scaleToWidth(canvas.width);
        svg.scaleToHeight(canvas.height);
        canvas.setBackgroundImage(svg, canvas.renderAll.bind(canvas));
      });

      document
        .getElementById("image-upload")
        .addEventListener("change", handleImageUpload);
      document
        .getElementById("image-upload-2")
        .addEventListener("change", handleImageUpload);
      document
        .getElementById("image-upload-3")
        .addEventListener("change", handleImageUpload);

      document
        .getElementById("text-input")
        .addEventListener("input", updateText);
      document
        .getElementById("font-family")
        .addEventListener("change", updateText);
      document
        .getElementById("font-weight")
        .addEventListener("change", updateText);
      document.getElementById("italic").addEventListener("change", updateText);
      document
        .getElementById("text-color")
        .addEventListener("input", updateTextColor);

      document
        .getElementById("shape-color")
        .addEventListener("input", updateShapeColor);
      document
        .getElementById("small-shape-color")
        .addEventListener("input", updateSmallShapeColor);

      function handleImageUpload(e) {
        const file = e.target.files[0];
        if (file) {
          const reader = new FileReader();
          reader.onload = function (event) {
            const imageUrl = event.target.result;
            fabric.Image.fromURL(imageUrl, function (img) {
              img.scaleToWidth(40); // Adjust the width
              img.set({ left: 100, top: 10 }); // Adjust the initial position
              canvas.add(img);
              canvas.sendToBack(img); // Send the image to the back
              canvas.renderAll();
            });
          };
          reader.readAsDataURL(file);
        }
      }

      // Add an event listener to the text input to select the text object when focused
      document
        .getElementById("text-input")
        .addEventListener("focus", selectTextObject);

      function selectTextObject() {
        const textObject = canvas.getActiveObject();
        if (textObject && textObject.type === "text") {
          canvas.setActiveObject(textObject);
          canvas.renderAll();
        }
      }

      // Update the text input event listeners
      document
        .getElementById("text-input")
        .addEventListener("input", updateText);
      document
        .getElementById("font-family")
        .addEventListener("change", updateText);
      document
        .getElementById("font-weight")
        .addEventListener("change", updateText);
      document.getElementById("italic").addEventListener("change", updateText);
      document
        .getElementById("text-color")
        .addEventListener("input", updateTextColor);

      // Update the updateText function
      function updateText() {
        const text = document.getElementById("text-input").value;
        const fontFamily = document.getElementById("font-family").value;
        const fontWeight = document.getElementById("font-weight").value;
        const isItalic = document.getElementById("italic").checked;
        const textColor = document.getElementById("text-color").value;

        // Remove existing text object before adding a new one
        canvas.forEachObject(function (obj) {
          if (obj.type === "text") {
            canvas.remove(obj);
          }
        });

        if (text) {
          const textObject = new fabric.Text(text, {
            left: canvas.width / 2,
            top: canvas.height / 2,
            fontSize: 18,
            fontFamily: fontFamily,
            fontWeight: fontWeight,
            fontStyle: isItalic ? "italic" : "normal",
            fill: textColor,
            originX: "center",
            originY: "center",
          });

          canvas.add(textObject);
          canvas.sendToFront(textObject); // Bring the text to the front
          canvas.renderAll();
        }
      }

      function updateShapeColor() {
        const shape = canvas
          .getObjects()
          .find((obj) => obj.type === "rect" && obj.name === "bgRect");
        if (shape) {
          shape.set({ fill: document.getElementById("shape-color").value });
          shape.visible = true; // Make the large rectangle visible
          canvas.renderAll();
        }
      }

      function updateSmallShapeColor() {
        const shape = canvas
          .getObjects()
          .find((obj) => obj.type === "rect" && obj.name === "centerRect");
        if (shape) {
          shape.set({
            fill: document.getElementById("small-shape-color").value,
          });
          shape.visible = true; // Make the small rectangle visible
          canvas.renderAll();
        }
      }

      function updateTextColor() {
        const textObject = canvas
          .getObjects()
          .find((obj) => obj.type === "text");
        if (textObject) {
          textObject.set({ fill: document.getElementById("text-color").value });
          canvas.renderAll();
        }
      }

      // Add a larger rectangle shape (background)
      const bgRect = new fabric.Rect({
        width: canvas.width,
        height: canvas.height,
        fill: "#000000",
        name: "bgRect", // Add a name to distinguish it
        selectable: false,
        visible: false, // Initially hidden
      });
      canvas.add(bgRect);

      // Add a smaller rectangle shape (centered)
      const centerRect = new fabric.Rect({
        width: 565, // Adjust the width
        height: 70, // Adjust the height
        fill: "#FF0000", // Initial color
        name: "centerRect", // Add a name to distinguish it
        left: canvas.width / 2,
        top: canvas.height / 2,
        originX: "center",
        originY: "center",
        selectable: false,
        visible: false, // Initially hidden
      });
      canvas.add(centerRect);
    </script>

javascript html fabricjs
1个回答
0
投票

您在找这个吗?下面的代码是一个设置,即使选择了对象也可以保留图层。

const canvas = new fabric.Canvas("spacebar-canvas", {
    preserveObjectStacking: true
});
© www.soinside.com 2019 - 2024. All rights reserved.