2d metaball

from http://www.somethinghitme.com/2012/06/06/2d-metaballs-with-canvas/

by jpeter06

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.2/proj4.js"></script>
<canvas id="canvas"></canvas>
<button id="changeB" onclick="cambiarRender()">change</button>
<button id="stopB" onclick="stop()">stop/move</button>
<button onclick="loadHeatmap()">loadHeatmap</button>
<script>
var potInst = `AGUAYO;418.582;4773;0 
ALUMINIO;139.979;4847.682;660 
ANLLARES;213.324;4746.143;0 
APARECID;214.65;4664.668;0 
BOIMENTE;134.718;4832.286;0 
BELESAR;114.598;4729.881;0 
CARTELLE;84.55;4691.437;0 
CAELGESE;413.044;4807.593;0 
COMPOSTI;207.187;4726.148;0 
EL PALO;207.114;4804.536;0 
PESOZ;185.244;4795.505;0 
ANTINANO;263.503;4804.951;0 
LA LOMBA;199.616;4722.142;0 
LA ROBLA;285.915;4742.073;0 
LADA;286.398;4798.81;0 
MASGALAN;72.732;4741.541;0 
MESON V.;66.627;4793.562;0 
MONTEARE;220.938;4714.504;0 
NARCEA;230.137;4798.308;0 
P.G.RODR;105.746;4820.374;0 
PENAGOS;435.946;4799.979;0 
SOTORIBE;265.857;4800.568;0 
TABIELLA;267.253;4827.853;0 
TINEO;233.544;4801.914;0 
TRIVES;149.417;4695.038;0 
VELILLA;350.86;4752.694;0 
VILECHA;287.19;4715.309;42.5 
VILLAMEC;253.88;4722.541;0 
ABANTO;479.913;4793.07;0 
ALDEADAV;194.468;4569.696;0 
ALMAZAN;541.075;4590.364;10.0 
AMOREBIE;527.221;4786.776;0 
SENGRACI;560.059;4685.658;0 
AZPEITIA;564.882;4787.393;0 
ARRUBAL;562.863;4702.871;0 
GARO-BAR;479.316;4739.748;0 
CASTEJON;610.375;4673.12;0 
ELEREBRO;612.443;4673.106;0 
GATICA;513.476;4804.686;0 
DUEROINT;165.265;4573.436;0 
C.RODRIG;208.986;4497.162;0 
GRIJOTA;376.124;4661.181;0 
GUENES;483.863;4784.212;0 
HERNANI;580.164;4789.657;0 
HERRERA;392.461;4713.851;0 
HINOJOSA;187.573;4540.07;0 
ICHASO;558.753;4769.331;0 
LORA;430.066;4713.392;0 
LA SERNA;611.086;4661.85;0 
MUDARRA;348.014;4627.024;0 
MURUARTE;597.207;4739.506;0 
OLMEDO;344.92;4606.413;0 
SANTURCE;492.132;4798.399;0 
SAUCELLE;183.288;4549.523;0 
TORDESIL;332.534;4596.788;0 
VILLARIN;214.073;4570.952;0 
VIRTUS;434.653;4757.444;0...

CSS

body{background:#000;}
#changeB{ position:absolute;top:4px;left:4px;}
#stopB{ position:absolute;top:4px;left:64px;}

JavaScript

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    tempCanvas = document.createElement("canvas"),
    tempCtx = tempCanvas.getContext("2d"),
    width = 700,
    height = 700,
    threshold = 210,
    colors = {r:255,g:0,b:0}, cycle = 0,
    points = [];

var conBorde=false;
var moverse=false;

function cambiarRender(){
	conBorde=!conBorde;
}
function stop(){
	moverse=!moverse;
}

canvas.width = tempCanvas.width = width;
canvas.height= tempCanvas.height= height;
const lineas = potInst.split('\n');
let maxVal = 60;
const maxAlpha = 255;
const gradientR = 15; //Radio del gradiente
let maxX = 0.0;
let maxY = 0.0;
let minX = 100000.0;
let minY = 100000.0;
const datos = [];
lineas.forEach((linea)=>{ 
	const dato = linea.split(';');
  if( true || estaciones.hasOwnProperty(dato[0])){
    const x = Number(dato[1]);
    const y = Number(dato[2]);
    const val = Number(dato[3]);
   // console.log(linea,x,y)
    //const val = Math.min(60,Number(dato[3]));
  //  datos.push([x,y,Math.max(3,Math.min(maxVal,Number(dato[3])))*factVal]);
    datos.push([x,y,val]);
    maxX = Math.max(maxX, x);
    maxY = Math.max(maxY, y);
    minX = Math.min(minX, x);
    minY = Math.min(minY, y); 
    maxVal = Math.max(maxVal, val);  
  }
})

const factVal = maxAlpha/maxVal;

console.log(datos[0])
console.log('total:',datos.length, 'maxVal:', maxVal, 'minX:',minX, 'maxX:',maxX,'minY:', minY,  'maxy:',maxY)
//Aplicamos ajustes MAx Min Width height
const factX = width /(maxX - minX);
const factY = width /(maxY - minY);
datos.forEach((dato)=>{ //console.log(dato)
	dato[2] = Math.max(dato[2] * factVal,12);
	dato[0] = (dato[0] - minX) * factX;
	dato[1] = (Math.abs(dato[1] - maxY)) * factY; //Invertimos para verlo bien
  points.push({x:dato[0],y:dato[1] , value:dato[2]});
})

console.log(datos);


function update(){
    var len = points.length;
    tempCtx.clearRect(0,0,width,height);
    while(len--){
        var point = points[len];
        tempCtx.beginPath();
...