ams
ams

Reputation: 75

How to trigger SVG animations from Angular Component method?

I'm trying to create an animation that triggers as I sort through an array of numbers. This animation should represent how the numbers in array get sorted.

Although, the sorting works fine, the animations do not get triggered as I sort through the numbers. I have tried multiple things but to no avail. I'm just starting out with Angular and would like some insight on this.

Angular Component

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-bubble',
  templateUrl: './bubble.component.html',
  styleUrls: ['./bubble.component.css']
})
export class BubbleComponent implements OnInit {
  numbers: number[] = [7, 13, 28, -9, 11, 0, -38, 17];
  cx = 100;
  left: number;
  right: number;
  beginWhen: string = "indefinite";

  sleep = ms => {
    return new Promise(resolve => setTimeout(resolve, ms))
  }

  swap = (i, j) => {
    return(this.sleep(3000).then(v => {
      //
      this.left = i;
      this.right = j;
      //begin elements
      //document get element by id .beginElement();
      this.beginWhen = "0s";
    }))
  } 

  constructor() { }

  ngOnInit(): void {
  }

  async bubbleSort() {
    for(let i = 0; i < this.numbers.length; i++) {
      for(let j = 1; j < (this.numbers.length - i) ; j++) {
        if (this.numbers[j-1] > this.numbers[j]) {
          this.beginWhen = "indefinite";
          await this.swap(j-1, j);
          let temp = this.numbers[j-1];
          this.numbers[j-1] = this.numbers[j];
          this.numbers[j] = temp;
        }
      }
    }
  }
}

HTML Code

<div>
    <svg width="1000" height="400" class="SVGline">
        <g *ngFor="let n of numbers; let i = index;">
            
            <circle id="{{ i }}-circle" [attr.cx]="100 + i*50" cy="50" r="20" />
            <line *ngIf="i != 0" [attr.x1]="120 + (i-1)*50" [attr.x2]="80 + i*50" y1="50" y2="50" stroke="#000000"/>
            <text id="{{ i }}-text" [attr.x]="100 + i*50" y="55" text-anchor="middle" stroke="#FFFFFF" stroke-width="2">{{ n }}</text>
            
        </g>
        <!-- <g *ngFor="let left of numbers; let i = index">
            <g *ngFor="let right of numbers; let j = index">
                <g *ngIf="left > right"> -->
        <animate [attr.href]="['#'+ left +'-circle']" attributeName="cx" [attr.from]="[100 + left*50]" [attr.to]="[100 + right*50]" dur="1s" [attr.begin]="[beginWhen]" fill="freeze" id="circ-anim" />
        <animate [attr.href]="['#'+ left +'-text']" attributeName="x" [attr.from]="[100 + left*50]" [attr.to]="[100 + right*50]" dur="1s" [attr.begin]="[beginWhen]" fill="freeze" id="text-anim" />
        <animate [attr.href]="['#'+ right +'-circle']" attributeName="cx" [attr.from]="[100 + right*50]" [attr.to]="[100 + left*50]" dur="1s" [attr.begin]="[beginWhen]" fill="freeze" id="circ-anim-" />
        <animate [attr.href]="['#'+ right +'-text']" attributeName="x" [attr.from]="[100 + right*50]" [attr.to]="[100 + left*50]" dur="1s" [attr.begin]="[beginWhen]" fill="freeze" id="text-anim-" />
        <!--         </g>
            </g>
        </g> -->
    </svg>
    <button class="btn btn-success" (click)="bubbleSort()">Sort</button>
</div>

Upvotes: 2

Views: 1142

Answers (1)

Brandon J. Boone
Brandon J. Boone

Reputation: 16472

Seems like adding begin="indefinite" is not enough. You also need to call the beginElement function on each <animation> node (SVGAnimationElement)

https://stackoverflow.com/a/52360704/402706.

The animation is running here, but looks like it needs some adjustments: https://stackblitz.com/edit/angular-ivy-fxenuz?file=src/app/bubble.component.ts

Upvotes: 1

Related Questions