How can we display the numbers between two given numbers in Ionic 2 while incrementing or decrementing the value?

I am developing a geolocation-based speed tracking feature that displays the speed on the screen. However, I have encountered a problem where there is a significant gap between the previous and current speed values, and I would like to implement a transition to smoothly display the numbers in between.
Example:

speed 1 -> 80
speed 2 -> 90
display -> 80 81 82 83 84 85 86 87 88 89 90

Despite trying various solutions, I have been unable to achieve the desired "transition."

In the 'location-tracker.ts' file:

startTracking(){
  this.watchSubscription = this.watch.subscribe((resp) => {
    this.zone.run(() => {
      var speedToSet = resp.coords.speed;
      this.setSpeed(speedToSet);
    });
  }, error => {
    console.log("Error: " + JSON.stringify(error));
  });
}

setSpeed(speedarg){

  if (speedarg == this.speed){
    return;
  }

  if (speedarg > this.speed){

    let val = this.speed;
    for (var i = val; i <= speedarg; i++){
      setTimeout(() => {
        this.speed = i;
      }, 30);
    }
  } else {

    let val = this.speed;
    for (var i = val; i >= speedarg; i--){
      setTimeout(() => {
        this.speed = i;
      }, 30);
    }
  }
}

In the 'home.html' file:

<ion-grid>
  <ion-row>
    <ion-col>
    Speed: {{locationTracker.speed}}
    </ion-col>
  </ion-row>
</ion-grid>

While I attempted the above solution, only the final number seems to update, as shown in the example:

speed 1 -> 80
speed 2 -> 90
display -> 90

Answer №1

To effectively implement this concept in Angular, one should leverage Observables.

Utilizing Interpolated Values

Initially, let's explore a basic function that interpolates values. This function is essential for displaying numbers when transitioning from one speed to another.

const interpolate = (from, to) => 
  Array.from({length: Math.abs(to - from) + 1})
    .map((_, i) => to - from > 0 ? from + i : from - i)

For instance, interpolate(1, 4) will output [1, 2, 3, 4]. It also accommodates descending sequences.

Streaming for Speed Changes

We require a stream that signals alterations in speed. This stream will be represented by a BehaviorSubject, allowing the initialization of a default value that is automatically emitted upon creation. We commence with the value zero.

public speed$ = new BehaviorSubject<number>(0)

Visualization Stream

The objective is to convert the speed stream into a stream of values that should be exhibited on the screen.

display$ = this.speed$
  .pairwise()
  .switchMap(([oldSpeed, newSpeed]) => {
    return Observable.of(...interpolate(oldSpeed, newSpeed))
      .map(x => Observable.of(x))
      .map(o => o.delay(30))
      .concatAll()
  })
  • pairwise is used to acquire the previous value as well. For an initial state of 0, shifting speed to 5 will produce [0, 5]. Subsequently altering the speed to 2 will generate [5, 2].
  • The aforementioned values are the ones that need to be interpolated. For [5, 2], we establish an observable that instantly emits 5, 4, 3, 2 (not as an array, but as individual values).
  • Subsequently, these values are transformed into a higher-order stream by mapping over each emitted value to an observable that emits the same value.
  • This facilitates the introduction of a delay for each of these inner streams. A 30-millisecond delay is utilized, but this duration can be tailored to specific preferences.
  • Subsequently, all these inner streams are concatenated together, resulting in the desired outcome: an observable of values that are emitted with a 30-millisecond delay between them.
  • This type of observable is emitted whenever a new set of values is received. switchMap is used to streamline this process, whilst also transitioning to the subsequent change if the speed is altered prior to completing the transition (as opposed to mergeMap, which allows for the overlap of flattened streams).
  • This approach yields the anticipated stream.

That summarizes it! Only 12 lines of code are required.

Here is a Blitz showcasing this implementation.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can we verify if this API response is accurate?

I am currently delving into the world of API's and developing a basic response for users when they hit an endpoint on my express app. One question that has been lingering in my mind is what constitutes a proper API response – must it always be an o ...

The combination of Material UI and React Hook Form is encountering an issue with submitting disabled checkboxes

My current challenge involves ensuring that all fields are disabled while the form is submitting. I have successfully implemented this for text, selects, and radios, but I am facing difficulties with required checkboxes. I am working with nextjs typescrip ...

Encountering challenges with periods in URL when utilizing a spring boot application alongside Angular in a live environment

Currently, I am in the process of developing a Spring boot + Angular application using JHipster and deploying it in a docker container with JIB. However, encountering an issue where URLs containing a dot are not functioning properly when accessed directly ...

Lazy Loading Child Components using Angular 2+ Router

I've been attempting to implement lazy loading on a children route that is already lazy loaded, but I haven't had any success so far. Here is the route structure I am working with: const routes: Routes = [ { path: 'customers', ...

Navigating in an Electron app using Angular

It appears that I am encountering difficulties with routing pages in my angular electron desktop application. Despite configuring the routing similar to an angular app, nothing seems to be functioning properly. I have specified router links such as "/hom ...

Using Vue-router and Typescript with beforeEnter guard - utilizing validated data techniques

As I utilize Vue along with vue-router and typescript, a common scenario arises where a single page is dedicated to displaying a Photo component. A route includes a beforeEnter guard that checks my store to verify the existence of the requested photo. ...

RxJs: Generating an observable based on changes in a field's value

Is there a way to generate an Observable using the variable this.pending as its source? I'm looking to create an Observable that will produce a new feed each time the value of this.pending changes. For example, if I update this.pending to be false i ...

The "shape" property is not available while utilizing generics with toZod

Short version: I encountered a type error, and here is the link to the TS PLAYGROUND I am looking to ensure type safety when creating zod schemas. To achieve this, I define the data type like so: type Option = { id: number }; Using this type definition ...

Can a function utilize a Generic-specified type property?

function extractStringValue<T extends object, S extends keyof PickByValue<T, string>>( obj: T, key: S ): string { return obj[key]; }; The PickByValue function extracts properties of object T with values of type string. type CustomType = ...

The property 'licenses' has incompatible types. The type 'License[]' cannot be assigned to type 'undefined' in the getServerSideProps function while using iron-session

I am encountering an issue with red squiggly lines appearing on the async keyword in my code: Argument of type '({ req, res }: GetServerSidePropsContext<ParsedUrlQuery, PreviewData>) => Promise<{ props: { admin: Admin; licenses?: undefined ...

Is it necessary to include a module in another module if it is not utilized in the template?

Is it necessary to import Module2 into Module1 if a component from Module2 is being used in Module1, but only in the typescript and not the template? For instance, as a @ContentChild(Component2) component2 like shown below (Note: both modules are secondary ...

The correct way to add to a string array that has been passed as props to a functional component

There is a parent component that establishes a useState hook with a string array. Then, there is a child component tasked with updating the string array. To accomplish this, both the string array and the useState function are passed to the child component. ...

Utilizing Angular Material Autocomplete to showcase a list of employees retrieved from a RestApi by

I need help implementing Angular Material Autocomplete to show only Employee names from the Rest API response that contains an array of employee data like the example below: { "employees": [ { "employeeID&quo ...

displaying an item within a text field

I have an input box created using Angular reactive forms <input type="text" formControlName="OrgName" placeholder="Enter name" maxlength="60"> <p class="fieldRequired" *ngIf="showNameMSg" ...

Maximizing Performance of JSON.stringify in Angular

In my Angular app, I have a service that retrieves JSON data from an API. At times, this API sends back over 400 records (JSON Objects). When I directly access the endpoint in my browser, it takes around 5 seconds to load all the JSON data onto the page. ...

Typescript: The property isComposing is not found on Event type

While working on a React app with Typescript, I encountered a Typescript error both during compile time and in the editor: TS2339: Property isComposing does not exist on type Event This issue arises when handling an OnChange event in an HTML Input element ...

Encountering an error while attempting to upgrade to Angular 9: Unable to locate the exported node name

Upon upgrading to Angular 9 and attempting to run my project, I encountered the following error: Compiling @angular/common/http : module as esm5 Compiling angular-font-awesome : module as esm5 Compiling angular-font-awesome : module as esm5 Error: Error ...

Setting up an Angular CLI project

In our Angular 2 application, we utilize native CSS components that contain some JavaScript files. These components have wrappers to convert them into Angular 2 components. Now, I am looking to create a new Angular 4 project using Angular CLI and incorpora ...

Set an interface to null within Angular 4

I've created an interface in Angular 4 called StatusDetail: interface StatusDetail { statusName: string, name: string } Next, I assigned some values to it within an Angular component: //Angular Component export class EditComponent implemen ...

Switch from using getElementById to useRef in React components

There is a requirement to update a functional component that currently uses getElementById to instead utilize the useRef hook. The original code snippet is as follows: import React, { useState, useEffect, useRef } from 'react'; import { createPo ...