canvas 什么情况下禁止拖动

JavaScript026

canvas 什么情况下禁止拖动,第1张

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.onmousedown=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("点击生效")

}

}

}

}

}

实现思路:

①鼠标按下+鼠标移动 → 拖拽

②鼠标松开 → 无拖拽

③鼠标偏移 → 拖拽距离

用JavaScript事件方法表示就是:

① onmousedown + onmousemove → startDrag()

② onmouseup → stopDrag()

drag.js代码:

var params = {

left: 0,

top: 0,

currentX: 0,

currentY: 0,

flag: false

}

//获取相关CSS属性

var getCss = function(o,key){

return o.currentStyle? o.currentStyle[key] : document.defaultView.getComputedStyle(o,false)[key] 

}

//拖拽的实现

var startDrag = function(bar, target, callback){

if(getCss(target, "left") !== "auto"){

params.left = getCss(target, "left")

}

if(getCss(target, "top") !== "auto"){

params.top = getCss(target, "top")

}

//o是移动对象

bar.onmousedown = function(event){

params.flag = true

if(!event){

event = window.event

//防止IE文字选中

bar.onselectstart = function(){

return false

}  

}

var e = event

params.currentX = e.clientX

params.currentY = e.clientY

}

document.onmouseup = function(){

params.flag = false

if(getCss(target, "left") !== "auto"){

params.left = getCss(target, "left")

}

if(getCss(target, "top") !== "auto"){

params.top = getCss(target, "top")

}

}

document.onmousemove = function(event){

var e = event ? event: window.event

if(params.flag){

var nowX = e.clientX, nowY = e.clientY

var disX = nowX - params.currentX, disY = nowY - params.currentY

target.style.left = parseInt(params.left) + disX + "px"

target.style.top = parseInt(params.top) + disY + "px"

}

if (typeof callback == "function") {

callback(parseInt(params.left) + disX, parseInt(params.top) + disY)

}

}

}

HTML/CSS

<style type="text/css">

#box{position:absolute left:100px top:100px padding:5px background:#f0f3f9 font-size:12px -moz-box-shadow:2px 2px 4px #666666 -webkit-box-shadow:2px 2px 4px #666666}

#main{border:1px solid #a0b3d6 background:white}

#bar{line-height:24px background:#beceeb border-bottom:1px solid #a0b3d6 padding-left:5px cursor:move}

#content{width:420px height:250px padding:10px 5px}

</style>

<div id="box">

    <div id="main">

        <div id="bar">拖拽</div>

        <div id="content">

            内容……

        </div>

    </div>

</div>

JS部分

<script src="drag.js" type="text/javascript"></script>

<script type="text/javascript">

    var oBox = document.getElementById("box")

    var oBar = document.getElementById("bar")

    startDrag(oBar, oBox)

</script>