display path into 4 segment using SVG View-box in angular

89 views Asked by At

i am having very big railway track as path in svg path...but i want to divide the track into 4 and display one by one...please suggest me a code in angular

i tried by splitting the values into 4 and marked the coordinate but it results missing line in previous track kindly help me with other solution

<path *ngFor="let path of part1" [attr.d]="path" fill="none" stroke="black" stroke-width="5">
<path *ngFor="let path of part2" [attr.d]="path" fill="none" stroke="black" stroke-width="5">

TS:

const splitData = this.final;
const chunkSize = Math.ceil(splitData.length / 4);

this.part1 = splitData.slice(0, chunkSize);
this.part2 = splitData.slice(chunkSize, 2 * chunkSize);
this.part3 = splitData.slice(2 * chunkSize, 3 * chunkSize);
this.part4 = splitData.slice(3 * chunkSize);
1

There are 1 answers

0
Eliseo On

"I want to divide the track into 4 and display one by one..."

So you need execute a function 4 times pausing a bit until execute two consecutive call to the function

For this you can use rxjs

    <ng-container *ngIf="obs$|async as time">
        <div *ngIf="time>=1">One</div>
        <div *ngIf="time>=2">Two</div>
        <div *ngIf="time>=3">Three</div>
        <div *ngIf="time>=4">Four</div>
    </ng-container>
    <button (click)="timer()">init</button>

  obs$!:Observable<any>
  timer()
  {
    //I put a delay
    this.obs$=timer(500,500).pipe(
       map(x=>x+1), //the observable return 1,2,3,4 each 500 miliseconds
       take(4))
  }

Well, if you want to draw "bit a bit" a svg the first is divided the svg in parts

  separatePath(d: string) {
    const match = d.match(/[a-zA-Z]{1,2}[\d. ,-]*/g) || [];
    const matchTransform: string[] = [];
    let i = 0;
    match.forEach((x) => {
      matchTransform[i] = (matchTransform[i] || '') + x;
      if (x.toLowerCase().indexOf('m') <= -1) i++;
    });
    matchTransform[matchTransform.length - 2] =
      matchTransform[matchTransform.length - 2] +
      matchTransform[matchTransform.length - 1];
    return matchTransform.slice(0, -1);
  }

If you want to draw "bit a bit" it's easy

    <ng-container *ngIf="obs$|async as time">
    <svg
      svg
      xmlns="http://www.w3.org/2000/svg"
      xml:space="preserve"
      width="50%"
      stroke="#1F1A17"
      stroke-width=".5"
      [attr.fill]="time*chunk==times?'#1F1A17':'transparent'"
      style="
        shape-rendering: geometricPrecision;
        text-rendering: geometricPrecision;
        image-rendering: optimizeQuality;
        fill-rule: evenodd;
        clip-rule: evenodd;
      "
      viewBox="0 0 205 105"
      xmlns:xlink="http://www.w3.org/1999/xlink"
    >
      <path [attr.d]="splitData.slice(0,time*chunk).join(' ')" stroke="black" />
    </svg>
  </ng-container>

where

  d ='M51.3428 88.6532c 7.66....'
  splitData = this.separatePath(this.d);
  times = this.splitData.length;
  chunk = (this.splitData || []).length / this.times;

  timer() {
    this.obs$ = timer(100, 200).pipe(
      map((x) => x + 1),
      take(this.times)
    );
  }

stackblitz

To calculate the position initial of each Pat it's more difficult. I suggest you calculate the different paths and save in a file.

You can change a bit the timer to makes Angular makes the calculate for us

timer() {
    this.obs$ = timer(100, 200).pipe(
      map((x) => x + 1),
      take(this.times),
      tap((x)=>{
        setTimeout(()=>{
          const point=this.path.nativeElement.getPointAtLength(this.path.nativeElement.getTotalLength() )
          if (this.splitData[x] && this.splitData[x].indexOf('M')!=0)
            this.splitData[x]="M"+(point.x)+" "+(point.y)+this.splitData[x]
      })
    })
    );
  }