Stack Overflow em Português Asked on November 30, 2021
Como posso fazer em javascript para selecionar um país e pinta-lo?
"Como posso fazer em javascript para selecionar um país e pinta-lo?" (Imagens rasterizadas)
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 (implementação recursiva 4 e 8 direções) (áreas < ~40000 pixeis)
'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>
Resultado com https://i.stack.imgur.com/JirA9.gif
Imagens SVG sem elementos rasterizados:
(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>
Answered by João Machado on November 30, 2021
Imagino que a solução mais eficaz seria o uso de SVG; Sugiro que busque um mapa como esse em svg, sendo ele representado de tal forma que se assemelhe ao exemplo abaixo:
<svg id="mapa-mundi">
<path id="brasil" d="..." />
<path id="usa" d="..." />
</svg>
E então vc poderia manipular livremente cada país usando JQuery e colorindo cada país de maneira independente, baseado na interação do usuário...
<style>
.colored{ fill:lightcoral }
</style>
$("#mapa-mundi > path").on("click",function() {
$(this).toggleClass('colored');
});
Answered by Vinicius Colares on November 30, 2021
Pintar exatamente a imagem eu acho que não é possível, pelo motivo de ela ser uma imagem .gif.
Há algumas outras opções, mas trabalhosas...
reproduzir cada país como uma imagem separada, sem fundo, colocando-as sobrepostas a uma imagem com o fundo azul. "Recortar" e Posicionar estas imagens será bem trabalhoso. Vc pode usar o GIMP para recortar as imagens. Para cada recorde vc deverá salvar uma nova imagem
Nomear os arquivos como -Branco. A parte importante seria o "-Branco", que deve ser exatamente igual
Criar uma cópia destas imagens coloridas. As inserindo na mesma posição da imagem em branco, com style='display:none' para escondê-la, nomeie-as como "-Pintado", o "-Pintado" deve ser exatamente igual.
Em cada uma das imagens, tanto nas brancas como nas coloridas, colocar o seguinte código:
onclick="pais = this.src.split(-); this.src=(pais[1]=="Branco"?pais[0]+"-Pintado":pais[0]+'-Branco')
Vc pode testar isso com imagens simples antes, como quadrados ou algo assim, antes de arriscar-se a ter todo o trabalho de separar as imagens
Outra opção seria vc usar uma imagem vetorial com , mas isso também te daria trabalho.
A opção do Vector maps é a mais indicada caso você não precise exatamente desta imagem
Answered by jefissu on November 30, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP