Scenes

Description

Here we'll create some scenes (day, night, at home, away) to simulate how our app controls the devices. We'll learn how to interact with a circular slider of z-view and some z-spots buttons.

Code

As we did previously, create a scenes.vue file inside the views folder and paste the following code:

<template>
  <z-view
  label="Scenes"
  slider
  :progress="progress"
  :style="styleActive">
    <h1>{{activeScene}}</h1>
    <div style="height: 60px;">
      {{msg}}
    </div>
    <div slot="extension">
        <z-spot
          v-for="(el, index) in elements"
          button
          size="s"
          :distance="120"
          :angle="325 + (90 / elements.length * index)"
          :style="activeScene === el.scene ? styleActive : ''"
          :key="index"
          @click.native="showMe(el)">
          <i class="fas" :class="el.icon"></i>
        </z-spot>
    </div>
  </z-view>
</template>
<script>
export default {
  data () {
    return {
      activeScene: 'Night',
      color: 'blue',
      msg: '',
      progress: 0,
      elements: [
        {scene: 'Day', color: 'orange', icon: 'fa-sun', msg: 'Cooling rooms, blinds opened, playing ambient music'},
        {scene: 'Night', color: 'blue', icon: 'fa-moon', msg: 'Blinds closed, AC in silence mode, motion sensors active'},
        {scene: 'Away', color: 'red', icon: 'fa-shield-alt', msg: 'Alarm armed, cameras activated, blinds closed'},
        {scene: 'At home', color: 'green', icon: 'fa-home', msg: 'Lights in ambient mode, playing relax music, coffee is being prepared'}
      ]
    }
  },
  computed: {
    styleActive () {
      return {
        borderWidth: '8px',
        borderColor: this.color,
        color: this.color
      }
    }
  },
  methods: {
    showMe (el) {
      if (this.activeScene !== el.scene) {
        this.progress = 5
        this.activeScene = el.scene
        this.color = el.color
        this.msg = 'Activating devices...'
        var vm = this
        var id = setInterval(function () {
          if (vm.progress >= 100) {
            clearInterval(id)
            vm.progress = 0
            vm.msg = el.msg
          } else if (vm.progress === 40) {
            vm.msg = 'Applying rules...'
            vm.progress++
          } else {
            vm.progress++
          }
        }, 20)
      } else {
        this.msg = 'This scene is already activated'
      }
    }
  }
}
</script>

What the code does

Don't panic! Most of the code is similar to settings view. But here we interact with a circular slider that is activated whenever the scene mode is changed to simulate the time required to activate it.

Also, we are going to dynamically compute the angles of each z-spot with a usefull trick.

z-view

In z-view we'll use two new properties that work together: slider and progress.

slider is a circular bar that runs over the perimeter of z-view according the value (0-100) of progress.

In this example, the shoMe() method modifies the progress property value using a js setInterval

z-spot

As we did on previous views, we are using z-spot with v-for to iterate over our scenes. We set the z-spots as buttons and define its proparties.

The angle approach

Previously, in the settings view we added a field anglein the array elements, but in real life maybe we can't do that with an existing collection. To solve that we have to tell angle that compute the correct angle for each z-spot depending on the length of scenes, and other parameters.


 


<!-- ... -->
  :angle="325 + (90 / elements.length * index)"
<!-- ... -->
  • '325' is the offset angle. It is the initial angle where each angle is calculated. In this case 325.

  • '90' indicates the degree range to distribute the angles. In other words, we want all elements distributed along 90 degress.

  • 'elements.length' counts all scenes we have, that are multiplied by the current index. That is a very granular formule to defines the angles for our z-spots. Depending on your needs, you can simplify it. For instance, if you want to uniformely distribute a bunch of z-spots around the parent element simply do this: :angle="(360 / elements.length * index)". You can define another angle (180, 270, etc). It's up to you.

showMe() method

Finally, we have a method called bashowMe(). This method is activated when a z-spot is clicked and runs a timer to increment the progress property. When progress has reached 40 we simulate that some rules are applied.

See