Disable resize option on a Custom Annotation Tool

Hello, We have a custom annotation tool that we use to annotate a text insertion in a document when the user reviews the document. We want to remove the resize option on the annotation icon that is displayed like a bubble shown in the screenshot. Can you please help with how this can be done?

image

Hi,

In your code of where it creates the annotation, can you try setting the ‘NoResize’ to be false?
Sample code snippet:

annotation.NoResize = false;

https://www.pdftron.com/api/web/Annotations.Annotation.html

Thanks,
Anthony Chen

  const updateXFDF = (action, xmlString, userSelect, userAnnotations) => {
    if (areAllAnnotationsEmpty(userAnnotations)) {
      const parser = new DOMParser();
      const xmlDoc = parser.parseFromString(xmlString, "text/xml");
      if (
        xmlDoc.getElementsByTagName("ffield").length > 0 &&
        xmlDoc.getElementsByTagName("widget").length > 0
      ) {
        const ffield = xmlDoc.getElementsByTagName("ffield")[0].outerHTML;
        const widget = xmlDoc.getElementsByTagName("widget")[0].outerHTML;
        setUserAnnotations((prevState) => {
          const updatedAnnotations = prevState.map((user) => {
            if (user.userID === userSelect) {
              return {
                ...user,
                xml: [{ ffield: ffield, widget: widget }],
              };
            }
            return user;
          });
          return updatedAnnotations;
        });
      }
    } else {
      // Iterate over each user's annotations
      const parser = new DOMParser();
      const xmlDoc = parser.parseFromString(xmlString, "text/xml");

      xmlDoc.querySelectorAll("widget").forEach((widget) => {
        const widgetName = widget.getAttribute("name");
        const ffieldName = widget.getAttribute("field");
        let widgetFound = false;
        userAnnotations.forEach((user) => {
          user.xml.forEach((xml) => {
            if (xml.widget.includes(widgetName)) {
              // Replace the ffield and widget with new values from the main XML
              xml.ffield = xmlDoc.querySelector(
                `ffield[name="${ffieldName}"]`
              ).outerHTML;
              xml.widget = widget.outerHTML;
              widgetFound = true;
            }
          });
        });
        // If the widget was not found in userAnnotations, add it
        if (!widgetFound) {
          userAnnotations.forEach((user) => {
            if (user.userID === userSelect) {
              // Assuming you want to add to the current user's annotations
              user.xml.push({
                ffield: xmlDoc.querySelector(`ffield[name="${ffieldName}"]`)
                  .outerHTML,
                widget: widget.outerHTML,
              });
            }
          });
        }
      });
      // Update the state with the modified userAnnotations
      setUserAnnotations(userAnnotations);
    }
  };
  // if using a class, equivalent of componentDidMount
  useEffect(() => {
    if (webViewer.attachmentBlob) {
      WebViewer(
        {
          path: "/webviewer/lib",
          showLocalFilePicker: true,
          fullAPI: true,
          licenseKey:****
        },

        viewer.current
      ).then(async (instance) => {
        setInstance(instance);
        instance.UI.loadDocument(base64ToBlob(webViewer.attachmentBlob), {
          filename: fileName,
        });
        const { documentViewer, annotationManager} =
          instance.Core;
        //======================================== disable header =====================================//
        instance.UI.disableElements([
          "annotationPopup",
          "outlinesPanelButton",
          "comboBoxFieldToolGroupButton",
          "listBoxFieldToolGroupButton",
          "toolsOverlay",
          "toolbarGroup-Shapes",
          "toolbarGroup-Edit",
          "toolbarGroup-Insert",
          "shapeToolGroupButton",
          "menuButton",
          "freeHandHighlightToolGroupButton",
          "underlineToolGroupButton",
          "freeHandToolGroupButton",
          "stickyToolGroupButton",
          "squigglyToolGroupButton",
          "strikeoutToolGroupButton",
          "notesPanel",
          "viewControlsButton",
          "selectToolButton",
          "toggleNotesButton",
          "searchButton",
          "freeTextToolGroupButton",
          "crossStampToolButton",
          "checkStampToolButton",
          "dotStampToolButton",
          "rubberStampToolGroupButton",
          "dateFreeTextToolButton",
          "eraserToolButton",
          "panToolButton",
          "signatureToolGroupButton",
          "viewControlsOverlay",
          "contextMenuPopup",
        ]);
        //======================================== disable header =====================================//

        //======================================== for cutome side bar =====================================//
        // Example handler for when the dropdown value changes
        const handleDropdownChange = (selectedValue) => {
          setSelectedUser(selectedValue);
        };

        const openCustomModal = () => {
          setOpenAddParticipentModal(true); // Open the custom modal
        };
        // Create a render function for the custom panel
        const renderCustomPanel = () => {
          return (
            <div>
              <label htmlFor="participantDropdown">{t("Participant")}</label>
              <select
                id="participantDropdown"
                name="Participant"
                onChange={(e) => handleDropdownChange(e.target.value)}
              >
                <option value="user1">user1</option>
                <option value="user2">user2</option>
                {/* Add more options as needed */}
              </select>
              <button onClick={openCustomModal}>Open Custom Modal</button>
            </div>
          );
        };

        var myCustomPanel = {
          tab: {
            dataElement: "customPanelTab",
            title: "customPanelTab",
            img: "/favicon-32x32.png",
          },
          panel: {
            dataElement: "customPanel",
            render: renderCustomPanel,
          },
        };

        instance.UI.setCustomPanel(myCustomPanel);
        //======================================== for cutome side bar =====================================//

        //======================================== header save button =====================================//
        async function generateBase64FromBlob(blob) {
          return new Promise((resolve, reject) => {
            const reader = new FileReader();

            reader.onload = function () {
              const base64String = reader.result.split(",")[1];
              resolve(base64String);
            };

            reader.onerror = function (error) {
              reject(error);
            };

            reader.readAsDataURL(blob);
          });
        }
        instance.UI.setHeaderItems((header) => {
          header.push({
            type: "actionButton",
            img: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/></svg>',
            onClick: async () => {
              const xfdfString = await annotationManager.exportAnnotations();
              console.log("xfdfStringxfdf String", xfdfString);

              // Remove annotations from the xfdfString
              const doc = documentViewer.getDocument();
              const data = await doc.getFileData({}); // No xfdfString for annotations
              const arr = new Uint8Array(data);
              const blob = new Blob([arr], { type: "application/pdf" });
              generateBase64FromBlob(blob)
                .then((base64String) => {
                  console.log(
                    "xfdfStringxfdf PDF Base64 String:",
                    base64String
                  );
                  // Here you can use the base64String as needed
                })
                .catch((error) => {
                  console.error("Error generating base64 string:", error);
                });
              // Dispatch your Redux action to send the data to the API
              if (Number(commingFrom) === 1) {
                const apiData = {
                  TaskID: taskId, // Assuming taskId is defined in your component
                  TaskAttachementID: attachmentID, // Assuming attachmentID is defined in your component
                  AnnotationString: xfdfString, // Pass the annotations data here
                };
                // for todo
                dispatch(addAnnotationsOnToDoAttachement(navigate, t, apiData));
              } else if (Number(commingFrom) === 2) {
                let notesData = {
                  NoteID: taskId,
                  NoteAttachementID: attachmentID,
                  AnnotationString: xfdfString,
                };
                dispatch(
                  addAnnotationsOnNotesAttachement(navigate, t, notesData)
                );
                // for notes
              } else if (Number(commingFrom) === 3) {
                let resolutionData = {
                  ResolutionID: taskId,
                  ResolutionAttachementID: attachmentID,
                  AnnotationString: xfdfString,
                };
                dispatch(
                  addAnnotationsOnResolutionAttachement(
                    navigate,
                    t,
                    resolutionData
                  )
                );
                // for resultion
              } else if (Number(commingFrom) === 4) {
                // for data room
                let dataRoomData = {
                  FileID: attachmentID,
                  AnnotationString: xfdfString,
                };

                dispatch(
                  addAnnotationsOnDataroomAttachement(navigate, t, dataRoomData)
                );
              }
            },
          });

          header.push({
            type: "actionButton",
            img: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/></svg>',
            onClick: async () => {},
          });
        });
        //======================================== header save button =====================================//

        //======================================== for documentLoaded =====================================//
        await documentViewer.getAnnotationsLoadedPromise();
        documentViewer.addEventListener("documentLoaded", async () => {
          // annotManager.setCurrentUser(name);
          if (webViewer.xfdfData !== "" && annotationManager) {
            try {
              await annotationManager.importAnnotations(
                pdfResponceDataRef.current
              );
            } catch (error) {
              console.log("importAnnotations", error);
            }
          }
        });
        //======================================== for documentLoaded =====================================//
      });
    }
  }, [webViewer.attachmentBlob]);

  useEffect(() => {
    if (Instance) {
      const { annotationManager } = Instance.Core;
      annotationManager.addEventListener(
        "annotationChanged",
        async (annotations, action, { imported }) => {
          if (imported) {
            return;
          }
          
          try {
            annotations.NoResize = false;
            // Export annotations to XFDF format using `exportAnnotations`
            const xfdfString = await annotationManager.exportAnnotations();

            // Update the user's annotations based on the action
            updateXFDF(
              action,
              xfdfString,
              selectedUserRef.current,
              userAnnotationsRef.current
            );
          } catch (error) {
            console.error("Error in annotationChanged event:", error);
          }
        }
      );
    }
  }, [Instance]);```

in the upper comment i have provide my code
what i want is that disable resized and rotation of annotations in my ui how can i do that
Screenshot 2024-01-17 120432

Hello prabahar.kuppuswamy1,

You can set the NoResize option on your annotation:
https://docs.apryse.com/api/web/Core.Annotations.Annotation.html#NoResize__anchor

Best regards,
Tyler