国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

你不知道的前端算法之文字避讓

yedf / 1958人閱讀

摘要:避讓算法采用的是四分位模型算法,接下來手把手教你寫避讓算法,老司機帶你裝逼帶你飛。創建四分位模型所謂四分位模型,每一個標記點都有上下左右四個放文字的位子,如果左邊放不下,那就放右邊試試,還不行就放到下面試試,以此類推,原理就這么簡單,哈哈。

本文作者:TalkingData 可視化工程師李鳳祿
編輯:Aresn

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

GitHub 地址:https://github.com/TalkingData/inmap

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

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

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

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

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

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

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

準備數據

inMap 接收的是經緯度數據,需要把它映射到 canvas 的像素坐標,這就用到了墨卡托轉換,墨卡托算法很復雜,以后我們會有多帶帶的一篇文章來講講他的原理。經過轉換,你得到的數據應該是這樣的:

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

好了,我們得到轉換后的像素坐標數據(x、y),就可以做下面的事情了。

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

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

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

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

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

所以代碼如下:

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

文字的寬度和高度得到后,我們就可以創建文字矩形的坐標系了。

創建四分位模型

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

創建右側虛擬矩形坐標描述:

右側虛擬矩形坐標的描述把圓點也包含在內了,是為了防止文字和圓點重疊。

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

代碼如下:

_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
    };
}

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

判斷碰撞

判斷兩個矩形是否覆蓋相交,根據矩形的 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;
}
創建虛擬文字集合對象
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);
});

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

代碼如下:

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();
    }
});

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

福利

分享兩位業內大牛的前端課程:

Aresn 大神,開源了很優秀的前端 UI 組件庫 iView,出版了《Vue.js實戰》一書。向大家推薦他的課程,Vue.js實戰系列教程,從本鏈接過去的打八折優惠,先到先得。

Chaos WebGL 專家,擅長 web 3D 開發。 主要有被《玩壞的地球系列課程》,很適合初學者。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90771.html

相關文章

  • 你不知道前端算法熱力圖實現

    摘要:目前支持散點圍欄熱力網格聚合等方式致力于讓大數據可視化變得簡單易用。如圖表示,紅色區域表示分析要素的密度大,而藍色區域表示分析要素的密度小。實現熱力原理讀取每個像素的值透明度,做一個顏色映射。 本文作者:TalkingData 可視化工程師李鳳祿編輯:Aresn 歡迎加入 QQ 群參與技術討論:618308202 inMap 是一款基于 canvas 的大數據可視化庫,專注于大數據方...

    zhaochunqi 評論0 收藏0
  • TalkingData 開源地理信息可視化框架 inMap

    摘要:本文作者可視化工程師李鳳祿是可視化團隊開源的一款基于的大數據可視化庫,專注于大數據方向點線面的可視化效果展示。目前支持散點圍欄熱力網格聚合等方式致力于讓大數據可視化變得簡單易用。后續會輸出創造更好的可視化圖形和算法,并后續推出版本。 showImg(https://segmentfault.com/img/bV0yHB?w=1600&h=900); 本文作者:TalkingData 可...

    xeblog 評論0 收藏0
  • 阿里王剛談自動駕駛:從單車智能到車路協同智能進化

    摘要:在今年的云棲大會上,阿里巴巴人工智能實驗室除了發布服務機器人天貓精靈太空蛋太空梭天貓精靈車載版,還重點推出了車路協同智能自動駕駛車。秒看懂智慧物流車和感知基站各位嘉賓,上午好我是王剛,我要介紹的是自動駕駛從單車智能跨到協同智能的進化。 在今年的云棲大會上,阿里巴巴人工智能實驗室除了發布AliGenie 3.0、服務機器人(天貓精靈太空蛋、太空梭)、天貓精靈車載版(TmallGenie ...

    shery 評論0 收藏0
  • 阿里王剛談自動駕駛:從單車智能到車路協同智能進化

    摘要:在今年的云棲大會上,阿里巴巴人工智能實驗室除了發布服務機器人天貓精靈太空蛋太空梭天貓精靈車載版,還重點推出了車路協同智能自動駕駛車。秒看懂智慧物流車和感知基站各位嘉賓,上午好我是王剛,我要介紹的是自動駕駛從單車智能跨到協同智能的進化。 在今年的云棲大會上,阿里巴巴人工智能實驗室除了發布AliGenie 3.0、服務機器人(天貓精靈太空蛋、太空梭)、天貓精靈車載版(TmallGenie ...

    Dongjie_Liu 評論0 收藏0
  • css - 收藏集 - 掘金

    摘要:絕對底部前端掘金來自國外的設計達人,純,可以實現當正文內容很少時,底部位于窗口最下面。有效解決圖片使用單位邊角缺失的問題前端掘金起因在移動端使用布局時圖片也需要用單位。 CSS 絕對底部 - 前端 - 掘金來自國外的設計達人,純CSS,可以實現: 當正文內容很少時,底部位于窗口最下面。當改變窗口高度時,不會出現重疊問題。甚至,創造該CSS的人還專門成立一個網站介紹這個CSS底部布局方案...

    phpmatt 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<