";let n=document.getElementById("TableOfContents");n&&(n.innerHTML=e)}rerender(){this.renderFilterMenu(),this.renderPageContent(),this.populateRightNav(),this.runHooks("afterRerender")}renderPageContent(){let e={};Object.keys(this.ifFunctionsByRef).forEach(t=>{let s=this.ifFunctionsByRef[t],o=s.value,n=(0,h.reresolveFunctionNode)(s,{variables:this.selectedValsByTraitId});this.ifFunctionsByRef[t]=n,o!==n.value&&(e[t]=n.value)});let t=document.getElementsByClassName("cdoc__toggleable");for(let n=0;n{this.fitCustomizationMenuToScreen()})}addDropdownEventListeners(){let e=document.getElementsByClassName("cdoc-dropdown");for(let t=0;t{let t=e.target;for(;!t.classList.contains("cdoc-dropdown")&&t.parentElement;)t=t.parentElement;let n=t.classList.toggle("cdoc-dropdown__expanded");t.setAttribute("aria-expanded",n.toString())});document.addEventListener("keydown",e=>{if(e.key==="Enter"){let t=e.target;t.classList.contains("cdoc-filter__option")&&t.click()}}),document.addEventListener("click",t=>{for(let n=0;nthis.handleFilterSelectionChange(e));this.addDropdownEventListeners()}locateFilterSelectorEl(){let e=document.getElementById("cdoc-selector");return!!e&&(this.filterSelectorEl=e,!0)}applyFilterSelectionOverrides(){let s=Object.keys(this.selectedValsByTraitId),e=!1,t=this.browserStorage.getTraitVals();Object.keys(t).forEach(n=>{s.includes(n)&&this.selectedValsByTraitId[n]!==t[n]&&(this.selectedValsByTraitId[n]=t[n],e=!0)});let n=(0,j.getTraitValsFromUrl)({url:new URL(window.location.href),traitIds:s});return Object.keys(n).forEach(t=>{this.selectedValsByTraitId[t]!==n[t]&&(this.selectedValsByTraitId[t]=n[t],e=!0)}),e}updateEditButton(){let t=document.getElementsByClassName("toc-edit-btn")[0];if(!t)return;let e=t.getElementsByTagName("a")[0];e&&(e.href=e.href.replace(/\.md\/$/,".mdoc.md/"))}revealPage(){this.runHooks("beforeReveal"),this.filterSelectorEl&&(this.filterSelectorEl.style.position="sticky",this.filterSelectorEl.style.backgroundColor="white",this.filterSelectorEl.style.paddingTop="10px",this.filterSelectorEl.style.visibility="visible",this.filterSelectorEl.style.zIndex="1000");let e=document.getElementById("cdoc-content");e&&(e.style.visibility="visible"),this.runHooks("afterReveal")}renderFilterMenu(){if(!this.filterSelectorEl||!this.filtersManifest)throw new Error("Cannot render filter selector without filtersManifest and filterSelectorEl");let e=(0,l.resolveFilters)({filtersManifest:this.filtersManifest,valsByTraitId:this.selectedValsByTraitId});Object.keys(e).forEach(t=>{let n=e[t];this.selectedValsByTraitId[t]=n.currentValue});let t=(0,y.buildCustomizationMenuUi)(e);this.filterSelectorEl.innerHTML=t,this.fitCustomizationMenuToScreen(),this.addFilterSelectorEventListeners()}fitCustomizationMenuToScreen(){let e=document.getElementById(g);if(!e)return;let s=e.classList.contains(n),t=document.getElementById(v);if(!t)throw new Error("Dropdown menu not found");let o=document.getElementById(b);if(!o)throw new Error("Menu wrapper not found");let i=e.scrollWidth>o.clientWidth;!s&&i?(e.classList.add(n),t.classList.remove(n)):s&&!i&&(e.classList.remove(n),t.classList.add(n))}get cdocsState(){return{selectedValsByTraitId:this.selectedValsByTraitId,ifFunctionsByRef:this.ifFunctionsByRef,filtersManifest:this.filtersManifest,browserStorage:this.browserStorage,filterSelectorEl:this.filterSelectorEl}}};e.ClientFiltersManager=r,t=r,s={value:0[0]}}),y=e(e=>{Object.defineProperty(e,"__esModule",{value:!0});var t=j();window.clientFiltersManager=t.ClientFiltersManager.instance}),y()})()Afirmación del contenido del lienzo con JavaScript
El contenido del lienzo se representa como datos de píxeles sin procesar, en lugar de elementos HTML estructurados. Esto significa que no puedes apuntar a elementos dentro de un lienzo utilizando selectores tradicionales como XPath o CSS, ya que no existe una representación DOM subyacente del contenido visual. Como resultado, acciones como hacer clic o pasar el cursor por encima no pueden interactuar con elementos dibujados dentro de un lienzo.
Para solucionarlo, puedes utilizar aserciones personalizadas de JavaScript para analizar los datos de píxeles del lienzo y verificar que el contenido esperado está presente.
¿Qué es un lienzo HTML?
El elemento canvas es una etiqueta (tag) HTML que proporciona una región dibujable en el navegador, lo que permite representar gráficos dinámicos mediante JavaScript. Se utiliza habitualmente para mostrar contenido visual, como tablas, gráficos, herramientas de edición de imágenes y animaciones.
Compatible con los principales navegadores modernos, el elemento <canvas> es versátil. Cuando se combina con bibliotecas JavaScript como Chart.js o D3.js, puede mostrar visualizaciones interactivas que responden a acciones del usuario como hacer clic o pasar el cursor por encima de un elemento, lo que permite funciones como información sobre tooltips personalizados o el resaltado de puntos de datos.
Interacción con un lienzo
Para trabajar con un elemento lienzo en JavaScript:
Seleccione el lienzo utilizando document.getElementById() o document.querySelector() y asígnalo a una variable.
Obtén el contexto de presentación llamando al método .getContext() en el elemento lienzo, especificando el tipo de contexto. El más frecuente es '2d' para gráficos bidimensionales.
Por ejemplo, define tu elemento lienzo:
<canvasid="canvas_ID"></canvas>
A continuación, ajusta su contenido con JavaScript:
//Store the canvas in a variable using its identifier
constcanvas_variable=document.getElementById("canvas_ID");//Obtain the context
constctx=canvas_variable.getContext("2d");//This code draws a green rectangle
ctx.fillStyle="green";ctx.fillRect(10,10,150,100);
Mozilla ofrece este parque de juegos, donde puedes experimentar, copiar y modificar este ejemplo.
Buscar un píxel en función de un color
Confirma que el siguiente gráfico utiliza los colores coral y verde esperados:
La estrategia más eficaz consiste en localizar al menos un píxel de color coral y otro de color verde. Empieza por identificar un píxel que coincida con el color coral.
El siguiente script muestra cómo recorrer las coordenadas x, y del lienzo para afirmar que al menos uno de sus píxeles coincide con el color de destino:
Comprobación JavaScript de ejemplo
// Defining the canvas element as a Variable
constcanvas=document.querySelector('canvas_ID');// Obtain the context
constctx=canvas.getContext('2d');/*
Recopila el área completa del lienzo comenzando en las coordenadas 0,0
La variable imageData contendrá:
- ancho: el ancho del lienzo
- altura: la altura del lienzo
- datos: una matriz que contiene los valores RGBA de cada píxel del lienzo
*/constimageData=ctx.getImageData(0,0,canvas.width,canvas.height);// Variable that stores the array of RGBA values
constdata=imageData.data;// RGBA definition of the color we are looking for (coral color)
consttargetColor={r:240,g:128,b:128};// Tolerance threshold (see note at the bottom)
constmaxDistance=20;// Function that calculates Euclidean distance
functioncolorDistance(r1,g1,b1,r2,g2,b2){returnMath.sqrt((r1-r2)**2+(g1-g2)**2+(b1-b2)**2);}// Flag that tells if the pixel color has been found or not
letfound=false;// Loop over the X axis of the canvas
for(letx=0;x<canvas.width&&!found;x++){// Loop over the Y axis of the canvas
for(lety=0;y<canvas.height;y++){//See note at the bottom.
constindex=(y*canvas.width+x)*4;constr=data[index];constg=data[index+1];constb=data[index+2];consta=data[index+3];if(a>0&&colorDistance(r,g,b,targetColor.r,targetColor.g,targetColor.b)<maxDistance){found=true;break;}}}// Return the boolean variable to tell if the Step was successful (true) or not (false)
returnfound;
Notas:
maxDistance: Esta variable indica la similitud entre el color del píxel actual y el color objetivo.
Una distancia de 0 significa una coincidencia exacta.
Una distancia de 20 significa una pequeña variación visual, imperceptible para el ojo humano.
const data = imageData.data;:
La variable imageData.data es una matriz de tipo donde cada píxel está representado por cuatro valores consecutivos: [R, G, B, A, R, G, B, A, ...]. Esto significa que cada píxel ocupa 4 bytes, independientemente de si el lienzo utiliza transparencia.
Los datos del primer píxel están en los índices 0–3: data[0] = red, data[1] = green, data[2] = blue, data[3] = alpha
El segundo píxel comienza en el índice 4, y así sucesivamente. Por eso debes utilizar la siguiente expresión para recorrer el lienzo:
const index = (y * canvas.width + x) * 4; y luego evaluar los contenidos no opacos con a > 0.
Si sabes que tu lienzo es totalmente opaco, puedes omitir la comprobación del valor alfa (a) en tu código. Sin embargo, recuerda que el canal alfa sigue presente en la matriz.
Hacer clic en el lienzo
JavaScript permite activar eventos mediante programación en elementos, lo que permite simular interacciones de usuario. Puedes utilizar el método addEventListener() para hacer que los elementos HTML respondan a acciones específicas, como los clics.
Después de configurar un escuchador, puedes enviar (o activar) un evento de clic. Con esta estrategia, puedes crear una función personalizada para simular un clic del usuario en coordenadas específicas:
Custom function example
//Store the canvas in a variable using its selector
constcanvas=document.querySelector('canvas_selector')//Add a JavaScript Listener for 'Click' actions.
canvas.addEventListener('click',function(event){//Obtain the bounding box of the canvas to calculate the click position.
constcanvasRect=canvas.getBoundingClientRect();constx=event.clientX-canvasRect.left;consty=event.clientY-canvasRect.top;});//Function that simulates a User's Click - expects a canvas and coordinates X,Y.
functionsimulateCanvasClick(user_canvas,x,y){//Obtain the bounding box of the canvas to calculate the click position.
constrect=user_canvas.getBoundingClientRect();//Define the Click event using the received coordinates
constclick_event=newMouseEvent('click',{clientX:rect.left+x,clientY:rect.top+y});// Perform the click
// Using dispatch will fire the event in line 20
user_canvas.dispatchEvent(click_event);}//Clicks on an element inside a canvas in coordinates 620, 8
simulateCanvasClick(canvas,620,8);
Afirmación de elementos activados por clics
Ahora que las piezas clave están en su lugar, puedes crear un flujo completo que incluya una aserción Synthetic. En el siguiente ejemplo, el test:
Busca en el lienzo el primer píxel que coincida con un color objetivo
Simula un clic en esa ubicación
Canvas interaction
// Defining the canvas element as a Variable
constcanvas=document.querySelector('canvas_selector');// Obtain the context
constctx=canvas.getContext('2d');// Add a JavaScript Listener for 'Click' actions.
canvas.addEventListener('click',function(event){constcanvasRect=canvas.getBoundingClientRect();constx=event.clientX-canvasRect.left;consty=event.clientY-canvasRect.top;console.log('Clicked at relative canvas position:',x,y);});// Function that simulates a User's Click - expects a canvas and coordinates X,Y.
functionsimulateCanvasClick(user_canvas,x,y){constrect=user_canvas.getBoundingClientRect();constclick_event=newMouseEvent('click',{clientX:rect.left+x,clientY:rect.top+y});user_canvas.dispatchEvent(click_event);}// Collect the full canvas area starting in coordinates 0,0
constimageData=ctx.getImageData(0,0,canvas.width,canvas.height);// Variable that stores the array of RGBA values
constdata=imageData.data;// RGBA definition of the color we are looking for (adjust the RGB values)
consttargetColor={r:A,g:B,b:C};// Tolerance threshold
constmaxDistance=20;// Function that calculates Euclidean distance
functioncolorDistance(r1,g1,b1,r2,g2,b2){returnMath.sqrt((r1-r2)**2+(g1-g2)**2+(b1-b2)**2);}// Flag that tells if the pixel color has been found or not
letfound=false;// Loop over the canvas
for(letx=0;x<canvas.width&&!found;x++){for(lety=0;y<canvas.height;y++){constindex=(y*canvas.width+x)*4;constr=data[index];constg=data[index+1];constb=data[index+2];consta=data[index+3];if(colorDistance(r,g,b,targetColor.r,targetColor.g,targetColor.b)<maxDistance){found=true;simulateCanvasClick(canvas,x,y);break;}}}returnfound;
En función del comportamiento de tu aplicación, las acciones de clic muestran o añaden un nuevo elemento HTML (como div) con el que puedes hacer afirmaciones.
Solucionar problemas
Trabajar con elementos de <canvas> e interacciones de JavaScript puede resultar complejo, especialmente para los usuarios que no están familiarizados con scripts de navegador. Los ejemplos de este artículo se ofrecen como guía general y pueden adaptarse a casos de uso específicos.
Nota: El servicio de asistencia de Datadog puede ayudar con problemas relacionados con cómo la monitorización Synthetic interactúa con <canvas>, pero no puede proporcionar ayuda para depurar despliegues personalizados de JavaScript.
A continuación encontrarás consejos y preguntas habituales que pueden servirte de guía para la resolución de problemas.
Obtener coordenadas exactas
Para determinar las coordenadas x e y del lugar donde hiciste clic en <canvas>, utiliza console.log para añadir una sentencia de impresión al método addEventListener. Esto imprimirá las coordenadas en la consola de DevTools del navegador.
Agregar escuchador con console.log
constcanvas=document.querySelector('canvas_selector');canvas.addEventListener('click',function(event){constcanvasRect=canvas.getBoundingClientRect();constx=event.clientX-canvasRect.left;consty=event.clientY-canvasRect.top;console.log('Clicked at relative canvas position:',x,y);});
Elegir el color adecuado
Un buen punto de partida es inspeccionar los estilos CSS utilizando las herramientas de desarrollo de tu navegador. La mayoría de los estilos incluyen la definición RGB del color.
El elemento lienzo solo admite valores de color RGBA. Formatos como HEX no son compatibles. Si tienes un color HEX, necesitas convertirlo a RGBA utilizando una herramienta online o un script de conversión.