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

你可能不知道的前端算法之文字避讓(inMap)

 更新時間:2018年01月12日 09:29:50   作者:Aresn  
這篇文章主要給大家介紹了關(guān)于前端算法之文字避讓的相關(guān)資料,對于這個知識相信很多的朋友都不知道,但看到效果會驚嘆不已,實現(xiàn)這一個效果主要利用的是inMap文字避讓功能,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。

前言

inMap 是一款基于 canvas 的大數(shù)據(jù)可視化庫,專注于大數(shù)據(jù)方向點線面的可視化效果展示。目前支持散點、圍欄、熱力、網(wǎng)格、聚合等方式;致力于讓大數(shù)據(jù)可視化變得簡單易用。

GitHub 地址:https://github.com/TalkingData/inmap(本地下載)

文檔地址:http://inmap.talkingdata.com/

在地理信息可視化中,我們經(jīng)常會遇到在地圖上標(biāo)記文字的需求,下面展示的是某流行 chart 圖表框架的效果:


要顯示的文字空間不夠時,就會造成文字重疊顯示混亂,用戶體驗很不友好。

怎么解決這個問題呢?我們采用文字避讓算法,解決這種坑爹的問題。

下面展示的是 inMap 文字避讓效果:

文字標(biāo)注算法是 GIS 中最復(fù)雜的問題之一(屬于 NP 復(fù)雜度問題,所以通常不能找到最優(yōu)解,只能找到較優(yōu)解)。

inMap 避讓算法采用的是四分位模型算法,接下來手把手教你寫避讓算法,老司機帶你裝逼帶你飛。

準(zhǔn)備數(shù)據(jù)

inMap 接收的是經(jīng)緯度數(shù)據(jù),需要把它映射到 canvas 的像素坐標(biāo),這就用到了墨卡托轉(zhuǎn)換,墨卡托算法很復(fù)雜,以后我們會有單獨的一篇文章來講講他的原理。經(jīng)過轉(zhuǎn)換,你得到的數(shù)據(jù)應(yīng)該是這樣的:

[
 {
 "name": "海門",//要顯示的文字
 "lng": 121.15,
 "lat": 31.89,
 "count": 7,
 "pixel": { //像素坐標(biāo)
  "x": 968,
  "y": 736
 }
 },
 {
 "name": "鄂爾多斯",
 "lng": 109.781327,
 "lat": 39.608266,
 "count": 5,
 "pixel": {
  "x": 659,
  "y": 478
 }
 },
...
]

好了,我們得到轉(zhuǎn)換后的像素坐標(biāo)數(shù)據(jù)(x、y),就可以做下面的事情了。

求出每段文字矩形的實際大小

measureText() 是 canvas 內(nèi)置的方法,返回字體寬度的像素單位:

let ctx = this.container.getContext('2d'); // canvas 上下文
let width= ctx.measureText(name).width;

我們通過 measureText 得到每個文字的寬度,canvas 并沒有直接獲取文字的方法,那文字的高度如何的得到呢?

我們通過反復(fù)測試發(fā)現(xiàn) canvas 的 font 等于 “13px Arial” 字體(別的字體不敢保證)的時候,文字的高度大概是 fontSize 的 1.1 倍。

所以代碼如下:

let fontSize = parseInt(ctx.font);
let height = fontSize * 1.1;

文字的寬度和高度得到后,我們就可以創(chuàng)建文字矩形的坐標(biāo)系了。

創(chuàng)建四分位模型


所謂四分位模型,每一個標(biāo)記點都有上下左右四個放文字的位子,如果左邊放不下,那就放右邊試試,還不行就放到下面試試,以此類推,原理就這么簡單,哈哈。

創(chuàng)建右側(cè)虛擬矩形坐標(biāo)描述:

右側(cè)虛擬矩形坐標(biāo)的描述把圓點也包含在內(nèi)了,是為了防止文字和圓點重疊。

在計算虛擬矩形的高度時有些坑,圓點大小不是固定的,是根據(jù)用戶動態(tài)配置的,圓點的直徑可能大于文字的高度,我們就設(shè)定虛擬矩形的高度永遠都是最大的那個,需要做一些特殊處理。

代碼如下:

_getLeftAnchor() {
  let x = this.center.x - this.radius - this.textReact.width,
    y = this.center.y - this.textReact.height / 2,
    diam = this.radius * 2,
    maxH = diam > this.textReact.height ? diam : this.textReact.height; //矩形的高度
  return {
    x,
    y,
    minX: x,
    maxX: this.center.x + this.radius,
    minY: this.center.y - maxH / 2,
    maxY: this.center.y + maxH / 2
  };
}

以此類推,描述下面、左面、上面的虛擬矩形坐標(biāo)。

判斷碰撞

判斷兩個矩形是否覆蓋相交,根據(jù)矩形的 minX,maxX,minY,maxY 判斷相交,原理比較簡單,代碼如下:

/**
 * 判斷分位是否相交
 * @param {*} target 
 */ 
isAnchorMeet(target) {
  let react = this.getCurrentRect(),
    targetReact = target.getCurrentRect();
  if ((react.minX < targetReact.maxX) && (targetReact.minX < react.maxX) &&
    (react.minY < targetReact.maxY) && (targetReact.minY < react.maxY)) {
    return true;
  }
  return false;
}

創(chuàng)建虛擬文字集合對象

let labels = pixels.map((val) => {
  let radius = val.pixel.radius + this.style.normal.borderWidth; //圓點半徑
  return new Label(val.pixel.x, val.pixel.y, radius, fontSize, byteWidth, val.name);
});

遞歸遍歷虛擬文字集合、判斷是否與其他相交,如果有相交就移動當(dāng)前文字位子,直到不相交為止。當(dāng)找不到合適位置時,就選擇隱藏當(dāng)前文字。

代碼如下:

do {
  var meet = false; //本輪是否有相交
  for (let i = 0; i < labels.length; i++) {
    let temp = labels[i];
    for (let j = 0; j < labels.length; j++) {
      if (i != j && temp.show && temp.isAnchorMeet(labels[j])) {
        temp.next();
        meet = true;
        break;
      }
    }
  }
} while (meet);

繪畫文字

labels.forEach(function (item) {
  if (item.show) { //是否顯示
    let pixel = item.getCurrentRect();
    ctx.beginPath();
    ctx.fillText(item.text, pixel.x, pixel.y);
    ctx.fill();
  }
});

文字避讓算法到目前介紹完了,對應(yīng)的 inMap 文件地址為https://github.com/TalkingData/inmap/blob/master/src/worker/helper/Label.js,接下來還會繼續(xù)給大家分享干貨。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • js頁面引導(dǎo)頁的實現(xiàn)思路總結(jié)

    js頁面引導(dǎo)頁的實現(xiàn)思路總結(jié)

    在同學(xué)們使用某些網(wǎng)站的新版本頁面的時候,經(jīng)常會出現(xiàn)一個類似于新手引導(dǎo)一樣的效果,本文主要介紹了js頁面引導(dǎo)頁的實現(xiàn)思路總結(jié),感興趣的可以了解一下
    2023-04-04
  • 詳解關(guān)于JSON.parse()和JSON.stringify()的性能小測試

    詳解關(guān)于JSON.parse()和JSON.stringify()的性能小測試

    這篇文章主要介紹了詳解關(guān)于JSON.parse()和JSON.stringify()的性能小測試,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • Javascript 鼠標(biāo)移動上去 滑塊跟隨效果代碼分享

    Javascript 鼠標(biāo)移動上去 滑塊跟隨效果代碼分享

    這篇文章主要介紹了Javascript 鼠標(biāo)移動上去 滑塊跟隨效果代碼,有需要的朋友可以參考一下
    2013-11-11
  • 談?wù)凧avaScript異步函數(shù)發(fā)展歷程

    談?wù)凧avaScript異步函數(shù)發(fā)展歷程

    對大部分JavaScript開發(fā)者而言,async函數(shù)仍是新鮮事物,其發(fā)展經(jīng)歷了漫長的旅程。本文將梳理總結(jié)JavaScript異步函數(shù)的發(fā)展歷程,并表示未來async函數(shù)將成為實現(xiàn)異步的主要方式。
    2015-09-09
  • JavaScript常用代碼書寫規(guī)范的超全面總結(jié)

    JavaScript常用代碼書寫規(guī)范的超全面總結(jié)

    這篇文章給大家全面總結(jié)了JavaScript常用代碼的書寫規(guī)范,分別利用推薦和不推薦的兩種示例代碼讓大家更能直接的了解書寫規(guī)范,其實關(guān)于javascript代碼規(guī)范我們應(yīng)該遵循古老的原則:“能做并不意味著應(yīng)該做”,好了,下面我們就來一起看看吧。
    2016-09-09
  • Svelte反應(yīng)式變量和函數(shù)工作原理詳解

    Svelte反應(yīng)式變量和函數(shù)工作原理詳解

    這篇文章主要為大家介紹了Svelte反應(yīng)式變量和函數(shù)工作原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • JavaScript如何實現(xiàn)精準(zhǔn)倒計時

    JavaScript如何實現(xiàn)精準(zhǔn)倒計時

    這篇文章主要為大家詳細介紹了JavaScript如何實現(xiàn)精準(zhǔn)倒計時功能,文中的示例代碼簡潔易懂,具有一定的借鑒價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02
  • 詳解使用JWT實現(xiàn)單點登錄(完全跨域方案)

    詳解使用JWT實現(xiàn)單點登錄(完全跨域方案)

    這篇文章主要介紹了詳解使用JWT實現(xiàn)單點登錄(完全跨域方案),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • JavaScript設(shè)計模式---單例模式詳解【四種基本形式】

    JavaScript設(shè)計模式---單例模式詳解【四種基本形式】

    這篇文章主要介紹了JavaScript設(shè)計模式---單例模式,結(jié)合實例形式詳細分析了JavaScript設(shè)模式中單例模式的四種基本形式定義與使用方法,需要的朋友可以參考下
    2020-05-05
  • JS hashMap實例詳解

    JS hashMap實例詳解

    這篇文章主要介紹了JS hashMap實例詳解的相關(guān)資料,包括刪除鍵值、獲取鍵值的相關(guān)知識,非常不錯具有參考借鑒價值,需要的朋友一起看看吧
    2016-05-05

最新評論

布拖县| 行唐县| 临沧市| 武定县| 班戈县| 光泽县| 九龙县| 靖宇县| 襄樊市| 宜良县| 洱源县| 修文县| 绥德县| 新竹县| 阿拉善右旗| 河北省| 万荣县| 阿坝| 承德市| 新闻| 宜兰县| 庆城县| 江津市| 许昌市| 泗阳县| 闽侯县| 深泽县| 金阳县| 清流县| 柞水县| 封丘县| 辽阳市| 贡觉县| 大石桥市| 南涧| 镇康县| 巴林右旗| 龙海市| 和静县| 虞城县| 武安市|