亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > HTML > 正文

canvas實現按住鼠標移動繪制出軌跡的示例代碼

2024-08-26 00:20:25
字體:
來源:轉載
供稿:網友

概要

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

2018年,給自己設定一個小目標:學會canvas,達到的效果是能用canvas實現一些css3不容易實現的動畫。

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

鼠標按住繪制軌跡

需求

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

canvas,鼠標軌跡,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}

總結

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。

 

注:相關教程知識閱讀請移步到HTML教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
热久久99这里有精品| 亚洲欧美国产精品va在线观看| 国产精品自拍偷拍视频| 91亚洲午夜在线| 中文字幕国产日韩| 亚洲三级黄色在线观看| 最好看的2019的中文字幕视频| 茄子视频成人在线| 欧美成人四级hd版| 国产精品久久久久免费a∨大胸| 91网站免费观看| 亚洲欧美日本精品| 日韩av免费看网站| 久久久久久有精品国产| 91中文精品字幕在线视频| 日本不卡视频在线播放| 久久精品影视伊人网| 日韩欧美亚洲范冰冰与中字| 成人在线国产精品| 亚洲一级一级97网| 日韩视频免费观看| 日本国产精品视频| 91精品国产综合久久久久久久久| 亚洲视频网站在线观看| 色偷偷88888欧美精品久久久| 8090理伦午夜在线电影| 欧美日韩在线视频观看| 国产99视频在线观看| 亚洲偷熟乱区亚洲香蕉av| 亚洲精品综合久久中文字幕| 欧美一级大胆视频| 色综合91久久精品中文字幕| 中文字幕久久亚洲| 欧美性资源免费| 日韩欧美高清在线视频| 91国产高清在线| 亚洲区在线播放| 欧美洲成人男女午夜视频| 日韩av三级在线观看| 性色av香蕉一区二区| 日韩成人在线视频网站| 亚洲一区二区久久久| 亚洲欧美日韩中文在线| 亚洲欧美在线x视频| 日韩av手机在线看| 日韩日本欧美亚洲| 欧美精品精品精品精品免费| 亚洲精品二三区| 欧美日韩亚洲激情| 国产日韩欧美视频| 一区二区欧美在线| 97超碰国产精品女人人人爽| 亚洲国产精品va| 伊人青青综合网站| 欧美成人高清视频| 亚洲国产精品小视频| 欧美黄色免费网站| 九九久久久久久久久激情| 91免费的视频在线播放| 欧美日韩人人澡狠狠躁视频| 国产一区二区三区免费视频| 日韩欧美aaa| 91系列在线观看| 亚洲久久久久久久久久久| 亚洲美女av网站| 搡老女人一区二区三区视频tv| 欧美日韩国产综合视频在线观看中文| 国产欧美最新羞羞视频在线观看| 国产一区二区三区丝袜| 国产成人亚洲综合青青| 日韩理论片久久| 福利一区视频在线观看| 亚洲精品日产aⅴ| 国产精品视频地址| 2019亚洲男人天堂| 国产精品伦子伦免费视频| 视频在线观看99| 亚洲美女av电影| 久久久久久97| 欧美性猛交xxx| 精品一区二区电影| 欧美激情免费观看| 成人综合网网址| 日韩av在线高清| 日韩精品在线免费观看视频| 亚洲成人a**站| 亚洲天堂第二页| 九九热视频这里只有精品| 91精品国产91久久久久久| 亚洲成人激情小说| 91精品免费视频| 国产精品久久久一区| 亚洲图片欧洲图片av| 亚洲精品一区av在线播放| 亚州国产精品久久久| 欧美日韩福利电影| 最新中文字幕亚洲| 少妇高潮久久久久久潘金莲| 国产精品wwwwww| 在线视频欧美日韩| 亚洲成人亚洲激情| 亚洲肉体裸体xxxx137| 亚洲精品国产美女| 亚洲摸下面视频| 伦伦影院午夜日韩欧美限制| 欧美激情在线视频二区| 欧美日韩国产成人高清视频| 欧美尺度大的性做爰视频| 亚洲国产精品成人av| 亚洲自拍偷拍色图| 日韩欧美亚洲国产一区| 欧美成人在线影院| 国产91色在线|免| 亚洲成人久久电影| 精品日韩视频在线观看| 国产日韩换脸av一区在线观看| 国产主播欧美精品| 欧美在线亚洲一区| 精品国产一区二区三区久久狼黑人| 亚洲精品国产成人| 国产精品6699| 成人情趣片在线观看免费| 国产精品久久一| 欧美性猛交xxxx乱大交极品| 亚洲精品国产suv| 欧美性猛交xxxx富婆| 影音先锋欧美精品| 国产91精品最新在线播放| 国产成人av在线播放| 久久在线免费视频| 国产成人一区二区三区电影| 亚洲欧美日韩中文在线| 欧美午夜精品久久久久久久| 亚洲精品一区二区久| 国产精品露脸av在线| 欧美激情一区二区三级高清视频| 一区二区三区美女xx视频| 97久久久免费福利网址| 久久成年人免费电影| 久久天天躁狠狠躁夜夜躁2014| 日韩欧美视频一区二区三区| 在线播放日韩专区| 最近日韩中文字幕中文| 97久久久久久| 日本欧美一级片| 亚洲欧美日韩久久久久久| 精品亚洲永久免费精品| 国产精品免费久久久久影院| 久久精品国产2020观看福利| 国产91ⅴ在线精品免费观看| 欧美性xxxx18| 久久av资源网站| 久久人人爽人人爽爽久久| 亚洲精品国产精品国自产观看浪潮| 国产精品91在线| 国产精品尤物福利片在线观看| 国产一区二区三区视频| 亚洲在线免费视频| 欧美激情二区三区| 亚洲国产一区二区三区四区| 成人激情视频小说免费下载| 国产日韩在线播放| 日韩av观看网址| 日韩欧美在线视频日韩欧美在线视频|