Animations don't work when triggered by Events published from a provider module

I have a page with this code:

import { Component } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { NavController } from 'ionic-angular';
import { Events } from 'ionic-angular';

@Component({
  selector: 'page-home',
  animations: [
    trigger('colorChange', [
      state('black', style({ background: 'black' })),
      transition('* => black', animate('100ms')),
      state('red', style({ background: 'red' })),
      transition('* => red', animate('100ms')),
      state('green', style({ background: 'green' })),
      transition('* => green', animate('100ms')),
      state('blue', style({ background: 'blue' })),
      transition('* => blue', animate('100ms')),
      state('yellow', style({ background: 'yellow' })),
      transition('* => yellow', animate('100ms')),
      state('orange', style({ background: 'orange' })),
      transition('* => orange', animate('100ms')),
      state('aqua', style({ background: 'aqua' })),
      transition('* => aqua', animate('100ms')),
      state('white', style({ background: 'white' })),
      transition('* => white', animate('100ms')),
      state('pink', style({ background: 'pink' })),
      transition('* => pink', animate('100ms'))
    ])
  ],
  //templateUrl: 'home.html'
  template: `
  <ion-header>
    <ion-navbar>
      <button ion-button menuToggle>
        <ion-icon name="menu"></ion-icon>
      </button>
      <ion-title>Home</ion-title>
    </ion-navbar>
  </ion-header>

  <ion-content padding [@colorChange]="currentColor">
    <button ion-button (click)="doColor(30)">Color Change</button>
  </ion-content>
`
})
export class HomePage {
  private colorCount: number = 0;
  private currentColor: string;
  private intervalID: any;

  colorArr: string[] = ['black', 'red', 'green', 'blue', 'yellow', 'orange', 'aqua', 'pink', 'white'];

  constructor(public navCtrl: NavController, public events: Events) {
    firebase.init();
    events.subscribe('doColorChange', args => {
      this.doColor(args);
    });
  //  events.publish('doColorChange', 30);
  }

  doColor(rate) {
    if (rate) {
      let interval: number = Math.round(1000 / (rate / 60) / 2); // 1000=mssec rate=BPM 60=secs/min /2= on/off per interval
      clearInterval(this.intervalID);
      this.intervalID = setInterval(() => {
        console.log('interval');
        this.changeColor();
      }, interval);
    } else {
      clearInterval(this.intervalID);
      this.currentColor = 'white';
    }
  }

  changeColor() {
    this.colorCount++;
    if (this.colorCount < this.colorArr.length) {
      this.currentColor = this.colorArr[this.colorCount];
    } else {
      this.colorCount = 0;
      this.currentColor = this.colorArr[0];
    }
  }
}

If I uncomment // events.publish('doColorChange', 30); , everything works as written. The page animates when doColor() is called. If doColorChange at line 55 is triggered from a subscribed event in a provider module, which is initialized in platform.ready(), everything still fires, this.changeColor() is called inside the setInterval,and changeColor() runs, but the animations don’t fire.

I’m leaving this up here because animations are tricky so someone may learn from it, but I found that I needed to wrap my call to doColor in an ngZone.run(). I don’t understand Angular 4 digesting yet, but events subscribed to from a provider need to be handled inside a zone.run