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

首頁 > 編程 > HTML > 正文

canvas實(shí)現(xiàn)按住鼠標(biāo)移動(dòng)繪制出軌跡的示例代碼

2024-08-26 00:20:25
字體:
供稿:網(wǎng)友

概要

工作以來,寫過vue、react、正則、算法、小程序等知識(shí),唯獨(dú)沒有寫過canvas,因?yàn)閷?shí)在不會(huì)??!

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

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

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

需求

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

canvas,鼠標(biāo)軌跡,canvas沿軌跡運(yùn)動(dòng)

原理

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

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

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

這是一個(gè)寬度800,高度400的畫布。為什么沒有寫px呢?哦,暫時(shí)沒搞懂,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學(xué)習(xí)</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、判斷當(dāng)前環(huán)境是否支持canvas。

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

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

3、獲取2d對(duì)象。

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

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

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

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

通常情況下,可以是x - rect.left和y - rect.top。但為什么實(shí)際上卻是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)起點(diǎn)。

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

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

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

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

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

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

源碼

分為3個(gè)文件,index.html、main.js、utils.js,這里用到了es6的語法,我是使用parcle配置好了開發(fā)環(huán)境,所以不會(huì)有報(bào)錯(cuò),如果你直接復(fù)制代碼,運(yùn)行的時(shí)候出現(xiàn)錯(cuò)誤,在無法升級(jí)瀏覽器的情況下,可以將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é)

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

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VeVb武林網(wǎng)。

 

注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到HTML教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
欧美在线free| 韩国日本美国免费毛片| 欧美久久久久久久久中文字幕| 欧美另类videosbestsex日本| 精品国产福利一区二区在线| 成人在线观看黄| 精品国产第一国产综合精品| 久久国产主播| 欧美国产97人人爽人人喊| 亚洲视频三区| 中文人妻一区二区三区| 亚洲成国产人片在线观看| 国产一区二区三区四区五区六区| 精品欧美一区二区三区久久久| 亚洲欧美综合精品久久成人| 精品小视频在线| 久久亚洲二区| 久久精品国产亚洲高清剧情介绍| 91高潮精品免费porn| 成在在线免费视频| av电影在线免费| 国产精品美女高潮无套| 欧美亚洲另类在线一区二区三区| 亚洲一区二区蜜桃| 国产亚洲精品一区二555| 国产精品天天狠天天看| 日韩视频一区在线| 免费av片风间由美在线| 私人影视中文字幕| 麻豆国产在线| 久久精品影视大全| 日韩精品一区二区三区丰满| 日韩欧美一二三四区| 高清shemale亚洲人妖| 男人与禽猛交狂配| 秋霞午夜鲁丝一区二区| 久久久久亚洲AV| 久久免费精品一区二区| 精精国产xxxx视频在线| 三年中国中文观看免费播放| 欧美激情一级欧美精品| 亚洲精品一区二三区不卡| 亚洲精品高清在线| 亚洲最新av网址| 免费看岛国视频在线观看| 91九蝌蚪视频| 台湾佬中文在线| 亚洲美女中文字幕| 国产精品一区二区人人爽| 中文在线а√在线| 亚洲欧洲另类精品久久综合| 玖玖玖免费嫩草在线影院一区| 日韩欧美在线123| 久久久久久久中文| 亚洲另类在线观看| 国内精品一区二区三区四区| yy6080久久伦理一区二区| 三上悠亚在线观看| a级片免费观看| 中文字幕在线视频网站| 国产精品狼人久久影院观看方式| 国产老熟女伦老熟妇露脸| 国产又爽又黄又刺激的软件| 欧美成人一级视频| 免费看黄视频网站| 欧美国产综合在线| 国产精品色午夜在线观看| 国产欧美综合在线观看第十页| 欧美黑人巨大xxx极品| 福利视频午夜| 国产精品suv一区二区69| 中文字幕在线永久在线视频| 亚洲最大的黄色网| 又黄又www的网站| 中文在线手机av| 91免费在线播放视频| 一区二区视频在线播放| 欧美日本韩国一区| 午夜精品99久久免费| 18禁免费观看网站| 日本一本草久p| 五月激情婷婷网| 中文字幕在线不卡一区二区三区| 全部a∨一极品视觉盛宴| 99精品视频中文字幕| 日本三级一区二区三区| 欧美亚洲色图校园春色| fc2ppv完全颜出在线播放| 中文字幕日韩精品一区| 国产伦精品一区二区三区四区免费| 青春草国产视频| 成人知道污网站| 亚洲精品第三页| 国产一区一区三区| 国产美女高潮一区二区三区| 男生和女生一起差差差视频| 国产精品一区二区婷婷| 欧美激情五月| 欧美亚洲国产一区二区三区va| 自拍日韩欧美| 久久精品国产亚洲av麻豆| 成人免费看片视频在线观看| 亚洲日本一区二区三区在线不卡| 国产精品视频黄色| 日韩高清欧美高清| 人妻丰满熟妇av无码区app| 亚洲国产精品电影在线观看| 一个人免费观看在线视频www| 青青在线精品| 色视频www在线播放国产| 免费大片黄在线| 欧美 日韩 国产 成人 在线| 一区二区三区欧美精品| 国产美女www爽爽爽视频| 欧美电影网站| a级片一区二区| 亚洲人成网站色ww在线| 日韩hd视频在线观看| 日本高清色图| www.av99| 99综合电影在线视频| 六月丁香综合| 黑丝av在线播放| 青青久久av北条麻妃黑人| 久草在线最新视频| 伊人情人综合网| 欧美日韩综合色| 精品国产31久久久久久| 久久久久久久久久久人体| 国产精品久久久久桃色tv| 日韩欧美黄色动漫| 亚洲国产视频网站| 久久天天躁狠狠躁夜夜躁| 一区二区三区视频观看| 97国产suv精品一区二区62| 一级黄色片毛片| 日日摸夜夜添一区| 精品人妻少妇嫩草av无码| 三区四区在线观看| 国产成人久久久精品一区| 欧美区国产区| 亚洲视频狠狠| 九色成人国产蝌蚪91| 婷婷综合国产| 国模gogo一区二区大胆私拍| 99在线视频精品| 国产精品亚洲一区二区无码| 99九九99九九九99九他书对| 久久免费区一区二区三波多野| 国产精品theporn88| 1024av视频| 懂色av一区二区三区免费观看| 天天色天天射天天综合网| 91桃色在线观看| 日本少妇激情视频| 亚洲网址在线| av成人免费在线观看| 亚洲成av人片在线观看| 亚欧日韩另类中文欧美| 亚洲欧美二区三区| 国产精选在线视频拍拍拍| 亚洲国产日韩综合一区| 天天想你在线观看完整版电影免费| 欧美日韩国产999| 狠狠干综合网| 性感美女一级片| 日本不卡视频一区二区| 日韩中文字幕亚洲一区二区va在线| 91无套直看片红桃在线观看| 免费av观看网站| 精品伦一区二区三区| 亚洲大胆精品| 小早川怜子一区二区三区| 国产免费高清av| 日韩亚洲精品电影| 欧亚洲嫩模精品一区三区| 怡春院在线视频| 国产一区国产二区国产三区| 日韩精品亚洲专区在线观看| www.亚洲人.com| 婷婷色一区二区三区| 成人激情免费电影网址| 国产精品免费观看视频| 国内精品视频| 中文字幕v亚洲ⅴv天堂| 成人av网站在线| 午夜影视日本亚洲欧洲精品| 992tv成人免费观看| 中文字幕精品综合| xvideos亚洲人网站| 国产一区二区福利视频| 男人女人靠逼视频| 超碰在线观看免费| 欧美一级夜夜爽| 最大av网站| 国产手机视频一区二区| 国产精品综合在线视频| 456亚洲精品成人影院| 青青操综合网| 欧美日韩另类丝袜其他| 久久av.com| 日本一区二区三区四区在线观看| 中文字幕亚洲综合久久五月天色无吗''| 午夜精品一二三区| 18被视频免费观看视频| 国产一区视频在线观看免费| 国产视频不卡| 麻豆精品网站| 国产一区二区三区免费在线| 亚洲综合色自拍一区| 四虎免费在线视频| 日韩精品中午字幕| 欧美日韩一区二区三区在线| 欧美性孕妇孕交| 性生活视频网站| 一区二区三区精品| 欧美mv和日韩mv国产网站| 欧美亚洲不卡| 日本熟妇人妻xxxxx| 嫩草影院一区二区三区| 清纯唯美亚洲经典中文字幕| 亚洲系列在线观看| 国产精品久久久久久久久久新婚| 欧美成人午夜做爰视频在线观看| 中文字幕在线免费观看视频| 亚洲精品国产高清久久伦理二区| 欧美国产一区二区在线观看| 日韩有码在线电影| 亚洲综合一区二区不卡| 久久影音资源网| 久久99国产精品| 全程偷拍露脸中年夫妇| 国产经典自拍视频在线观看| av免费在线视| 国产精品精品一区二区三区午夜版| 亚洲综合激情六月婷婷在线观看| 97se亚洲国产综合自在线| free极度另类性欧美| 日本一区二区免费视频| avove在线观看| 中文字幕在线三区| 国产一区二区三区精品欧美日韩一区二区三区| 中国老头性行为xxxx| 精品久久久久久亚洲| 中文先锋资源| 欧美日韩一区二区免费在线观看| 毛片在线免费| 日韩爱爱小视频| 亚洲激情电影中文字幕| 我和岳m愉情xxxⅹ视频| 涩涩漫画在线观看| 特黄aaaaaaaaa毛片免费视频| 欧美日韩一区二区国产| 少妇的滋味中文字幕bd| 欧美影院一区| 成人午夜大片| 日日干日日操日日射| 午夜美女福利视频| 日韩免费一区二区三区在线播放| 亚洲欧洲精品一区二区精品久久久| 污视频免费在线观看网站| av官网在线| 久久久久国产精品视频| 黄色免费视频观看| 写真福利理论片在线播放| 亚洲欧美另类图片小说| 国产不卡在线观看| 欧美一级大片在线观看| 不卡的国产精品| 在线免费不卡视频| 亚洲国产精品av| 一本色道久久综合精品竹菊| 久久久久久久久久免费视频| 欧美日韩亚洲一区三区| 国产乱码字幕精品高清av| 精品国产aⅴ一区二区三区东京热| 日韩欧美专区| 亚洲韩国青草视频| 婷婷免费在线视频| 日韩毛片在线| 最新中文字幕免费视频| 永久免费毛片在线观看| 久久久久久久九九九九| 91综合久久一区二区| 日韩小视频在线观看专区| 伊人伊成久久人综合网小说| 欧美一级大黄| 久久不卡日韩美女| 免费91麻豆精品国产自产在线观看| 国产一级视频| 国产又粗又黄又爽的视频| 91麻豆免费在线视频| 日韩午夜小视频| 极品中文字幕一区| 国产亚洲精品午夜高清影院| 99热在线网站| 欧美一级二级在线观看| 国产欧美综合视频| 日韩高清电影免费| 久久99热国产| 在线视频中文字幕久| 青青草精品在线视频| 激情丁香综合| 亚洲激情在线播放| 日韩少妇内射免费播放| 免费观看成人性生生活片| 国产精品678| 国产字幕视频一区二区| 91p在线观看| 亚洲人做受高潮| 久久影视电视剧免费网站| 久久综合九九| 欧美日韩成人影院| 亚洲欧美制服丝袜| 在线观看国产精品入口男同| 美女免费黄色| 婷婷夜色潮精品综合在线| 亚洲专区第一页| 成人全视频高清免费观看| 残酷重口调教一区二区| 超碰在线公开97| 欧美日韩精品一区二区三区在线观看| 97精品国产97久久久久久免费| 高清shemale亚洲人妖| 九九热精品免费视频| 99.玖玖.com| 哺乳一区二区三区中文视频| 国产国语**毛片高清视频|