/* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable prefer-const */ import type { IActivityHandler } from "@vertigis/workflow"; import html2canvas from 'html2canvas'; /** An interface that defines the inputs of the activity. */ interface LegendCreatorInputs { /** * @displayName Class Name * @description Legend Class name * @required */ className: string; } /** An interface that defines the outputs of the activity. */ interface LegendCreatorOutputs { /** * @description The result of the activity. */ imageBase64: string; } /** * @displayName Create Legend * @category EBTA Utilities * @description Create Legend Ver1.4 */ function convertSVGTagstoIMG(container) { let svgElements: NodeListOf = container.querySelectorAll('svg[role="img"]'); let SVGDom = Array.from(svgElements).filter(svg => { let svgElement = svg; let gTag = svgElement.querySelector('g'); return gTag && gTag.querySelector('image'); }); SVGDom.forEach(svg => { let svgElement = svg; // Create a new element let img = document.createElement('img'); let imageDOM = svgElement.querySelector('image'); if (imageDOM) { let imageurl = imageDOM.getAttribute('href'); // Transfer the relevant attributes img.alt = imageDOM.getAttribute('alt') || ''; img.src = imageurl || ''; // Use xlink:href for the src img.width = parseInt(imageDOM.getAttribute('width') || '0'); img.height = parseInt(imageDOM.getAttribute('height') || '0'); svg.parentNode!.replaceChild(img, svg); } else { console.log('No image found inside svg.'); } }); console.log('IMG conversion finished'); } async function captureElementByClassToFile(className: string): Promise { // Query the DOM for the first element with the specified class name const element :HTMLElement = document.querySelector(`.${className}`)!; if (!element) { throw new Error(`Element with class ${className} not found`); } // Ensure all external images have the crossOrigin attribute set try { convertSVGTagstoIMG(element) const images:NodeListOf = element.querySelectorAll('img[src]') ; images.forEach((img) => { if (!img.crossOrigin) { img.crossOrigin = 'anonymous'; } }); const originalStyles = { backgroundColor: element.style.backgroundColor, color: element.style.color }; // Reverse the dark mode styles element.style.backgroundColor = 'white'; element.style.color = 'black'; // Apply the same style changes to all children, and backup the original const children : NodeListOf = element.querySelectorAll('*'); const originalChildStyles:{element: HTMLElement, backgroundColor: string, color: string}[] = []; children.forEach(child => { originalChildStyles.push({ element: child, backgroundColor: child.style.backgroundColor, color: child.style.color }); child.style.backgroundColor = 'white'; child.style.color = 'black'; }); // Capture the element using html2canvas with useCORS option const canvas = await html2canvas(element, { useCORS: true, logging: true, backgroundColor: '#ffffff', allowTaint: true , scale:2.5 }); // Convert the canvas to Base64 image let imageBase64 = canvas.toDataURL("image/jpeg"); // Revert to the original styles element.style.backgroundColor = originalStyles.backgroundColor; element.style.color = originalStyles.color; // Revert the styles of all children originalChildStyles.forEach(({ element, backgroundColor, color }) => { element.style.backgroundColor = backgroundColor; element.style.color = color; }); return imageBase64; } catch (error) { throw new Error(`Failed to capture legend screenshot: ${(error as Error).message}`); } } /** * @displayName Legend Creator * @category VertiGIS Utilities * @description Create Legend Ver1.4 */ export default class LegendCreatorActivity implements IActivityHandler { /** Perform the execution logic of the activity. */ async execute(inputs: LegendCreatorInputs): Promise { const imageBase64 = await captureElementByClassToFile(inputs.className); console.log('Legend creator version 1.4'); return { imageBase64: imageBase64 }; } }