Construindo um infográfico interativo com Vue.js

Publicados: 2022-03-10
Resumo rápido ↬ Você já teve um requisito em que teve que projetar e construir uma experiência interativa na web, mas o sistema de grade ficou aquém? Além disso, os elementos de design se transformaram em formas incomuns que simplesmente não se encaixariam nos layouts regulares da web? Neste artigo, vamos construir um infográfico interativo usando Vue.js, SVG e GreenSock usando dados dinâmicos e layout incomum.

Este artigo apresenta uma abordagem moderna para a construção de um infográfico interativo. Você com certeza pode ter um infográfico simples com todas as informações disponíveis antecipadamente - sem qualquer interação do usuário. Mas pensar em construir uma experiência interativa muda o cenário tecnológico que escolhemos. Portanto, vamos entender primeiro, por que Vue.js? E você verá porque GSAP (GreenSock Animation Platform) e SVG (Scalable Vector Graphics) se tornam escolhas óbvias.

Vue.js fornece maneiras práticas de construir interfaces de usuário dinâmicas baseadas em componentes onde você pode manipular e gerenciar elementos DOM de maneiras poderosas. Neste caso, será SVG. Você pode atualizar e gerenciar facilmente diferentes elementos SVG - dinamicamente - usando apenas um pequeno subconjunto de recursos disponíveis no Vue.js - alguns dos recursos básicos que se encaixam aqui são vinculação de dados, renderização de lista, vinculação de classe dinâmica para nomear um alguns. Isso também permite que você agrupe elementos SVG relevantes e os transforme em componentes.

Vue.js joga bem com bibliotecas externas sem perder sua glória, isso é GSAP aqui. Existem muitos outros benefícios de usar o Vue.js, um dos quais é que o Vue.js permite isolar modelos, scripts e estilos relacionados para cada componente. Dessa forma, o Vue.js promove a estrutura modular do aplicativo.

Leitura recomendada : Substituindo o jQuery pelo Vue.js: nenhuma etapa de compilação é necessária

O Vue.js também vem empacotado com poderosos ganchos de ciclo de vida que permitem explorar os diferentes estágios do aplicativo para modificar o comportamento do aplicativo. Configurar e manter aplicativos Vue.js não requer um grande compromisso, o que significa que você pode adotar uma abordagem em fases para dimensionar seu projeto à medida que avança.

O infográfico é muito leve no sentido visual, pois o objetivo principal deste artigo é aprender a pensar em termos de dados, elementos visuais e, claro, Vue.js — o framework que possibilita toda a interatividade. Além disso, usaremos o GreenSock, uma biblioteca para animar elementos SVG. Antes de mergulharmos, dê uma olhada na demonstração.

Mais depois do salto! Continue lendo abaixo ↓

Começaremos com:

  1. A visão geral dos dados para infográfico;
  2. preparação de imagens SVG;
  3. Uma visão geral dos componentes Vue no contexto da arte SVG;
  4. Amostras de código e diagramas de interatividade chave.

O infográfico que vamos construir é sobre o Tour De France, o evento anual de corridas de bicicleta realizado na França.

Crie um infográfico interativo com Vue.js, SVG e GreenSock
Tour De France — Etapas interativas do jogo de listagem de bicicletas (roda traseira) e equipes participantes (roda dianteira). (Visualização grande)

Visão geral dos dados do Tour de France

No design de infográficos, os dados direcionam o design do seu infográfico. Portanto, ao planejar o design do seu infográfico, é sempre uma boa ideia ter todos os dados, informações e estatísticas disponíveis para o assunto em questão.

Durante o Tour De France de 2017, aprendi tudo sobre este maior evento de ciclismo que pude em 21 dias de jogo em julho, e me familiarizei com o assunto.

As entidades básicas da raça que decidi seguir no meu design são,

  • Estágios,
  • Equipes,
  • Rotas,
  • Vencedores,
  • Comprimento e classificações de cada percurso.

Esta próxima parte do processo depende do seu estilo de pensamento, então você pode ser criativo aqui.

Criei dois conjuntos de dados, um para estágios e outro para equipes. Esses dois conjuntos de dados têm várias linhas de dados (mas within limit ) — que correspondem a duas rodas da bicicleta com vários raios em cada uma. E isso definiu o elemento-chave do design, The Bicycle Art que você viu no início - onde cada raio será interativo e responsável por direcionar as informações reveladas na tela.

Eu mencionei within limits acima, porque o que estamos buscando neste caso não é uma visualização de dados completa no contexto de big data, mas sim um infográfico com dados de alto nível.

Portanto, gaste tempo de qualidade com dados e procure semelhanças, diferenças, hierarquia ou tendências que possam ajudá-lo a transmitir uma história visual. E não se esqueça da incrível combinação de SVG e Vue.js enquanto estiver nisso, pois ajudará você a encontrar o equilíbrio certo entre informações (dados), interatividade (Vue.js) e elementos de design (SVG Artwork ) do infográfico.

Aqui está o snippet de um objeto de dados de estágio:

 { "ID": 1, "NAME": "STAGE 01", "DISTANCE": "14", "ROUTE": "KMDUSSELDORF / DUSSELDORF", "WINNER": "THOMAS G.",
    "UCI_CODE": "SKY",
    "TYPE": "Individual Time Trial",
    "DATE": "Saturday July 1st",
    "KEY_MOMENT": " Geraint Thomas takes his first win at 32"
}

E snippet de objeto de dados de equipe conforme abaixo:

 { "ID": 1,
    "UCI_CODE": "SKY",
    "NAME": " TEAM SKY",
    "COUNTRY": "Great Britain",
    "STAGE_VICTORIES": 1,
    "RIDERS": 8
}

Este infográfico é operado por uma lógica muito simples.

UCI_CODE (Union Cycliste Internationale) é a chave de conexão entre o palco e o objeto da equipe. Quando um estágio é clicado, primeiro ativaremos esse estágio, mas também usaremos a chave UCI_CODE para ativar a equipe vencedora correspondente.

Preparação SVG

Tendo alguns conjuntos de dados e um conceito aproximado de arte de bicicleta pronto, aqui está o SVG CodePen estático do infográfico que criei.

Veja o Pen Static Bicycle SVG de Krutie(@krutie) no CodePen.

Veja o Pen Static Bicycle SVG de Krutie(@krutie) no CodePen.

Criamos apenas um raio para cada roda, porque criaremos dinamicamente o restante dos raios usando vários registros encontrados no conjunto de dados e os animaremos usando a Biblioteca GreenSock.

O fluxo de trabalho para criar esse código SVG também é muito simples. Crie sua arte infográfica no Adobe Illustrator e salve como SVG. Certifique-se de nomear cada group e layer enquanto estiver trabalhando no Illustrator, porque você precisará desses ids para separar partes do código SVG que eventualmente preencherão a área <template> dos componentes Vue. Lembre-se de que os nomes de camada fornecidos no Illustrator se tornam element ids na marcação SVG.

Você também pode usar o SVGOMG e otimizar ainda mais o código SVG exportado do Adobe Illustrator.

Nota importante: Se você usar o SVGOMG para otimizar a marcação SVG, seu código certamente ficará limpo, mas observe que ele converterá todos os elementos <rect> em <path> com o atributo d . Isso resulta na perda dos valores x e y do retângulo, caso você deseje ajustar alguns pixels manualmente mais tarde.

Segunda coisa, certifique-se de desmarcar a opção Clean Id (opções do lado direito na interface SVGOMG), isso ajudará a manter todos os grupos e ids intactos que foram criados no Illustrator.

Visão geral do componente Vue

Mesmo que a interatividade e o fluxo de dados em seu projeto de infográfico sejam de natureza bastante simples, você deve sempre reservar um momento para elaborar um diagrama de árvore de componentes.

Isso ajudará especialmente no caso de você não estar usando nenhum mecanismo de dados compartilhados, onde os componentes filhos são dependentes dos valores enviados do componente pai (ou seja, via props) ou vice-versa (ou seja, this.$emit events). Esta é sua chance de fazer um brainstorming desses valores de prop, emitir eventos e dados locais — e documentá-los antes de começar a escrever o código.

Árvore de componentes Vue
Árvore de componentes Vue. (Visualização grande)

O diagrama acima é o instantâneo dos componentes Vue que é parcialmente derivado dos requisitos de interatividade e parcialmente baseado na marcação SVG. Você deve ser capaz de ver como a marcação SVG será dividida com base nessa estrutura de árvore. É bastante autoexplicativo do ponto de vista da hierarquia.

  1. A roda de corrente imitará a rotação dos raios.
  2. O componente de palco é a roda traseira que listará todos os 21 estágios.
  3. O componente de detalhes do palco exibirá informações relacionadas em um caminho curvo (lado esquerdo).
  4. O componente da equipe é a roda dianteira que listará todas as equipes participantes nos raios.
  5. O componente de detalhes da equipe exibirá informações relacionadas em um caminho curvo (lado direito).
  6. A navegação incluirá o botão voltar e próximo para acessar os estágios.

O diagrama abaixo representa os mesmos componentes Vue vistos acima, mas no contexto do design do infográfico.

Componentes Vue misturados em SVG
Componentes Vue misturados em SVG. (Visualização grande)

Menos é mais – deve ser a abordagem que você deve tentar adotar ao trabalhar em projetos semelhantes. Pense nos requisitos de animação e transição que você tem, se puder usar o TweenLite em vez do TweenMax - faça isso. Se você tiver a opção de escolher formas elementares e caminhos mais simples em vez de complexos - tente optar por elementos leves que sejam fáceis de animar - sem nenhuma perda de desempenho.

A próxima seção irá guiá-lo por uma parte emocionante com animação GreenSock e Vue.js.

Animação GreenSock

Vejamos mais de perto:

  1. Animação de texto em um caminho curvo;
  2. Animação falou em uma roda.
### Animação de texto em um caminho curvo

Lembre-se do caminho curvo visto ao redor da roda da bicicleta, esse caminho curvo é ligeiramente maior que o raio da roda da bicicleta. Portanto, quando animarmos o texto nesse caminho, ele parecerá seguir a forma da roda.

Veja o texto da caneta em um caminho curvo por Krutie (@krutie) no CodePen.

Veja o texto da caneta em um caminho curvo por Krutie (@krutie) no CodePen.

path e textPath é uma doce combinação de elementos SVG que permite definir texto em qualquer caminho usando o atributo xlink:href .

 <pathlanguage-javascript">curvedPath " stroke="none" fill="none" d="..."/>

<text>
  <textPath xlink:href=" #curvedPath "
          class="stageDetail"
          startOffset="0%">
          {{ stage.KEY_MOMENT }}
   </textPath>
</text>

Para animar o texto ao longo do caminho, simplesmente animaremos seu atributo startOffset usando GreenSock.

 tl.fromTo( ".stageDetail", 1, { opacity: 0,
  attr: { startOffset: "0%" }
},
{opacity: 1,
  attr: { startOffset: "10%" }

}, 0.5 );

À medida que você aumenta a porcentagem de startOffset , o texto percorre o perímetro do círculo.

Em nosso projeto final, essa animação é acionada toda vez que um raio é clicado. Agora, vamos passar para uma parte mais emocionante da animação.

Animando estágios/raios dentro da roda

É visível na demonstração que os componentes do stage e team são semelhantes por natureza, com algumas pequenas diferenças. Então, vamos nos concentrar em apenas uma roda da bicicleta.

O exemplo do CodePen abaixo amplia apenas as três ideias principais:

  1. Buscar dados do estágio;
  2. Organize os spokes dinamicamente com base nos dados;
  3. Reorganize os raios quando o palco (spoke) for clicado.

Veja a Animação da Roda da Caneta TDF por Krutie (@krutie) no CodePen.

Veja a Animação da Roda da Caneta TDF por Krutie (@krutie) no CodePen.

Você deve ter notado no CodePen SVG estático acima que os raios não são nada além de retângulos SVG e texto agrupado. Eu os agrupei porque queria escolher tanto o texto quanto o retângulo para fins de animação.

 <g v-for="stage in stages" class="stage">

    <rect x="249" y="250" width="215" height="1" stroke="#3F51B5" stroke-width="1"/>

    <text transform="translate(410 245)" fill="#3F51B5" >
      {{ stage.NAME }}
    </text>

</g>

Vamos renderizá-los na área <template> do componente Vue usando valores obtidos da fonte de dados.

Quando todos os 21 estágios estiverem disponíveis na tela, definiremos suas posições iniciais chamando, digamos, setSpokes() .

 // setSpokes() let stageSpokes = document.querySelectorAll(".stage") let stageAngle = 360/this.stages.length _.map(stageSpokes, (item, index) => { TweenMax.to(item, 2, { rotation: stageAngle*index, transformOrigin: "0% 100%" }, 1) }

Três elementos-chave para preparar o palco são:

  1. Rotação
    Para girar os spokes, simplesmente mapeamos todos os elementos com className stage e definimos o valor de rotation dinâmica que é calculado para cada spoke.
  2. Transformar Origem
    Observe o valor transformOrigin no código acima, que é tão importante quanto o valor do index , porque “0% 100%” permite que cada raio gire a partir do centro da roda.
  3. stageAngle
    Isso é calculado usando o número total de estágios dividido por 360 graus. Isso nos ajudará a colocar todos os raios uniformemente em um círculo de 360 ​​graus.

ADICIONANDO INTERATIVIDADE

O próximo passo seria adicionar um evento de clique em cada estágio para torná-lo interativo e reativo a alterações de dados - portanto, ele dará mais vida a uma imagem SVG!

Digamos que, se stage/spoke for clicado, ele executa goAnimate() , que é responsável por ativar e girar o stage que está sendo clicado usando o parâmetro stageId .

 goAnimate (stageId) { // activate stage id this.activeId = stageId // rotate spokes }

Usaremos o DirectionalRotationPlugin… que é um ingrediente chave para esta interatividade. E sim, está incluído no TweenMax.

Existem três maneiras diferentes de usar este plugin. Anima a propriedade de rotação em 1) sentido horário, 2) anti-horário e 3) na menor distância calculada até o destino.

Como você já deve ter adivinhado, estamos usando a terceira opção para girar a distância mais curta entre o estágio atual e o novo estágio.

Revise o CodePen acima e você verá como o Stage 01 está constantemente se movendo ao redor do círculo, deixando seu local original para o novo estágio ativo em um ângulo de 0 graus.

Primeiro, precisamos encontrar o ângulo de um estágio que está sendo clicado e trocar sua rotação com o estágio 01 . Então, como encontramos o valor de rotação do estágio que está sendo clicado? Confira o diagrama abaixo.

Cálculo da distância do Estágio 01 até o estágio 'clicado'
Cálculo da distância da Etapa 01 até a etapa 'clicada'. (Visualização grande)

Por exemplo, se a Etapa 05 for clicada (como você pode ver acima), a jornada da Etapa 01 para a Etapa 05 requer 4 x valor do ângulo.

E, portanto, podemos obter o ângulo correto usando (Active stage Id - 1) * 17 degree, seguido por '_short' string postfix para acionar o plug-in de rotação direcional.

 angle = 360/21 stages = 17 activeId = 5
new angle = ( (activeId-1) *angle)+'_short'
          = ((5-1)\*17)+'_short'
          = 68

A função final goAnimate() será algo como abaixo:

 _.map(spokes, (item, index) => { if(activeId == index+1) { // active stage TweenMax.to(item, 2, { rotation: 0+'_short', transformOrigin: "0 100%" }) } else if (index == 0) { // first stage TweenMax.to(item, 2,
    { rotation: (activeId*angle)-angle+'_short',
      transformOrigin: "0 100%"
    })

  } else {
    TweenMax.to(item, 2, 
    { rotation: index*angle+'_short', 
      transformOrigin: "0 100%"
    })
  }

}) // end of map

Assim que tivermos a roda traseira pronta, a roda dianteira (para equipe) deve seguir a mesma lógica com alguns ajustes.

Em vez do palco, buscaremos os dados da equipe e atualizaremos o ponto de registro do atributo transformOrigin para habilitar a geração de spokes do ponto de registro oposto ao da roda do palco.

 // set team spokes map(teamSpokes, (index, key) => { TweenMax.to(index, 2, { rotation: angle*key, transformOrigin: "100% 100%" }, 1) })

Projeto final

Como eu, se você escreveu todas as funções relacionadas a animação e dados nos próprios componentes Vue. É hora de limpá-los usando Vuex e Mixins.

Usando o gerenciamento de estado Vuex para alimentar as duas rodas com dados
Usando o gerenciamento de estado Vuex para alimentar as duas rodas com dados. (Visualização grande)

VUEX

Vuex facilita o gerenciamento de dados compartilhados entre componentes e, mais importante, simplifica seu código, mantendo methods e data() limpos e organizados, deixando os componentes apenas para renderizar os dados, não para manuseá-los.

Os ganchos do ciclo de vida são um local muito adequado para executar qualquer solicitação HTTP. Buscamos os dados iniciais no gancho created , quando o aplicativo Vue foi inicializado, mas ainda não foi montado no DOM.

Variáveis ​​de estado vazias, stages e teams são atualizados usando mutações neste estágio. Em seguida, usamos o watcher (apenas uma vez) para acompanhar essas duas variáveis ​​e, assim que elas são atualizadas, chamamos o script de animação (de mixin.js ).

Toda vez que o usuário interage com o estágio ou componente da equipe, ele se comunica com o armazenamento Vuex, executa setActiveData e atualiza os valores atuais do estágio e da equipe. É assim que definimos dados ativos.

E quando os dados ativos são definidos após a atualização do estado, o goAnimate entrará em ação para animar (rotação direcional) os raios usando valores atualizados.

Leitura recomendada : Criando entradas personalizadas com Vue.js

Mixins

Agora que os dados são tratados pelo Vuex, vamos separar as animações do GreenSock. Isso evitará que nossos componentes Vue fiquem cheios de scripts de animação longos. Todas as funções do GreenSock são agrupadas no arquivo mixin.js .

Como você tem acesso ao Vuex Store dentro do Mixins, todas as funções GSAP usam variáveis ​​de state para animar elementos SVG. Você pode ver store.js e mixin.js totalmente funcionais no exemplo do CodeSandbox aqui.

Conclusão

Criar infográficos interativos e envolventes exige que você seja analítico com os dados, criativo com visuais e eficiente com a tecnologia que usa, que neste caso é o Vue.js. Você ainda pode usar esses conceitos em seu projeto. Como nota final, deixarei você com esta roda de cores interativa circular abaixo que usa uma ideia semelhante à que discutimos neste artigo.

Veja a Paleta de Cores Circular Pen Material UI feita com Vue JS e GSAP por Krutie (@krutie) no CodePen.

Veja a Paleta de Cores Circular Pen Material UI feita com Vue JS e GSAP por Krutie (@krutie) no CodePen.

Sem dúvida, o Vue.js tem muitos recursos excelentes; podemos criar infográficos interativos com apenas algumas coisas, como observadores, propriedades computadas, mixins, diretivas (veja o exemplo da roda de cores) e alguns outros métodos. Vue.js é a cola que mantém a animação SVG e GreenSock juntas de forma eficiente, dando a você ampla oportunidade de ser criativo com qualquer assunto e interatividade personalizada ao mesmo tempo.