3
"How can I javascript to select a country and paint it?" (Raster images)
https://en.wikipedia.org/wiki/Flood_fill
https://en.wikipedia.org/wiki/Graph_traversal
https://en.wikipedia.org/wiki/Connected-component_labeling
http://www.algorytm.org/podstawy-grafiki/flood-fill/flood-fill-js.html (4 and 8 directions recursive implementation) (areas < ~40000 pixels)
'use strict';
let draw = async ( ) => {
const targetColor = 0xffffffff|0; // int32 rgba (cor branca).
let randomColor; // cor de preechimento.
const colorTolerance = 55; // 55 // 1 - 128 - 1020.
/*
let src = 'JirA9.gif'; // https://i.stack.imgur.com/JirA9.gif
*/
let src = URL.createObjectURL( new Blob( [
( await (await fetch( 'https://upload.wikimedia.org/wikipedia/commons/4/4d/BlankMap-World.svg' )).text() )
.replace( /#000000/g, '#ffffff' )
.replace( /#ffffff/g, '#99aaff' )
.replace( /#c0c0c0/g, '#ffffff' )
], { type:'image/svg+xml' } )
);
let canvas = document.getElementById( 'Mapa' );
let W, H, ctx;
let load = ( ) => {
W = img.naturalWidth;
H = img.naturalHeight;
canvas = Object.assign( canvas, {
style: `
transform: scale(${canvas.width / W}, ${canvas.height / H});
transform-origin: 0px 0px;
`,
width: W,
height: H
} );
ctx = canvas.getContext( '2d', { alpha: false } );
ctx.fillStyle = '#99AAFF'; // '#FFFFFF';
ctx.fillRect( 0, 0, W, H );
ctx.drawImage( img, 0, 0 );
}
let img = Object.assign( new Image( ),
{ /*crossOrigin: 'anonymous',*/ src: src, /*onload: load*/ } );
img.addEventListener( 'load', load );
let rv = new Int32Array( 1000 );
crypto.getRandomValues( rv );
rv.sort();
//rv.sort((a, b) => b - a);
let it = 0;
let click = ( ev ) => {
let x = ev.offsetX * W / W|0;
let y = ev.offsetY * H / H|0;
randomColor = rv[ ++it ];
let imgData = ctx.getImageData( 0, 0, W, H );
let data = new Int32Array( imgData.data.buffer );
if( data[ ( y * W + x ) ] != targetColor ) return;
let pixToCheck = [ x, y ];
/*
while( pixToCheck[0] ){ // ===> Algoritmo I
y = pixToCheck.pop();
x = pixToCheck.pop();
data[ ( y * W + x ) ] == targetColor && ( data[ ( y * W + x ) ] = randomColor ) && pixToCheck.push(
(x), (y + 1), // N
(x), (y - 1), // S
(x + 1), (y), // E
(x - 1), (y) // O
);
}
*/
let color, colorDiff;
while( pixToCheck.length > 0 ){ // ===> Variante A
y = pixToCheck.pop();
x = pixToCheck.pop();
color = data[ ( y * W + x ) ];
if( !( color != randomColor ) ) continue;
colorDiff = (targetColor & 255) - (color & 255) + (targetColor >>> 8 & 255) - (color >>> 8 & 255) + (targetColor >>> 16 & 255) - (color >>> 16 & 255) + (targetColor >>> 24 & 255) - (color >>> 24 & 255);
if( !( colorDiff > -colorTolerance && colorDiff < colorTolerance ) ) continue;
data[ ( y * W + x ) ] = randomColor;
pixToCheck.push(
(x + 1), (y),
(x - 1), (y),
(x), (y + 1),
(x), (y - 1)
);
}
ctx.putImageData( imgData, 0, 0 );
}
canvas.addEventListener( 'click', click );
}; draw()
<canvas title="click" id="Mapa" width="1000" height="508"></canvas>
Note: In the code above variant A and algorithm I can be used separately with the following differences:
Result with https://i.stack.imgur.com/JirA9.gif
SVG images without raster elements:
(async () => {
let Mapa = document.querySelector( '.Mapa' );
let srcSVG = new DOMParser()
.parseFromString( await (await fetch( 'https://upload.wikimedia.org/wikipedia/commons/4/4d/BlankMap-World.svg' )).text(), 'image/svg+xml' )
.querySelector( 'svg' );
srcSVG.style.transform = `scale(${Mapa.width.baseVal.value / srcSVG.width.baseVal.value}, ${Mapa.height.baseVal.value / srcSVG.height.baseVal.value})`;
srcSVG.style.transformOrigin = '0 0';
srcSVG.addEventListener( 'click', ( ev ) => {
if( ev.target.id != 'ocean' ) ev.target.style.fill = `rgba(
${ Math.random() * 256 & 255 }, /*R*/
${ Math.random() * 256 & 255 }, /*G*/
${ Math.random() * 256 & 255 }, /*B*/
${ 1.0 } /*A*/
)`;
}
);
Mapa.parentNode.replaceChild( srcSVG, Mapa );
})();
<svg xmlns="http://www.w3.org/2000/svg" class="Mapa" width="1000" height="508"></svg>
http://jqvmap.com/
– Diego Souza