admin管理员组

文章数量:1394161

I have built an application with different widgets you can drop into a dashboard. Each widget contains a ponent that a user would like to see (kind of like grafana if you've ever seen it).

Question: When the user drags the grid-item to increase or decrease the size, how do you update the html inside of my ponent to adjust to the size of the new item?

What I've tried:

  • attempted to wrap the p tags in an SVG and use viewport.
  • attempted to change my size to VW to dynamically scale by the viewport but the viewport is not of the ponent but of the entire spa.
  • I attempted to get the parent size using this.$parent and did some math to get the text size and dynamically assign it to a ponent but this was very messy. Also, the sizes displayed were not right.

Below is my code for my grid using the vue-grid-layout package

<grid-layout
  ref="widgetGrid"
  :layout.sync="widgets"
  :col-num="12"
  :row-height="verticalSize"
  :is-draggable="editable"
  :is-resizable="editable"
  :is-mirrored="false"
  :responsive="true"
  :autoSize="editable"
  :prevent-collision="false"
  :vertical-pact="false"
  :margin="[10, 10]"
  :use-css-transforms="true"
  @layout-updated="layoutUpdatedEvent"
>
  <grid-item
    :ref="`widget_${widget.i}`"
    v-for="widget in widgets"
    :key="widget.i"
    :x="widget.x"
    :y="widget.y"
    :w="widget.w"
    :h="widget.h"
    :i="widget.i"
    :static="!editable"
  >
    <template>
      <ponent
        :is="widget.WidgetType"
        :setup="false"
        :widgetConfig="widget.WidgetConfig"
      ></ponent>
    </template>
  </grid-item>
</grid-layout>

My ponent that I'm trying to resize the text for is below. It's a vue file and I've included styling.

<template>
  <div>
    <div id="clock">
      <p class="date">{{ date }}</p>
      <p class="time">{{ time }}</p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      time: '',
      date: '',
      week: ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'],
      ticker: null
    };
  },
  created() {
    this.ticker = setInterval(this.updateTime, 1000);
  },
  mounted() {
    this.showDate =
      this.widgetConfig?.Settings?.find((x) => x.Key === 'ShowDate').Value ||
      false;
    this.showTime =
      this.widgetConfig?.Settings?.find((x) => x.Key === 'ShowTime').Value ||
      false;
  },
  methods: {
    updateTime() {
      let cd = new Date();
      this.time =
        this.zeroPadding(cd.getHours(), 2) +
        ':' +
        this.zeroPadding(cd.getMinutes(), 2) +
        ':' +
        this.zeroPadding(cd.getSeconds(), 2);

      this.date =
        this.zeroPadding(cd.getFullYear(), 4) +
        '-' +
        this.zeroPadding(cd.getMonth() + 1, 2) +
        '-' +
        this.zeroPadding(cd.getDate(), 2) +
        ' ' +
        this.week[cd.getDay()];
    },
    zeroPadding(num, digit) {
      let zero = '';
      for (let i = 0; i < digit; i++) {
        zero += '0';
      }
      return (zero + num).slice(-digit);
    }
  },
};
</script>

<style lang="scss" scoped>
html,
body {
  height: 100%;
}
body {
  background: #0f3854!important;
  background: radial-gradient(ellipse at center, #0a2e38 0%, #000000 70%)!important;
  background-size: 100%;
}
p {
  margin: 0;
  padding: 0;
}
#clock {
  font-family: 'Share Tech Mono', monospace;
  color: #ffffff;
  text-align: center;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  color: #daf6ff;
  text-shadow: 0 0 20px rgba(10, 175, 230, 1), 0 0 20px rgba(10, 175, 230, 0);
  .time {
    letter-spacing: 0.05em;
    font-size: 1vw;
    padding: 5px 0;
  }
  .date {
    letter-spacing: 0.1em;
    font-size: 1vw;
  }
  .text {
    letter-spacing: 0.1em;
    font-size: 1vw;
    padding: 20px 0 0;
  }
}
</style>

Nuxt Config

module.exports = {
  head: {
    titleTemplate: '',
    title: 'QVue',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'QVue Web UI' },
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
  },
  css: [],
  plugins: [
    { src: '@/plugins/vueGrid', ssr: false }
  ],
  publicRuntimeConfig: {},
  privateRuntimeConfig: {},
  ponents: true,
  buildModules: [
    '@nuxtjs/vuetify'
  ],
  modules: [
    '@nuxtjs/axios'
  ],
  axios: {
  },
  build: {
  },
  render: {
    pressor: false,
  },
  srcDir: 'client/',
};

I have built an application with different widgets you can drop into a dashboard. Each widget contains a ponent that a user would like to see (kind of like grafana if you've ever seen it).

Question: When the user drags the grid-item to increase or decrease the size, how do you update the html inside of my ponent to adjust to the size of the new item?

What I've tried:

  • attempted to wrap the p tags in an SVG and use viewport.
  • attempted to change my size to VW to dynamically scale by the viewport but the viewport is not of the ponent but of the entire spa.
  • I attempted to get the parent size using this.$parent and did some math to get the text size and dynamically assign it to a ponent but this was very messy. Also, the sizes displayed were not right.

Below is my code for my grid using the vue-grid-layout package

<grid-layout
  ref="widgetGrid"
  :layout.sync="widgets"
  :col-num="12"
  :row-height="verticalSize"
  :is-draggable="editable"
  :is-resizable="editable"
  :is-mirrored="false"
  :responsive="true"
  :autoSize="editable"
  :prevent-collision="false"
  :vertical-pact="false"
  :margin="[10, 10]"
  :use-css-transforms="true"
  @layout-updated="layoutUpdatedEvent"
>
  <grid-item
    :ref="`widget_${widget.i}`"
    v-for="widget in widgets"
    :key="widget.i"
    :x="widget.x"
    :y="widget.y"
    :w="widget.w"
    :h="widget.h"
    :i="widget.i"
    :static="!editable"
  >
    <template>
      <ponent
        :is="widget.WidgetType"
        :setup="false"
        :widgetConfig="widget.WidgetConfig"
      ></ponent>
    </template>
  </grid-item>
</grid-layout>

My ponent that I'm trying to resize the text for is below. It's a vue file and I've included styling.

<template>
  <div>
    <div id="clock">
      <p class="date">{{ date }}</p>
      <p class="time">{{ time }}</p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      time: '',
      date: '',
      week: ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'],
      ticker: null
    };
  },
  created() {
    this.ticker = setInterval(this.updateTime, 1000);
  },
  mounted() {
    this.showDate =
      this.widgetConfig?.Settings?.find((x) => x.Key === 'ShowDate').Value ||
      false;
    this.showTime =
      this.widgetConfig?.Settings?.find((x) => x.Key === 'ShowTime').Value ||
      false;
  },
  methods: {
    updateTime() {
      let cd = new Date();
      this.time =
        this.zeroPadding(cd.getHours(), 2) +
        ':' +
        this.zeroPadding(cd.getMinutes(), 2) +
        ':' +
        this.zeroPadding(cd.getSeconds(), 2);

      this.date =
        this.zeroPadding(cd.getFullYear(), 4) +
        '-' +
        this.zeroPadding(cd.getMonth() + 1, 2) +
        '-' +
        this.zeroPadding(cd.getDate(), 2) +
        ' ' +
        this.week[cd.getDay()];
    },
    zeroPadding(num, digit) {
      let zero = '';
      for (let i = 0; i < digit; i++) {
        zero += '0';
      }
      return (zero + num).slice(-digit);
    }
  },
};
</script>

<style lang="scss" scoped>
html,
body {
  height: 100%;
}
body {
  background: #0f3854!important;
  background: radial-gradient(ellipse at center, #0a2e38 0%, #000000 70%)!important;
  background-size: 100%;
}
p {
  margin: 0;
  padding: 0;
}
#clock {
  font-family: 'Share Tech Mono', monospace;
  color: #ffffff;
  text-align: center;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  color: #daf6ff;
  text-shadow: 0 0 20px rgba(10, 175, 230, 1), 0 0 20px rgba(10, 175, 230, 0);
  .time {
    letter-spacing: 0.05em;
    font-size: 1vw;
    padding: 5px 0;
  }
  .date {
    letter-spacing: 0.1em;
    font-size: 1vw;
  }
  .text {
    letter-spacing: 0.1em;
    font-size: 1vw;
    padding: 20px 0 0;
  }
}
</style>

Nuxt Config

module.exports = {
  head: {
    titleTemplate: '',
    title: 'QVue',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'QVue Web UI' },
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
  },
  css: [],
  plugins: [
    { src: '@/plugins/vueGrid', ssr: false }
  ],
  publicRuntimeConfig: {},
  privateRuntimeConfig: {},
  ponents: true,
  buildModules: [
    '@nuxtjs/vuetify'
  ],
  modules: [
    '@nuxtjs/axios'
  ],
  axios: {
  },
  build: {
  },
  render: {
    pressor: false,
  },
  srcDir: 'client/',
};

Share Improve this question edited Oct 13, 2020 at 15:20 Jenuel Ganawed 3847 silver badges16 bronze badges asked Oct 1, 2020 at 20:08 FunkelFunkel 1831 gold badge6 silver badges22 bronze badges 2
  • 2 Don't forget to clearTimeout in destroyed... – Michal Levý Commented Oct 7, 2020 at 12:23
  • @MichalLevý Thanks for the remendation! – Funkel Commented Oct 7, 2020 at 13:20
Add a ment  | 

1 Answer 1

Reset to default 6 +300

If you'd like to resize the text size for your clock ponent, one solution is uses svg -> viewbox the one you already mentioned. But you need to use <text> instead of <p>.

Below is the demo:

Vue.ponent('v-clock',{
    template:`
      <svg viewBox="0 0 100 100" xmlns="http://www.w3/2000/svg">
        <text x="0" y="25" fill="red">{{date}}</text>
        <text x="0" y="75" fill="red">{{time}}</text>
      </svg>
    `,
  data() {
    return {
      time: '',
      date: '',
      week: ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'],
      ticker: null
    };
  },
  created() {
    this.ticker = setInterval(this.updateTime, 1000);
  },
  mounted() {
    this.showDate =
      this.widgetConfig?.Settings?.find((x) => x.Key === 'ShowDate').Value ||
      false;
    this.showTime =
      this.widgetConfig?.Settings?.find((x) => x.Key === 'ShowTime').Value ||
      false;
  },
  methods: {
    updateTime() {
      let cd = new Date();
      this.time =
        this.zeroPadding(cd.getHours(), 2) +
        ':' +
        this.zeroPadding(cd.getMinutes(), 2) +
        ':' +
        this.zeroPadding(cd.getSeconds(), 2);

      this.date =
        this.zeroPadding(cd.getFullYear(), 4) +
        '-' +
        this.zeroPadding(cd.getMonth() + 1, 2) +
        '-' +
        this.zeroPadding(cd.getDate(), 2) +
        ' ' +
        this.week[cd.getDay()];
    },
    zeroPadding(num, digit) {
      let zero = '';
      for (let i = 0; i < digit; i++) {
        zero += '0';
      }
      return (zero + num).slice(-digit);
    }
  }
})

new Vue ({
  el:'#app',
  data () {
    return {
      size: 100
    }
  }
})
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  <input v-model.number="size" type="range" min="50" max="500"/>
  <div :style="{width: size + 'px', height: size + 'px'}" style="border: solid 1px blue">
    <v-clock></v-clock>
  </div>
</div>

本文标签: javascripthow to dynamically resize text in a vue componentStack Overflow