Implementando Visualizações com Gráficos F2 em Mini-Programas DingTalk

Sincronização de Renderização e Ajustes na Biblioteca

A integração da biblioteca F2 da Alibaba em mini-programas DingTalk apresenta desafois específicos relacionados ao ciclo de vida assíncrono do setData. Problemas dimensionais inconsistentes entre diferentes gráficos ocorrem porque as operações de renderização não aguardam a conclusão da atualização de dados.

Para garantir consistência visual, é necessário estabelecer dimensões fixas antes da carga dos dados e somante executar a inicialização dos gráficos dentro do callback de setData. Além disso, modificações no módulo-fonte da F2 são requeridas para compatibilidade completa com o ambiente DingTalk.

Localize o arquivo de origem da biblioteca F2 no diretório node_modules e aplique as seguintes alterações na seção de gerenciamento de canvas:

// Modifique a função de redimensionamento para usar uniões de pixels específicas do DingTalk
_resizeCanvas: function() {
  const query = dd.createSelectorQuery();
  query.select(`#${this.canvasId}`).boundingClientRect();
  query.exec((ret) => {
    if (ret && ret[0]) {
      const { width, height } = ret[0];
      this.setData({
        canvasWidth: width * this.pixelRatio,
        canvasHeight: height * this.pixelRatio
      }, () => {
        this.chart.changeSize(width, height);
      });
    }
  });
}

Exemplo Prático: Gráfico de Rosca e Gráfico de Barras Empilhadas

Componente JavaScript configurado com dois tipos de visualizações distintos:

Component({
  data: {
    dadosProporcao: [
      { tipo: 'Avanço', valorPercentual: 0.6, eixoX: '1' },
      { tipo: 'Montagem', valorPercentual: 0.4, eixoX: '1' },
      { tipo: 'Auxiliar', valorPercentual: 0.1, eixoX: '1' },
      { tipo: 'Falha', valorPercentual: 0.3, eixoX: '1' },
      { tipo: 'Outros', valorPercentual: 0.2, eixoX: '1' }
    ],
    dadosComparativos: [
      { etapa: 'Escavação', faixa: '163', quantidade: 16 },
      { etapa: 'Escavação', faixa: '175', quantidade: 26 },
      { etapa: 'Parada', faixa: '163', quantidade: 16 },
      { etapa: 'Parada', faixa: '175', quantidade: 26 },
      { etapa: 'Anel', faixa: '163', quantidade: 36 },
      { etapa: 'Anel', faixa: '185', quantidade: 25 },
      { etapa: 'Parada', faixa: '185', quantidade: 25 },
      { etapa: 'Parada', faixa: '195', quantidade: 25 },
      { etapa: 'Anel', faixa: '195', quantidade: 25 },
      { etapa: 'Anel', faixa: '275', quantidade: 25 },
      { etapa: 'Anel', faixa: '275', quantidade: 25 },
      { etapa: 'Anel', faixa: '375', quantidade: 25 },
      { etapa: 'Anel', faixa: '375', quantidade: 25 },
      { etapa: 'Anel', faixa: '475', quantidade: 25 },
      { etapa: 'Parada', faixa: '475', quantidade: 25 }
    ],
    legendaPercentuais: {
      'Avanço': '60%',
      'Montagem': '40%',
      'Auxiliar': '10%',
      'Falha': '30%',
      'Outros': '20%'
    }
  },
  methods: {
    renderizarGraficoCircular(instancia) {
      instancia.clear();
      const dados = this.data.dadosProporcao;
      const legendas = this.data.legendaPercentuais;
      
      instancia.source(dados, {
        valorPercentual: {
          formatador: function(val) {
            return (val * 100).toFixed(0) + '%';
          }
        }
      });
      
      instancia.legenda({
        posicao: 'topo',
        alinhamento: 'centro',
        formatadorItem: function(val) {
          return val + '  ' + legendas[val];
        }
      });
      
      instancia.dicaFerramenta(false);
      
      instancia.coordenada('polar', {
        transposta: true,
        raio: 1.9
      });
      
      instancia.eixo(false);
      
      instancia.intervalo()
        .posicao('eixoX*valorPercentual')
        .cor('tipo', ['#61E2C4', '#52AAFE', '#A0AEFA', '#F38E68', '#868B96'])
        .ajuste('empilhamento')
        .estilo({
          larguraLinha: 1,
          traco: '#fff',
          uniaoLinha: 'arredondada',
          extremidadeLinha: 'arredondada'
        })
        .animacao({
          aparecer: {
            duracao: 1200,
            suavizacao: 'bounceOut'
          }
        });
      
      instancia.renderizar();
    },
    
    renderizarGraficoLinear(instancia) {
      instancia.clear();
      const dados = this.data.dadosComparativos;
      
      instancia.escala({
        faixa: {
          alcance: [0.05, 1]
        }
      });
      
      instancia.fonte(dados, {
        etapa: {
          minimo: 0,
          formatador: function(val) {
            return val;
          }
        }
      });
      
      instancia.intervalo()
        .posicao('faixa*quantidade')
        .cor('etapa')
        .ajuste('empilhamento');
      
      instancia.renderizar();
    }
  }
});

Implementação no template AXML:

<dd-charts idCanvas="grafico-circular" aoDesenhar="renderizarGraficoCircular"></dd-charts>
<dd-charts idCanvas="grafico-linear" aoDesenhar="renderizarGraficoLinear"></dd-charts>

Tags: dingtalk-miniprogram f2-charts data-visualization canvas-rendering asynchronous-rendering

Publicado em 9-7 08:40