简体   繁体   English

如何修复vuejs中svg的getTotalLength()的结果时间?

[英]how to fix timing of result for getTotalLength() of svg in vuejs?

this.$refs.pathID.getTotalLength() returns 0 when it should return the length, and returns the legnth when it should return 0 . this.$refs.pathID.getTotalLength()在应该返回长度时返回0 ,在应该返回0时返回长度。

my vue component is a svg path element, there is a button to toggle the path.我的 vue 组件是一个 svg 路径元素,有一个按钮可以切换路径。 the toggle is accomplished via binding the d atttribute of the path to a property called path .切换是通过将路径的d属性绑定到名为path的属性来完成的。 there is a function that runs on mount that generates the value for the d attribute, ive set this value to a property called pathValue .有一个在mount上运行的函数,它为d属性生成值,我将此值设置为一个名为pathValue的属性。 so, if clicked == true then path = pathValue , else path = null .所以,如果clicked == true那么path = pathValue ,否则path = null this works as expected.这按预期工作。

further i watch path so that when there is a change, (onclick) then the path length should be recalculated, and its value set to a css custom variable.我进一步watch path ,以便在发生更改时(onclick),然后应重新计算路径长度,并将其值设置为 css 自定义变量。

<template>
  <main>

    <svg viewBox="0 0 415 200">
      <path ref="pathID" :d=path />
    </svg>

    <button @click="show()">nsr</button>

  </main>
</template>

<script>
  export default {
    data() {
      return {
        path: null,
        clicked: true,
        pathValue: null,
        pathLength: 0
      }
    },

    methods: {
      show() {
        if(this.clicked) {
          this.path = this.pathValue
          this.clicked = !this.clicked
        } else {
          this.path = null
          this.clicked = !this.clicked
        }
      },

      generatePath() {
        // generates a string value for the d-attribute were binding to path
        let path = "M410 100,"
        for(let i = 0; i < 5; i++) {
          path += `
          h-10, 
          q-5 -20, -10 0, 
          h-10, 
          s-5 -100, -10 -0, 
          s-5 50, -10 0, 
          h-10, 
          q-10 -20, -20 0, 
          h-5`
        }
        return path
      }
    },

    mounted() {
      this.pathValue = this.generatePath()
    },

    watch: {

      path: function() {
        // trigger computed setter here when path is changed onclick
        this.calculatePathLength = this.$refs.pathID
      },
      pathLength: function() {

        // set custom variable here
      this.$refs.pathID.style.setProperty("--path-length", this.calculatePathLength)
      console.log('value of computed property: ' + this.calculatePathLength)
      }
    },

    computed: {
      calculatePathLength: {
        get: function() {

          return this.pathLength
        },
        set: function(x) {

          this.pathLength = x.getTotalLength()
          console.log('path length is: ' + this.pathLength)
        }
      }
    }
  }
</script>

so when the button is clicked, the value of the d-attribute should be updated, the watcher should notes the change in path and the setter of the computed property calculatePathLength is called, updates the value of pathLength , then the watcher for pathLength should call the getter in setting the custom property var(--path-length) .因此,当单击按钮时,应更新d-attribute的值,观察者应注意path的变化,并调用计算属性calculatePathLength的设置器,更新pathLengthwatcher应调用设置自定义属性var(--path-length)的吸气剂。

so the expected result should be that pathLength should be logged, it is.所以预期的结果应该是应该记录 pathLength,它是。 but when it should be non-zero it is zero, and when it should be zero it is non-zero但是当它应该是非零时它是零,当它应该是零时它是非零

When you change this.path you need to give time for the svg element to redraw before the new getTotalLength() can be calculated.当您更改this.path时,您需要给 svg 元素重新绘制的时间,然后才能计算新的getTotalLength()

Vue provides the this.$nextTick() function exactly for this purpose. Vue 正是为此目的提供了this.$nextTick()函数。 To make your code above work:要使您的代码在上面工作:

watch: {
    path: function() {
        // trigger computed setter here when path is changed onclick
        this.$nextTick(()=>this.calculatePathLength = this.$refs.pathID);
    },
    ...

this question was answered on the vue forum here , the explanation is that the svg is not given enough time to update before measure the path length, and this is the purpose of the vue.$nextTick() .这个问题在这里的 vue 论坛上得到了回答,解释是在测量路径长度之前没有给 svg 足够的时间来更新,这就是vue.$nextTick()的目的。 here is the code that fixes the above situation:这是解决上述情况的代码:

    watch: {

      path() {
        this.$nextTick(() => this.pathLength = this.$refs.pathID.getTotalLength());
      }
    },

thank you @wildhart谢谢@wildhart

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM