Interagindo com ECharts: Eventos e Ações Programáticas

A biblioteca ECharts proporciona um mecanismo flexível para lidar com a interação do usuário e o controle programático de gráficos. Desenvolvedores podem capturar diversos eventos dsiparados pelas operações do usuário ou pelo comportamento dos componentes do gráfico, permitindo a execução de funções de callback para ações como navegação, exibição de modais ou exploração detalhada de dados.

Existem principalmente duas categorias de eventos em ECharts:

  • Eventos de Interação do Usuário: Acionados por ações diretas do mouse, como cliques ou passar o cursor sobre elementos visuais do gráfico.
  • Eventos de Comportamento de Componentes: Disparados quando componentes interativos do gráfico, como legendas ou zoom de dados, mudam de estado. Por exemplo, a modificação do estado de seleção de uma legenda dispara o evento 'legendselectchanged'.

Um exemplo básico de escuta de um evento de clique em um gráfico ECharts:

const graficoInstancia = echarts.init(document.getElementById('containerPrincipal'));

graficoInstancia.on('click', (eventoParametros) => {
    // Exibe o nome do item clicado no console
    console.log(eventoParametros.name);
});

Manipulação de Eventos do Mouse

ECharts oferece suporte a eventos padrão do mouse, incluindo 'click', 'dblclick', 'mousedown', 'mousemove', 'mouseup', 'mouseover', 'mouseout', 'globalout' e 'contextmenu'. Esses eventos permitem uma interação detalhada com os elementos do gráfico.

Considere um cenário onde um clique em uma barra de um gráfico aciona uma pesquisa online relacionada ao item clicado:

// Inicializa a instância do ECharts baseada no DOM preparado
const meuGraficoBarras = echarts.init(document.getElementById('areaDoGrafico'));

// Define as opções e os dados do gráfico
const configuracaoGrafico = {
    xAxis: {
        type: 'category',
        data: ["Camisa","Suéter","Blusa","Calça","Salto","Meia"]
    },
    yAxis: {
        type: 'value'
    },
    series: [{
        name: 'Vendas',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
    }]
};

// Aplica as configurações e renderiza o gráfico
meuGraficoBarras.setOption(configuracaoGrafico);

// Escuta o evento de clique e abre uma página de pesquisa no Google
meuGraficoBarras.on('click', (parametrosEvento) => {
    window.open('https://www.google.com/search?q=' + encodeURIComponent(parametrosEvento.name));
});

Todos os eventos do mouse recebem um objeto de parâmetro, que contém informações detalhadas sobre o elemento gráfico clicado. A estrutura comum desce objeto é a seguinte:

{
    // Tipo de componente ao qual o elemento clicado pertence
    // Ex: 'series', 'markLine', 'markPoint', 'timeLine', etc.
    componentType: string,
    // Tipo da série (ex: 'line', 'bar', 'pie'). Relevante quando componentType é 'series'.
    seriesType: string,
    // Índice da série na array 'option.series'. Relevante quando componentType é 'series'.
    seriesIndex: number,
    // Nome da série. Relevante quando componentType é 'series'.
    seriesName: string,
    // Nome dos dados ou da categoria
    name: string,
    // Índice dos dados dentro da array 'data'
    dataIndex: number,
    // Item de dado original
    data: Object,
    // Para gráficos como Sankey ou Graph que possuem 'nodeData' e 'edgeData',
    // este valor pode ser 'node' ou 'edge', indicando o que foi clicado.
    // Para outros gráficos, dataType geralmente não tem significado.
    dataType: string,
    // Valor dos dados
    value: number|Array,
    // Cor do elemento gráfico. Relevante quando componentType é 'series'.
    color: string
}

Filtrando Eventos com Parâmetros de Consulta (Query)

Para interações mais específicas, pode ser necessário identificar exatamente qual parte do gráfico foi clicada. O objeto de parâmetros do evento permite essa distinção:

meuGraficoBarras.on('click', (eventInfo) => {
    if (eventInfo.componentType === 'markPoint') {
        console.log(`Ponto de marcação clicado na série ${eventInfo.seriesIndex}`);
    } else if (eventInfo.componentType === 'series') {
        if (eventInfo.seriesType === 'graph') {
            if (eventInfo.dataType === 'edge') {
                console.log('Borda do grafo clicada.');
            } else {
                console.log('Nó do grafo clicado.');
            }
        } else {
            console.log(`Elemento da série de tipo ${eventInfo.seriesType} clicado.`);
        }
    }
});

Para maior precisão, o método on de ECharts aceita um parâmetro query opcional. Isso permite que você registre um callback que será acionado apenas quando o evento ocorrer em elementos gráficos que correspondam a critérios específicos. A assinatura do método torna-se chart.on(nomeEvento, query, handler).

O query pode ser uma string (indicando o tipo de componente) ou um Object (para critérios mais detalhados).

Query como String

Quando query é uma string, ela geralmente representa o tipo principal do componente (ex: 'series') ou um subtipo (ex: 'series.line').

const graficoPrincipal = echarts.init(document.getElementById('graficoContainer'));

graficoPrincipal.on('click', 'series', () => {
    console.log('Um elemento de qualquer série foi clicado.');
});
graficoPrincipal.on('mouseover', 'series.line', () => {
    console.log('O mouse passou sobre um elemento de uma série do tipo "line".');
});
graficoPrincipal.on('click', 'dataZoom', () => {
    console.log('Um elemento do componente DataZoom foi clicado.');
});
graficoPrincipal.on('contextmenu', 'xAxis.category', () => {
    console.log('Botão direito clicado no eixo X de categoria.');
});

Query como Objeto

Quando query é um Object, ele pode incluir uma ou mais das seguintes propriedades para filtrar os eventos:

{
    <mainType>Index: number, // Índice do componente (e.g., seriesIndex, xAxisIndex)
    <mainType>Name: string, // Nome do componente (e.g., seriesName, xAxisName)
    <mainType>Id: string,   // ID do componente (e.g., seriesId, xAxisId)
    dataIndex: number,      // Índice do item de dado
    name: string,           // Nome do item de dado
    dataType: string,       // Tipo do dado (e.g., 'node', 'edge' para grafos)
    element: string         // Nome do elemento em séries customizadas
}

Exemplos práticos de uso do objeto query:

graficoPrincipal.setOption({
    // ... opções do gráfico ...
    series: [{
        name: 'VendasMensais',
        type: 'bar',
        data: [120, 200, 150, 80, 70, 110]
    }]
});

graficoPrincipal.on('mouseover', { seriesName: 'VendasMensais' }, () => {
    console.log('Mouse sobre um elemento da série "VendasMensais".');
});

graficoPrincipal.setOption({
    // ... opções do gráfico ...
    series: [{
        // ... primeira série ...
    }, {
        name: 'DetalhesProduto',
        type: 'pie',
        data: [
            { name: 'ProdutoA', value: 121 },
            { name: 'ProdutoB', value: 33 }
        ]
    }]
});

graficoPrincipal.on('click', { seriesIndex: 1, name: 'ProdutoA' }, () => {
    console.log('Clicado no "ProdutoA" da segunda série.');
});

graficoPrincipal.setOption({
    // ... opções do gráfico ...
    series: [{
        type: 'graph',
        layout: 'force',
        nodes: [{ name: 'Nó1', value: 10 }, { name: 'Nó2', value: 20 }],
        edges: [{ source: 0, target: 1, label: { formatter: 'Conexão' } }]
    }]
});

graficoPrincipal.on('click', { dataType: 'node' }, () => {
    console.log('Um nó do grafo foi clicado.');
});
graficoPrincipal.on('click', { dataType: 'edge' }, () => {
    console.log('Uma aresta do grafo foi clicada.');
});

Com as informações do objeto de parâmetros, é possível construir lógicas complexas para, por exemplo, buscar dados adicionais e atualizar o gráfico dinamicamente. Imagine um cenário onde o clique em uma barra dispara uma requisição para obter dados detalhados:

const graficoDadosDinamicos = echarts.init(document.getElementById('containerDinamico'));

// ... (configuração inicial do gráfico, por exemplo, um gráfico de barras) ...

graficoDadosDinamicos.on('click', async (eventParams) => {
    try {
        const response = await fetch(`/api/detalhes?item=${encodeURIComponent(eventParams.name)}`);
        const detalhes = await response.json();

        // Exemplo: Atualiza uma nova série com os dados detalhados (e.g., um gráfico de pizza)
        graficoDadosDinamicos.setOption({
            series: [{
                name: 'DetalheItem',
                type: 'pie',
                radius: ['40%', '55%'],
                data: detalhes.data, // Assumindo que 'detalhes.data' é um array de objetos { name, value }
                label: {
                    formatter: '{b}: {c} ({d}%)'
                }
            }]
        });
        console.log(`Detalhes carregados para: ${eventParams.name}`);
    } catch (error) {
        console.error('Erro ao buscar detalhes:', error);
    }
});

Eventos de Comportamento de Componentes

Componentes interativos em ECharts, como legendas, zoom de dados ou seleção de linha do tempo, também disparam eventos que refletem suas mudanças de estado. A documentação oficial lista todos os eventos e seus respectivos parâmetros.

Um exemplo comum é escutar mudanças na seleção de itens da legenda:

const graficoComLegenda = echarts.init(document.getElementById('graficoComportamental'));

// ... (configuração do gráfico com uma legenda) ...

graficoComLegenda.on('legendselectchanged', (parametrosLegenda) => {
    const nomeLegenda = parametrosLegenda.name;
    const estaSelecionado = parametrosLegenda.selected[nomeLegenda];

    if (estaSelecionado) {
        console.log(`A série '${nomeLegenda}' foi ATIVADA.`);
    } else {
        console.log(`A série '${nomeLegenda}' foi DESATIVADA.`);
    }
    // Exibe o estado completo de todas as legendas
    console.log('Estados atuais da legenda:', parametrosLegenda.selected);
});

Acionando Comportamentos de Gráficos Programaticamente (dispatchAction)

Além de reagir às interações do usuário, muitas vezes é necessário controlar o comportamento do gráfico por meio de código, como exibir tooltips específicos, alternar a seleção de legendas ou focar em partes do gráfico. Em versões anteriores do ECharts (como 2.x), isso era feito através de chamadas a métodos internos de componentes (ex: myChart.component.tooltip.showTip), o que era menos flexível e acoplado à estrutura interna.

No ECharts 3 e posteriores, essa funcionalidade foi unificada através do método myChart.dispatchAction({ type: '' }). Este método permite invocar qualquer ação suportada pelo gráfico de forma consistente, simplificando o controle e facilitando o rastreamento de fluxos de interação.

A documentação de Actions (Ações) detalha os tipos de ação disponíveis e seus parâmetros. Um exemplo clássico é a animação de destaque sequencial em um gráfico de pizza:

const graficoAnimadoPizza = echarts.init(document.getElementById('graficoPizzaAnimado'));

const opcoesPizza = {
    title : {
        text: 'Destaque Programático em Gráfico de Pizza',
        left: 'center'
    },
    tooltip: {
        trigger: 'item',
        formatter: "{a} <br/>{b} : {c} ({d}%)"
    },
    legend: {
        orient: 'vertical',
        left: 'left',
        data: ['Acesso Direto','Marketing por E-mail','Publicidade Afiliada','Anúncio em Vídeo','Mecanismo de Busca']
    },
    series : [
        {
            name: 'Fontes de Acesso',
            type: 'pie',
            radius : '55%',
            center: ['50%', '60%'],
            data:[
                {value:335, name:'Acesso Direto'},
                {value:310, name:'Marketing por E-mail'},
                {value:234, name:'Publicidade Afiliada'},
                {value:135, name:'Anúncio em Vídeo'},
                {value:1548, name:'Mecanismo de Busca'}
            ],
            itemStyle: {
                emphasis: {
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowColor: 'rgba(0, 0, 0, 0.5)'
                }
            }
        }
    ]
};

graficoAnimadoPizza.setOption(opcoesPizza);

let indiceSegmentoAtual = -1; // Usar uma variável para controlar o índice fora do setInterval

setInterval(() => {
    const totalSegmentos = opcoesPizza.series[0].data.length;

    // Desativa o destaque do segmento anterior, se houver
    if (indiceSegmentoAtual !== -1) {
        graficoAnimadoPizza.dispatchAction({
            type: 'downplay',
            seriesIndex: 0,
            dataIndex: indiceSegmentoAtual
        });
    }

    // Avança para o próximo segmento
    indiceSegmentoAtual = (indiceSegmentoAtual + 1) % totalSegmentos;

    // Ativa o destaque do segmento atual
    graficoAnimadoPizza.dispatchAction({
        type: 'highlight',
        seriesIndex: 0,
        dataIndex: indiceSegmentoAtual
    });

    // Exibe o tooltip para o segmento atual
    graficoAnimadoPizza.dispatchAction({
        type: 'showTip',
        seriesIndex: 0,
        dataIndex: indiceSegmentoAtual
    });
}, 1500); // Intervalo de 1.5 segundos

Tags: echarts javascript DataVisualization EventHandling ChartingLibrary

Publicado em 6-30 00:24