"use strict";
var jQuery = require("jquery");
/**
* @ignore
* 画布
*/
function MouseEvent(session, viewID, displayElem) {
jQuery(displayElem).attr("tabindex", 0);//绑定div去响应键盘消息,需要自己设置焦点
displayElem.style.outline = "none";
var button = -1;//记录鼠标按下的键值
// 当网络请求断开后,解绑鼠标监听
session.addNetworkCloseListener(function(){
jQuery(displayElem).off('mousedown mouseup mousemove mousewheel DOMMouseScroll mouseleave mouseenter dblclick', sendMouseEvent);
jQuery(displayElem).off('touchend touchstart touchmove', sendTouchEvent);
});
// 处理鼠标事件
function sendMouseEvent(e) {
var obj = {
type : -1,
x: e.offsetX,
y: e.offsetY
};
if(e.preventDefault) e.preventDefault();
switch (e.type) {
case 'mousedown':
obj.type = 1;
obj.button = e.which;
button = obj.button;
displayElem.focus(); //鼠标选中的元素切回焦点(因input元素的焦点在选择之后是不会切回的)
break;
case 'mouseup':
obj.type = 2;
obj.button = e.which;
button = -1;
break;
case 'mousemove':
obj.type = 3;
break;
case 'mousewheel':
obj.wheelDelta = e.originalEvent.wheelDelta;
obj.type = 4;
displayElem.focus();
break;
case 'DOMMouseScroll':
obj.wheelDelta = -e.originalEvent.detail * 40; // detail为3的倍数,wheelDelta是120的倍数
obj.type = 4;
break;
case 'dblclick':
obj.type = 5;
break;
case 'mouseenter':
jQuery(document).off("mouseup mousemove contextmenu", docMouseEvent);
break;
case 'mouseleave':
if (button >= 0){
jQuery(document).on('mouseup mousemove contextmenu', docMouseEvent);
}
return false;
default:
break;
}
if (obj.type > 0 && obj.x && obj.y) {
session.request(viewID, "mouseEvent", obj);
if(obj.type === 5){ //因浏览器dblclick不发送up消息,所以在此自己发送一次,不然后台的处理
obj.type = 2;
obj.button = 1;
session.request(viewID, "mouseEvent", obj);
}
}
//不能返回false,会同时调用preventDefault和stopPropagation
return true;
}
function getElementTop(element){
var actualTop = element.offsetTop;
var current = element.offsetParent;
while (current !== null){
actualTop += current.offsetTop;
current = current.offsetParent;
}
return actualTop;
}
function getElementLeft(element){
var actualLeft = element.offsetLeft;
var current = element.offsetParent;
while (current !== null){
actualLeft += current.offsetLeft;
current = current.offsetParent;
}
return actualLeft;
}
function docMouseEvent(e) {
var obj = {
type: -1,
x: e.pageX - getElementLeft(displayElem),
y: e.pageY - getElementTop(displayElem)
};
switch (e.type) {
case 'mousemove':
e.preventDefault();
obj.type = 3;
break;
case 'mouseup':
obj.type = 2;
obj.button = button;
button = -1;
break;
case 'contextmenu':
jQuery(document).off("mouseup mousemove contextmenu",docMouseEvent);//解绑会立刻生效,所以此时需要返回false
return false;
default:
break;
}
if (obj.type > 0 && obj.x && obj.y) {
session.request(viewID, "mouseEvent", obj);
}
return true;
}
var offsetLeft = 0;
var offsetTop = 0;
var touchRecord = [];
var touchMoved = false;
var touchNum = 0;
var pointTouchstart = false;
var touchmove = false;
var pointTouchend = false;
var startobj = {
type : -1,
x: -1,
y: -1
};
function handleTouchStart(touchEven)
{
var obj = {
type : -1,
x: -1,
y: -1
};
var trs = [];
var touches = touchEven.originalEvent.changedTouches;
for (var i = 0; i < touches.length; ++i)
{
trs.push({
id: touches[i].identifier,
x: touches[i].pageX - offsetLeft,
y: touches[i].pageY - offsetTop
});
}
for (var i = 0; i < trs.length; ++i)
{
touchRecord.push(trs[i]);
}
touchNum = touchRecord.length;
if (touchNum === 1 && !touchMoved)
{
pointTouchstart = true;
startobj.type = 1;
startobj.button = 1;
startobj.x = trs[0].x;
startobj.y = trs[0].y;
}
return obj;
}
function handleTouchMove(touchEven)
{
var obj = {
type : -1,
x: -1,
y: -1
};
if (touchNum > 2)
{
return obj;
}
var touches = touchEven.originalEvent.changedTouches;
if (touches.length < 1)
{
return obj;
}
var trs = [];
for (var i = 0; i < touches.length; ++i)
{
trs.push({
id: touches[i].identifier,
x: touches[i].pageX - offsetLeft,
y: touches[i].pageY - offsetTop
});
}
var preNum = touchNum;
var newTouch = [];
var oldTouch = [];
for (var i = 0; i < trs.length; ++i)
{
var find = false;
for (var j = 0; j < touchRecord.length; ++j)
{
if (trs[i].id === touchRecord[j].id)
{
find = true;
oldTouch.push({
id: trs[i].id,
oldx: touchRecord[j].x,
oldy: touchRecord[j].y,
x: trs[i].x,
y: trs[i].y,
movex: trs[i].x - touchRecord[j].x,
movey: trs[i].y - touchRecord[j].y
});
touchRecord[j] = trs[i];
}
}
if (!find && !touchMoved)
{
newTouch.push(trs[i]);
touchRecord.push(trs[i]);
}
}
touchNum = touchRecord.length;
if (touchNum > 2)
{
return obj;
}
if (trs.length === 1 && touchNum === 1)//rotate
{
obj.type = 3;
if (!touchMoved)
{
obj.type = 1;
}
obj.button = 1;
obj.x = trs[0].x;
obj.y = trs[0].y;
touchRecord[0] = trs[0];
}
else if (touchNum === 2)
{
var centerX = (touchRecord[0].x + touchRecord[1].x) / 2;
var centerY = (touchRecord[0].y + touchRecord[1].y) / 2;
if (!touchMoved)
{
obj.type = 1;
obj.button = 2;
obj.x = centerX;
obj.y = centerY;
}
else if (oldTouch.length === 2)
{
var oldDistance = Math.sqrt((oldTouch[1].oldx - oldTouch[0].oldx)*(oldTouch[1].oldx - oldTouch[0].oldx) + (oldTouch[1].oldy - oldTouch[0].oldy)*(oldTouch[1].oldy - oldTouch[0].oldy));
var newDistance = Math.sqrt((oldTouch[1].x - oldTouch[0].x)*(oldTouch[1].x - oldTouch[0].x) + (oldTouch[1].y - oldTouch[0].y)*(oldTouch[1].y - oldTouch[0].y));
if (Math.abs(oldDistance - newDistance) < 10)//pan
{
obj.type = 3;
obj.button = 2;
obj.x = centerX;
obj.y = centerY;
}
else
{
obj.wheelDelta = -120 * Math.ceil((oldDistance - newDistance)/Math.abs(oldDistance - newDistance)); //wheelDelta是120的倍数
obj.type = 4;
obj.x = centerX;
obj.y = centerY;
}
}
}
touchMoved = true;
return obj;
}
function handleTouchEnd(touchEven)
{
touchMoved = false;
var obj = {
type : -1,
x: -1,
y: -1
};
var trs = [];
var touches = touchEven.originalEvent.changedTouches;
for (var i = 0; i < touches.length; ++i)
{
trs.push({
id: touches[i].identifier,
x: touches[i].pageX - offsetLeft,
y: touches[i].pageY - offsetTop
});
}
if (touchNum === 1)
{
pointTouchend = true;
obj.type = 2;
obj.button = 1;
obj.x = trs[0].x;
obj.y = trs[0].y;
}
else if (touchNum === 2)
{
obj.type = 2;
obj.button = 2;
obj.x = trs[0].x;
obj.y = trs[0].y;
}
touchRecord = [];
return obj;
}
var touchend = false;
function sendTouchEvent(e)
{
var obj = {
type : -1,
x: -1,
y: -1
};
offsetLeft = getElementLeft(displayElem);
offsetTop = getElementTop(displayElem);
switch (e.type) {
case 'touchstart':
obj = handleTouchStart(e);
displayElem.focus(); //鼠标选中的元素切回焦点(因input元素的焦点在选择之后是不会切回的)
break;
case 'touchend':
touchend = true;
obj = handleTouchEnd(e);
break;
case 'touchmove':
touchmove = true;
obj = handleTouchMove(e);
break;
default:
break;
}
if(pointTouchstart && !touchmove && pointTouchend){
session.request(viewID, "mouseEvent", startobj);
}
if(touchend){
pointTouchend = false;
touchmove = false;
pointTouchstart = false;
touchend = false;
}
if (obj.type > 0 && obj.x && obj.y) {
session.request(viewID, "mouseEvent", obj);
}
e.preventDefault();
//不能返回false,会同时调用preventDefault和stopPropagation
return true;
}
jQuery(displayElem).on('mousedown', sendMouseEvent);
jQuery(displayElem).on('mouseup', sendMouseEvent);
jQuery(displayElem).on('mousemove', sendMouseEvent);
jQuery(displayElem).on('mousewheel', sendMouseEvent);
jQuery(displayElem).on('DOMMouseScroll', sendMouseEvent);
jQuery(displayElem).on('mouseleave', sendMouseEvent);
jQuery(displayElem).on('mouseenter', sendMouseEvent);
jQuery(displayElem).on('dblclick', sendMouseEvent);
jQuery(displayElem).on('contextmenu', false);
jQuery(displayElem).on('touchstart', sendTouchEvent);
jQuery(displayElem).on('touchmove', sendTouchEvent);
jQuery(displayElem).on('touchend', sendTouchEvent);
// 处理键盘事件
function sendKeyboardEvent(e) {
var code = e.keyCode ? e.keyCode : e.which;
var obj = {
code: code
};
switch (e.type) {
case 'keydown':
obj.type = 0;
break;
case 'keyup':
obj.type = 1;
break;
default:
break;
}
session.request(viewID, "keyEvent", obj);
return true;
}
jQuery(displayElem).on('keydown', sendKeyboardEvent);
jQuery(displayElem).on('keyup', sendKeyboardEvent);
};
module.exports = MouseEvent;