Der dynamische Effekt, Worte in Worte zu verschmelzen, ist umwerfend

Ich nehme an der Rekrutierung des Signierprogramms für Ersteller der Nuggets Technology Community teil. Klicken Sie auf den Link, um sich zu registrieren und einzureichen .

Vorwort

Als ich fl_chart einführte, um ein Diagramm zu zeichnen, sah ich, dass das Plug-in die folgenden dynamischen Effekte hatte, und die zufällig verstreuten Punkte wurden schließlich zum Flutter-Logo kombiniert, was ziemlich cool ist. In diesem Artikel werden wir besprechen, wie man einen ähnlichen Effekt erzielt.

Logoanimation.gif

Gitter

Bevor wir die Code-Implementierung erklären, wollen wir zunächst ein Wissen bekannt machen, das heißt Gitter. Punktmatrix ist im täglichen Leben sehr verbreitet, z. B. als Werbebildschirm, Parksystemanzeige, die in der Branche als LED-Anzeige bezeichnet wird.

Bild.png

Die LED-Anzeige ist eigentlich eine Anzeigetafel, die aus vielen LED-Leuchten besteht, und dann kann die Anzeige von Text und Grafiken realisiert werden, indem einige Lichter ein- und einige Lichter ausgeschaltet werden. Wenn der Punktabstand des LED-Displays klein genug und die Farben satt genug sind, stellt es eigentlich unser tägliches Display dar. Das Prinzip zum Beispiel des OLED-Displays ist ähnlich. Das gleiche Prinzip wird in dem zuvor gemeldeten Studentenwohnheim verwendet, indem die Lichter in jedem Raum ein- und ausgeschaltet werden.

Bild.png

Schauen wir uns nun an, wie die LED den Text darstellt. Wir wollen zum Beispiel das „Insel“-Zeichen des Codes Bauer auf der Insel darstellen. Auf einer 16x16-Punktmatrix erhält man durch Anordnen (das Layout von verschiedene Schriftarten werden etwas anders sein) Unterschied).

Da jede Zeile 16 Punkte hat, können wir 16-Bit-Binärzahlen entsprechen, das Schwarze als 1 markieren und das Grau als 0 markieren, und jede Zeile kann eine Binärzahl erhalten. Beispielsweise ist die 8. Spalte der ersten Zeile oben 1 und die anderen sind 0. Die entsprechende Binärzahl ist 0000000100000000 und die entsprechende Hexadezimalzahl ist 0x0100. Die anderen Zeilen werden ebenfalls auf diese Weise berechnet, und das letzte Wort "Insel" entspricht 16 Hexadezimalzahlen, wie unten gezeigt.

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

Mit dieser Grundlage können wir Flutter verwenden, um Bitmap-Grafiken zu zeichnen.

Punktmatrix-Grafiken

Zuerst zeichnen wir ein "LED-Panel", das eine Matrix aus mehreren Punkten zeichnen soll. Das ist relativ einfach, halten Sie den gleichen Abstand ein und zeichnen Sie den gleichen Kreis Linie für Linie. Zum Beispiel zeichnen wir eine 16x16-Punktmatrix Implementieren Sie den Code wie folgt.

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);
  }
}
复制代码

Der gezeichnete Effekt ist wie folgt:

Bild.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。

bitweises UND

通过这样的逻辑我们就可以判断一行的 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);
    }
  }
}
复制代码

绘制的结果如下所示。

Bild.png

由点聚集成字的动画实现

Lassen Sie uns als Nächstes überlegen, wie Sie einen ähnlichen Animationseffekt erzielen können, der zu Beginn erwähnt wurde. Tatsächlich ist die Methode sehr einfach, das heißt, je nach Anzahl der LEDs, die der Text "aufleuchten" soll, zeichnen Sie zuerst so viele LEDs an zufälligen Positionen und steuern Sie dann diese LEDs, um sich durch Animation an die Zielposition zu bewegen - Das heißt, der Text sollte dort sein, wo gezeichnet werden soll. Die Formel für diese Bewegung lautet wie folgt, wobei t der Animationswert ist, der von 0 bis 1 reicht.

mobile Formel

Es ist zu beachten, dass während des Ziehvorgangs keine zufälligen Punkte generiert werden können, was zu einer neuen zufälligen Position für jede Ziehung führt, dh die Ausgangsposition ändert sich, was dazu führt, dass die obige Formel nicht gilt, und die erwartete Wirkung wird nicht erreicht. Außerdem kann es nicht in die buildMethode , da die Methode Build bei jeder Aktualisierung aufgerufen wird, wodurch sich auch die Anfangsposition ändert. Das Generieren zufälliger Positionen sollte also in der initStateMethode . Aber es gibt ein neues Problem, das heißt, es gibt keine initStateMethode in der Methode, und die contextBildschirmbreite und -höhe können nicht erhalten werden, also kann die Position nicht direkt generiert werden. Wir müssen nur einen 0-1zufälligen Koeffizienten generieren und dann den Bildschirm multiplizieren Breite und Höhe beim Zeichnen Die tatsächliche Ausgangsposition wird erhalten. Der Anfangspositionskoeffizienten-Erzeugungscode lautet wie folgt:

@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(),
    );
  });
  ...
}
复制代码

wordBitCountist zu zählen, wie viele Bits 1 in einem Wort sind, um die Anzahl der zu zeichnenden "LEDs" zu kennen. Als nächstes kommt der Zeichnungscode. Dieses Mal zeichnen wir kein Licht, das nicht hell ist, und dann wird die zu beleuchtende Position durch die obige Positionsberechnungsformel berechnet, die sicherstellt, dass die zufällige Position am Anfang gezeichnet wird Prozess der Animation, bewegen Sie sich allmählich zur Zielposition und konvergieren Sie schließlich zu einem Wort, um den erwarteten Animationseffekt zu erzielen.Der Code lautet wie folgt.

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++;
      }
    }
  }
}
复制代码

Lassen Sie uns den Effekt sehen, ist es nicht cool? Der vollständige Quellcode wurde eingereicht an: Zeichnungsbezogener Quellcode , der Dateiname lautet: dot_font.dart.

点阵汇聚文字动画.gif

Zusammenfassen

Dieser Artikel stellt das Konzept der Punktmatrix vor und wie Text und Grafiken basierend auf der Punktmatrix gezeichnet werden, und zeichnet schließlich zuerst zufällige Punkte und sammelt sie dann in Animationseffekten von Text. Es ist ersichtlich, dass der Animationseffekt des Teilens des Ganzen durch Null und des anschließenden Sammelns der Null zum Ganzen ziemlich cool ist. Tatsächlich können auf der Grundlage dieses Ansatzes interessantere Animationseffekte erstellt werden.

Ich denke du magst

Origin juejin.im/post/7120233450627891237
Empfohlen
Rangfolge