Echarts圖例legend過多,采用翻頁處理

問題:
圖例可以跟地圖有聯(lián)動效果,用來當列表使用,與地圖有聯(lián)動效果,簡直太棒了,但是echarts圖例太多,實在太占用空間,遮擋圖表,又無法移動legend層。當屏幕小,滿屏幕都是圖例呀。。。如下圖,頭疼。

image.png

翻閱echarts相關(guān)文檔,百度,Q群等途徑尋找解決方法,都沒有得到想要答案。于是鼓起勇氣嘗試修改源碼。
開始的想法是:右邊一列,不換行顯示,出現(xiàn)滾動條,可以向下滾動。后來研究了echarts源碼,覺得在canvas上加滾動條有點困難,所以選擇了 向下翻頁 的方式。

效果圖:

image.png

原理

echarts創(chuàng)建legend層是先創(chuàng)建每一條圖例,再計算位置,全部渲染出來。發(fā)現(xiàn)echarts里一段主要代碼,就是這里實現(xiàn)了"圖例換行"

// Wrap when width exceeds maxHeight or meet a `newline` group
if (nextY > maxHeight || child.newline) {
    x += currentLineMaxSize + gap;
    y = 0;
    nextY = moveY;
    currentLineMaxSize = rect.width;
}
else {
    currentLineMaxSize = Math.max(currentLineMaxSize, rect.width);
}

那么,是不是可以把 ”換行“ 變成 “換頁”! .oh,good idea,get ! 于是這么干!

步驟如下:

為了避免 改動 會引起其他問題。通過自定義新的字段參數(shù)控制。
主要需要改動以下幾個地方:

1.html頁面中改動

我在初始化echarts的div標簽下面添加<div class="js-eclegend-tool" style="position: absolute;right: 20px;top: 40%"></div>,用于存放上下翻頁按鈕,下面會用到。我寫在echarts容器下面,css樣式?jīng)Q定它的位置,代碼如下:

<div class="ibox">
        <!--初始化echarts實例的容器-->
    <div id="eBaiduMap" class="ibox-size" style="width: 100%;"></div>
        <!--用于存放上下翻頁按鈕.js-eclegend-tool容器,頁面中的修改只需增加下面這一句-->
    <div class="js-eclegend-tool" style="position: absolute;right: 20px;top: 40%"></div>
</div>

2.修改option配置

實例化echarts時,修改option配置,即添加pagemode: true,留意注釋為//注意的地方

//modify by danhuan
legend: {
    orient: 'vertical', //注意
    right:0,
    top: 0, //注意
    //bottom:0,
    //left:0,
    //width:200,
    pagemode: true, //注意,自定義的字段,開啟圖例分頁模式,只有orient: 'vertical'時才有效
    height:"100%",
    data: legendData,
    itemHeight:18,
    itemWidth: 18,
    textStyle: {
        fontWeight: 'bolder',
        fontSize: 12,
        color:'#fff'
    },
    inactiveColor:'#aaa',
    //padding: [20, 15],
    backgroundColor: 'rgba(0, 0, 0, 0.7)',
    shadowColor: 'rgba(0, 0, 0, 0.5)',
    shadowBlur: 5,
    zlevel: 100
},

3.修改echarts源碼,總共兩處修改

第一處修改,在源碼中找到以下代碼:

image.png

為了你們方便復(fù)制查找,我把該截圖的代碼粘貼出來,即:

layout: function (group, componentModel, api) {
                var rect = layout.getLayoutRect(componentModel.getBoxLayoutParams(), {
                    width: api.getWidth(),
                    height: api.getHeight()
                }, componentModel.get('padding'));
                layout.box(
                    componentModel.get('orient'),
                    group,
                    componentModel.get('itemGap'),
                    rect.width,
                    rect.height
                );

                positionGroup(group, componentModel, api);
            },

找到這幾行代碼,修改為以下代碼:

layout: function (group, componentModel, api) {
    var rect = layout.getLayoutRect(componentModel.getBoxLayoutParams(), {
        width: api.getWidth(),
        height: api.getHeight()
    }, componentModel.get('padding'));

    /*modify by danhuan 為了避免影響到其他模塊,傳參數(shù)判斷修改 legend 是否要分頁  s*/
    if(componentModel.get('pagemode')){//如果 legend 啟用分頁 modify by danhuan
        layout.box(
            componentModel.get('orient'),
            group,
            componentModel.get('itemGap'),
            rect.width,
            rect.height,
            componentModel.get('pagemode') //modify by danhuan
        );
    }
    if(!componentModel.get('pagemode')){
        layout.box(
            componentModel.get('orient'),
            group,
            componentModel.get('itemGap'),
            rect.width,
            rect.height
        );
    }
    /*modify by danhuan 傳參數(shù)判斷修改 legend 是否要分頁  e*/

    positionGroup(group, componentModel, api);
},

這樣做的目的是為了將步驟2的自定義參數(shù) pagemode: true 傳進echarts ,為了避免有其他方法調(diào)用layout方法導(dǎo)致其他圖表錯誤,所以用了判斷if(componentModel.get('pagemode')){...},有參數(shù) pagemode: true 時,才會進入改動的代碼。

第二處修改:

找到以下代碼function boxLayout(orient, group, gap, maxWidth, maxHeight)...截圖如下:


image.png

將該函數(shù)修改為:

function boxLayout(orient, group, gap, maxWidth, maxHeight,pagemode) {
    //console.log(group);
    var x = 0;
    var y = 0;
    if (maxWidth == null) {
        maxWidth = Infinity;
    }
    if (maxHeight == null) {
        maxHeight = Infinity;
    }
    var currentLineMaxSize = 0;
    group.eachChild(function (child, idx) {
        //console.log(child, idx);

        var position = child.position;
        var rect = child.getBoundingRect();
        var nextChild = group.childAt(idx + 1);
        var nextChildRect = nextChild && nextChild.getBoundingRect();
        var nextX;
        var nextY;
        if (orient === 'horizontal') {
            var moveX = rect.width + (nextChildRect ? (-nextChildRect.x + rect.x) : 0);
            nextX = x + moveX;
            // Wrap when width exceeds maxWidth or meet a `newline` group
            if (nextX > maxWidth || child.newline) {
                x = 0;
                nextX = moveX;
                y += currentLineMaxSize + gap;
                currentLineMaxSize = rect.height;
            }
            else {
                currentLineMaxSize = Math.max(currentLineMaxSize, rect.height);
            }
        }
        else {
            var moveY = rect.height + (nextChildRect ? (-nextChildRect.y + rect.y) : 0);

            nextY = y + moveY;

            /*by danhuan s*/
                    if(pagemode){

                        //console.log(pagemode);
                        if (nextY > maxHeight || child.newline) {
                            var html = '<div class="js-prePage"> &lt;img style="width: 32px;height: 32px;cursor: no-drop" src="/mapout-web-visual/img/up-disable.png"  title="已經(jīng)是第一頁"/></div>';
                            html += '<div class="js-nextPage"> &lt;img  style="width: 32px;height: 32px;cursor: pointer" src="/mapout-web-visual/img/down-icon.png" title="下一頁"/></div>';
                            $('.js-eclegend-tool').html(html);
                        }
                        else {
                            currentLineMaxSize = Math.max(currentLineMaxSize, rect.width);
                        }
                    }else{
                        //console.log(pagemode);
                        // Wrap when width exceeds maxHeight or meet a `newline` group
                        if (nextY > maxHeight || child.newline) {
                            x += currentLineMaxSize + gap;
                            y = 0;
                            nextY = moveY;
                            currentLineMaxSize = rect.width;
                        }
                        else {
                            currentLineMaxSize = Math.max(currentLineMaxSize, rect.width);
                        }
                    }
                    /*by danhuan e*/
        }

        if (child.newline) {
            return;
        }

        position[0] = x;
        position[1] = y;

        orient === 'horizontal'
            ? (x = nextX + gap)
            : (y = nextY + gap);
    });
}

修改的代碼意思:在圖例總高度大于legend容器高度,需要換行時, 不讓其換行,而是一直向下畫圖例, 同時向 步驟1 建的容器$('.js-eclegend-tool')里面添加 ‘上一頁’、‘下一頁’ 按鈕。

4.添加按鈕事件

給”上一頁“, ”下一頁“按鈕添加事件,通過echarts的setOption改變legend層的top,實現(xiàn)其翻頁

/*=====legend 的分頁控制 事件=s===*/
        var PageEvent = function (i) {
            var percent = -i * 98 + '%';
            myChart.setOption({
                legend: {
                    top: percent
                }
            });
        };

        if (option.legend.pagemode) {
            $('body').on('click', '.js-prePage', function () {

                if (clickCount > 0) {
                    clickCount = clickCount - 1;
                    PageEvent(clickCount);
                    //console.log(clickCount+'上一頁');
                    $('.js-prePage img').attr({'src': '/mapout-web-visual/img/up-icon.png', 'title': '上一頁'});
                    $('.js-prePage img').css('cursor','pointer');
                    //$('.js-nextPage img').attr('src','/mapout-web-visual/img/down-icon.png');
                    if(clickCount==0){
                        $('.js-prePage img').attr({'src': '/mapout-web-visual/img/up-disable.png', 'title': '已經(jīng)是第一頁'});
                        $('.js-prePage img').css('cursor','no-drop');
                    }
                } else {
                    //console.log(clickCount+'已經(jīng)是第一頁');
                    $('.js-prePage img').attr({'src': '/mapout-web-visual/img/up-disable.png', 'title': '已經(jīng)是第一頁'});
                    $('.js-prePage img').css('cursor','no-drop');
                }
            });
            $('body').on('click', '.js-nextPage', function () {
                clickCount = clickCount + 1;
                //console.log(clickCount);
                PageEvent(clickCount);
                $('.js-prePage img').attr({'src': '/mapout-web-visual/img/up-icon.png', 'title': '上一頁'});
                $('.js-prePage img').css('cursor','pointer');
            });
        }
        /*=====legend 的分頁控制 事件=e===*/

按鈕圖標:


up-icon.png
up-disable.png
down-icon.png
down-disable.png

以上僅個人想法,請多多指教!希望能得到您更多寶貴的想法。

已修改的echarts的github地址 :https://github.com/danhuan/echarts-changed-legend 直接使用該js,可以省略第三步驟的修改源代碼

本文簡書地址:http://m.itdecent.cn/p/869853a7c8ce

洪丹煥 創(chuàng)建于 2017.05.24

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容