Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

291
Visualizações
Medidor de calibre SVG con trazos dinámicos

Estoy tratando de construir un SVG algo similar a: ingrese la descripción de la imagen aquí

Los trazos son completamente dinámicos, ya que provienen de una API. Quiero colocar los trazos en los puntos recibidos (como una matriz de valores porcentuales). No necesita estar en orden y la distancia entre 2 golpes no necesita ser igual

Estoy intentando con algo como a continuación, pero no puedo encontrar una lógica para la ubicación de los trazos. Traté de seguir la respuesta aquí: https://stackoverflow.com/a/66076805/6456247 pero la distancia entre trazos aquí es igual. En mi escenario, no son consistentes.

Enlace de violín: https://jsfiddle.net/puq8v594/2/

 let divisionsElement = document.getElementById('divisions'); let length = parseInt(divisionsElement.getAttribute("r")) * Math.PI; let divisionsArray = [20,30,80,90]; //stroke at 20%, 30%,80%,90% position let METER_DIVISIONS_GAP = 0.2; divisionsArray.map(ele => { setupPath(ele); }) function setupPath(val) { divisionsElement.setAttribute("stroke-dasharray", val + ' ' +METER_DIVISIONS_GAP); }
 circle { fill: none; } .circle-back { stroke: #F8F6F0; stroke-width:9px; } .circle-fill { stroke: grey; stroke-width: 10px; } .circle-progress { stroke: blue; stroke-width:9px; }
 <svg viewBox="0 0 126 126" preserveAspectRatio="xMinYMin meet"> <clipPath id="cut-off"> <rect x="0" y="0" width="100%" height="50" /> </clipPath> <clipPath id="progress-percent"> <path x="0" y="0" width="12%" height="50" /> </clipPath> <g> <circle r="35%" cx="40%" cy="40%" class="circle-fill" clip-path="url(#cut-off)" /> <circle id="divisions" r="35%" cx="40%" cy="40%" class="circle-back" clip-path="url(#cut-off)" stroke-dasharray="20 0.5" stroke-dashoffset="25" /> <circle r="35%" cx="40%" cy="40%" class="circle-progress" clip-path="url(#progress-percent)" /> </g> </svg>

-----------EDITAR------------

Para alguien que quiera implementar esto con soporte para IE, pude implementarlo haciendo algunos cambios en el código de Michael.

 var data = [10,20,10,10,25,25]; var dataSum = 0; for (let i = 0; i < data.length - 1; i++) { dataSum += data[i]; } var drawArray = ""; var indexOfFill = 2; var arcPath = document.getElementById("meter-back"); var filledPath = document.getElementById("meter-fill"); var totalLength = arcPath.getTotalLength(); function drawPath() { // Draw the background strokes let test=''; for (i = 0; i < data.length; i++) { let barLen = ((data[i]) * totalLength) / 100; test = test + ((barLen) - (0.2 * (dataSum / 100)) + " " + 0.2 * (dataSum / 100) + " ") } arcPath.setAttribute("stroke-dasharray", test); animate(filledPath, totalLength, 0,50); }drawPath(); function animate(el,length,end,percentage) { el.style.visibility = 'visible'; if (end <= percentage) { el.style.strokeOpacity = 5; let gap = 100 - end; let offset = 100; el.style.strokeDasharray = ((end / 100) * length) + ' ' + ((gap / 100) * length); el.style.strokeDashoffset = (offset / 100) * length; animate(el, length, ++end, percentage); } }
 <svg width="100%" height="600px" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet"> <defs> <filter id="outline" y="-50%" height="200%"> <feMorphology operator="erode" radius="0.2" /> <feComposite operator="out" in="SourceGraphic" result="outline" /> <feFlood flood-color="grey" /> <feComposite operator="in" in2="outline" /> <feComposite operator="atop" in2="SourceGraphic" /> </filter> </defs> <g filter="url(#outline)"> <path fill="none" stroke-dasharray="" stroke-width="20" stroke="grey" d="M30 100 A 40 40 0 0 1 170 100" /> <path id="meter-back" fill="none" stroke-dasharray="" stroke-width="20" stroke="white" d="M30 100 A 40 40 0 0 1 170 100" /> <path id="meter-fill" fill="none" stroke-dasharray="" stroke="rgba(128,128,128,0.5)" stroke-width="20" d="M30 100 A 40 40 0 0 1 170 100" style="visibility: hidden;" ></path> </g> </svg>

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Podría ser más fácil hacer esto como solo una ruta de arco con una longitud de ruta establecida en 100 (o casi 100).

 let data =[5 , 10 , 25 ,25 , 6 , 9 , 20]; let i=0; let drawArray = ""; let arcPath = document.getElementById("meter"); function setupPath() { for (i=0; i < data.length; i++) { drawArray = drawArray + (data[i] - 0.5) + " 0.5 "; } arcPath.setAttribute("stroke-dasharray", drawArray); }; setupPath();
 <svg width="800px" height="600px" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet"> <path id="meter" fill="none" stroke-dasharray="" stroke-width="20" stroke="blue" pathLength="99.5" d="M30 100 A 40 40 0 0 1 170 100" /> </svg>

Actualizar:

Por la pregunta, pensé que esperaba una serie de valores porcentuales que suman 100 como entrada. Pero si no conoce la cantidad de valores o su suma, puede normalizar los datos de la siguiente manera. Además, puede agregar un contorno usando un filtro, lo que le evita tener que hacer muchas matemáticas para dibujar segmentos de arco explícitamente.

También me di cuenta de que quería un relleno parcial, para que pueda controlar hasta dónde se llena el indicador, cambiando la variable - indexOfFill.

 var data = [5, 10 ,25 ,25 ,6 ,9 ,20 ,16 ,33 ,45 ,67]; var dataSum = data.reduce((partial_sum, a) => partial_sum + a, 0); var indexOfFill = 3; var i=0; var drawArray = ""; var arcPath = document.getElementById("meter-back"); var filledPath = document.getElementById("meter-fill"); function setupPath() { // Draw the background for (i=0; i < data.length; i++) { drawArray = drawArray + (data[i] - (0.5 * (dataSum/100)) + " " + 0.5*(dataSum/100) +" ")}; arcPath.setAttribute("stroke-dasharray", drawArray); arcPath.setAttribute("pathLength", dataSum - (0.5 * (dataSum/100))); //Draw the fill drawArray=""; for (i=0; i < indexOfFill; i++) { if ( (i + 1) === indexOfFill ) { drawArray = drawArray + (data[i] - (0.5 * (dataSum/100)) + " " + dataSum) } else { drawArray = drawArray + (data[i] - (0.5 * (dataSum/100)) + " " + 0.5*(dataSum/100) +" ")}}; filledPath.setAttribute("stroke-dasharray", drawArray); filledPath.setAttribute("pathLength", dataSum - (0.5 * (dataSum/100))); }; setupPath();
 <svg width="800px" height="600px" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet"> <defs> <filter id="outline" y="-50%" height="200%"> <feMorphology operator="erode" radius="0.2"/> <feComposite operator="out" in="SourceGraphic" result="outline"/> <feFlood flood-color="black"/> <feComposite operator="in" in2="outline"/> <feComposite operator="atop" in2="SourceGraphic"/> </filter> </defs> <g filter="url(#outline)"> <path id="meter-back" fill="none" stroke-dasharray="" stroke-width="20" stroke="white" pathLength="99.5" d="M30 100 A 40 40 0 0 1 170 100" /> <path id="meter-fill" fill="none" stroke-dasharray="" stroke-width="20" stroke="rgb(90,90,220)" pathLength="99.5" d="M30 100 A 40 40 0 0 1 170 100" /> </g> </svg>

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda