如何实现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.onmousedown=function(e){
        moveFlag=true;
        var clickEvent=window.event||e;
        var mwidth=clickEvent.clientX-divObj.offsetLeft;
        var mheight=clickEvent.clientY-divObj.offsetTop;
        document.onmousemove=function(e){
            var moveEvent=window.event||e;
            if(moveFlag){
                divObj.style.left=moveEvent.clientX-mwidth+"px";
                divObj.style.top=moveEvent.clientY-mheight+"px";
                divObj.onmouseup=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左边和上边的距离。如果不加修正:

这就是不加修正的结果,当光标点下时,div的坐标即左上角会与光标坐标一致。

修正后:

点击时光标总会“粘”在div某点上。

接下来绘制图片:

首先定义全局变量X和Y,它们是为了实时更新图像的绘制坐标。

 var ctx=document.getElementById("myCanvas").getContext("2d");
 var img=document.getElementById("myImg");
    function drawImg(){
        ctx.clearRect(0,0,1000,500);
        ctx.beginPath();
        ctx.drawImage(img,X,Y);
        ctx.closePath();
        ctx.stroke();
    }

    window.onload=function(){
        setInterval(drawImg,1);
    }

获取“画笔”,获取图片对象。这里setInterval循环执行绘制图片的函数,以刷新图片的位置,setInterval的间隔值越小,拖拽起来越“流畅”。

同时别忘了clearRect,当图片移动到下一个位置时,清除上一个位置的图片,参数为Canvas画布的坐标和尺寸。

在拖拽时将修正后的光标坐标传给X、Y:

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

这个就看个人的要求了,注意是要同时限定div和图片的活动范围。1000与500为本例的画布大小,如果是在整个页面里活动就换成innerWidth或innerHeight。

彻底隐藏div看看效果:

最后说下点击事件,这里要注意的是在拖拽的过程中onmousedown与onmouseup二者就构成了一个click过程,但我们不希望在拖拽结束后触发点击事件。

这里有个比较简单的办法,定义一个clickFlag默认为false,当onmousedown时设为true,若进行了onmousemove事件时设为false。

在最后onmouseup时判断clickFlag的值,为true时才触发点击事件。也就是说当你按下鼠标时,只有不发现移动,松开鼠标时才会触发点击事件。

 

整理后的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.onmousemove=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.onmouseup=function(){
                    moveFlag=false;
                    if(clickFlag){
                        alert("点击生效");
                    }
                }
            }
        }
    };

本例到此结束,更多功能大家有兴趣可以自己开发,感谢您的浏览,也感谢每个对我这菜鸟提意见的人。

转载于:https://www.cnblogs.com/ghost-xyx/p/3833179.html

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Python中的tkinter库的canvas组件来实现图片裁剪。以下是一个基本的示例代码: ```python import tkinter as tk from PIL import Image, ImageTk class ImageCropper: def __init__(self, image_path): self.root = tk.Tk() self.canvas = tk.Canvas(self.root, width=500, height=500) self.canvas.pack() self.image = Image.open(image_path) self.tk_image = ImageTk.PhotoImage(self.image) self.canvas.create_image(0, 0, anchor=tk.NW, image=self.tk_image) self.rect = None self.start_x = None self.start_y = None self.end_x = None self.end_y = None self.canvas.bind("<Button-1>", self.on_button_press) self.canvas.bind("<B1-Motion>", self.on_move_press) self.canvas.bind("<ButtonRelease-1>", self.on_button_release) self.root.mainloop() def on_button_press(self, event): self.start_x = event.x self.start_y = event.y if not self.rect: self.rect = self.canvas.create_rectangle(self.start_x, self.start_y, 1, 1, outline='red', width=3) def on_move_press(self, event): if self.rect: self.end_x = event.x self.end_y = event.y self.canvas.coords(self.rect, self.start_x, self.start_y, self.end_x, self.end_y) def on_button_release(self, event): if self.rect: self.image = self.image.crop((self.start_x, self.start_y, self.end_x, self.end_y)) self.tk_image = ImageTk.PhotoImage(self.image) self.canvas.delete(self.rect) self.canvas.create_image(0, 0, anchor=tk.NW, image=self.tk_image) if __name__ == '__main__': cropper = ImageCropper('image.jpg') ``` 在这个示例代码中,我们首先创建了一个名为ImageCropper的类,它接收一个图像路径作为参数。我们创建了一个tkinter的canvas组件,并将图像加载到canvas中。 我们还定义了一个on_button_press方法,用于在鼠标左键按下时创建一个矩形。on_move_press方法用于跟踪鼠标移动,从而更新矩形的位置和大小。最后,on_button_release方法用于在鼠标释放时裁剪图像,删除矩形并更新canvas中的图像。 在main函数中,我们实例化ImageCropper类并传递要裁剪的图像路径。运行程序后,我们可以使用鼠标选择要裁剪的区域,然后按下鼠标左键并拖动以选择区域。释放鼠标左键后,程序将裁剪图像并更新canvas中的图像

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值