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.mzph.cn/news/536864.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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;…

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亲听项目 亲听项目专注于帮助用户收集、展示、…

在既有系统中打通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;我们在程序中开始创建对…

dbunit java_java - 错误地抛出了Java DBUnit AmbiguousTableNameException - 堆栈内存溢出

我正在尝试DBUnit(2.6.0)&#xff0c;我正在尝试导出我的完整数据库(PostgreSQL)。 但是抛出以下异常&#xff1a;线程“main”中的异常org.dbunit.database.AmbiguousTableNameException&#xff1a;FLYWAY_SCHEMA_HISTORY这是正确的行为&#xff0c;因为我有两个具有相同名称…

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类…

权限组件(6):权限分配的角色管理

效果图&#xff1a; 为了方便开发&#xff0c;先把中间件注释掉&#xff0c;要不还要在角色-权限表中添加对应关系。又因为二级菜单和面包屑导航需要中间件的变量&#xff0c;所以要在layout.html里面把这两个也注释掉。setting.py# rbac.middlewares.rbac.RbacMiddleware layo…

02-Django基础知识

一、内容回顾 1、web应用程序 2、HTTP协议 a、http协议特性 b、http请求格式 c、http响应格式 3、wsgiref模块 4、Django下载与简单应用 a、Django简介&#xff08;MTV&#xff09; b、下载django命令 c、创建项目命令 d、创建app应用 e、启动项目   二、今日概要 1、路由层&…

java解析上的jar包里的pom_Maven引入本地Jar包并打包进War包中的方法

1.概述在平时的开发中&#xff0c;有一些Jar包因为种种原因&#xff0c;在Maven的中央仓库中没有收录&#xff0c;所以就要使用本地引入的方式加入进来。2. 拷贝至项目根目录项目根目录即pom.xml文件所在的同级目录&#xff0c;可以在项目根目录下创建文件夹lib&#xff0c;如下…

java静态工厂方法模式_设计模式:简单工厂模式(静态工厂方法模式)

简单工厂的构成包括三个角色&#xff1a;1)抽象产品类2)具体产品类(继承抽闲产品类)3)工厂类(生产具体产品)具体代码实现1、抽象产品类/*** 抽象类*/public abstract class Car {/*** 产品抽象方法&#xff0c;将会由具体产品类实现*/public abstract void driving();}2、具体产…

Kibana中的Coordinate Map地图报索引错误的问题

今天做地图定位展示&#xff0c;展示的是ApacheWeb服务器的访问日志文件中的来源IP。但是中间出现了报错环节&#xff0c;说是索引不能匹配到geo_point类型&#xff0c;实在是不懂这是在说什么&#xff0c;后来在网站找了方法就解决了。主要报错如下&#xff1a; 报错信息&…

windows软链接的建立及删除

2019独角兽企业重金招聘Python工程师标准>>> 1.建立举例 # 建立d:develop链接目录&#xff0c;指向远程的目标服务器上的e盘的对应目录。 mklink /d d:\develop \\138.20.1.141\e$\develop# 建立d:develop链接目录&#xff0c;指向远程的目标服务器上的e盘的对应目录…

php原生类,反序列化之PHP原生类的利用

正文文章围绕着一个问题&#xff0c;如果在代码审计中有反序列化点&#xff0c;但是在原本的代码中找不到pop链该如何?N1CTF有一个无pop链的反序列化的题目&#xff0c;其中就是找到php内置类来进行反序列化。基础知识首先还是来回顾一下序列化中的魔术方法&#xff0c;下面也…

Spectral Bounds for Sparse PCA: Exact and Greedy Algorithms[贪婪算法选特征]

目录 概括Sparse PCA Formulation非常普遍的问题Optimality ConditionsEigenvalue Bounds算法代码概括 这篇论文&#xff0c;不像以往的那些论文&#xff0c;构造优化问题&#xff0c;然后再求解这个问题&#xff08;一般都是凸化&#xff09;。而是&#xff0c;直接选择某些特…

TikTok与环保:短视频如何引领可持续生活方式?

在数字时代&#xff0c;社交媒体平台扮演着塑造文化和价值观的关键角色。而TikTok&#xff0c;作为一款全球短视频平台&#xff0c;不仅塑造着用户的娱乐方式&#xff0c;还在悄然地引领着可持续生活方式的潮流。本文将深入探讨TikTok与环保之间的关系&#xff0c;分析短视频如…