Como sempre, basta olhar as fotos!
O efeito é o seguinte:
Grandes imagens HD!
Trabalho como programador há muitos anos, mas meus velhos olhos estão turvos e não consigo ver a animação com clareza? ! Então veja as capturas de tela estáticas! ! !
Os efeitos de diferentes pontuações são os seguintes:
Depois de assistir ao show do vendedor, vamos dar uma olhada no processo de produção do produto!
O Canvas desenha um círculo 1. No vue, o código em <template lang=pug> é o seguinte:
canvas#baseCanvas é o anel cinza na parte inferior
canvas#myCanvas é o anel colorido acima
Precisamos usar o estilo CSS para nos ajudar a cobrir o anel colorido no topo do anel cinza.
2. Estilo CSS: 3. Código de desenho estilo js-canvasEsse código também é muito simples, basta olhar a API do canvas
3-1 No componente vue, defina as variáveis necessárias na parte superior da tag do script.
3-2. No objeto método de vue, três métodos são definidos:
drawBaseCanvas: usado para desenhar o anel cinza inferior. Como o círculo cinza não tem efeito de animação, basta desenhar um círculo cinza completo no início. drawClrCanvas: usado para desenhar o anel colorido acima. clearCanvas: usado para limpar a tela. Isto é o que a animação do anel colorido exige. Porque o núcleo do nosso efeito de animação de anel é limpar o anel colorido de vez em quando, aumentar o valor do ângulo final e redesenhá-lo, para que seja uma animação contínua.
Aqui está o código para os três métodos:
Os códigos nos três métodos acima são quase todos aplicativos da API canvas, basta ler o tutorial.
Somente no método draoClrCanvas, ao desenhar um círculo de tela, o valor inicial e o valor final são definidos no parâmetro arc.
O valor inicial determina a posição inicial do desenho do círculo, e o valor final determina a posição final (parece que disse bobagem, mas depois de pensar muito sobre o texto de descrição do pensamento, não quero excluí-lo hahaha)
O cálculo deste valor final é bastante problemático para mim.
Por que a variável de contagem precisa ser calculada assim? Esqueci como descobri.
this.grade é um número inteiro positivo dentro de 100, indicando a pontuação. É definido em dados e o padrão é 0 pontos.
Portanto, o círculo colorido é invisível a princípio, porque o ponto inicial e o ponto final são ambos 0 pontos.
Se você alterar o valor da nota, de 0 a 100, o valor do anel de cores da tela também será alterado.
Desta forma, à medida que modificamos gradativamente o valor da nota e o redesenhamos, os anéis coloridos aumentarão gradativamente para obter o efeito de animação.
Efeito de animação de anelDevido às minhas necessidades especiais aqui, a animação precisa ser acionada toda vez que o usuário se volta para o swiper onde a tela está localizada (mais tarde, é mais problemático e exige que o histograma e as partes da tela tenham um efeito de entrada antes da animação começar. O efeito é o mais longo da imagem acima (como aquela animação gif).
Então eu tenho que usar o swiper para conseguir isso. Na função de retorno de chamada do interruptor do swiper, a pontuação da nota é continuamente incrementada de 0 e o desenho do anel colorido é reativado para obter o efeito de animação.
O swiper que uso no vue é 'vue-awesome-swiper'. Escrevi as etapas para seu uso em outros artigos.
Existe um objeto on na configuração do swiper em vue-data. A função slideChange no objeto on é a função de retorno de chamada que é acionada toda vez que o deslizador vira a página.
Aqui falarei sobre alguns pontos especiais:
(1) vm: É uma variável que armazenei no script vue. Ela é inicializada como nula e, em seguida, montada, é atribuída como um objeto de instância vue.
Inicialize os dados e desenhe círculos cinza
Por meio desse método, obtenho os valores dos atributos grade e gradeTarget na função vue instance object-data-swiper-callback e os modifico.
ps: Não sei se essa é uma abordagem estúpida. Quando fiz isso, encontrei um problema que não sabia como obter a instância vue no retorno de chamada do swiper. Portanto, havia um caminho tortuoso para salvar o país. Se eu tiver uma solução melhor, espero que você possa me dar uma nova ideia. Muito obrigado, querido.
(2) (this.activeIndex == 2 && vm.isStar) || (this.activeIndex == 1 && !vm.isStar)
Esse julgamento é feito por causa dos negócios e pode ser ignorado.
isso aponta para o objeto swiper na função swiperChange. this.activeIndex é uma propriedade da instância swiper. Em termos oficiais, ele retorna o índice do bloco ativo atual (bloco de ativação). Você pode entender que ele está se referindo à página que você está acessando no momento, que é o subscrito do slide que você está vendo no momento.
Devido à minha identidade como usuário, decidirei de forma decisiva se exibirei a página anterior do swiper onde a tela atual está localizada. Se não for exibido, a página anterior não será desenhada e o subscrito do deslizador correspondente da página atual se tornará (índice-1).
Resumindo, quando as condições forem atendidas e o usuário acessar a página do swiper onde a tela está localizada, acionarei a lógica de desenho do anel no if. Caso contrário, vá para else para inicializar o estado da página de dados, limpe o cronômetro para pausar a animação e limpe o anel colorido.
(3)vm.aniShow
Conforme mencionei em meu último artigo “Desenhando Histogramas com CSS Puro”, a animação do histograma deve ser discutida junto com a animação do canvas. Porque a implementação da animação precisa cooperar com a alternância do swiper. Esse é o código aqui:
Quando o atributo vue - data - aniShow se tornar verdadeiro, o nome da classe ani será adicionado a div.row:
Da mesma forma, se aniShow for verdadeiro, a altura do progresso será anexada ao seu próprio valor alvo, ou seja, a altura real do progresso será atribuída à altura do atributo de estilo após ser convertida em porcentagem.
Neste momento, como a transição de progresso monitora a mudança de altura, a animação crescente do histograma com o aumento da altura começa.
Sob o nome de classe ani, o atraso na transição do progresso atinge o seu efeito de incremento altamente escalonado.
Pode ser confuso apenas ler a descrição do texto, mas observe novamente o efeito:
(4) Parte do código de desenho do círculo colorido
gradeTarget é a pontuação real, que é o resultado final a ser sorteado.
A nota começa em 0 e aumenta até o tamanho de gradeTarget.
Não fiz ++vm.grade diretamente aqui e não sei o que estava pensando na época.
Se julgar, se a nota aumentar para o valor alvo gradeTarget ou for maior que o valor alvo, pare de incrementar e deixe grade = gradeTarget. Julgamento que pertence ao valor crítico. Na função de movimento também é considerada detecção de colisão.
Pelo contrário, se a meta não for atingida, a última tela desenhada será apagada e um novo anel colorido será redesenhado após a alteração gradual da nota.
(5) Coloque tudo isso em setTimeout, faça uma pausa de 500 milissegundos antes de executar, para esperar que o gráfico de barras e o gráfico de anéis entrem no mercado antes de começar a desenhar o efeito incremental do círculo.
Na verdade, o código acima é um processo lógico muito simples. Os leitores devem ser capazes de entendê-lo depois de ler o código uma vez.
Novas ideias:
Fiz esse efeito há muito tempo, quando estava resolvendo o método de produção hoje, pensei em uma solução de otimização para meu próprio código:
Na verdade, não há necessidade de chamar novamente o método de desenho do círculo colorido no cronômetro. O que alteramos diretamente é o atributo this.grade. Seria bom monitorar as alterações deste atributo. Desta forma, quando esta propriedade for modificada no temporizador, o método ring será executado automaticamente.
Isso ainda é uma ideia e ainda precisa da minha prática.
Efeito incremental do texto intermediário:Como a nota é uma pontuação crescente a cada vez, você pode usar a vinculação de dados bidirecional do Vue para vincular diretamente a nota como um valor de pontuação à visualização DOM correspondente.
Finalmente, a animação do anel e do gráfico de barras acima é combinada com a animação para controlar o atraso da animação. Muito simples.
Código-fonte index.vue:
(Observe que o código-fonte foi ligeiramente organizado e extraído separadamente. Para completar e proteger outros códigos de negócios, alguns nomes de variáveis foram modificados, que podem ser ligeiramente diferentes das capturas de tela anteriores)
<template lang='pug'> .indexs#Indexs.app-bg transição(nome=fade) swiper#swiperBox(:options=swiperOption ref=mySwiper) swiper-slide.swiper-slide1 .container .up swiper-slide.swiper -slide2(v-if=isShow) .my-shark .up swiper-slide.swiper-slide3 .container .data-cont .data.data01 .data01-charts .row(v-for='item,index in Data' :key=index :class='aniShow ? ani:') . data-txt {{item.grade > 0? item.grade: 'Sem dados'}} .progress(:class='item.grade == 0 ? nodata : ' :style='height: ' + (aniShow ? (item.grade >= 100 ? (100 * 1,5) / 100 : item.grade == 0 ? 0,04 : item.grade * 1,5/100 ) : 0) +'rem') span.pg-data .week {{item.week}} .data.data02 .data02-charts .canvas-box //- baseCanvas canvas#baseCanvas.my-canvas(ref=baseCanvas width=174 height=174) //- canvas canvas#myCanvas.my-canvas.clr-canvas(ref=myCanvas width =174 altura=174) .canvas-data #[span.num {{grade}}]pontos</template><script>var vm = null, timer1 = null, /* valor básico da tela*/ c = null, //document.getElementById(myCanvas = null, //canvas-2d canvas x = 161/2 + 1, //coordenada central do círculo r = (161); - 10) / 2; //Tamanho do raio/* componente swiper*/import { swiper, swiperSlide } from vue-awesome-swiper;importar { getData } from ../io/getData;export default { name: Índices, componentes: { swiper, swiperSlide }, data() { return { grade: 0, //Pontuação do gráfico de rosca gradeTarget: 78,54, //Número de pontuação real , você pode modificar isShow: true após solicitar dados via ajax, // Se deve exibir o swiper da segunda página aniShow: false, // Se deve ativar a animação do gráfico de colunas Data: [{ week: primeira semana, nota: 0}, {semana: segunda semana, nota: 30}, {semana: terceira semana, nota: 99,99}, {semana: quarta semana, nota: 76,98}, {semana: quinta semana, nota: 100 }], swiperOption: { //parâmetros do swiper notNextTick: true, direção: vertical, grabCursor: true, setWrapperSize: true, autoHeight: true, slidesPerView: 1, mousewheel: false, mousewheelControl: false, height: window.innerHeight, //Configuração de altura, preenchendo a altura do dispositivo ResistanceRatio: 0, observeParents: true, InitialSlide: 2 - 1, //Ao definir a inicialização , a página de exibição padrão do swiper, começando do zero: { slideChange() { if ( (this.activeIndex == 2 && vm.isShow) || (this.activeIndex == 1 && !vm.isShow) ) { console.log(this.activeIndex, vm.isShow, draw Animation(function() { // Exibir animação do histograma vm.aniShow = true); // O cronômetro aciona continuamente o desenho de anéis coloridos para obter o efeito de animação do anel timer1 = setInterval(function() { // Altera a redação da pontuação intermediária var num = vm.grade; num++; if (num >= vm.gradeTarget) { vm.grade = vm.gradeTarget; /60); }, 500); Após virar a página, inicialize o status da página de dados, limpe o cronômetro para pausar a animação e limpe os anéis coloridos console.log (outras páginas); ; vm.clearCanvas(); this.$refs.myCanvas; ctx = c.getContext(2d); this.drawBaseCanvas() }, métodos: { drawBaseCanvas() { // desenho da tela/* valor básico*/ var c = this.$refs.baseCanvas , //document.getElementById(myCanvas); // depurador ctx = c.getContext(2d), o = x, randius = r; /*Círculo cinza padrão*/ ctx.strokeStyle = #eee; ctx.lineWidth = 10; ; }, clearCanvas() { // Limpa a tela ctx.clearRect(0, 0, 200, 200); drawClrCanvas() { var gradiente = ctx.createLinearGradient(75, 50, 5, 90); gradiente.addColorStop(0, #C88EFF); Para preencher ctx.lineWidth = 10; ctx.shadowColor = rgba(191.142.255, 0,36); x, r, Math.PI, Math.PI * contagem, falso); ctx.stroke(); } }};</script><style lang='scss'>// coluna chart.row { posição: índice z: 1; - 0,08 - 0,38rem; alinhamento de texto: centro;}.data-txt {tamanho da fonte: 0,2rem; 0,2rem; margem inferior: 0,09rem;}.progress { altura: 0rem; transição: altura 0,5s facilidade de entrada;}.ani { @for $i de 1 a 6 { &:nth-of-type( #{$i}) { .progress { atraso de transição: #{$i * 0,15}s } } } // &:nth-of-type(1) { // .progress { // atraso de transição: .4s; // } // } // &:nth-of-type(2) { // .progress { // atraso de transição: .8s; } // } // &:nth-of-type(3) { // .progress { // atraso de transição: 1s; // } // } // &:nth-of-type(4) { / /.progresso { // atraso de transição: 1,4s; // } // } // &:nth-of-type(5) { // .progress { // atraso de transição: 1,8s; dados { display: bloco; largura: 0,12rem altura: 100%; margem: 0 fundo automático: gradiente linear (0deg, #c88eff 0%, #7e5cff 100%); box-shadow: 0 -0,04rem 0,14rem 0 rgba(129, 93, 255, 0,4); dados { raio da borda: 0; none; : 0,32rem; altura: 1,61rem;}.canvas-box {posição: float relativo: esquerda; 1,61rem; altura: 1,61rem;margem esquerda: 0,92rem;}.my-canvas {largura: 1,61rem;altura: 1,61rem;}.clr-canvas {posição: topo absoluto: 0; .canvas-data {posição: topo absoluto: 0,56rem; esquerda: 0; margem direita: 0; -0,1rem;alinhamento do texto: centro;tamanho da fonte: 0,24rem;tamanho da fonte: 0,32rem;
O texto acima é todo o conteúdo deste artigo. Espero que seja útil para o estudo de todos. Também espero que todos apoiem a Rede VeVb Wulin.