El efecto dinámico de la convergencia de palabras en palabras es deslumbrante

Estoy participando en el reclutamiento del programa de firma de creadores de la Comunidad Tecnológica de Nuggets, haga clic en el enlace para registrarse y enviar .

prefacio

Cuando introduje fl_chart para dibujar un gráfico, vi que el complemento tenía los siguientes efectos dinámicos, y los puntos dispersos al azar finalmente se combinaron en el logotipo de Flutter, que es bastante bueno. En este artículo, discutiremos cómo lograr un efecto similar.

logo animacion.gif

enrejado

Antes de explicar la implementación del código, primero popularicemos un conocimiento, es decir, la red. La matriz de puntos es muy común en la vida diaria, como la pantalla publicitaria, la pantalla del sistema de estacionamiento, que se llama pantalla LED en la industria.

imagen.png

La pantalla LED es en realidad un panel de visualización compuesto por muchas luces LED, y luego la visualización de texto y gráficos se puede realizar encendiendo y apagando algunas luces. Cuando el paso de punto de la pantalla LED es lo suficientemente pequeño y los colores son lo suficientemente ricos, en realidad forma nuestra pantalla diaria.Por ejemplo, el principio de la pantalla OLED es similar. El mismo principio se utiliza en el edificio de dormitorios universitarios del que se informó anteriormente al controlar las luces de cada habitación para que se enciendan y apaguen.

imagen.png

Ahora echemos un vistazo a cómo el LED muestra el texto. Por ejemplo, queremos mostrar el carácter "Isla" del granjero de código en la isla. En una matriz de puntos de 16x16, se obtiene el siguiente resultado organizando (el diseño de diferentes fuentes serán algo diferentes) diferencia).

Debido a que cada línea tiene 16 puntos, podemos corresponder a números binarios de 16 bits, marcar el negro como 1 y marcar el gris como 0, y cada línea puede obtener un número binario. Por ejemplo, la octava columna de la primera línea anterior es 1 y las otras son 0. El número binario correspondiente es 0000000100000000 y el número hexadecimal correspondiente es 0x0100. Las otras líneas también se calculan de esta manera, y la palabra final "isla" corresponde a 16 números hexadecimales, como se muestra a continuación.

 [
   0x0100, 0x0200, 0x1FF0, 0x1010, 
   0x1210, 0x1150, 0x1020, 0x1000,
   0x1FFC, 0x0204, 0x2224, 0x2224,
   0x3FE4, 0x0004, 0x0028, 0x0010
 ];
复制代码

Con esta base, podemos usar Flutter para dibujar gráficos de mapa de bits.

gráficos de matriz de puntos

Primero, dibujamos un "panel LED", que consiste en dibujar una matriz compuesta por varios puntos. Esto es relativamente simple, mantenemos el mismo espacio y dibujamos el mismo círculo línea por línea. Por ejemplo, dibujamos una matriz de puntos de 16x16 para implementar el código de la siguiente manera.

var paint = Paint()..color = Colors.grey;
final dotCount = 16;
final fontSize = 100.0;
var radius = fontSize / dotCount;
var startPos =
    Offset(size.width / 2 - fontSize, size.height / 2 - 2 * fontSize);
for (int i = 0; i < dotCount; ++i) {
  var position = startPos + Offset(0.0, radius * i * 2);
  for (int j = 0; j < dotCount; ++j) {
    var dotPosition = startPos + Offset(radius * 2 * j, position.dy);
    canvas.drawCircle(dotPosition, radius, paint);
  }
}
复制代码

El efecto dibujado es el siguiente:

imagen.png

接下来是点亮对应的位置来绘制文字了。上面我们讲过了,每一行是一个16进制数,那么我们只需要判断每一行的16进制数的第几个 bit是1就可以了,如果是1就点亮,否则不点亮。点亮的效果用不同的颜色就可以了。 怎么判断16进制数的第几个 bit 是不是1呢,这个就要用到位运算技巧了。实际上,我们可以用一个第 N 个 bit 是1,其他 bit 都是0的数与要判断的数进行“位与”运算,如果结果不为0,说明要判断的数的第 N 个 bit 是1,否则就是0。听着有点绕,看个例子,我们以0x0100为例,按从第0位到第15位逐个判断第0位和第15位是不是1,代码如下:

for (i = 0 ; i < 16; ++i) {
  if ((0x0100 & (1 << i)) > 0) {
    // 第 i 位为1
  }
}
复制代码

这里有两个位操作,1 << i是将1左移 i 位,为什么是这样呢,因为这样可以构成0x0001,0x0002,0x0004,...,0x8000等数字,这些数字依次从第0位,第1位,第2位,...,第15位为1,其他位都是0。然后我们用这样的数与另外一个数做位与运算时,就可以依次判断这个数的第0位,第1位,第2位,...,第15位是否为1了,下面是一个计算示例,第11位为1,其他位都是0,从而可以 判断另一个数的第11位是不是0。

bit a bit Y

通过这样的逻辑我们就可以判断一行的 LED 中第几列应该点亮,然后实现文字的“显示”了,实现代码如下。wordHex是对应字的16个16进制数的数组。dotCount的值是16,用于控制绘制16x16大小的点阵。每隔一行我们向下移动一段直径距离,每隔一列,我们向右移动一段直径距离。然后如果当前绘制位置的数值对应的 bit位为1,就用蓝色绘制,否则就用灰色绘制。这里说一下为什么左移的时候要用dotCount - j - 1,这是因为绘制是从左到右的,而16进制数的左边是高位,而数字j是从小到大递增的,因此要通过这种方式保证判断的顺序是从高位(第15位)到低位(第0位),和绘制的顺序保持一致。

 for (int i = 0; i < dotCount; ++i) {
  var position = startPos + Offset(0.0, radius * i * 2);
  for (int j = 0; j < dotCount; ++j) {
    var dotPosition = startPos + Offset(radius * 2 * j, position.dy);

    if ((wordHex[i] & ((1 << dotCount - j - 1))) != 0) {
      paint.color = Colors.blue[600]!;
      canvas.drawCircle(dotPosition, radius, paint);
    } else {
      paint.color = Colors.grey;
      canvas.drawCircle(dotPosition, radius, paint);
    }
  }
}
复制代码

绘制的结果如下所示。

imagen.png

由点聚集成字的动画实现

A continuación, consideremos cómo lograr un efecto de animación similar al mencionado al principio. De hecho, el método es muy simple, es decir, de acuerdo con la cantidad de LED que el texto debe "encender", primero dibuje tantos LED en posiciones aleatorias y luego controle estos LED para moverse a la posición de destino a través de la animación. es decir, el texto debe estar donde dibujar. La fórmula para este movimiento es la siguiente, donde t es el valor de la animación, que va de 0 a 1.

fórmula móvil

Cabe señalar que no se pueden generar puntos aleatorios durante el proceso de dibujo, lo que dará como resultado una nueva posición aleatoria para cada dibujo, es decir, la posición inicial cambiará, dando como resultado que la fórmula anterior no se cumple, y el no se logrará el efecto esperado. Además, no se puede construir en el buildmétodo , porque se llamará al método de construcción cada vez que actualice, lo que también hará que cambie la posición inicial. Por lo tanto, la generación de posiciones aleatorias debe hacerse en el initStatemétodo . Pero hay un nuevo problema, es decir, no hay ningún initStatemétodo en el método, y contextno se puede obtener el ancho y el alto de la pantalla, por lo que la posición no se puede generar directamente. Solo necesitamos generar un 0-1coeficiente aleatorio y luego multiplicar la pantalla ancho y alto al dibujar.Se obtiene la posición inicial real. El código de generación del coeficiente de posición inicial es el siguiente:

@override
  void initState() {
  super.initState();
  var wordBitCount = 0;
  for (var hex in dao) {
    wordBitCount += _countBitOne(hex);
  }
  startPositions = List.generate(wordBitCount, (index) {
    return Offset(
      Random().nextDouble(),
      Random().nextDouble(),
    );
  });
  ...
}
复制代码

wordBitCountes contar cuantos bits hay 1 en una palabra para saber el numero de "LEDs" a dibujar. El siguiente es el código de dibujo. Esta vez, no dibujaremos la luz que no es brillante, y luego la posición que se iluminará se calcula mediante la fórmula de cálculo de posición anterior, lo que garantiza que la posición aleatoria se dibuje al principio. Con el proceso de animación, muévase gradualmente a la posición de destino y finalmente converja en una palabra para lograr el efecto de animación esperado. El código es el siguiente.

void paint(Canvas canvas, Size size) {
  final dotCount = 16;
  final fontSize = 100.0;
  var radius = fontSize / dotCount;
  var startPos =
      Offset(size.width / 2 - fontSize, size.height / 2 - fontSize);
  var paint = Paint()..color = Colors.blue[600]!;

  var paintIndex = 0;
  for (int i = 0; i < dotCount; ++i) {
    var position = startPos + Offset(0.0, radius * i * 2);
    for (int j = 0; j < dotCount; ++j) {
      // 判断第 i 行第几位不为0,不为0则绘制,否则不绘制
      if ((wordHex[i] & ((1 << dotCount - j))) != 0) {
        var startX = startPositions[paintIndex].dx * size.width;
        var startY = startPositions[paintIndex].dy * size.height;
        var endX = startPos.dx + radius * j * 2;
        var endY = position.dy;
        var animationPos = Offset(startX + (endX - startX) * animationValue,
            startY + (endY - startY) * animationValue);
        canvas.drawCircle(animationPos, radius, paint);
        paintIndex++;
      }
    }
  }
}
复制代码

Veamos el efecto, ¿no es genial? El código fuente completo se ha enviado a: Código fuente relacionado con el dibujo , el nombre del archivo es: dot_font.dart.

点阵汇聚文字动画.gif

Resumir

Este artículo presenta el concepto de matriz de puntos y cómo dibujar texto y gráficos basados ​​en matriz de puntos, y finalmente dibuja puntos aleatorios primero y luego los reúne en efectos de animación de texto. Se puede ver que el efecto de animación de dividir el todo a cero y luego reunir el cero al total es bastante bueno. De hecho, con base en este enfoque, se pueden construir efectos de animación más interesantes.

Supongo que te gusta

Origin juejin.im/post/7120233450627891237
Recomendado
Clasificación