【问题标题】:Get image width and height working 50% of the time in vue js获取图像宽度和高度在 vue js 中工作 50% 的时间
【发布时间】:2021-12-12 14:03:39
【问题描述】:

我在视图文件中有这个结构,在 Vue js(已编辑)中:

<template>
    <div>
        <h1>{{quiz.name}}</h1>
    </div>
    <div class="quizForm">
        <div class="quizQuestContainer">
            <div class="quizQuestions" v-for="(question, index) in quiz.questions"
            :key = index >
            <div v-if="index === questionIndex">
                <h2>{{ question.text }}</h2>
                <ol>
                    <li v-for="(response, index) in question.responses"
                        :key = index
                    >
                    <label>
                       
                        <input type="radio" 
                            :value="[response.res_value === question.solution]"
                            :name="index" 
                        > {{response.res_text}}
                    </label>
                    </li>
                </ol>
                <button v-if="questionIndex > 0" v-on:click="prev">
                    prev
                </button>
                <button v-on:click="next">
                    next
                </button>
            </div>
        </div>
        <div v-if="questionIndex === quiz.questions.length">
            <h2> Quiz finished</h2>
        </div>
    </div>
    <div class="quizImage">
            <div class="ImageArea">
                <img :src="imageCrop(quiz.iiif)">
                <br/>    
            </div>
</template>
<script>
    import sourceData from '@/data.json'

    export default {
      props:{
        id: {type: String, required: true}
      },
      data(){
        return {
            questionIndex: 0,

        }
      },

      computed:{
        quiz(){
            return sourceData.quizzes.find(quiz =>quiz.id === parseInt(this.id))
            },
        },
       methods: {
         // Go to next question
       next: function() {
         this.questionIndex++;
       },
       // Go to previous question
       prev: function() {
           this.questionIndex--;
       },

       imageCrop: function(iiif) { 
          let image = new Image();
          image.src = iiif; 
          let width =  image.width; 
          let height = image.height;
          return image.src + " this is width " + width + " and this is height " + height
       }
</script>

有时我得到正确的高度和宽度,但有时我得到 0 和 0。是否存在一些缓存问题?方法是正确的方法吗?我是 Vue 的新手,所以我不太了解它是如何工作的。

编辑:如果我使用

 image.onload = () => {
       let height = image.height;
       let width = image.width;
       return image.src + " this is width " + width + " and this is height " + height
 }

页面上没有任何内容。我试图进行这样的错误处理:

nameError: function(){
        try {
            const error = new Error();
            return error.message;
        } catch (ex) {
            return ex.message;
        }

它会在 DOM 中生成一个事件:

const 调用者 = (e) => { // 异步边缘情况 #6566:内部点击事件触发补丁,事件处理程序 // 在补丁期间附加到外部元素,并再次触发。这 // 发生是因为浏览器在事件传播之间触发微任务滴答。 // 解决方案很简单:我们在附加处理程序时保存时间戳, // 并且只有当传递给它的事件被触发时,处理程序才会触发 // 附加后。 const timeStamp = e.timeStamp || _getNow(); if (skipTimestampCheck || timeStamp >= invoker.attached - 1) { callWithAsyncErrorHandling(patchStopImmediatePropagation(e, invoker.value), instance, 5 /* NATIVE_EVENT_HANDLER */, [e]); }

数据JSON是这样的:

{
    "quizzes": [
      {
        "name": "Quiz A",
        "slug": "quiz-1",
        "image": "D000533S_AlbiniW_ST40.jpg",
        "iiif": "https://gallica.bnf.fr/iiif/ark:/12148/btv1b9042253v/f1/full/,550/0/native.jpg", 
        "id": 1,
        "description":
          "First quiz",
        "questions": [
            {
              "text": "Question 1",
              "responses": [
                {"res_text": "Wrong",
                  "res_value": "a"
                }, 
                {"res_text": "Right",
                  "res_value": "b"
                }
              ],
              "solution": "a"
            }, 
            {
              "text": "Question 2",
              "responses": [
                {"res_text": "Right",
                  "res_value": "a"
                }, 
                {"res_text": "Wrong",
                  "res_value": "b"
                }
              ],
              "solution": "b"
          }
        ]
      },

等等

【问题讨论】:

  • 我相信您需要先加载图片,然后再测量其尺寸 (image.onload = function() { get dimensions here })
  • 我以为 new Image() 已经完成了。我试试
  • new Image() 会创建一个图像对象。设置 src 然后告诉浏览器加载该图像,但这是一个异步过程。因此,当您尝试获取图像的宽度和高度时,大多数时候您不会得到您期望的结果。我认为它有时会起作用,因为浏览器已经下载并缓存了图像。

标签: javascript image webpack vuejs3 onload


【解决方案1】:

正如@theshark 在 cmets 中指出的那样,创建图像以检索其尺寸是一个异步过程。 AFAIK,您将无法在渲染中使用这种方法的结果。

目前尚不清楚您要达到什么目的,但最简单的方法是在您的 imageCrop 方法获得尺寸后将尺寸存储在组件的数据中。此方法不必在模板中调用,而是在 created 挂钩中调用。

您可以直接在模板中绑定组件的数据:

<template>
  <div>
    <div>
      <h1>{{quiz.name}}</h1>
    </div>
    <div class="myImageData">
       {{ src }} this is width {{ width }} and this is height {{ height }}
    </div>
    <div class="quizImage">
        <div class="ImageArea">
          <img :src="src">
          <br/>    
        </div>
    </div>
    <button @click="prev">⬅️</button>
    <button @click="next">➡️</button>
  </div>
</template>

<script>
import sourceData from '@/data.json'
export default {
 props:{
    id: {type: String, required: true}
  },
  data() {
    return {
      src: "",
      width: 0,
      height: 0,
      questionIndex: 0,
    }
  },
  computed:{
    quiz(){
      return sourceData.quizzes.find(quiz => quiz.id === this.questionIndex);
    },
  },
  updated() {
    this.imageCrop();
  },
  created() {
    this.questionIndex = parseInt(this.id);
    this.imageCrop();
  },
  methods: {
   next: function() {
     this.questionIndex++;
   },
   prev: function() {
     this.questionIndex--;
   },
   imageCrop: function() {
      const iiif = this.quiz.iiif;
      let image = new Image();
      image.onload = (event) => {
        this.width = event.target.width;
        this.height = event.target.height;
        this.src = event.target.src;
      }
      image.src = iiif; 
    }
  }
}
</script>

(在看到完整的代码后,我建议将逻辑拆分为更小的组件)

【讨论】:

  • 谢谢,唯一的问题是在模板中我从存储 url 的 json 调用特定数据。这实际上是一个计算函数。所以我需要在模板中传递计算,我想。 computed:{ quiz(){ return sourceData.quizzes.find(quiz =&gt;quiz.id === parseInt(this.id)) }, }, 在模板中我调用{{ imageCrop(quiz.iiif) }}
  • 您应该发布带​​有组件层次结构的完整代码示例以获得相关帮助
  • 你说得对,我用完整的代码编辑了
  • 这段代码在我看来并不完整; this.id 和 this.questionIndex 之间有什么联系?你的数据结构(data.json)是什么样的?该模板具有多个根元素等。不过,我更新了答案以匹配您的代码。
  • 已编辑,不完整之处见谅
猜你喜欢
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
相关资源
最近更新 更多