Browse Source

获取灾情数据

huangxingxing 1 year ago
parent
commit
b687a7d3cc
4 changed files with 672 additions and 3 deletions
  1. 48 0
      src/control/fireControl.js
  2. 51 0
      src/control/waterControl.js
  3. 8 3
      src/reader/LegacyAsciiParser.js
  4. 565 0
      src/view/case.vue

+ 48 - 0
src/control/fireControl.js

@@ -0,0 +1,48 @@
+//火灾 控制类
+import vtkUnstructuredDataReader from "../reader/UnstructuredDataReader.js";
+
+export class fireControl {
+    constructor(){
+        //事故编号
+        this.aid=5 ;
+        //当前步数
+        this.step;
+        //总步数
+        this.stepsum=10;
+        //url
+        this._url ="http://192.168.0.131:8187/TransServlet?channelNo=service&clientToken=e47b87eec69545559d1e81e56626da68&userId=5f06c8bc77234f969d13e160b54c27e3&aid=5&stype=Fire";
+        //几何数据
+        this.polydata;
+        //Scalars 数据 array[setp]=Map(scalars,value[points]=array),
+        this.scalars=new Array();
+        this.reader =vtkUnstructuredDataReader.newInstance();
+    }
+    //几何数据初始化
+   async initGemetry() {
+    await this.reader.setUrl(this._url+"&transCode=D000014" ).then(() => {
+            this.polydata= this.reader.getOutputData(0);
+        });
+    }
+    //标量数据初始化
+    async initScalrs(){
+        for (let index = 0; index <= this.stepsum; index++) {
+           await this.reader.setUrl(this._url+"&transCode=D00009&step="+ index ).then(() => {
+            const scalarMap = this.reader.getOutputData(1);
+            this.scalars.push(scalarMap);
+            });
+        }
+    }
+    //获取第几步标量数据
+    async getScalrsByStep(step){
+        this.step =step;
+        this.reader.setUrl(this._url+"&transCode=D00009&step="+ this.step ).then(() => {
+            const scalarMap = this.reader.getOutputData(1);
+            this.scalars[step]=scalarMap;
+        });
+    }
+    
+}
+
+export function createFireControl(){
+    return new fireControl();
+}

+ 51 - 0
src/control/waterControl.js

@@ -0,0 +1,51 @@
+//火灾 控制类
+import vtkUnstructuredDataReader from "../reader/UnstructuredDataReader.js";
+
+export class waterControl {
+    constructor(){
+        //事故编号
+        this.aid=5 ;
+        //当前步数
+        this.step;
+        //总步数
+        this.stepsum=10;
+        //url
+        this._url ="http://192.168.0.131:8187/TransServlet?channelNo=service&clientToken=e47b87eec69545559d1e81e56626da68&userId=5f06c8bc77234f969d13e160b54c27e3&aid=5&stype=Water";
+        //几何数据
+        this.polydata;
+        //Scalars 数据 array[setp]=Map(scalars,value[points]=array),
+        this.scalars=new Array();
+        this.reader =vtkUnstructuredDataReader.newInstance();
+    }
+    //几何数据初始化
+   async initGemetry() {
+    await this.reader.setUrl(this._url+"&transCode=D000014" ).then(() => {
+            this.polydata= this.reader.getOutputData(0);
+        });
+        console.log( this.polydata);
+    }
+    //标量数据初始化
+    async initScalrs(){
+        //火灾
+        for (let index = 0; index <= this.stepsum; index++) {
+           await this.reader.setUrl(this._url+"&transCode=D00009&step="+ index ).then(() => {
+            const scalarMap = this.reader.getOutputData(1);
+            this.scalars.push(scalarMap);
+            });
+        }
+        console.log( this.scalars);
+    }
+    //获取第几步标量数据
+    async getScalrsByStep(step){
+        this.step =step;
+        this.reader.setUrl(this._url+"&transCode=D00009&step="+ this.step ).then(() => {
+            const scalarMap = this.reader.getOutputData(1);
+            this.scalars[step]=scalarMap;
+        });
+    }
+    
+}
+
+export function createWaterControl(){
+    return new waterControl();
+}

+ 8 - 3
src/reader/LegacyAsciiParser.js

@@ -49,7 +49,7 @@ const TYPE_PARSER = {
       switch (type) {
       switch (type) {
         case 'UNSTRUCTURED_GRID':
         case 'UNSTRUCTURED_GRID':
           datamodel.dataset = vtkPolyData.newInstance();
           datamodel.dataset = vtkPolyData.newInstance();
-          datamodel.scalars=new Map();
+          // datamodel.scalars=new Map();
           break;
           break;
         default:
         default:
           console.error(`Dataset of type ${type} not supported`);
           console.error(`Dataset of type ${type} not supported`);
@@ -107,14 +107,19 @@ const TYPE_PARSER = {
       // 300.00
       // 300.00
       // 300.00
       // 300.00
       // 300.00
       // 300.00
+      if(!dataModel.scalars){
+        dataModel.scalars=new Map();
+      }
+      
       const [type, name, dataType] = line.split(' ');
       const [type, name, dataType] = line.split(' ');
       const numOfComp = 1;
       const numOfComp = 1;
-      const array = new DATATYPES[dataType](dataModel.dataset.getNumberOfPoints());
+      const array = new DATATYPES[dataType](dataModel.POINT_DATA);
       const dataArray = vtkDataArray.newInstance({
       const dataArray = vtkDataArray.newInstance({
         name:name,
         name:name,
-        size:dataModel.dataset.getNumberOfPoints()
+        size:dataModel.POINT_DATA
       });
       });
       dataModel.scalars.set(name,array);
       dataModel.scalars.set(name,array);
+      
       // dataModel.dataset.getPointData().setScalars(dataArray);
       // dataModel.dataset.getPointData().setScalars(dataArray);
       dataModel.arrayHandler = createArrayHandler(array, dataArray.setData, numOfComp);
       dataModel.arrayHandler = createArrayHandler(array, dataArray.setData, numOfComp);
       return true;
       return true;

+ 565 - 0
src/view/case.vue

@@ -0,0 +1,565 @@
+<template>
+  <div>
+    <div>
+      <!--button @click="increment">Count is: {{ count }}</button-->
+    </div>
+    <div id="vtkContainer" />
+    <div class="tool">
+      <div
+        class="img"
+        v-for="(item, index) in listArray"
+        :key="index"
+        @click="add(item.id)"
+      >
+        <el-image :src="item.img" fit="cover" /><span>{{ item.name }}</span>
+      </div>
+
+      <div class="left_container">
+        <div class="leftdialong" v-show="dialogVisible">
+          <div class="time">当前时间:{{ count }}</div>
+          <div class="block">
+            <el-form-item label="物理量">
+              <el-cascader
+                transfer="true"
+                placeholder="灾情/物理量"
+                clearable
+                :popper-append-to-body="false"
+                v-model="arrvalue"
+                :options="options"
+                @change="handleChange($event)"
+              ></el-cascader>
+            </el-form-item>
+          </div>
+          <!-- <el-form-item
+          label="动画开始"
+      
+        >
+          <el-input
+               v-model="starttime"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item>
+         <el-form-item
+          label="动画结束"
+      
+        >
+          <el-input
+                 v-model="endtime"
+            autocomplete="off"
+          ></el-input>
+        </el-form-item> -->
+          <div class="block">
+            <span class="demonstration">动画开始</span>
+            <el-slider
+              :max="endtime"
+              :min="starttime"
+              v-model="count"
+              @change="sliderchange"
+            ></el-slider>
+            <span class="demonstration">动画结束</span>
+          </div>
+
+          <div class="itemlist">
+            <div class="item" @click="play(500)">播&nbsp;&nbsp;放</div>
+            <div class="item" @click="suspend">暂&nbsp;&nbsp;停</div>
+            <div class="item" @click="Prev">上一分钟</div>
+            <div class="item" @click="increment">下一分钟</div>
+          </div>
+          <!-- <button @click="inOpacity">透明度: {{ opacity }}</button> -->
+          <div class="dialog-footer">
+            <span class="btn" @click="dialogVisible = false">关 闭</span>
+            <!-- <el-button>关 闭</el-button> -->
+            <!-- <el-button type="primary" @click="dialogVisible = false">确 定</el-button> -->
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 内容 -->
+    <!-- 内容 -->
+    <div>
+      <!-- :title1="title1" -->
+      <evolutionView ref="evolution" />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import p1 from "@/assets/img/u3479.png";
+import p2 from "@/assets/img/u10068.png";
+import p3 from "@/assets/img/12.png";
+import p4 from "@/assets/img/u3883.png";
+import p5 from "@/assets/img/u3405.png";
+import * as d3 from "d3-scale";
+import { formatDefaultLocale } from "d3-format";
+import { ref, onMounted, reactive } from "vue";
+import "@kitware/vtk.js/Rendering/Profiles/Geometry";
+import vtkRenderWindowWithControlBar from "@kitware/vtk.js/Rendering/Misc/RenderWindowWithControlBar";
+import vtkFullScreenRenderWindow from "@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow";
+
+import vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
+import vtkMapper from "@kitware/vtk.js/Rendering/Core/Mapper";
+import vtkUnstructuredDataReader from "../reader/UnstructuredDataReader.js";
+import { createFireControl } from "../control/fireControl.js";
+import vtkScalarBarActor from "@kitware/vtk.js/Rendering/Core/ScalarBarActor";
+import vtkLookupTable from "@kitware/vtk.js/Common/Core/LookupTable";
+import vtkDataArray from "@kitware/vtk.js/Common/Core/DataArray.js";
+import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
+import { I } from "@kitware/vtk.js/macros2.js";
+import { Representation } from "@kitware/vtk.js/Rendering/Core/Property/Constants";
+import evolutionView from "./evolutionView.vue";
+
+import vtkConeSource from "@kitware/vtk.js/Filters/Sources/ConeSource";
+import vtkSphereMapper from "@kitware/vtk.js/Rendering/Core/SphereMapper";
+import vtkPixelSpaceCallbackMapper from "@kitware/vtk.js/Rendering/Core/PixelSpaceCallbackMapper";
+import vtkSphereSource from "@kitware/vtk.js/Filters/Sources/SphereSource";
+
+import vtkAxesActor from "@kitware/vtk.js/Rendering/Core/AxesActor";
+import vtkCubeAxesActor from "@kitware/vtk.js/Rendering/Core/CubeAxesActor";
+import vtk2DShape from '@kitware/vtk.js/Filters/Sources/Arrow2DSource';
+import vtkTriangleFilter from '@kitware/vtk.js/Filters/General/TriangleFilter';
+
+// import {RouterView,RouterLink} from "vue-router"
+// const router=RouterView();
+
+// const props = {};
+let time = 3 * 60;
+let evolution = ref();
+let listArray = reactive([
+  { id: 0, img: p1, name: "灾情演化" },
+  { id: 1, img: p2, name: "演化过程" },
+  { id: 2, img: p3, name: "灾情历史" },
+  { id: 3, img: p4, name: "日志" },
+]);
+// let title1=ref("我是父组件")
+let dialogVisible = ref(false);
+let num = ref(4);
+let starttime = ref(1);
+let endtime = ref(60);
+let timenum = ref(2);
+let isstop = ref(false);
+let arrvalue = reactive([]);
+let options = reactive([
+  {
+    value: "fire",
+    label: "火灾",
+    children: [
+      {
+        value: "Temperature",
+        label: "温度",
+      },
+      {
+        value: "Pressure",
+        label: "压强",
+      },
+      {
+        value: "SO2",
+        label: "SO2",
+      },
+      {
+        value: "CO2",
+        label: "CO2",
+      },
+    ],
+  },
+  {
+    value: "Water",
+    label: "水灾",
+    children: [
+      {
+        value: "Height",
+        label: "水位高度",
+      },
+    ],
+  },
+]);
+function add(id) {
+  if (id == 2) {
+    dialogVisible.value = true;
+    evolution.value.isshow = false;
+  } else if (id == 1) {
+    // router.push("/myDemo");
+  } else if (id == 0) {
+    evolution.value.isshow = true;
+    evolution.value.getdata();
+    dialogVisible.value = false;
+  }
+}
+// 响应式状态
+const count = ref(0);
+const opacity = ref(0.1);
+const min = ref(0);
+const max = ref(1);
+const scalarFAll = ref([]); //火灾标量
+const scalarWAll = ref([]); //水灾标量
+/*
+Temperature:温度
+Pressure:压强
+SO2:SO2
+CO2:CO2
+Height:水位高度
+*/
+// const scalarName = ref("CO2");
+//  const filedir =ref("data/Fire/");
+//const scalarName = ref("Height");
+const filedir = ref("data/Water/");
+// const renderWindowWith = vtkRenderWindowWithControlBar.newInstance({
+//     controlSize: 11,
+//   });
+
+const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
+const renderer = fullScreenRenderer.getRenderer();
+const renderWindow = fullScreenRenderer.getRenderWindow();
+const mapper = vtkMapper.newInstance();
+const actor = vtkActor.newInstance();
+
+// actor.getProperty().setRepresentation(Representation.WIREFRAME);//线
+// actor.getProperty().setRepresentation(Representation.POINTS);//点
+actor.getProperty().setRepresentation(Representation.SURFACE); //面
+
+// 用来修改状态、触发更新的函数
+function inOpacity() {
+  opacity.value = opacity.value + 0.1;
+  actor.getProperty().setOpacity(opacity.value);
+  renderWindow.render();
+}
+function getMinMax(scalars) {
+  // console.log("getMinMax:",scalars);
+  min.value = scalars[0];
+  max.value = scalars[0];
+  for (let index = 0; index <= scalars.length; index++) {
+    let scalar = scalars[index];
+    if (min.value > scalar) {
+      min.value = scalar;
+    }
+    if (max.value < scalar) {
+      max.value = scalar;
+    }
+  }
+  // console.log("max,min:", max.value, min.value);
+}
+//时间
+function sleep(numberMillis) {
+  var now = new Date();
+  var exitTime = now.getTime() + numberMillis;
+  console.log(exitTime);
+}
+function handleChange(val) {
+  arrvalue = val;
+  min.value = 0.0;
+  max.value = 1.0;
+  changeScalar();
+}
+//暂停
+function suspend() {
+  isstop.value = false;
+  console.log(isstop.value);
+}
+//滑块
+function sliderchange(val) {
+  // console.log(val);
+  changeScalar();
+}
+
+//播放
+function play(time) {
+  isstop.value = true;
+  const sleep = (timeout = time) =>
+    new Promise((resolve, reject) => {
+      setTimeout(resolve, timeout);
+    });
+  let timer = async (timeout) => {
+    while (count.value < endtime.value && isstop.value) {
+      // if (isstop.value == true) {
+      await sleep(time);
+      changeScalar();
+      count.value++;
+      // }
+    }
+  };
+  timer(time);
+}
+//回到上一页
+function Prev() {
+  isstop.value = false;
+  count.value--;
+  changeScalar();
+}
+// 用来修改状态、触发更新的函数
+function increment() {
+  isstop.value = false;
+  if (count.value == endtime.value) {
+    return;
+  }
+  count.value++;
+  changeScalar();
+}
+function changeScalar() {
+  var scalars;
+  if (arrvalue[0] == "fire") {
+    scalars = scalarFAll.value[count.value];
+  } else {
+    scalars = scalarWAll.value[count.value];
+  }
+  const polydata = mapper.getInputData();
+  const scalarArray = scalars.get(arrvalue[1]);
+  // console.log("scalarArray:", scalarArray);
+  const dataArray = vtkDataArray.newInstance({
+    name: arrvalue[1],
+    size: polydata.getNumberOfPoints(),
+  });
+  dataArray.setData(scalarArray);
+  getMinMax(scalarArray);
+  mapper.setScalarRange(min.value, max.value); //设置范围
+  scalarBarActor.setAxisLabel(arrvalue[1]);
+  polydata.getPointData().setScalars(dataArray);
+  mapper.clearColorArrays(); //强制重建颜色
+  actor.getProperty().setOpacity(count.value); //设置错误的透明度使得页面重新加载  不设置不刷新页面
+  renderWindow.render();
+}
+//加载所有 标量数据
+function loadScalarAll() {
+  //水灾
+  // for (let index = 0; index <= 15; index++) {
+  //   const reader = vtkUnstructuredDataReader.newInstance();
+  //   const url="http://192.168.0.131:8187/TransServlet?channelNo=service&clientToken=e47b87eec69545559d1e81e56626da68&transCode=D00009&userId=5f06c8bc77234f969d13e160b54c27e3&aid=5&stype=Water&step="
+  //   reader.setUrl(url + index ).then(() => {
+  //     const scalars = reader.getOutputData(1);
+  //     scalarWAll.value[index] = scalars;
+  //   });
+  // }
+  //火灾
+  for (let index = 1; index <= 4; index++) {
+    const reader = vtkUnstructuredDataReader.newInstance();
+    const url =
+      "http://192.168.0.131:8187/TransServlet?channelNo=service&clientToken=e47b87eec69545559d1e81e56626da68&transCode=D00009&userId=5f06c8bc77234f969d13e160b54c27e3&aid=5&stype=Fire&step=";
+    reader.setUrl(url + index).then(() => {
+      console.log("url + index ", index);
+      const scalars = reader.getOutputData(1);
+      scalarFAll.value[index] = scalars;
+      console.log("url end  ");
+    });
+  }
+  console.log("scalarAll.value:", scalarFAll);
+}
+//设置
+function generateTicks(numberOfTicks) {
+  return (helper) => {
+    const lastTickBounds = helper.getLastTickBounds();
+    // compute tick marks for axes
+    const scale = d3
+      .scaleLinear()
+      .domain([0.0, 1.0])
+      .range([lastTickBounds[0], lastTickBounds[1]]);
+    const samples = scale.ticks(numberOfTicks);
+    const ticks = samples.map((tick) => scale(tick));
+    // Replace minus "\u2212" with hyphen-minus "\u002D" so that parseFloat() works
+    formatDefaultLocale({ minus: "\u002D" });
+    const format = scale.tickFormat(ticks[0], ticks[ticks.length - 1], numberOfTicks);
+    const tickStrings = ticks
+      .map(format)
+      .map((tick) => Number(parseFloat(tick).toPrecision(12)).toPrecision()); // d3 sometimes adds unwanted whitespace
+    helper.setTicks(ticks);
+    helper.setTickStrings(tickStrings);
+  };
+}
+//安装时
+onMounted(() => {
+  arrvalue = ["Water", "Height"];
+  // const sphereSource = vtkSphereSource.newInstance({
+  //   center: [495960.36, 5402540.18, -424.27],
+  //   radius: 3.02,
+  //   phiResolution: 20,
+  //   thetaResolution:20,
+  // });
+
+  // const mapper1 = vtkMapper.newInstance();
+  // mapper1.setInputConnection(sphereSource.getOutputPort());
+  // const actor1 = vtkActor.newInstance();
+  // actor1.setMapper(mapper1);
+  // actor1.getProperty().setColor([0.95, 0.45, 0.95]);
+  // renderer.addActor(actor1);
+
+// choices include triangle, star, arrow4points, arrow6points
+  const initialValues = { base:-0.1,shape: 'arrow4points',center: [495960.36, 5402540.18, -424.27],width: 20.0,height:20,direction:[0,1,1] };
+   
+  // const triangleFilter = vtkTriangleFilter.newInstance();
+  const shapeSource2 = vtk2DShape.newInstance(initialValues);
+  // triangleFilter.setInputConnection(shapeSource2.getOutputPort());
+
+  const mapper2 = vtkMapper.newInstance();
+  mapper2.setInputConnection(shapeSource2.getOutputPort());
+  const actor2 = vtkActor.newInstance();
+  actor2.setMapper(mapper2);
+  renderer.addActor(actor2);
+
+  // const cubeAxes = vtkCubeAxesActor.newInstance();
+  // cubeAxes.setCamera(renderer.getActiveCamera());
+  // cubeAxes.setDataBounds(actor1.getBounds());
+  // renderer.addActor(cubeAxes);
+
+
+  // const axesActor = vtkAxesActor.newInstance();
+  // renderer.addActor(axesActor);
+
+
+
+  renderer.resetCamera();
+  renderWindow.render();
+  fireRead();
+});
+
+function fireRead() {
+  var fcon = createFireControl();
+  fcon
+    .initGemetry()
+    .then((result) => {
+      fcon
+        .initScalrs()
+        .then((result) => {
+          const scalarArray = fcon.scalars[3].get("Pressure");
+          // console.log("scalarArray:", scalarArray);
+          const dataArray = vtkDataArray.newInstance({
+            name: arrvalue[1],
+            size: fcon.polydata.getNumberOfPoints(),
+          });
+          dataArray.setData(scalarArray);
+          fcon.polydata.getPointData().setScalars(dataArray);
+          mapper.setInputData(fcon.polydata);
+          getMinMax(scalarArray);
+          mapper.setScalarRange(min.value, max.value); //设置范围
+          actor.setMapper(mapper);
+          renderer.addActor(actor);
+
+          initScalarBar();
+          renderer.resetCamera();
+          renderWindow.render();
+        })
+        .catch((err) => {});
+    })
+    .catch((err) => {});
+}
+
+// 初始化 bar
+function initScalarBar() {
+  const scalarBarActor = vtkScalarBarActor.newInstance();
+  let lut = mapper.getLookupTable();
+  scalarBarActor.setScalarsToColors(lut);
+  // console.log("lut:", lut.getRange());
+  // Change the number of ticks (TODO: add numberOfTicks to ScalarBarActor)
+  scalarBarActor.setGenerateTicks(generateTicks(5));
+  scalarBarActor.setAxisLabel(arrvalue[1]);
+  scalarBarActor.setDrawAboveRangeSwatch(true);
+  //修改设条颜色
+  const ctf = vtkColorTransferFunction.newInstance();
+  ctf.addRGBPoint(0.0, 0.0, 0.0, 1.0);
+  ctf.addRGBPoint(1.0, 0.0, 1.0, 0.5);
+  ctf.addRGBPoint(2.0, 0.0, 1.0, 0.0);
+  ctf.addRGBPoint(3.0, 1.0, 0.5, 0.0);
+  ctf.addRGBPoint(4.0, 1.0, 0.0, 0.0);
+  mapper.setLookupTable(ctf);
+  lut = mapper.getLookupTable();
+  scalarBarActor.setScalarsToColors(lut);
+  renderer.addActor(scalarBarActor);
+}
+</script>
+
+<style>
+.controls {
+  position: absolute;
+  top: 25px;
+  left: 25px;
+  background: white;
+  padding: 12px;
+}
+.haha {
+  color: #fff;
+}
+.tool {
+  position: fixed;
+  top: 50px;
+  left: 20px;
+
+  z-index: 205;
+}
+.img {
+  width: 48px;
+  margin: -6px 0;
+  padding: 8px 10px;
+  background-color: rgba(255, 255, 255, 0.1);
+  font-size: 12px;
+  transform: scale(0.9);
+}
+.img span {
+  color: #fff;
+  display: inline-block;
+}
+.img .el-image {
+  width: 34px;
+}
+.leftdialong {
+  padding: 15px;
+  width: 300px;
+  position: relative;
+  top: -248px;
+  left: 69px;
+  border-radius: 5px;
+  box-shadow: 0px 3px 10px rgba(255, 255, 255, 0.1);
+}
+.leftdialong .el-form-item__label {
+  font-size: 12px;
+  color: #fff !important;
+  padding-left: 6px;
+}
+.time {
+  color: #fff;
+  font-size: 12px;
+  margin-bottom: 30px;
+}
+.itemlist {
+  display: flex;
+}
+.item {
+  background-color: rgba(255, 255, 255, 0.1);
+  margin: 5px;
+  padding: 5px 9px;
+  border-radius: 5px;
+  font-size: 14px;
+  transform: scale(0.8);
+  color: #fff;
+}
+.dialog-footer {
+  margin-top: 30px;
+  text-align: right;
+}
+.block {
+  display: flex;
+}
+.demonstration {
+  padding: 5px 5px 5px 0;
+  font-size: 12px;
+  color: #fff;
+  display: inline-block;
+  width: 100px;
+  height: 24px;
+  line-height: 24px;
+}
+.block .el-slider {
+  padding: 0 5px;
+}
+.cascadeer .el-cascader {
+  width: 100%;
+}
+.cascadeer .asterisk-left {
+  width: 100% !important;
+  font-size: 12px;
+}
+.btn {
+  background-color: rgba(255, 255, 255, 0.1);
+  margin: 5px;
+  padding: 5px 9px;
+  border-radius: 5px;
+  font-size: 14px;
+  transform: scale(0.8);
+  color: #fff;
+}
+</style>