6

ここでは Stack Overflow で、Canvas 自体に対する Canvas Element のイベントの座標を取得する方法について、多くの回答があります。次の解決策 ( ) を使用していますが、キャンバスに境界線を追加する場合を除きgetEventPosition、うまく機能します。

/**** This solution gives me an offset equal to the border size
 **** when the canvas has a border. Example:
 **** <canvas style='border: 10px solid black; background: #333;' id='gauge_canvas' width='500' height='500'></canvas>
 ****/

// Get DOM element position on page
this.getPosition = function(obj) {
    var x = 0, y = 0;
    if (obj.offsetParent) {
        do {
            x += obj.offsetLeft;
            y += obj.offsetTop;
            obj = obj.offsetParent;
        } while (obj);
    }
    return {'x': x, 'y': y};
};

// Get mouse event position in DOM element (don't know how to use scale yet).
this.getEventPosition = function(e, obj, aux_e, scale) {

    var evt, docX, docY, pos;

    evt = (e ? e : window.event);
    if (evt.pageX || evt.pageY) {
        docX = evt.pageX;
        docY = evt.pageY;
    } else if (evt.clientX || evt.clientY) {
        docX = evt.clientX + document.body.scrollLeft +
            document.documentElement.scrollLeft;
        docY = evt.clientY + document.body.scrollTop +
            document.documentElement.scrollTop;
    }
    // This works on hammer.js
    else if (typeof aux_e !== 'undefined') {
        docX = aux_e.touches[0].x;
        docY = aux_e.touches[0].y;
    }
    pos = this.getPosition(obj);
    if (typeof scale === 'undefined') {
        scale = 1;
    }
    return {'x': (docX - pos.x) / scale, 'y': (docY - pos.y) / scale};
};

このコードは私のライブラリに属しており、ユーザーが指定したキャンバス要素を使用できるため、ユーザーがライブラリに縁取りされたキャンバスを指定すると、問題が発生します。国境を考慮した解決策はありますか?

4

2 に答える 2

3

これが私の最近の実験に使用しているものです。

http://jsfiddle.net/simonsarris/te8GQ/5/

var stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(can, undefined)['paddingLeft'], 10) || 0;
var stylePaddingTop = parseInt(document.defaultView.getComputedStyle(can, undefined)['paddingTop'], 10) || 0;
var styleBorderLeft = parseInt(document.defaultView.getComputedStyle(can, undefined)['borderLeftWidth'], 10) || 0;
var styleBorderTop = parseInt(document.defaultView.getComputedStyle(can, undefined)['borderTopWidth'], 10) || 0;
var html = document.body.parentNode;
var htmlTop = html.offsetTop;
var htmlLeft = html.offsetLeft;

function getMouse(e) {
    var element = can,
        offsetX = 0,
        offsetY = 0,
        mx, my;

    // Compute the total offset
    if (element.offsetParent !== undefined) {
        do {
            offsetX += element.offsetLeft;
            offsetY += element.offsetTop;
        } while ((element = element.offsetParent));
    }

    // Add padding and border style widths to offset
    // Also add the <html> offsets in case there's a position:fixed bar
    offsetX += stylePaddingLeft + styleBorderLeft + htmlLeft;
    offsetY += stylePaddingTop + styleBorderTop + htmlTop;

    mx = e.pageX - offsetX;
    my = e.pageY - offsetY;

    // We return a simple javascript object (a hash) with x and y defined
    return {
        x: mx,
        y: my
    };
}

これは、任意の境界線とパディングで機能し、HTML をオフセットするオブジェクト (stumbleupon バーなど) でシムするページでも機能します。ブラウザがズームされている場合にも機能します。

タッチデバイスでも問題なく動作するようです。

于 2012-09-09T21:05:25.740 に答える
0

これを試して:

this.getPosition = function(obj) {
    var x = 0, y = 0;
    if (obj.offsetParent) {
        do {
            x += obj.clientLeft;
            y += obj.clientTop;
            obj = obj.offsetParent;
        } while (obj);
    }
    return {'x': x, 'y': y};
};

clientLeftclientTop境界線を含めますがoffsetLeft、含めoffsetTopません。

他の要素を含めたくない場合は、次のようにするとうまくいくでしょう。

this.getPosition = function(obj) {
    return{'x': obj.clientLeft,
           'y': obj.clientTop};
};
于 2012-09-09T20:01:47.727 に答える