html5 canvas onmouseover,Canvas 内部元素如何实现 mouseover/mousemove 事件?

这篇文章详细解读了Collie.Layer中mouseover事件的处理逻辑,通过循环判断和边界检查,展示了如何根据鼠标位置找到目标显示对象。涉及私有方法如_fireEvent和_getTargetOnHitEvent,以及移动设备环境下的特殊处理。
摘要由CSDN通过智能技术生成

自己看源代碼不就好了

和我想得一樣,就是循環判斷,比大小確定範圍,直到找到爲止。

想要實現 mouseover 啥的,自己照着 _fireEvent 調用 _getTargetOnHitEvent 即可

/**

* 레이어에서 이벤트가 일어났을 때 표시 객체에 이벤트를 발생 시킨다

*

* @param {Object} e 이벤트 원본

* @param {String} sType 이벤트 타입, mouse 이벤트로 변형되서 들어온다

* @param {Number} nX 이벤트가 일어난 상대좌표

* @param {Number} nY 이벤트가 일어난 상대좌표

* @return {Boolean} 표시 객체에 이벤트가 발생했는지 여부

* @private

*/

_fireEvent : function (e, sType, nX, nY) {

var oDisplayObject = null;

var bIsNotStoppedBubbling = true;

// 캔버스에서 이전 레이어에 객체에 이벤트가 일어났으면 다음 레이어의 객체에 전달되지 않는다

if (sType !== "mousemove" && !collie.Renderer.isStopEvent(sType)) {

var aDisplayObjects = this._oLayer.getChildren();

oDisplayObject = this._getTargetOnHitEvent(aDisplayObjects, nX, nY);

// mousedown일 경우 객체를 저장한다

if (oDisplayObject) {

bIsNotStoppedBubbling = this._bubbleEvent(oDisplayObject, sType, e, nX, nY);

if (sType === "mousedown") {

this._setMousedownObject(oDisplayObject);

}

if (sType === "mouseup") {

this._unsetMousedownObject(oDisplayObject);

}

}

}

// mouseup 처리가 안된 경우 임의 발생

if (sType === "mouseup" && this._getMousedownObject() !== null) {

oDisplayObject = this._getMousedownObject();

this._bubbleEvent(oDisplayObject, sType, e, nX, nY);

this._unsetMousedownObject(oDisplayObject);

}

/**

* click 이벤트, 모바일 환경일 때는 touchstart, touchend를 비교해서 좌표가 일정 이내로 움직였을 경우 click 이벤트를 발생한다d

* @name collie.Layer#click

* @event

* @param {Object} htEvent

* @param {collie.DisplayObject} htEvent.displayObject 대상 객체

* @param {HTMLEvent} htEvent.event 이벤트 객체

* @param {Number} htEvent.x 상대 x좌표

* @param {Number} htEvent.y 상대 y좌표

*/

/**

* mousedown 이벤트, 모바일 환경일 때는 touchstart 이벤트도 해당 된다.

* @name collie.Layer#mousedown

* @event

* @param {Object} htEvent

* @param {collie.DisplayObject} htEvent.displayObject 대상 객체

* @param {HTMLEvent} htEvent.event 이벤트 객체

* @param {Number} htEvent.x 상대 x좌표

* @param {Number} htEvent.y 상대 y좌표

*/

/**

* mouseup 이벤트, 모바일 환경일 때는 touchend 이벤트도 해당 된다.

* @name collie.Layer#mouseup

* @event

* @param {Object} htEvent

* @param {collie.DisplayObject} htEvent.displayObject 대상 객체

* @param {HTMLEvent} htEvent.event 이벤트 객체

* @param {Number} htEvent.x 상대 x좌표

* @param {Number} htEvent.y 상대 y좌표

*/

/**

* mousemove 이벤트, 모바일 환경일 때는 touchmove 이벤트도 해당 된다.

* @name collie.Layer#mouseup

* @event

* @param {Object} htEvent

* @param {collie.DisplayObject} htEvent.displayObject 대상 객체

* @param {HTMLEvent} htEvent.event 이벤트 객체

* @param {Number} htEvent.x 상대 x좌표

* @param {Number} htEvent.y 상대 y좌표

*/

if (bIsNotStoppedBubbling) { // stop되면 Layer이벤트도 일어나지 않는다

this._oLayer.fireEvent(sType, {

event : e,

displayObject : oDisplayObject,

x : nX,

y : nY

});

}

return !!oDisplayObject;

},

/**

* 이벤트 대상을 고른다

* - 가장 위에 있는 대상이 선정되어야 한다

* @private

* @param {Array|collie.DisplayObject} vDisplayObject

* @param {Number} nX 이벤트 상대 x 좌표

* @param {Number} nY 이벤트 상대 y 좌표

* @return {collie.DisplayObject|Boolean}

*/

_getTargetOnHitEvent : function (vDisplayObject, nX, nY) {

var oTargetObject = null;

if (vDisplayObject instanceof Array) {

for (var i = vDisplayObject.length - 1; i >= 0; i--) {

// 자식부터

if (vDisplayObject[i].hasChild()) {

oTargetObject = this._getTargetOnHitEvent(vDisplayObject[i].getChildren(), nX, nY);

// 찾았으면 멈춤

if (oTargetObject) {

return oTargetObject;

}

}

// 본인도

oTargetObject = this._getTargetOnHitEvent(vDisplayObject[i], nX, nY);

// 찾았으면 멈춤

if (oTargetObject) {

return oTargetObject;

}

}

} else {

return this._isPointInDisplayObjectBoundary(vDisplayObject, nX, nY) ? vDisplayObject : false;

}

},

/**

* DisplayObject 범위 안에 PointX, PointY가 들어가는지 확인

*

* @private

* @param {collie.DisplayObject} oDisplayObject

* @param {Number} nPointX 확인할 포인트 X 좌표

* @param {Number} nPointY 확인할 포인트 Y 좌표

* @return {Boolean} 들어간다면 true

*/

_isPointInDisplayObjectBoundary : function (oDisplayObject, nPointX, nPointY) {

// 안보이는 상태거나 이벤트를 받지 않는다면 지나감

if (

!oDisplayObject._htOption.useEvent ||

!oDisplayObject._htOption.visible ||

!oDisplayObject._htOption.width ||

!oDisplayObject._htOption.height ||

(oDisplayObject._htOption.useEvent === "auto" && !oDisplayObject.hasAttachedHandler())

) {

return false;

}

var htHitArea = oDisplayObject.getHitAreaBoundary();

// 영역 안에 들어왔을 경우

if (

htHitArea.left <= nPointX && nPointX <= htHitArea.right &&

htHitArea.top <= nPointY && nPointY <= htHitArea.bottom

) {

// hitArea 설정이 없으면 사각 영역으로 체크

if (!oDisplayObject._htOption.hitArea) {

return true;

} else {

var htPos = oDisplayObject.getRelatedPosition();

// 대상 Point를 상대 좌표로 변경

nPointX -= htPos.x;

nPointY -= htPos.y;

// transform 적용

var aHitArea = oDisplayObject._htOption.hitArea;

aHitArea = collie.Transform.points(oDisplayObject, aHitArea);

return this._isPointInPolygon(aHitArea, nPointX, nPointY);

}

}

return false;

},

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值