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

資訊專欄INFORMATION COLUMN

前端系列——canvas實現(xiàn)按住鼠標(biāo)移動繪制出軌跡

CloudDeveloper / 2434人閱讀

摘要:鼠標(biāo)按住繪制軌跡需求在一塊畫布上,初始狀態(tài)畫布什么都沒有,現(xiàn)在,我想給畫布加一點鼠標(biāo)事件,用鼠標(biāo)在畫布上寫字。獲取當(dāng)前鼠標(biāo)相對于的坐標(biāo)。的解構(gòu)賦值繪制起點。但是由于瀏覽器會自動幫你判斷并且移交事件處理,所以完全不用擔(dān)心。

概要

工作以來,寫過vue、react、正則、算法、小程序等知識,唯獨沒有寫過canvas,因為實在不會啊!

2018年,給自己設(shè)定一個小目標(biāo):學(xué)會canvas,達到的效果是能用canvas實現(xiàn)一些css3不容易實現(xiàn)的動畫。

本文作為學(xué)習(xí)canvas的第一篇收獲,很多人初學(xué)canvas做的第一個demo是實現(xiàn)一個“鐘”,當(dāng)然,我也實現(xiàn)了一個,不過不講這個,而是講講一個更有趣、也更簡單的玩意。

鼠標(biāo)按住繪制軌跡 需求

在一塊canvas畫布上,初始狀態(tài)畫布什么都沒有,現(xiàn)在,我想給畫布加一點鼠標(biāo)事件,用鼠標(biāo)在畫布上寫字。具體的效果是鼠標(biāo)移動到畫布上任意一點,然后按住鼠標(biāo),移動鼠標(biāo)的位置,就可以開始寫字啦!

原理

先簡單分析下思路,首先我們需要一個canvas畫布,然后計算鼠標(biāo)在畫布上的位置,給鼠標(biāo)綁定onmousedown事件和onmousemove事件,在移動過程中繪制出路徑,松開鼠標(biāo)的時候,繪制結(jié)束。

這個思路雖然很簡單,但是里面有些地方需要小技巧實現(xiàn)。

1、需要一個html文件,包含canvas元素。

這是一個寬度800,高度400的畫布。為什么沒有寫px呢?哦,暫時沒搞懂,canvas文檔推薦的。



    
        
        
        canvas學(xué)習(xí)
        
        

        
        
        
    
    
        
        
    

2、判斷當(dāng)前環(huán)境是否支持canvas。

在main.js中,我們寫一個自執(zhí)行函數(shù),下面是兼容性判斷的代碼片段,“代碼主體”中將會是實現(xiàn)需求的核心。

(function() {
    let theCanvas = document.querySelector("#theCanvas")
    if (!theCanvas || !theCanvas.getContext) {
        //不兼容canvas
        return false
    } else {
        //代碼主體
    }
})()

3、獲取2d對象。

   let context = theCanvas.getContext("2d")

4、獲取當(dāng)前鼠標(biāo)相對于canvas的坐標(biāo)。

為什么要獲取這個坐標(biāo)呢?因為鼠標(biāo)默認(rèn)是獲取當(dāng)前窗口的相對坐標(biāo),而canvas可以位于頁面上的任何位置,所以需要通過計算才能得到真實的鼠標(biāo)坐標(biāo)。

將獲取鼠標(biāo)相對于canvas的真實坐標(biāo)封裝成了一個函數(shù),如果你覺得抽象,可以在草稿紙上畫圖來理解為什么要這么運算。

通常情況下,可以是x - rect.left和y - rect.top。但為什么實際上卻是x - rect.left * (canvas.width/rect.width)呢?

canvas.width/rect.width表示判斷canvas中存在的縮放行為,求出縮放的倍數(shù)。

const windowToCanvas = (canvas, x, y) => {
    //獲取canvas元素距離窗口的一些屬性,MDN上有解釋
    let rect = canvas.getBoundingClientRect()
    //x和y參數(shù)分別傳入的是鼠標(biāo)距離窗口的坐標(biāo),然后減去canvas距離窗口左邊和頂部的距離。
    return {
        x: x - rect.left * (canvas.width/rect.width),
        y: y - rect.top * (canvas.height/rect.height)
    }
}

5、有了第4步的利器函數(shù),我們可以給canvas加上鼠標(biāo)事件了!

先給鼠標(biāo)綁定按下onmousedown事件,用moveTo繪制坐標(biāo)起點。

theCanvas.onmousedown = function(e) {
    //獲得鼠標(biāo)按下的點相對canvas的坐標(biāo)。
    let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
    //es6的解構(gòu)賦值
    let { x, y } = ele
    //繪制起點。
    context.moveTo(x, y)
}

6、移動鼠標(biāo)的時候,沒有鼠標(biāo)長按事件,又該怎么監(jiān)聽呢?

這里用到的小技巧是在onmousedown內(nèi)部再執(zhí)行一個onmousemove(鼠標(biāo)移動)事件,這樣就能監(jiān)聽按住鼠標(biāo)并且移動了。

theCanvas.onmousedown = function(e) {
    //獲得鼠標(biāo)按下的點相對canvas的坐標(biāo)。
    let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
    //es6的解構(gòu)賦值
    let { x, y } = ele
    //繪制起點。
    context.moveTo(x, y)
    //鼠標(biāo)移動事件
    theCanvas.onmousemove = (e) => {
        //移動時獲取新的坐標(biāo)位置,用lineTo記錄當(dāng)前的坐標(biāo),然后stroke繪制上一個點到當(dāng)前點的路徑
        let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
        let { x, y } = ele
        context.lineTo(x, y)
        context.stroke()
    }
}

7、鼠標(biāo)松開的時候,不再繪制路徑。

有什么辦法可以讓onmouseup事件中阻止掉上面監(jiān)聽的2種事件呢?方法挺多的,設(shè)置onmousedown和onmousemove為null算是一種,我這里用到了“開關(guān)”。isAllowDrawLine設(shè)置為bool值,來控制函數(shù)是否執(zhí)行,具體代碼可以看下面完整的源碼。

源碼

分為3個文件,index.html、main.js、utils.js,這里用到了es6的語法,我是使用parcle配置好了開發(fā)環(huán)境,所以不會有報錯,如果你直接復(fù)制代碼,運行的時候出現(xiàn)錯誤,在無法升級瀏覽器的情況下,可以將es6語法改成es5.

1、index.html
上面已經(jīng)展示了,不再復(fù)述。

2、main.js

import { windowToCanvas } from "./utils"
(function() {
    let theCanvas = document.querySelector("#theCanvas")
    if (!theCanvas || !theCanvas.getContext) {
        return false
    } else {
        let context = theCanvas.getContext("2d")
        let isAllowDrawLine = false
        theCanvas.onmousedown = function(e) {
            isAllowDrawLine = true
            let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
            let { x, y } = ele
            context.moveTo(x, y)
            theCanvas.onmousemove = (e) => {
                if (isAllowDrawLine) {
                    let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
                    let { x, y } = ele
                    context.lineTo(x, y)
                    context.stroke()
                }
            }
        }
        theCanvas.onmouseup = function() {
            isAllowDrawLine = false
        }
    }
})()

3、utils.js

/*
* 獲取鼠標(biāo)在canvas上的坐標(biāo)
* */
const windowToCanvas = (canvas, x, y) => {
    let rect = canvas.getBoundingClientRect()
    return {
        x: x - rect.left * (canvas.width/rect.width),
        y: y - rect.top * (canvas.height/rect.height)
    }
}

export {
    windowToCanvas
}
總結(jié)

這里有個誤區(qū),我用的是canvas對象綁定事件 theCanvas.onmouseup,其實canvas不能綁定事件,真正綁定的是document和window。但是由于瀏覽器會自動幫你判斷并且移交事件處理,所以完全不用擔(dān)心。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/107157.html

相關(guān)文章

  • 前端動畫調(diào)研-V1

    摘要:支持動畫狀態(tài)的,在動畫開始,執(zhí)行中,結(jié)束時提供回調(diào)函數(shù)支持動畫可以自定義貝塞爾曲線任何包含數(shù)值的屬性都可以設(shè)置動畫倉庫文檔演示功能介紹一定程度上,也是一個動畫庫,適用所有的屬性,并且實現(xiàn)的能更方便的實現(xiàn)幀動畫,替代復(fù)雜的定義方式。 動畫調(diào)研-V1 前言:動畫從用途上可以分為兩種,一種是展示型的動畫,類似于一張GIF圖,或者一段視頻,另一種就是交互性的動畫。這兩種都有具體的應(yīng)用場景,比如...

    ddongjian0000 評論0 收藏0
  • 實踐是檢驗程序員的唯一標(biāo)準(zhǔn)01:用戶不想跟你說話并向你扔出一張圖片 - 圖片上傳組件開發(fā)【思路篇】

    摘要:表示不一定是原生形式的數(shù)據(jù)。接口基于,繼承了的功能并將其擴展使其支持用戶系統(tǒng)上的文件。讀取操作完成的時候,會變成已完成,并觸發(fā)事件,同時屬性將包含一個格式的字符串編碼以表示所讀取文件的內(nèi)容。 溫馨提示:這里除了一些幼稚的小組件啥也沒有溫馨提示-續(xù):這是一個新的系列,寫一些實際開發(fā)中遇到的一些常用的功能,想法笨拙,代碼亂套 寫在前面 圖片上傳,作為web端一個常用的功能,在不同的項目中有...

    PiscesYE 評論0 收藏0

發(fā)表評論

0條評論

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