N formas de optimizar la barra de progreso

Autor: Mai Le Fuente: https://developer.hs.net/thread/2159

necesidad

Implemente una barra de progreso con funciones de pausa y reproducción. La representación es más o menos la siguiente:

2.png

La función no es muy complicada y no siento que haya ninguna dificultad técnica. Lo primero que pensé fue usar un temporizador para realizar esta función. El botón puede controlar el inicio y la pausa del temporizador. A continuación, vue se utiliza para realizar la primera versión.

Implementación del temporizador

el código se muestra a continuación:

3FA276AD-57A3-45CD-925C-8BDB48DD414D.png

<script>
let timer, totalTime = 3000;
export default {
  name: "Progress",
	data() {
		return {
			isPlay: false,
			progress: 0
		}
	},

	methods: {
		run() {
			timer = setInterval(() => {
				const {progress} = this;
				this.progress = progress + 2;
				if(this.progress === 100) {
					this.cancel();
				}
			}, 3000/ 100)
		},
		cancel() {
			clearInterval(timer);
			timer = null;
		},
		changePlay() {
			const { isPlay } = this;
			this.isPlay = !isPlay;
			if(this.isPlay) {
				this.run();
			} else {
				this.cancel();
			}
		},
		replay() {
			this.isPlay = true;
			this.progress = 0;
			this.run();
		}
	}
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
	.g-contain {
		width: 240px;
		height: 25px;
		border-radius: 25px;
		background: #eee;
		overflow: hidden;
}
	.g-progress {
		height: inherit;
		border-radius: 25px 0 0 25px;
		background: #0f0;
	}
</style>

Incremento rápido de la variable a través de un temporizador progressPara lograr el aumento del progreso, cada cambio de la variable hará que la vista vuelva a calcular y renderizar, y hará que toda la página se rehaga y redibuje continuamente. Si el proyecto no es muy complicado, parece que el problema no es grande. Si encuentra un proyecto a gran escala o un proyecto con muchos nodos DOM en la página, sentirá un retraso evidente.

prueba:

Agregue 100 millones de elementos a la página,

data() {
		return {
			isPlay: false,
			progress: 0,
			arr: []
		}
	},
	created() {
		for(let i = 0; i < 100000; i ++) {
			this.arr[i] = i;
		}
	},

1647681376897.jpg

Haga clic en el botón de reproducción, puede ver que la página se ha atascado y la reproducción se ha ralentizado.

Optimización 1

Usa animaciones css.

4DC90A53-ECAC-48F7-8F99-BD4A6DE0C50D.png

<script>
export default {
  name: "Progress",
	data() {
		return {
			isPlay: false,
			type: 0, // 0播放, 1 重播
			totalTime: 2
		}
	},
	methods: {
		end(){},

		changePlay() {
			const { isPlay } = this;
			this.isPlay = !isPlay;
		},
		replay() {
			const { type } = this;
			this.isPlay = true;
			this.type = type ? 0 : 1;
		}
	}
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
	@keyframes play { 
    to {width: 100%}  
	}

	@keyframes replay {
    to {width: 100%}  
	}
	.g-contain {
		width: 240px;
		height: 25px;
		border-radius: 25px;
		background: #eee;
		overflow: hidden;
}
	.g-progress {
		width: 0;
		height: inherit;
		border-radius: 25px 0 0 25px;
		background: #0f0;
		/* animation-timing-function: linear; */
		-webkit-animation-timing-function: linear;
	}
	.g-progress.play {
		animation: play 3s infinite linear;
	}
	.g-progress.replay {
		animation: replay 3s infinite linear;
	}
	.g-progress.animationplay {     /* 使animation动画启动 */
		animation-play-state: running;
    -webkit-animation-play-state: running;
	}

	.g-progress.animationpause {    /* 使animation动画暂停 */
		animation-play-state: paused;
		-webkit-animation-play-state: paused;
	}
</style>

El uso de la animación de fotogramas clave CSS3 para controlar el cambio de la barra de progreso reduce muchos cálculos y reduce el consumo de rendimiento hasta cierto punto.

Sin embargo, este método aún activará con frecuencia el reflujo y el redibujado de toda la página.

Renderice el componente de lista larga para ver el efecto:

lista.vue

<template>
	<ul>
		<li v-for="(i, index) in arr" :key="index">{{i}}</li>
	</ul>
</template>

<script>
export default {
  name: "List",
	data() {
		return {
			arr: []
		}
	},
	created() {
		for(let i = 0; i < 100000; i ++) {
			this.arr[i] = i;
		}
	}
};
</script>


Introduzca el registro utilizando:

import List from './List.vue'
components: {
    List
  },

Durante el proceso de reproducción, aunque también hay un bloqueo, es mejor que la solución anterior, no es conveniente ver los resultados aquí, finalmente, se adjunta el código, que se puede descargar y probar.

Optimización 2

Use animación CSS y habilite la aceleración de GPU. GPU es principalmente responsable de la renderización 3D y la aceleración de hardware.

Esta solución no tiene diferencia entre la lógica de optimización 1 y la estructura de la página, la diferencia está en el estilo:

<style scoped>
@keyframes play { 
    0% {  
      transform: translateX(-50%) scaleX(0);  /* 用 scaleX 来代替 width */
    }
    to {
	transform: translateX(0) scaleX(1);
    }
}
@keyframes replay {
    0% {  
      transform: translateX(-50%) scaleX(0);  /* 用 scaleX 来代替 width */
    }
		to {
					transform: translateX(0) scaleX(1);
		} 
	}
	.g-contain {
		width: 240px;
		height: 25px;
		border-radius: 25px;
		background: #eee;
		overflow: hidden;
}
	.g-progress {
		width: 100%;
		height: inherit;
		border-radius: 25px 0 0 25px;
		background: #0f0;
                will-change: transform; /**通知浏览器提前过好优化 */ 
		animation-timing-function: linear;
		-webkit-animation-timing-function: linear;
	}
	.g-progress.play {
		animation: play 3s infinite linear;
	}
	.g-progress.replay {
		animation: replay 3s infinite linear;
	}
	.g-progress.animationplay {     /* 使animation动画启动 */
		animation-play-state: running;
    -webkit-animation-play-state: running;
	}

	.g-progress.animationpause {    /* 使animation动画暂停 */
		animation-play-state: paused;
		-webkit-animation-play-state: paused;
	}
</style>


Use will-change: transform; /**Notifique al navegador para optimizar por adelantado*/

Use transform para habilitar la aceleración de GPU.

Ingrese al componente Lista y pruébelo, y encontrará que el retraso obvio en la página ha desaparecido.

Resumir:

Al usar la animación, puede optimizar el rendimiento haciendo que la página forme diferentes capas compuestas.

Como abrir:

  • Propiedad CSS de transformación 3D o perspectiva
  • Los elementos que usan decodificación de video acelerada video>tienen 3D
  • (WebGL) contexto o canvaselemento de contexto 2D acelerado
  • Complementos híbridos (como Flash)
  • Anima tu opacidad con CSS o usa un elemento de transformación animado (en navegadores anteriores, este método aún causará repintados y reordenamientos)
  • Elementos con filtros CSS acelerados
  • Un elemento tiene un nodo descendiente que contiene una capa compuesta (en otras palabras, un elemento tiene un elemento secundario que está en su propia capa)
  • El elemento tiene un hermano de índice z más bajo que contiene una capa compuesta (en otras palabras, el elemento se representa encima de la capa compuesta)

Github

{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/3620858/blog/5495612
Recomendado
Clasificación