最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue?處理異步加載順序問(wèn)題之如何在Konva中確保文本在圖片之上顯示

 更新時(shí)間:2024年07月09日 09:34:18   作者:Dandelion  
在處理Konva中的異步加載順序問(wèn)題時(shí),確保在圖像加載完成后再添加其他元素是關(guān)鍵,通過(guò)將回調(diào)函數(shù)放在imageObj.onload中,并正確處理變量捕獲,我們可以確保文本總是繪制在圖片之上,這不僅解決了顯示順序的問(wèn)題,也為未來(lái)的調(diào)試提供了明確的方向,感興趣的朋友一起看看吧

Vue 處理異步加載順序問(wèn)題:在Konva中確保文本在Konva之上顯示

在使用Konva開發(fā)應(yīng)用時(shí),我們經(jīng)常會(huì)遇到需要將文本繪制在圖片之上的情況。一個(gè)常見的問(wèn)題是,由于圖像加載是異步的,文本有時(shí)會(huì)顯示在圖片下方。這篇博客將總結(jié)如何正確處理這種異步加載順序問(wèn)題。

我之前寫過(guò)一篇博客,主要是為了說(shuō)明如何通過(guò)父子組件來(lái)控制Konva組件間的先后繪制順序,利用了Vue的生命周期(自定義父子組件mounted執(zhí)行順序)。這種方法適用于將Konva組件分開到不同的Vue組件中,通過(guò)Vue的生命周期來(lái)確保正確的繪制順序。然而,這種方法并不適用于所有情況,比如說(shuō)必須在同一個(gè)文件中編寫,一起調(diào)用,或者都在setup語(yǔ)法糖中等情況。本文將探討在這些情況下如何確保文本在圖片之上顯示。

問(wèn)題描述

我們希望在繪制圖片后,再在圖片上方繪制文本。一個(gè)簡(jiǎn)單的代碼片段如下:

for (let i = 0; i < 4; i++) {
    const geometry = {
        x: 100 + (i % 2 === 0 ? 0 : 150),
        y: 50 + (i < 2 ? 0 : 100),
        width: 100,
        height: 100,
    };
    addWidgetImgToLayer(geometry, './img/b.png', true, group, 'click', () => {}, () => {
        addShapesToLayer(geometry, 'text', false, group, `${i + 1}`);
    });
}

初步實(shí)現(xiàn)

我們實(shí)現(xiàn)了兩個(gè)函數(shù):addWidgetImgToLayer用于加載圖片,addShapesToLayer用于添加Shapes(這里添加了Text)。

const addWidgetImgToLayer = (geometry, src, listening = false, parent, eventType, eventFunc, callback) => {
    const layer = konvaStore.layers['consoleLayer'];
    const imageObj = new Image();
    let konvaImage = null;
    imageObj.onload = () => {
        konvaImage = new Konva.Image({
            ...geometry,
            image: imageObj,
            listening: listening,
        });
        if (eventType && eventFunc) {
            konvaImage.on(eventType, eventFunc);
        }
        if (parent) {
            parent.add(konvaImage);
        } else {
            layer.add(konvaImage);
        }
        layer.batchDraw();
        if (callback) {
            callback();
        }
    };
    imageObj.src = src;
    return imageObj;
};
const addShapesToLayer = (geometry, type, listening = false, parent, text) => {
    const layer = konvaStore.layers['consoleLayer'];
    let shape = null;
    if (type === 'text') {
        shape = new Konva.Text({
            ...geometry,
            listening: listening,
            text: text,
            fontSize: 20,
            align: 'center',
            verticalAlign: 'middle',
        });
    }
    if (parent) {
        parent.add(shape);
    } else {
        layer.add(shape);
    }
    layer.batchDraw();
    return shape;
};

異步問(wèn)題

這里的關(guān)鍵在于imageObj.onload回調(diào)函數(shù)。圖片加載是異步的,代碼不會(huì)等待圖片加載完成才執(zhí)行接下來(lái)的語(yǔ)句。因此,必須確保回調(diào)函數(shù)在圖片加載完成后才執(zhí)行添加文本的操作。

嘗試1:直接回調(diào)

我們首先嘗試使用回調(diào)來(lái)確保順序執(zhí)行:

for (let i = 0; i < 4; i++) {
    const geometry = {
        x: 100 + (i % 2 === 0 ? 0 : 150),
        y: 50 + (i < 2 ? 0 : 100),
        width: 100,
        height: 100,
    };
    addWidgetImgToLayer(geometry, './img/b.png', true, group, 'click', () => {}, () => {
        addShapesToLayer(geometry, 'text', false, group, `${i + 1}`);
    });
}

然而,這種方式下,我們遇到了無(wú)法傳遞參數(shù)的問(wèn)題。在回調(diào)函數(shù)中,無(wú)法訪問(wèn)循環(huán)中的變量geometrygroup。

嘗試2:在函數(shù)中寫回調(diào)

我們嘗試在addWidgetImgToLayer函數(shù)中編寫回調(diào),但放在了imageObj.onload之外:

const addWidgetImgToLayer = (geometry, src, listening = false, parent, eventType, eventFunc, callback) => {
    const layer = konvaStore.layers['consoleLayer'];
    const imageObj = new Image();
    let konvaImage = null;
    imageObj.onload = () => {
        konvaImage = new Konva.Image({
            ...geometry,
            image: imageObj,
            listening: listening,
        });
        if (eventType && eventFunc) {
            konvaImage.on(eventType, eventFunc);
        }
        if (parent) {
            parent.add(konvaImage);
        } else {
            layer.add(konvaImage);
        }
        layer.batchDraw();
    };
    if (callback) {
        callback();
    }
    imageObj.src = src;
    return imageObj;
};

這導(dǎo)致了文本依然在圖片下方的問(wèn)題,因?yàn)榛卣{(diào)函數(shù)立即執(zhí)行,而不是等待圖片加載完成再執(zhí)行。分析發(fā)現(xiàn),問(wèn)題依然是異步加載的問(wèn)題,即使解決了參數(shù)傳遞問(wèn)題,這種方法也不能正確得到想要的結(jié)果。

嘗試3:將回調(diào)移至imageObj.onload內(nèi)部

我們意識(shí)到了JavaScript的異步執(zhí)行機(jī)制。在函數(shù)嵌套的情況下,異步函數(shù)會(huì)在調(diào)用堆棧清空后才執(zhí)行。我們需要確?;卣{(diào)函數(shù)在圖片加載完成后才執(zhí)行。

const addWidgetImgToLayer = (geometry, src, listening = false, parent, eventType, eventFunc, callback) => {
    const layer = konvaStore.layers['consoleLayer'];
    const imageObj = new Image();
    let konvaImage = null;
    imageObj.onload = () => {
        konvaImage = new Konva.Image({
            ...geometry,
            image: imageObj,
            listening: listening,
        });
        if (eventType && eventFunc) {
            konvaImage.on(eventType, eventFunc);
        }
        if (parent) {
            parent.add(konvaImage);
        } else {
            layer.add(konvaImage);
        }
        layer.batchDraw();
        if (callback) {
            callback();
        }
    };
    imageObj.src = src;
    return imageObj;
};
// 使用 addWidgetImgToLayer 并確?;卣{(diào)在圖片加載完成后執(zhí)行
for (let i = 0; i < 4; i++) {
    const geometry = {
        x: 100 + (i % 2 === 0 ? 0 : 150),
        y: 50 + (i < 2 ? 0 : 100),
        width: 100,
        height: 100,
    };
    // 這里可以使用兩種不同的實(shí)現(xiàn)方式,現(xiàn)在是比較簡(jiǎn)潔的格式,下面會(huì)詳細(xì)說(shuō)明
    addWidgetImgToLayer(geometry, './img/b.png', true, group, 'click', () => {}, () => {
        addShapesToLayer(geometry, 'text', false, group, `${i + 1}`);
    });
}

比較兩種實(shí)現(xiàn)方式

在解決這個(gè)問(wèn)題時(shí),我們還可以采用兩種不同的實(shí)現(xiàn)方式:

方式1:使用立即執(zhí)行函數(shù)表達(dá)式(IIFE)

addWidgetImgToLayer(dispBtnGeometrys[i], './img/b.png', true, group, 'click', () => { }, (function (geo, grp, idx) {
    return function () {
        addShapesToLayer(geo, 'text', false, grp, `${idx}`);
    };
})(dispBtnGeometrys[i], group, i + 1));

這種寫法使用了一個(gè)立即執(zhí)行函數(shù)表達(dá)式(IIFE),這個(gè)函數(shù)會(huì)立即執(zhí)行并返回一個(gè)新的函數(shù)。通過(guò)這種方式,可以捕獲循環(huán)中的當(dāng)前變量狀態(tài),并在異步回調(diào)中使用。

方式2:直接傳遞回調(diào)

for (let i = 0; i < 4; i++) {
    let geometry = {
        x: 100 + (i % 2 === 0 ? 0 : 150),
        y: 50 + (i < 2 ? 0 : 100),
        width: 100,
        height: 100,
    };
    addWidgetImgToLayer(geometry, './img/b.png', true, group, 'click', () => {}, () => {
        addShapesToLayer(geometry, 'text', false, group, `${i + 1}`);
    });
}

這種寫法直接傳遞了一個(gè)回調(diào)函數(shù)給addWidgetImgToLayer。通過(guò)使用let聲明來(lái)確保每次循環(huán)迭代中創(chuàng)建一個(gè)新的塊作用域,變量捕獲是正確的。

主要區(qū)別

  • 變量捕獲

    • 第一種寫法通過(guò)IIFE來(lái)捕獲當(dāng)前循環(huán)迭代中的變量狀態(tài),確保異步回調(diào)中使用的是當(dāng)前迭代的值。
    • 第二種寫法直接傳遞回調(diào),如果使用let聲明或其他方法,能正確捕獲每次迭代中的變量狀態(tài)。
  • 代碼可讀性

    • 第一種寫法較為復(fù)雜,但能夠確保異步回調(diào)中的變量正確捕獲當(dāng)前狀態(tài)。

第二種寫法更簡(jiǎn)潔,但需要確保使用let聲明或其他方法正確捕獲變量,而不能使用var(此處使用到的是循環(huán)變量i)。

在JavaScript中,var聲明的變量在函數(shù)作用域內(nèi)是共享的,這意味著在異步回調(diào)中,它們的值可能會(huì)變成最后一次迭代的值。這會(huì)導(dǎo)致我們期望的結(jié)果不正確。而let聲明的變量在每次循環(huán)迭代中都會(huì)創(chuàng)建一個(gè)新的塊作用域,從而確保異步回調(diào)中捕獲的是當(dāng)前迭代的值。

示例解釋

使用 var 聲明的問(wèn)題

for (var i = 0; i < 4; i++) {
    const geometry = {
        x: 100 + (i % 2 === 0 ? 0 : 150),
        y: 50 + (i < 2 ? 0 : 100),
        width: 100,
        height: 100,
    };
    addWidgetImgToLayer(geometry, './img/b.png', true, group, 'click', () => {}, () => {
        console.log(i);  // 可能會(huì)輸出4,而不是期望的0, 1, 2, 3,可能在其他位置被修改過(guò)了,它們指向同一個(gè)地址
        addShapesToLayer(geometry, 'text', false, group, `${i + 1}`);
    });
}

因?yàn)?code>var聲明的變量i在函數(shù)作用域內(nèi)是共享的(有點(diǎn)像Python),所以在異步回調(diào)中,i的值可能是循環(huán)結(jié)束時(shí)的值(4),而不是期望的0, 1, 2, 3。

使用 let 聲明解決問(wèn)題

for (let i = 0; i < 4; i++) {
    let geometry = {
        x: 100 + (i % 2 === 0 ? 0 : 150),
        y: 50 + (i < 2 ? 0 : 100),
        width: 100,
        height: 100,
    };
    addWidgetImgToLayer(geometry, './img/b.png', true, group, 'click', () => {}, () => {
        console.log(i);  // 輸出期望的0, 1, 2, 3,使用let聲明變量不會(huì)出現(xiàn)問(wèn)題
        addShapesToLayer(geometry, 'text', false, group, `${i + 1}`);
    });
}

let聲明的變量i在每次循環(huán)迭代中都會(huì)創(chuàng)建一個(gè)新的塊作用域,因此在異步回調(diào)中,i的值是當(dāng)前迭代的值,確保輸出的是期望的0, 1, 2, 3。

其他捕獲變量的方法

另一種確保變量捕獲正確的方法是使用立即執(zhí)行函數(shù)表達(dá)式(IIFE):

for (var i = 0; i < 4; i++) {
    (function(i) {
        let geometry = {
            x: 100 + (i % 2 === 0 ? 0 : 150),
            y: 50 + (i < 2 ? 0 : 100),
            width: 100,
            height: 100,
        };
        addWidgetImgToLayer(geometry, './img/b.png', true, group, 'click', () => {}, () => {
            console.log(i);  // 輸出期望的0, 1, 2, 3,可以理解為使用IIFE的話開辟空間事會(huì)先對(duì)使用到的數(shù)據(jù)進(jìn)行了值拷貝
            addShapesToLayer(geometry, 'text', false, group, `${i + 1}`);
        });
    })(i);
}

通過(guò)IIFE,每次循環(huán)迭代都會(huì)創(chuàng)建一個(gè)新的函數(shù)作用域,確保異步回調(diào)中的變量是當(dāng)前迭代的值。

結(jié)論

在第二種寫法中,通過(guò)使用let聲明或IIFE,確保異步回調(diào)函數(shù)中捕獲的變量值是當(dāng)前迭代的值,而不是循環(huán)結(jié)束后的值。這是確保變量正確捕獲和代碼正確執(zhí)行的關(guān)鍵。

總結(jié)

在處理Konva中的異步加載順序問(wèn)題時(shí),確保在圖像加載完成后再添加其他元素是關(guān)鍵。通過(guò)將回調(diào)函數(shù)放在imageObj.onload中,并正確處理變量捕獲,我們可以確保文本總是繪制在圖片之上。這不僅解決了顯示順序的問(wèn)題,也為未來(lái)的調(diào)試提供了明確的方向。

到此這篇關(guān)于Vue 處理異步加載順序問(wèn)題之如何在Konva中確保文本在圖片之上顯示的文章就介紹到這了,更多相關(guān)Vue 異步加載順序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue實(shí)現(xiàn)天氣預(yù)報(bào)功能

    Vue實(shí)現(xiàn)天氣預(yù)報(bào)功能

    這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)天氣預(yù)報(bào)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • vue2從數(shù)據(jù)變化到視圖變化之diff算法圖文詳解

    vue2從數(shù)據(jù)變化到視圖變化之diff算法圖文詳解

    這篇文章主要介紹了vue2從數(shù)據(jù)變化到視圖變化之diff算法圖文詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 通過(guò)vue如何設(shè)置header

    通過(guò)vue如何設(shè)置header

    這篇文章主要介紹了通過(guò)vue如何設(shè)置header,每個(gè)項(xiàng)目都有頭部但是內(nèi)容不一樣;這種情況我們可以考慮在app.vue中創(chuàng)建公共頭部,那么怎么配置公共頭部header,下面小編通過(guò)實(shí)例代碼詳細(xì)講解,需要的朋友可以參考下
    2023-02-02
  • vue調(diào)試工具vue-devtools安裝及使用方法

    vue調(diào)試工具vue-devtools安裝及使用方法

    本文主要介紹 vue的調(diào)試工具 vue-devtools 的安裝和使用,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-11-11
  • vue項(xiàng)目中vue-i18n和element-ui國(guó)際化開發(fā)實(shí)現(xiàn)過(guò)程

    vue項(xiàng)目中vue-i18n和element-ui國(guó)際化開發(fā)實(shí)現(xiàn)過(guò)程

    這篇文章主要介紹了vue項(xiàng)目中vue-i18n和element-ui國(guó)際化開發(fā)實(shí)現(xiàn)過(guò)程,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2018-04-04
  • 詳解vue如何給特殊字段設(shè)置插槽

    詳解vue如何給特殊字段設(shè)置插槽

    這篇文章主要為大家詳細(xì)介紹了vue如何實(shí)現(xiàn)給特殊字段設(shè)置插槽,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以學(xué)習(xí)一下
    2023-09-09
  • 基于 Vue 3 + Element Plus自定義時(shí)間范圍選擇組件使用教程

    基于 Vue 3 + Element Plus自定義時(shí)間范圍選擇組件使

    本文介紹了一個(gè)基于Vue 3和Element Plus的自定義時(shí)間范圍選擇組件,該組件提供雙向綁定的開始時(shí)間和結(jié)束時(shí)間選擇,支持常用快捷選項(xiàng),對(duì)vue elementplus時(shí)間范圍選擇組件相關(guān)知識(shí)感興趣的朋友一起看看吧
    2025-07-07
  • vue中實(shí)現(xiàn)頁(yè)面刷新以及局部刷新的方法

    vue中實(shí)現(xiàn)頁(yè)面刷新以及局部刷新的方法

    這篇文章主要給大家介紹了關(guān)于vue中實(shí)現(xiàn)頁(yè)面刷新以及局部刷新的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-01-01
  • vue自定義穿梭框支持遠(yuǎn)程滾動(dòng)加載的實(shí)現(xiàn)方法

    vue自定義穿梭框支持遠(yuǎn)程滾動(dòng)加載的實(shí)現(xiàn)方法

    這篇文章主要介紹了vue自定義穿梭框支持遠(yuǎn)程滾動(dòng)加載,iview是全局注入,基本使用原先的類名進(jìn)行二次創(chuàng)建公共組件,修改基礎(chǔ)js實(shí)現(xiàn)邏輯,本文結(jié)合實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • laravel-admin 與 vue 結(jié)合使用實(shí)例代碼詳解

    laravel-admin 與 vue 結(jié)合使用實(shí)例代碼詳解

    由于 Laravel-admin 采用的是 pjax 的方式刷新頁(yè)面,意味著很多頁(yè)面刷新的操作,這篇文章主要介紹了laravel-admin 與 vue 結(jié)合使用,需要的朋友可以參考下
    2019-06-06

最新評(píng)論

南江县| 木兰县| 山东| 泸西县| 盐源县| 滦南县| 天长市| 郸城县| 拉萨市| 瓮安县| 科尔| 昌江| 孟村| 黎平县| 壶关县| 象山县| 马山县| 汕头市| 丘北县| 东丽区| 迭部县| 南江县| 莲花县| 托克托县| 滕州市| 乐清市| 荔波县| 荣成市| 通许县| 辰溪县| 偏关县| 东莞市| 崇礼县| 汉川市| 台东县| 阆中市| 苏尼特左旗| 金昌市| 林州市| 南郑县| 博爱县|