python canvas畫移動物體_如何實現Canvas圖像的拖拽、點擊等操作

上一篇Canvas的博文寫完后,有位朋友希望能對Canvas繪制出來的圖像進行點擊、拖拽等操作,因為Canvas繪制出的圖像能很好的美化。好像是想做爐石什么的游戲,我也沒玩過。

Canvas在我的理解中就好像在一張畫布上繪制圖像,它只能看到卻“摸”不到,那要如何進行操作呢。我不知道網上是怎么做的,這里用自己的想法做了個DEMO分享給大家。

思路:

雖然Canvas不能拖拽,但div可以拖拽,那怎么把二者結合起來呢。初步想法是將一個與Canvas圖像大小差不多的div覆蓋在其上,在拖拽div時將獲取的光標坐標修正后傳給Canvas繪制函數并刷新圖像的位置。

既然要覆蓋,先做些準備工作:

1.將div與Canvas畫布均position:absolute,否則無法重疊。

2.將div的z-index值設置大點,保證其在Canvas畫面之上。

準備工作完成后,我們先來看div的拖拽:

var divObj=document.getElementById("cover");var moveFlag=false;

divObj.οnmοusedοwn=function(e){

moveFlag=true;var clickEvent=window.event||e;var mwidth=clickEvent.clientX-divObj.offsetLeft;var mheight=clickEvent.clientY-divObj.offsetTop;

document.οnmοusemοve=function(e){var moveEvent=window.event||e;if(moveFlag){

divObj.style.left=moveEvent.clientX-mwidth+"px";

divObj.style.top=moveEvent.clientY-mheight+"px";

divObj.οnmοuseup=function(){

moveFlag=false;

}

}

}

};

來解讀下這段代碼:首先獲取div對象,設置拖拽標志moveFlage,當onmousedown時為true表示可以拖動,當onmouseup時為false表示不能拖動了。

var clickEvent=window.event||e;var mwidth=clickEvent.clientX-divObj.offsetLeft;var mheight=clickEvent.clientY-divObj.offsetTop;

這三行代碼是為了修正光標位置。當點擊時,記錄下光標在div上的位置。mwidth和mheight表示光標落點相對于div左邊和上邊的距離。如果不加修正:

628eb2d5c2c3e29d4aacfedfda921cb4.gif

這就是不加修正的結果,當光標點下時,div的坐標即左上角會與光標坐標一致。

修正后:

d2a310a2e93fb679a14c62800288b639.gif

點擊時光標總會“粘”在div某點上。

接下來繪制圖片:

首先定義全局變量X和Y,它們是為了實時更新圖像的繪制坐標。

var ctx=document.getElementById("myCanvas").getContext("2d");var img=document.getElementById("myImg");functiondrawImg(){

ctx.clearRect(0,0,1000,500);

ctx.beginPath();

ctx.drawImage(img,X,Y);

ctx.closePath();

ctx.stroke();

}

window.οnlοad=function(){

setInterval(drawImg,1);

}

獲取“畫筆”,獲取圖片對象。這里setInterval循環執行繪制圖片的函數,以刷新圖片的位置,setInterval的間隔值越小,拖拽起來越“流暢”。

同時別忘了clearRect,當圖片移動到下一個位置時,清除上一個位置的圖片,參數為Canvas畫布的坐標和尺寸。

在拖拽時將修正后的光標坐標傳給X、Y:

X=moveEvent.clientX-mwidth;

Y=moveEvent.clientY-mheight;

c797afd5ddb73a944554f8b5a1c2c517.gif

最后加上div和圖像的活動范圍:

if(moveEvent.clientX<=mwidth){

divObj.style.left=0+"px";

X=0;

}if(parseInt(divObj.style.left)+divObj.offsetWidth >=1000){

divObj.style.left=1000 - divObj.offsetWidth+"px";

X=1000 -divObj.offsetWidth;

}if(moveEvent.clientY<=mheight){

divObj.style.top=0+"px";

Y=0;

}if(parseInt(divObj.style.top)+divObj.offsetHeight>=500){

divObj.style.top=500-divObj.offsetHeight+"px";

Y=500-divObj.offsetHeight;

}

這個就看個人的要求了,注意是要同時限定div和圖片的活動范圍。1000與500為本例的畫布大小,如果是在整個頁面里活動就換成innerWidth或innerHeight。

徹底隱藏div看看效果:

e33a60b22d56ea5d00a6a79ed814e832.gif

最后說下點擊事件,這里要注意的是在拖拽的過程中onmousedown與onmouseup二者就構成了一個click過程,但我們不希望在拖拽結束后觸發點擊事件。

這里有個比較簡單的辦法,定義一個clickFlag默認為false,當onmousedown時設為true,若進行了onmousemove事件時設為false。

在最后onmouseup時判斷clickFlag的值,為true時才觸發點擊事件。也就是說當你按下鼠標時,只有不發現移動,松開鼠標時才會觸發點擊事件。

8a14224fc591c629b85848ef16bb8f4d.gif

整理后的JS代碼:

//繪制圖片坐標

var X=0;var Y=0;//js部分

var divObj=document.getElementById("cover");var moveFlag=false;//區別moueseup與click的標志

var clickFlag=false;//拖拽函數

divObj.οnmοusedοwn=function(e){

moveFlag=true;

clickFlag=true;var clickEvent=window.event||e;var mwidth=clickEvent.clientX-divObj.offsetLeft;var mheight=clickEvent.clientY-divObj.offsetTop;

document.οnmοusemοve=function(e){

clickFlag=false;var moveEvent=window.event||e;if(moveFlag){

divObj.style.left=moveEvent.clientX-mwidth+"px";

divObj.style.top=moveEvent.clientY-mheight+"px"; 將鼠標坐標傳給Canvas中的圖像

X=moveEvent.clientX-mwidth;

Y=moveEvent.clientY-mheight; 下面四個條件為限制div以及圖像的活動邊界

if(moveEvent.clientX<=mwidth){

divObj.style.left=0+"px";

X=0;

}if(parseInt(divObj.style.left)+divObj.offsetWidth >=1000){

divObj.style.left=1000 - divObj.offsetWidth+"px";

X=1000 -divObj.offsetWidth;

}if(moveEvent.clientY<=mheight){

divObj.style.top=0+"px";

Y=0;

}if(parseInt(divObj.style.top)+divObj.offsetHeight>=500){

divObj.style.top=500-divObj.offsetHeight+"px";

Y=500-divObj.offsetHeight;

}

divObj.οnmοuseup=function(){

moveFlag=false;if(clickFlag){

alert("點擊生效");

}

}

}

}

};

本例到此結束,更多功能大家有興趣可以自己開發,感謝您的瀏覽,也感謝每個對我這菜鳥提意見的人。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536864.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536864.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536864.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Git基礎知識教程整理(Git基本操作)

Git簡介 Git是目前世界上最先進的分布式版本控制系統&#xff08;沒有之一&#xff09;。Linux之父Linux用C語言寫了Git分布式版本控制系統。 分布式版本控制系統與集中式版本控制系統的區別 區別分布式集中式中央服務器有&#xff0c;版本庫集中存放在中央服務器&#xff0c;工…

python plot map_使用matplotlibbasemap在邊界打印

我在繪制多邊形時遇到了困難&#xff0c;例如&#xff0c;在使用matplotlib basemap生成的地圖邊界上繪制多邊形。在下面的示例中&#xff0c;地圖邊界由日期線指定。我試圖通過指定三角形頂點的坐標來繪制一個跨越日期線的三角形。當所有的坐標都在地圖內時&#xff0c;這種方…

SQL查詢語句 group by后, 字符串合并

合并列值 --******************************************************************************************* 表結構&#xff0c;數據如下&#xff1a; id value ----- ------ aa bb aaa bbb ccc 需要得到結果&#xff1a; id values ------ ----------- aa,bb aaa…

Git 基礎 —— 常用命令

Git 基礎學習系列 Git 基礎 —— 安裝 配置 別名 對象Git 基礎 —— 常用命令Git 基礎 —— 常見使用場景Git基礎 —— Github 的使用git init 創建 Git 本地倉庫 遠端無倉庫&#xff0c;本地無倉庫&#xff0c;本地新建一個倉庫 git init git_learning 遠端有倉庫&#xff0c;…

python安裝caffe_Linux下caffe的安裝

下載caffe并保存到一個目錄下(推薦放到 /home 目錄)安裝依賴項&#xff1a;sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compilersudo apt-get install --no-install-recommends libboost-all-devsudo apt-…

linux 訪問Windows 共享文件的方法

2019獨角獸企業重金招聘Python工程師標準>>> 1 安裝Samba服務 2 啟動 samba服務 /etc/init.d/smb restart 3 安裝插件 cifs解決只讀掛載&#xff1a;yum install cifs-utils.x86_64 4 在windows下共享一個可以用的文件夾 5 將 windows 共享文件夾掛載到linux上 命令…

基于Blink構建親聽項目以及全鏈路debug項目實時響應能力

案例與解決方案匯總頁&#xff1a;阿里云實時計算產品案例&解決方案匯總 本文全面總結了大數據項目組在親聽項目以及全鏈路debug項目上進行的實時流處理需求梳理&#xff0c;架構選型&#xff0c;以及達成效果 一、背景介紹 1.1親聽項目 親聽項目專注于幫助用戶收集、展示、…

python的重點_python知識點

"""author:lei"""import os#os.path.join() 將分離的部分合成一個整體filenameos.path.join(/home/ubuntu/python_coding,split_func)print filename#輸出為&#xff1a;/home/ubuntu/python_coding/split_func#os.path.splitext()將文件名和擴展…

在既有系統中打通Apache Ignite、MySQL和Node.js

為什么80%的碼農都做不了架構師&#xff1f;>>> 介紹 在本系列的第一篇文章中&#xff0c;安裝了Node.js、Ignite的Node.js瘦客戶端包&#xff0c;并且測試了一個示例應用。在本文中&#xff0c;可以看一下Ignite在處理其它數據源&#xff08;比如關系數據庫&#…

java hashmap 的api_JAVA基礎--JAVA API集合框架(ArrayList、HashSet、HashMap使用)

一、集合Collection1. 集合介紹變量&#xff1a;表示的內存中的一個空間&#xff0c;只能保存確定類型的單個數據數組&#xff1a;表示的是內存中的多個連續的空間&#xff0c;這些空間中可以存儲多個同類型的數據。后期繼續學習面向對象技術&#xff0c;我們在程序中開始創建對…

Vue進階知識筆記

利用v-for循環出的多個li標簽&#xff0c;點擊不同的li變換顏色 方法一 <ul v-for"(item,index) in list" :key"index" class"details"><li ref"lisd" click"faillist(index)" :class"{active:ind index}&qu…

teamcity mysql 配置_CentOS 7 上 TeamCity 安裝

CentOS 7 上 TeamCity 安裝非入門教程, 初次接觸centos/docker的朋友需要謹慎一. 安裝 MySQL為了后續的需要, 這里安裝了 Docker, 當然如果你已經有了 MySQL 或者其它推薦的數據庫[MySQL, PostgreSQL, Oracle, MS SQL], 則可忽略1. 安裝 Docker補充:# 啟動dockersudo systemctl…

Python網絡請求庫Requests,媽媽再也不會擔心我的網絡請求了(二)

本文同步發表于我的微信公眾號&#xff0c;掃一掃文章底部的二維碼或在微信搜索 極客導航 即可關注&#xff0c;每個工作日都有文章更新。 一、概況 接著上篇說&#xff0c;如果你真以為Requests網絡請求庫只有Get請求和Post請求&#xff0c;那就大錯特錯了。它還一些其他用法&…

dbunit java_java - 錯誤地拋出了Java DBUnit AmbiguousTableNameException - 堆棧內存溢出

我正在嘗試DBUnit(2.6.0)&#xff0c;我正在嘗試導出我的完整數據庫(PostgreSQL)。 但是拋出以下異常&#xff1a;線程“main”中的異常org.dbunit.database.AmbiguousTableNameException&#xff1a;FLYWAY_SCHEMA_HISTORY這是正確的行為&#xff0c;因為我有兩個具有相同名稱…

Docker 命令詳解(run篇)

參考&#xff1a;https://www.cnblogs.com/yfalcon/p/9044246.html 命令格式&#xff1a;docker run [OPTIONS] IMAGE [COMMAND] [ARG...]Usage: Run a command in a new container中文意思為&#xff1a;通過run命令創建一個新的容器&#xff08;container&#xff09; 常用選…

java 同步 lock_關于java:同步是否像Lock.lock()一樣駐留并發線程?

當我們調用lock.lock()或嘗試輸入synchronized塊時&#xff0c;如果其他某個線程已經獲得了該鎖&#xff0c;則我們的線程將阻塞。 現在我的問題是&#xff0c;當我們查看lock.lock()的實現時&#xff0c;它會將獲取鎖委托給AQS&#xff0c;而AQS實際將當前線程駐留在該線程中(…

Idea項目中常見錯誤及筆記(Old)

1、Idea基礎設置&#xff1a; File-->settings--> 1>修改字體&#xff1a;Font 2>修改編碼格式&#xff1a;File Encodings(全部UTF-8,右下方復選框勾中--防止程序中的漢字轉為ASCII碼) 3>修改行號&#xff1a;Appearance&#xff1a;show line numbers show me…

java接口服務編排_GOKU API Gateway CE V3.1.0 發布:新增服務編排、配置版本管理等...

Goku API Gateway (中文名&#xff1a;悟空 API 網關)是一個基于 Golang 開發的微服務網關&#xff0c;能夠實現高性能 HTTP API 轉發、服務編排、多租戶管理、API 訪問權限控制等目的&#xff0c;擁有強大的自定義插件系統可以自行擴展&#xff0c;并且提供友好的圖形化配置界…

maxcompute 2.0復雜數據類型之array

2019獨角獸企業重金招聘Python工程師標準>>> 1. 含義 類似于Java中的array。有序、可重復。 2. 場景 什么樣的數據&#xff0c;適合使用array類型來存儲呢&#xff1f;這里列舉了幾個我在開發中實際用到的場景。 2.1 標簽類的數據 為什么說標簽類數據適合使用array類…

java中匿名數組_Swagger UI:數組中的多個匿名對象

對象數組的定義如下&#xff1a;type: arrayitems:type: objectproperties:prop1:type: stringprop2:type: integer# etc.在您的示例中&#xff0c;響應包含具有屬性 balanceDisplaySettings 的對象&#xff0c;并且此屬性包含對象數組 . 這可以定義如下&#xff1a;paths:/Pat…