Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quantum-kittens
GitHub Repository: quantum-kittens/platypus
Path: blob/main/frontend/vue/components/AmplitudeDisk/AmplitudeDisk.vue
3375 views
<template>
  <div
    class="amplitude-disk"
    :style="`--magnitude: ${internalAmplitude.magnitude}; --phase: ${internalAmplitude.phase}`"
    @pointerout="stopGrabbingArrow"
  >
    <div
      v-if="internalAmplitude.magnitude > 0.01"
      class="amplitude-disk__magnitude-disk"
      :class="{'amplitude-disk__magnitude-disk_amplitude-overflow': amplitudeOverflow}"
    />
    <AmplitudeArrow
      class="amplitude-disk__arrow"
      :amplitude="internalAmplitude"
      :is-interactive="isInteractive"
      @updateAmplitude="updateInternalAmplitude"
    />
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue-demi'
import { Point } from '@mathigon/euclid'
import AmplitudeArrow from './AmplitudeArrow.vue'
import { Amplitude } from './amplitude'

export default defineComponent({
  name: 'AmplitudeDisk',
  components: {
    AmplitudeArrow
  },
  props: {
    magnitude: {
      type: Number,
      required: false,
      default: 0.7071
    },
    phase: {
      type: Number,
      required: false,
      default: 30
    },
    isInteractive: {
      type: Boolean,
      required: false,
      default: false
    },
    showControls: {
      type: Boolean,
      required: false,
      default: false
    }
  },
  data () {
    return {
      isGrabbing: false,
      center: new Point(0, 0),
      internalAmplitude: { phase: 30, magnitude: 1 }
    }
  },
  computed: {
    amplitudeOverflow (): boolean {
      return this.internalAmplitude.magnitude > 1
    }
  },
  watch: {
    phase (newVal) {
      this.updateInternalAmplitude({ phase: newVal, magnitude: this.internalAmplitude.magnitude } as Amplitude)
    },
    magnitude (newVal) {
      this.updateInternalAmplitude({ phase: this.internalAmplitude.phase, magnitude: newVal } as Amplitude)
    }
  },
  mounted () {
    this.updateInternalAmplitude({ phase: this.phase, magnitude: this.magnitude } as Amplitude)
  },
  methods: {
    updateInternalAmplitude (amplitude: Amplitude) {
      this.internalAmplitude = { phase: amplitude.phase, magnitude: Math.min(amplitude.magnitude, 1.1) }
      this.$emit('updateAmplitude', this.internalAmplitude)
    }
  }
})
</script>

<style lang="scss" scoped>
@import 'carbon-components/scss/globals/scss/typography';
@import '~/../scss/variables/colors.scss';

.amplitude-disk {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background-color: $background-color-light;
  position: relative;
  margin: $spacing-05;

  &__magnitude-disk {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    transition: all 0.5s ease-in-out;
    width: calc(var(--magnitude, 1) * 100%);
    height: calc(var(--magnitude, 1) * 100%);
    border-radius: 50%;
    background-color: $background-color-quaternary;
    border: 1px solid $block-border-color;

    &_amplitude-overflow {
      background-color: $status-color-wrong;
      opacity: 0.7;
    }
  }

  &__arrow {
    position: absolute;
    left: 50%;
    top: 50%;
  }

  &__secondary {
    position: absolute;
    left: 50%;
    top: 50%;

    &__wrapper {
      position: absolute;
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      pointer-events: none;
      transform: rotate(calc(var(--phase, 30) * -1deg)) translate(calc(var(--magnitude, 1) * 50%), 0)  rotate(calc(var(--phase, 30) * 1deg));
    }
  }
}
</style>