首頁  >  文章  >  web前端  >  canvas實作按住滑鼠移動繪製出軌跡的方法實例

canvas實作按住滑鼠移動繪製出軌跡的方法實例

小云云
小云云原創
2018-02-02 14:01:142004瀏覽

需求

在一塊canvas畫布上,初始狀態畫布什麼都沒有,現在,我想在畫布上加一點滑鼠事件,用滑鼠在畫布上寫字。具體的效果是滑鼠移動到畫布上任意一點,然後按住滑鼠,移動滑鼠的位置,就可以開始寫字囉!

本文作為學習canvas的第一篇收穫,許多人初學canvas做的第一個demo是實現一個“鐘”,當然,我也實現了一個,不過不講這個,而是講講一個更有趣、也更簡單的玩意。

滑鼠按住繪製軌跡

canvas實作按住滑鼠移動繪製出軌跡的方法實例

#原理

先簡單分析下思路,首先我們需要一個canvas畫布,然後計算滑鼠在畫布上的位置,給滑鼠綁定onmousedown事件和onmousemove事件,在移動過程中繪製出路徑,放開滑鼠的時候,繪製結束。

這個想法雖然很簡單,但裡面有些地方需要小技巧實作。

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

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

<!doctype html>
<html class="no-js" lang="zh">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title>canvas学习</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <link rel="manifest" href="site.webmanifest">
        <link rel="apple-touch-icon" href="icon.png">
        <link rel="stylesheet" href="css/main.css">
    </head>
    <body>
        <canvas id="theCanvas" width="800" height="400"></canvas>
        <script src="js/main.js"></script>
    </body>
</html>

2、判斷目前環境是否支援canvas。

在main.js中,我們寫一個自執行函數,下面是相容性判斷的程式碼片段,「程式碼主體」中將會是實作需求的核心。

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

3、取得2d物件。

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

4、取得目前滑鼠相對於canvas的座標。

為什麼要取得這個座標呢?因為滑鼠預設是取得目前視窗的相對座標,而canvas可以位於頁面上的任何位置,所以需要透過計算才能得到真實的滑鼠座標。

將取得滑鼠相對於canvas的真實座標封裝成了一個函數,如果你覺得抽象,可以在草稿紙上畫圖來理解為什麼要這麼運算。

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

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

const windowToCanvas = (canvas, x, y) => {
    //获取canvas元素距离窗口的一些属性,MDN上有解释
    let rect = canvas.getBoundingClientRect()
    //x和y参数分别传入的是鼠标距离窗口的坐标,然后减去canvas距离窗口左边和顶部的距离。
    return {
        x: x - rect.left * (canvas.width/rect.width),
        y: y - rect.top * (canvas.height/rect.height)
    }
}

5、有了第4步的利器函數,我們可以為canvas加上滑鼠事件了!

先給滑鼠綁定按下onmousedown事件,用moveTo繪製座標起點。

theCanvas.onmousedown = function(e) {
    //获得鼠标按下的点相对canvas的坐标。
    let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
    //es6的解构赋值
    let { x, y } = ele
    //绘制起点。
    context.moveTo(x, y)
}

6、移動滑鼠的時候,沒有滑鼠長按事件,又該怎麼監聽呢?

這裡用到的小技巧是在onmousedown內部再執行一個onmousemove(滑鼠移動)事件,這樣就能監聽按住滑鼠並且移動了。

theCanvas.onmousedown = function(e) {
    //获得鼠标按下的点相对canvas的坐标。
    let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
    //es6的解构赋值
    let { x, y } = ele
    //绘制起点。
    context.moveTo(x, y)
    //鼠标移动事件
    theCanvas.onmousemove = (e) => {
        //移动时获取新的坐标位置,用lineTo记录当前的坐标,然后stroke绘制上一个点到当前点的路径
        let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
        let { x, y } = ele
        context.lineTo(x, y)
        context.stroke()
    }
}

7、滑鼠放開的時候,不再繪製路徑。

有什麼辦法可以讓onmouseup事件中阻止掉上面監聽的2種事件呢?方法還蠻多的,設定onmousedown和onmousemove為null算是一種,我這裡用到了「開關」。 isAllowDrawLine設定為bool值,來控制函數是否執行,具體程式碼可以看下面完整的原始碼。

原始碼

分成3個文件,index.html、main.js、utils.js,這裡用到了es6的語法,我是使用parcle配置了開發環境,所以不會有報錯,如果你直接複製程式碼,執行的時候出現錯誤,在無法升級瀏覽器的情況下,可以將es6語法改成es5.

1、index.html
上面已經展示了,不再複述。

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

/*
* 获取鼠标在canvas上的坐标
* */
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
}

相關推薦:

CSS與JS實現唯美星空軌跡運動效果

#canvas貝塞爾公式推導與物件跟隨複雜曲線軌跡運動


###################################################################################### ###css3動畫中圓形運動軌跡的實作###############

以上是canvas實作按住滑鼠移動繪製出軌跡的方法實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn