canvas控件--折線圖--區(qū)間選擇功能(下)

上一篇,我們討論了如何通過(guò)canvas繪制一個(gè)折線圖
接下來(lái),我們將給這個(gè)折線圖實(shí)現(xiàn)鼠標(biāo)交互效果

首先,鼠標(biāo)在我們的折線圖上移動(dòng)時(shí),我們要一個(gè)藍(lán)色的豎線跟隨鼠標(biāo)移動(dòng)
要實(shí)現(xiàn)這個(gè)效果,我們一步一步來(lái)
1、我們需要在canvas的mousemove事件方法中,根據(jù)鼠標(biāo)位置clientX/Y,和容器的top/left值,計(jì)算出鼠標(biāo)所在處的canvas坐標(biāo);
2、根據(jù)鼠標(biāo)坐標(biāo)判斷鼠標(biāo)是否在折線圖上,如果鼠標(biāo)在折線圖上,將鼠標(biāo)x軸坐標(biāo)(即橫向坐標(biāo))保存在mousemovePositionx變量中,如果鼠標(biāo)不在折線圖上,將mousemovePositionx變量設(shè)置為null;
3、drow方法中判斷mousemovePositionx變量是否為null,若不為null,則根據(jù)mousemovePositionx的值繪制藍(lán)色線段
在線展示及代碼

然后,我們分解一下鼠標(biāo)拖動(dòng)選擇時(shí)間區(qū)間這個(gè)操作
1、鼠標(biāo)按下; 2、鼠標(biāo)移動(dòng); 3、鼠標(biāo)抬起
實(shí)際上我們只需要在鼠標(biāo)按下時(shí)記錄鼠標(biāo)按下的位置,鼠標(biāo)抬起時(shí),根據(jù)鼠標(biāo)抬起位置和之前記錄的鼠標(biāo)按下的位置,便可以得到拖拽動(dòng)作選擇的區(qū)間
但是這樣做,鼠標(biāo)移動(dòng)時(shí)沒(méi)有任何交互效果
為了更好的用戶體驗(yàn),我們可以在鼠標(biāo)移動(dòng)方法中,通過(guò)鼠標(biāo)位置與鼠標(biāo)按下位置,將已選擇區(qū)間記錄下來(lái),供draw方法繪制相應(yīng)交互效果

       mousedown = e => {
            const x = e.clientX - L,
                y = e.clientY - T;
            if (y > chartTop && y < chartBottom && x > chartLeft && x < chartRight ) {
                mouseDownZB = x;
            } else {
                mouseDownZB = null;
            }
        }
        mousemove = e => {
            const x = e.clientX - L,
                y = e.clientY - T;
            if (y > chartTop && y < chartBottom && x > chartLeft && x < chartRight ) {
                mouseMovePosition = x;
                if (mouseDownZB !== null) {
                    mouseSelected = [mouseDownZB, x];
                } else {
                    mouseSelected = null;
                }
            } else {
                mouseMovePosition = null;
            }
        }
        mouseup = e => {
            mouseDownZB = null;
            mouseSelected = null;
        }

        drawOther = () => {
            ...
            if (mouseSelected !== null) {
                ctx.save();
                ctx.fillStyle = "rgba(55, 183, 248, 0.5)";
                ctx.beginPath();
                ctx.rect(mouseSelected[0], chartTop, Math.abs(mouseSelected[0] - mouseSelected[1]), ylength);
                ctx.fill();
            }
        }

上面這段代碼,實(shí)現(xiàn)了鼠標(biāo)拖拽選擇區(qū)間,mouseup中將mouseDownZB,mouseSelected兩個(gè)變量置為null,此時(shí)我們已經(jīng)選擇了一個(gè)區(qū)間,需要將沒(méi)有選擇的區(qū)間置為灰色,
因此我需要在將變量mouseSelected置為null前,賦值變量hasSelected = mouseSelected
drawOther方法中添加代碼

if (hasSelected !== null) {
    ctx.save();
    ctx.strokeStyle = '#CCCCCC';
    ctx.fillStyle = 'rgba(230, 230, 230, 0.8)';
    ctx.beginPath();
    ctx.rect(chartLeft, chartTop, hasSelected[0] - chartLeft, ylength);
    ctx.fill();
    ctx.stroke();
    ctx.beginPath();
    ctx.rect(hasSelected[1], chartTop, chartRight - hasSelected[1], ylength);
    ctx.fill();
    ctx.stroke();
    ctx.restore();
}

查看代碼,細(xì)心的同學(xué)可能已經(jīng)發(fā)現(xiàn)了,第一次選擇區(qū)間后,再選擇區(qū)間,偶爾在上部會(huì)出現(xiàn)一道灰線,如下圖


這個(gè)問(wèn)題與canvas劃線的方式有關(guān),有興趣的同學(xué)自行百度,這里我們只需修改一下清除畫(huà)布方法即可
ctx.clearRect(chartLeft, chartTop - 1, xlength, ylength + 1);//清除變動(dòng)區(qū)域

標(biāo)記出已選擇部分還不夠,我們需要計(jì)算出選擇區(qū)域起止點(diǎn)具體時(shí)間

data[Math.ceil((hasSelected[0] - chartLeft) / xstep)].date;
data[Math.floor((hasSelected[1] - chartLeft) / xstep)].date

這樣一個(gè)簡(jiǎn)單的附帶區(qū)間選擇的折線圖就完成了
查看es6簡(jiǎn)化版在線示例及代碼
查看es5完整版版在線示例及代碼

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

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

  • 根據(jù)項(xiàng)目上的需求封裝的一個(gè)控件,不知道叫什么好,暫時(shí)命名為時(shí)間區(qū)間選擇器吧。簡(jiǎn)單來(lái)講,就是一個(gè)折線圖,x軸為時(shí)間,...
    王恩智閱讀 1,128評(píng)論 0 1
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程,因...
    小菜c閱讀 7,380評(píng)論 0 17
  • 基本介紹 關(guān)于 canvas 的基本使用,可以參考以下兩個(gè)網(wǎng)站: Android Canvas繪圖詳解(圖文) -...
    LiuHDme閱讀 3,513評(píng)論 0 0
  • 一場(chǎng)陽(yáng)光清掃 點(diǎn)點(diǎn)被毀壞的暗。樹(shù)枝 斜向一座建筑物的頂端: 用石頭構(gòu)架地基與外表, 層層上升。也許能夠—— 無(wú)限延...
    一個(gè)名叫Alan的男子閱讀 324評(píng)論 1 3
  • 堅(jiān)持寫(xiě)字二十天之后,我停下來(lái)了。這二十天里我每天花費(fèi)四到六個(gè)小時(shí)來(lái)寫(xiě),但寫(xiě)出來(lái)的僅僅是自己覺(jué)得姑且成文而已。本來(lái)以...
    Sora夜白鹿閱讀 1,541評(píng)論 52 54

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