index.vue 4.49 KB
<script lang="ts" setup>
  import { ComponentPropsConfigType, DataFetchUpdateFn } from '/@/views/visual/packages/index.type';
  import { option } from './config';
  import { useDataFetch } from '/@/views/visual/packages/hook/useSocket';
  import { computed } from 'vue';
  import { ref } from 'vue';
  import { unref } from 'vue';
  import { DeviceName } from '/@/views/visual/commonComponents/DeviceName';

  const props = defineProps<{
    config: ComponentPropsConfigType<typeof option>;
  }>();

  const currentValue = ref(25);

  const getDesign = computed(() => {
    const { option, persetOption } = props.config;
    const { componentInfo } = option;
    const { flowmeterConfig, unit, fontColor } = componentInfo || {};
    const { backgroundColor, waveFirst, waveSecond, waveThird } = flowmeterConfig || {};
    const {
      flowmeterConfig: presetFlowmeterConfig,
      unit: persetUnit,
      fontColor: presetFontColor,
    } = persetOption || {};
    const {
      backgroundColor: presetBackgroundColor,
      waveFirst: presetWaveFirst,
      waveSecond: presetWaveSecond,
      waveThird: presetWaveThird,
    } = presetFlowmeterConfig || {};
    return {
      backgroundColor: backgroundColor ?? presetBackgroundColor,
      waveFirst: waveFirst ?? presetWaveFirst,
      waveSecond: waveSecond ?? presetWaveSecond,
      waveThird: waveThird ?? presetWaveThird,
      unit: unit ?? persetUnit,
      fontColor: fontColor ?? presetFontColor,
    };
  });

  const getWaveHeight = computed(() => {
    const value = unref(currentValue);
    return value <= 0 ? 0 : -value - 15;
  });

  const getHeight = computed(() => {
    const value = unref(currentValue);
    return value >= 100 ? 0 : 100 - value + 10;
  });

  const updateFn: DataFetchUpdateFn = (message, attribute) => {
    const { data = {} } = message;
    const [latest] = data[attribute] || [];
    const [_, value] = latest;
    currentValue.value = Number(value);
  };

  useDataFetch(props, updateFn);
</script>

<template>
  <main class="w-full h-full flex flex-col justify-center items-center relative">
    <DeviceName :config="config" />
    <svg
      class="waves-rect"
      viewBox="0 0 100 100"
      preserveAspectRatio="none"
      xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
    >
      <defs>
        <path
          id="wave"
          d="M-160 118c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v100h-352z"
        />
      </defs>
      <rect
        class="bgColor"
        x="0"
        y="0"
        width="100"
        height="100"
        :fill="getDesign.backgroundColor"
      />
      <g class="height" :transform="`translate(0 ${getWaveHeight})`">
        <use class="wave waveFirst" xlink:href="#wave" :fill="getDesign.waveFirst" x="0" y="0" />
        <use class="wave waveSecond" xlink:href="#wave" :fill="getDesign.waveSecond" x="0" y="2" />
        <use class="wave waveThird" xlink:href="#wave" :fill="getDesign.waveThird" x="0" y="4" />
      </g>
      <rect
        class="waveThird"
        :transform="`translate(0 ${getHeight})`"
        x="0"
        y="0"
        width="100"
        height="100"
        :fill="getDesign.waveThird"
      />
    </svg>
    <div
      class="absolute w-full h-full top-0 left-0 text-center text-lg flex items-center justify-center flex-col"
      :style="{ color: getDesign.fontColor }"
    >
      <div>{{ currentValue }}</div>
      <div class="ml-1">{{ getDesign.unit }}</div>
    </div>
  </main>
</template>

<style lang="less" scoped>
  .waves-rect {
    width: 90%;
    height: 90%;
  }

  @keyframes move {
    from {
      transform: translate(-90px, 0%);
    }

    to {
      transform: translate(85px, 0%);
    }
  }

  .wave {
    animation: move 3s linear infinite;
    animation-play-state: running;
  }

  .wave:nth-child(1) {
    animation-delay: -2s;
    animation-duration: 9s;
  }

  .wave:nth-child(2) {
    animation-delay: -4s;
    animation-duration: 6s;
  }

  .wave:nth-child(3) {
    animation-delay: -6s;
    animation-duration: 3s;
  }

  .waves-rect > g + rect {
    // transform: translateY(
    //   calc(calc(100 - var(--value)) * var(--full-flag) * 1% + var(--full-flag) * 15%)
    // );
    transition: transform linear 1s;
  }

  .height {
    // transform: translateY(calc(var(--value) * -1% - 10% + var(--over-min-flag) * 10%));
    transition: transform linear 1s;
  }

  .waves-rect .text {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    color: #fff;
    font-weight: 700;
  }
</style>