Pergunta

Eu construí um motor de visualização de dados analítico para lona, ??tendo sido solicitados para adicionar dica-como pairar sobre elementos de dados para mostrar métricas detalhadas para o ponto de dados sob o cursor.

Para simples bar & gráficos Gaant, gráficos da árvore e nó de mapas com áreas quadradas simples ou pontos específicos de interesse, eu era capaz de implementar esta sobrepondo DIVs com posição absoluta com: atributos do pairo, mas existem algumas visualizações mais complicadas, como gráficos de pizza e um processamento de fluxo de tráfego que tem centenas de áreas separadas definidas por curvas bezeir.

É possível anexar algum modo uma sobreposição, ou acionar um evento quando o usuário mouses sobre um específico fechada caminho?

Cada área em que as necessidades em foco a ser especificado é definido da seguinte forma:

context.beginPath();
context.moveTo(segmentRight, prevTop);
context.bezierCurveTo(segmentRight, prevTop, segmentLeft, thisTop, segmentLeft, thisTop);
context.lineTo(segmentLeft, thisBottom);
context.bezierCurveTo(segmentLeft, thisBottom, segmentRight, prevBottom, segmentRight, prevBottom);
/*
 * ...define additional segments...
 */
// <dream> Ideally I would like to attach to events on each path:
context.setMouseover(function(){/*Show hover content*/});
// </dream>
context.closePath();

A ligação a um objeto como este é quase trivial de implementar em Flash ou Silverlight, uma vez mas a implementação Canvas atual tem a vantagem de usar diretamente o nosso API Javascript existente e integrar com outros elementos Ajax, nós estamos esperando para evitar colocar Flash no o mix.

Todas as idéias?

Foi útil?

Solução

Você pode manipular o evento mousemove e obter o x, y coordenadas a partir do evento. Então você provavelmente vai ter que iterar sobre todos os seus caminhos para testar se o ponto é sobre o caminho. Eu tive um problema semelhante que pode ter algum código que você poderia usar.

looping sobre as coisas desta forma pode ser lento, especialmente no IE. Uma maneira que você poderia acelerá-lo - e este é um hack, mas seria bastante eficaz - seria mudar a cor que cada caminho é desenhado com para que ele não é perceptível por seres humanos, mas para que cada caminho é desenhado em uma cor diferente. Ter uma tabela para pesquisar cores para caminhos e basta olhar a cor do pixel sob o mouse.

Outras dicas

Canvas Sombra

O melhor método que tenho visto em outros lugares para detecção mouseover é repetir a parte do seu desenho que você deseja detectar em um escondido tela, apagada. Em seguida, armazene o objeto ImageData. Você pode então verificar a matriz ImageData para o pixel de interesse e retornar true se o valor alfa é maior que 0.

// slow part
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillRect(100,100,canvas.width-100,canvas.height-100);
var pixels = ctx.getImageData(0,0,canvas.width,canvas.height).data;

// fast part
var idx = 4 * (mouse_x + mouse_y * canvas.width) + 3;
if (pixels[idx]) { // alpha > 0
  ...
}

Vantagens

  • Você pode detectar o que quiser desde que você está apenas repetindo os métodos de contexto. Isso funciona com PNG alpha, formas compostas loucos, texto, etc.
  • Se a imagem é bastante estático, então você só precisa fazer isso uma vez por área de interesse.
  • A "máscara" é lento, mas olhando para cima o pixel é sujeira barato. Assim, a "parte fast" é ótimo para detecção de mouseover.

Desvantagens

  • Este é um devorador de memória. Cada máscara é W * H * 4 valores. Se você tem uma área da tela pequena ou poucas áreas para mascarar, não é tão ruim assim. gerenciador de tarefas Uso do Chrome para uso de memória monitor.
  • Não há atualmente um problema conhecido com getImageData no Chrome e Firefox. Os resultados não são lixo coletado imediatamente se você anular a variável, por isso, se você fizer isso com muita freqüência, você vai ver aumento de memória rapidamente. Ele eventualmente, obter lixo coletado e não deve travar o navegador, mas pode ser desgastante para máquinas com pequenas quantidades de RAM.

um corte para economizar memória

Em vez de armazenar a matriz ImageData todo, podemos basta lembrar que pixels têm alfa valores. Ele salva uma grande quantidade de memória, mas acrescenta um loop para o processo de máscara.

var mask = {};
var len = pixels.length;
for (var i=3;i<len;i+=4) if ( pixels[i] ) mask[i] = 1;

// this works the same way as the other method
var idx = 4 * (mouse_x + mouse_y * canvas.width) + 3;
if (mask[idx]) {
  ...
}

Isto pode ser feito usando o método ctx.isPointInPath, mas não é implementado em ExCanvas para IE. Mas uma outra solução seria a utilização de mapas HTML, como eu fiz para esta pequena biblioteca: http :. //phenxdesign.net/projects/phenx-web/graphics/example.htm você pode obter inspiração dele, mas ainda é um pouco de buggy

Eu sugeriria sobrepor um mapa de imagem com coordenadas adequadas definidas sobre as áreas para corresponder seus itens desenhados à lona. Desta forma, você recebe dicas de ferramentas e um monte de outros DOM funcionalidade / Browser gratuitamente.

eu precisava fazer detectar cliques do mouse para uma grade de quadrados (como células de uma planilha excel). Para acelerar, eu dividido a grade em regiões recursivamente reduzir para metade até um pequeno número de células permaneceram, por exemplo, para uma grade de 100x100, os primeiros 4 regiões podem ser as grades 50x50 compreendendo os quatro quadrantes. Em seguida, estes podem ser divididos em quatro outro cada (portanto, dando 16 regiões de 25x25 cada). Isto requer um pequeno número de comparações e, finalmente, a grelha de 25x25 poderia ser testada para cada célula (625 comparações neste exemplo).

Não é um livro de Eric Rowell chamado "HTML5 Canvas COOKBOOK". Nesse livro há um capítulo chamado "Interagindo com a tela: Ouvintes Anexar evento para Formas e Regiões". mousedown, mouseup, mouseover, mouseout, mousemove, touchstart, touchend e eventos TouchMove podem ser implementadas. Eu sugiro que você leia isso.

Isto não pode ser feito (bem, pelo menos não tão facilmente), porque os objetos que você desenhar sobre a tela (caminhos) não são representados como os mesmos objetos na tela. O que quero dizer é que ele é apenas um contexto 2D simples e uma vez que você tirado algo sobre ele, completamente esquece como foi desenhado. É apenas um conjunto de pixels para ele.

Para assistir mouseover e os gostos para isso, você precisa de algum tipo de tela gráficos de vetor, que é SVG ou implementar seu próprio no topo do existente (que é o que Sam Hasler sugerido)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top