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

vue3實(shí)現(xiàn)模擬地圖站點(diǎn)名稱按需顯示的功能(車輛模擬地圖)

 更新時(shí)間:2024年06月22日 09:43:32   作者:鄒瓊俊  
最近在做車輛模擬地圖,在實(shí)現(xiàn)控制站點(diǎn)名稱按需顯示,下面通過本文給大家分享vue3實(shí)現(xiàn)模擬地圖站點(diǎn)名稱按需顯示的功能,感興趣的朋友跟隨小編一起看看吧

很久很久沒有更新博客了,因?yàn)閷?shí)在是太忙了,每天都有公司的事情忙不完.......

最近在做車輛模擬地圖,在實(shí)現(xiàn)控制站點(diǎn)名稱按需顯示時(shí),折騰了好一段時(shí)間,特此記錄一下。最終界面如下圖所示:

站點(diǎn)顯示需求:首末站必須顯示,從第一個(gè)站開始,如果站點(diǎn)名稱能顯示下,則顯示,如果站點(diǎn)名稱會重疊則隱藏,以此類推。當(dāng)界面寬度變化時(shí),車輛模擬地圖自動變化,保證站點(diǎn)名稱能夠最大限度的顯示。

最開始我用的比例換算法,算法復(fù)雜度是O,結(jié)果總是不準(zhǔn)。盡管一開始我就覺得算法的復(fù)雜度應(yīng)該是O2。我之前卻一直想著只遍歷一次就算出來,我也嘗試過把需求描述得很詳細(xì)去問chatgpt,可是它就像個(gè)傻子一樣輸出各種算法錯(cuò)誤代碼。

需要注意的地方:由于站點(diǎn)的名稱內(nèi)容是千奇百怪的,可以有空格,各種特殊圖標(biāo),所以站點(diǎn)文字的長度計(jì)算是一個(gè)問題,這里是通過canvas來計(jì)算的。還有,這里我添加了一個(gè)限制,站點(diǎn)文字內(nèi)容我最大顯示120px,超出隱藏并顯示省略號,站點(diǎn)名稱上添加了title顯示全稱。

/**
 * 獲取站點(diǎn)名稱
 * @param item 
 * @param showFullName 是否總是顯示站點(diǎn)全名
 */
/** */
export const getSiteName = (item: any,showFullName?:boolean=false) => {
  const { siteSign } = simulatedMapConf.value;
  let name = '';
  if (siteSign == 'firstWord') {
    name = getSubStrByPreNum(item.stationName);
  } else if (siteSign == 'order') {
    name = item.stationSeq + '';
  } else {
    name=showFullName?item.stationName:(item.show? item.stationName:''); //show控制站點(diǎn)名稱是否顯示
  }
  return name || '';
}
/**
 * 獲取站點(diǎn)名稱寬度
 * @param item 站點(diǎn)對象
 * @param showFullName 是否總是顯示站點(diǎn)全名
 * @returns 
 */
export const getSiteNameWidth = (item: any,showFullName?:boolean=false) => {
  const name =showFullName?item.stationName: getSiteName(item,showFullName);
  const width= calculateStringWidth(name);
  return width>siteMaxWidth?siteMaxWidth:width;
}
/**
 * 根據(jù)字符串計(jì)算出界面渲染的寬度
 * @param str 
 * @returns 
 */
function calculateStringWidth(str:string) {
  // 創(chuàng)建一個(gè)虛擬的 <canvas> 元素
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  // 設(shè)置字體樣式
  ctx.font = '12px sans-serif';
  // 使用 canvas 的 measureText 方法測量字符串的寬度
  const width = ctx.measureText(str).width;
  // 返回計(jì)算出的寬度
  return width;
}

最核心的算法:

//計(jì)算上行站點(diǎn),控制站點(diǎn)是否顯示在模擬地圖上
    function calcSite(station: any, lineWidth: number) {
        if (station.length < 1) return [];
        station.forEach((f: any, index) => {
            f.show=false;
        });
        const lastSiteLength = getSiteNameWidth(station[station.length - 1], true) / 2;//站點(diǎn)文字寬度
        let lastLeft = getSiteCx(station[station.length - 1], station.length - 1);//最后一個(gè)站點(diǎn)left
        lastLeft = toDecimal(lastLeft - lastSiteLength);
        station.forEach((f: any, index) => {
            let siteLength = getSiteNameWidth(f, true);//站點(diǎn)文字寬度
            let bigHalf = siteLength / 2;//獲取當(dāng)前的半寬
            f.left = getSiteCx(f, index); 
            if (index == 0 || index == station.length - 1) { //第一項(xiàng)和最后一項(xiàng)必須顯示
                f.show = true;
            } else {
                const preShowIndex = getLastTrueIndex(station); //獲取前面最近一個(gè)顯示站點(diǎn)的索引
                const preEndLeft = toDecimal(station[preShowIndex].left + getSiteNameWidth(station[preShowIndex], true) / 2);//上一項(xiàng)顯示的站點(diǎn)名稱結(jié)束left位置
                f.show = toDecimal(f.left - bigHalf) >=preEndLeft && preEndLeft < lastLeft; //如果上一個(gè)顯示站點(diǎn)文字的結(jié)尾位置 小于等于 當(dāng)前站點(diǎn)文字的開始位置  并且小于最后一個(gè)站點(diǎn)文字的開始位置
if (f.show && toDecimal(f.left + bigHalf) > lastLeft) {
                    f.show = false;
                }
            }
        })
    }

獲取前面最近一個(gè)顯示站點(diǎn)的索引:

//獲取list集合中最后一項(xiàng)show的index位置
    function getLastTrueIndex(dataList: any) {
        // 從數(shù)組末尾第2項(xiàng)開始向前遍歷
        for (let i = dataList.length - 2; i >= 0; i--) {
            if (dataList[i].show === true) {
                return i;  // 返回第一個(gè)找到的最后一個(gè)為true的索引
            }
        }
        return -1;  // 如果未找到符合條件的對象,返回-1
    }

下行站點(diǎn)的計(jì)算有些差別,因?yàn)橄滦姓军c(diǎn)是從右至左,所以left基本上是反著的:

//計(jì)算下行站點(diǎn),控制站點(diǎn)是否顯示在模擬地圖上 getDownSiteCx
    function calcDownSite(station: any, lineWidth: number) {
        if (station.length < 1) return [];
        station.forEach((f: any, index) => {
            f.show=false;
        });
        const lastSiteLength = getSiteNameWidth(station[station.length - 1], true) / 2;//站點(diǎn)文字寬度
        let lastLeft = getDownSiteCx(station[station.length - 1], station.length - 1);//最后一個(gè)站點(diǎn)left
        lastLeft = toDecimal(lastLeft + lastSiteLength);
        station.forEach((f: any, index) => {
            let siteLength = getSiteNameWidth(f, true);//站點(diǎn)文字寬度
            let bigHalf = siteLength / 2;//獲取當(dāng)前的半寬
            f.left = getDownSiteCx(f, index); 
            if (index == 0 || index == station.length - 1) { //第一項(xiàng)和最后一項(xiàng)必須顯示
                f.show = true;
            } else {
                const preShowIndex = getLastTrueIndex(station); //獲取前面最近一個(gè)顯示站點(diǎn)的索引
                const preEndLeft = toDecimal(station[preShowIndex].left - getSiteNameWidth(station[preShowIndex], true) / 2);//上一項(xiàng)顯示站的的結(jié)束left位置
                f.show = toDecimal(f.left + bigHalf) <=preEndLeft && preEndLeft > lastLeft;
                if (f.show && toDecimal(f.left - bigHalf) < lastLeft) {
                    f.show = false;
                }
            }
        })
    }

另外獲取站點(diǎn)中心點(diǎn)位置的方法

//獲取上行站點(diǎn)水平x位置
    const getSiteCx = (item: any, index: number) => {
        return startleft.value + dLayout.lineWidth * index;
    }
    //獲取下行站點(diǎn)水平x位置
    const getDownSiteCx = (item: any, index: number) => {
        return downStartleft.value - layout.endLine - dLayout.downLineWidth * index;
    }

說明:站點(diǎn)的布局采用css絕對定位。第一個(gè)版本這塊我是采用的svg畫的,后來發(fā)現(xiàn)擴(kuò)展起來越來越麻煩,周末就在家花了半天時(shí)間全部改造為html實(shí)現(xiàn)了。

我最開始的有問題代碼是上下行站點(diǎn)共用的,最大的問題是會出現(xiàn)跳站點(diǎn)顯示的情況,代碼如下的:

//計(jì)算站點(diǎn),控制站點(diǎn)是否顯示在模擬地圖上
    function calcSite(station: any, lineWidth: number) {
        let availableWidth = (station.length - 1) * lineWidth; //總長度
        //記錄顯示站點(diǎn)的長度
        let totalLength = 0;
        station.forEach((f: any, index) => {
            let siteLength = getSiteNameWidth(f, true);
            let bigHalf =siteLength / 2;//獲取比較大的半寬
            let bigHalfPre = 0;
            //計(jì)算上一項(xiàng)的文字半寬
            if (index >= 1) {
                let siteLengthPre = getSiteNameWidth(station[index - 1], true);
                bigHalfPre =siteLengthPre / 2;
            }
            f.left = toDecimal(lineWidth * index);
            f.show =index==0?true: f.left >=toDecimal(totalLength);
            if(index >= 1&&station[index-1].show&&bigHalf+bigHalfPre>lineWidth){
                f.show=false;
            }
            if (f.show) {
                let times = getDivisor(siteLength, lineWidth);
                totalLength += times * lineWidth;
            }
        })
    }
/**
 * 兩個(gè)數(shù)相除有余數(shù)時(shí)結(jié)果加1
 * @param all 被除數(shù) 站點(diǎn)寬度
 * @param num 除數(shù)  線寬
 * @returns 
 */
export const getDivisor=( all:number,item:number)=>{
    if(all<=item) return 1;
    let diff:number=0;
    if(item<=20){
        diff=2.5;
    }
    if(item<=30){
        diff=2;
    }
    else if(item<=40){
        diff=1.5;
    }
    else if(item<=46){
        diff=1.05;
    }
    else if(item<=50){
        diff=1;
    }
    return all%item==0?(all/item):(Math.ceil(all/item)+diff);
}

到此這篇關(guān)于vue3實(shí)現(xiàn)模擬地圖上,站點(diǎn)名稱按需顯示的功能的文章就介紹到這了,更多相關(guān)vue3站點(diǎn)名稱按需顯示內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue實(shí)現(xiàn)父子組件的事件傳遞的示例代碼

    Vue實(shí)現(xiàn)父子組件的事件傳遞的示例代碼

    在Vue.js這個(gè)現(xiàn)代化的前端框架中,組件化是其核心理念之一,正確的組件間通信是實(shí)現(xiàn)高效和可維護(hù)代碼的關(guān)鍵,在許多應(yīng)用程序中,父子組件之間的事件傳遞是一個(gè)常見的需求,,本文將深入探討在Vue中如何實(shí)現(xiàn)父子組件的事件傳遞,并輔以示例代碼來展示這些概念
    2025-01-01
  • Vue面試中observable原理詳解

    Vue面試中observable原理詳解

    這篇文章主要為大家介紹了vue面試observable原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Vue項(xiàng)目報(bào)錯(cuò):parseComponent問題及解決

    Vue項(xiàng)目報(bào)錯(cuò):parseComponent問題及解決

    這篇文章主要介紹了Vue項(xiàng)目報(bào)錯(cuò):parseComponent問題及解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • vue?axios?form-data格式傳輸數(shù)據(jù)和文件方式

    vue?axios?form-data格式傳輸數(shù)據(jù)和文件方式

    這篇文章主要介紹了vue?axios?form-data格式傳輸數(shù)據(jù)和文件方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • vue3的setup語法糖簡單封裝ckediter的過程

    vue3的setup語法糖簡單封裝ckediter的過程

    Vue3官方提供了 script setup 語法糖,只需在script標(biāo)簽中添加setup,組件只需引入不用注冊,屬性和方法也不用返回,今天通過本文給大家分享vue3的setup語法糖簡單封裝ckediter的過程,感興趣的朋友一起看看吧
    2023-10-10
  • axios取消請求與避免重復(fù)請求

    axios取消請求與避免重復(fù)請求

    在項(xiàng)目中經(jīng)常有一些場景會連續(xù)發(fā)送多個(gè)請求,而異步會導(dǎo)致最后得到的結(jié)果不是我們想要的,并且對性能也有非常大的影響,這篇文章主要給大家介紹了關(guān)于axios取消請求與避免重復(fù)請求的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • Vue無法對iframe進(jìn)行緩存的解決方案

    Vue無法對iframe進(jìn)行緩存的解決方案

    項(xiàng)目采用的若依框架,但系統(tǒng)中會嵌入大屏、報(bào)表頁面,是使用iframe來實(shí)現(xiàn)的,若依框架的菜單管理中提供了緩存功能,是使用keep-alive實(shí)現(xiàn)的,但對于iframe頁面并不生效,所以本文介紹了關(guān)于Vue無法對iframe進(jìn)行緩存的解決方案記錄,需要的朋友可以參考下
    2024-12-12
  • vue中下載文件的方法示例詳解

    vue中下載文件的方法示例詳解

    這篇文章主要介紹了vue中下載文件的方法,通過實(shí)例代碼講解了下載后端返回文件和下載本地文件,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • vue使用動畫實(shí)現(xiàn)滾動表格效果

    vue使用動畫實(shí)現(xiàn)滾動表格效果

    這篇文章主要為大家詳細(xì)介紹了vue使用動畫實(shí)現(xiàn)滾動表格效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • vue watch如何深度監(jiān)聽數(shù)組每一項(xiàng)的變化

    vue watch如何深度監(jiān)聽數(shù)組每一項(xiàng)的變化

    這篇文章主要介紹了vue watch如何深度監(jiān)聽數(shù)組每一項(xiàng)的變化問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07

最新評論

寿阳县| 枣强县| 凤城市| 屏南县| 玉环县| 寿阳县| 鲁甸县| 满城县| 包头市| 寿宁县| 准格尔旗| 中宁县| 贺州市| 云梦县| 东乡县| 会泽县| 绵阳市| 浦城县| 新闻| 绥棱县| 沙雅县| 麦盖提县| 伊川县| 宁远县| 大足县| 萨嘎县| 贺州市| 苏尼特左旗| 赤壁市| 商都县| 白水县| 谢通门县| 宁化县| 东源县| 甘南县| 巴马| 南部县| 新郑市| 房产| 朝阳市| 上虞市|