मैं एक कैनवास तत्व पर माउस क्लिक के निर्देशांक कैसे प्राप्त करूं?


276

कैनवास तत्व पर क्लिक इवेंट हैंडलर जोड़ने का सबसे सरल तरीका क्या है जो क्लिक के x और y निर्देशांक (कैनवास तत्व के सापेक्ष) को लौटाएगा?

कोई लीगेसी ब्राउज़र संगतता की आवश्यकता नहीं है, सफारी, ओपेरा और फ़ायरफ़ॉक्स करेंगे।


यह सामान्य डोम तत्वों से माउस की घटनाओं को प्राप्त करने से अलग नहीं होना चाहिए। quirksmode का उस पर अच्छा संदर्भ है।
Airportyh

4
आपके द्वारा ऊपर सूचीबद्ध कोड तभी काम करता है जब कैनवास अन्य कंटेनरों के अंदर गहरा नहीं होता है। सामान्य तौर पर आपको jquery ऑफसेट फ़ंक्शन [var testDiv = $ ('# testDiv') जैसे कुछ का उपयोग करने की आवश्यकता होती है; क्रॉस ऑफ़सेट तरीके से सही ऑफ़सेट प्राप्त करने के लिए var ऑफ़सेट = testDiv.offset ();]। यह *** में एक वास्तविक दर्द है।
आरोन वॉटर्स

अपडेट के साथ पोस्ट किया गया कोड कैनवास स्क्रॉल करने वाले पेज पर काम करने में विफल रहता है।
टिमोथी किम

मैंने अपने पुराने "उत्तर" को हटा दिया जो प्रश्न के अद्यतन के रूप में शामिल था। जैसा कि उल्लेख किया गया है, यह पुराना और अपूर्ण था।
टॉम

3
चूँकि यहाँ 50 उत्तरों की तरह है, मैं सलाह देता हूँ कि लोग इस उत्तर पर स्क्रॉल करें: देशभक्त - एक अच्छा और सरल 5 लाइनर।
इगोर एल।

जवाबों:


77

संपादित करें 2018: यह उत्तर बहुत पुराना है और यह पुराने ब्राउज़रों के लिए चेक का उपयोग करता है जो अब आवश्यक नहीं हैं, क्योंकि clientXऔर clientYगुण सभी वर्तमान ब्राउज़रों में काम करते हैं। आप एक सरल, अधिक हाल के समाधान के लिए पैट्रियक्स उत्तर की जांच करना चाह सकते हैं ।

मूल उत्तर:
जैसा कि मैंने एक लेख में बताया था, मैं वापस मिल गया लेकिन अब मौजूद नहीं है:

var x;
var y;
if (e.pageX || e.pageY) { 
  x = e.pageX;
  y = e.pageY;
}
else { 
  x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; 
  y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; 
} 
x -= gCanvasElement.offsetLeft;
y -= gCanvasElement.offsetTop;

मेरे लिए पूरी तरह से ठीक काम किया।


30
यह समाधान हमेशा काम नहीं करता है - जब रायन आर्टेकोना का जवाब अधिक सामान्य मामले में काम करता है जब कैनवास आवश्यक रूप से पूरे पृष्ठ के सापेक्ष नहीं होता है।
क्रिस जॉनसन

3
यह समाधान फिट नहीं है यदि प्रदर्शन मायने रखता है, क्योंकि प्रत्येक क्लिक / चाल पर डोम का उपयोग किया जाता है। और getBoundingClientRect अब मौजूद है, और अधिक सुरुचिपूर्ण है।
GameAlchemist

192

यदि आप सादगी पसंद करते हैं, लेकिन फिर भी क्रॉस-ब्राउज़र कार्यक्षमता चाहते हैं, तो मैंने पाया कि यह समाधान मेरे लिए सबसे अच्छा काम करता है। यह @ Aldekein के समाधान का सरलीकरण है लेकिन jQuery के बिना

function getCursorPosition(canvas, event) {
    const rect = canvas.getBoundingClientRect()
    const x = event.clientX - rect.left
    const y = event.clientY - rect.top
    console.log("x: " + x + " y: " + y)
}

const canvas = document.querySelector('canvas')
canvas.addEventListener('mousedown', function(e) {
    getCursorPosition(canvas, e)
})

यदि पृष्ठ नीचे स्क्रॉल किया गया है, तो मुझे लगता है कि किसी को दस्तावेज़ की स्क्रॉल ऑफ़सेट को भी ध्यान में रखना चाहिए।
Peppe एलजी

8
@ PeppeL-G बाउंडिंग क्लाइंट आयत आपके लिए गणना करता है। टिप्पणी पोस्ट करने से पहले आप इसे आसानी से जांच सकते हैं (यह वही है जो मैंने किया था)।
टॉम ज़ातो -

1
@ TomášZato, ओह, getBoundingClientRectदृश्य बंदरगाह के सापेक्ष स्थिति देता है? तब मेरा अनुमान गलत था। मैंने इसका कभी भी परीक्षण नहीं किया क्योंकि यह मेरे लिए कभी समस्या नहीं थी, और मैं कृपया अन्य पाठकों को संभावित रूप से देखी गई समस्या के बारे में चेतावनी देना चाहता था, लेकिन आपके स्पष्टीकरण के लिए धन्यवाद।
Peppe LG

1
यदि कैनवास छोटा है तो यह काम नहीं करता है। यकीन नहीं है कि अगर यह एक ब्राउज़र बग है।
जेरोन

2
मेरे जैसे किसी के लिए उपयोग जोड़ें:var canvas = document.getElementById('canvasID'); canvas.addEventListener("mousedown", function (e) { getCursorPosition(canvas, e);});
स्नोयन

179

अद्यतन (5/5/16): देशभक्तों के उत्तर का उपयोग किया जाना चाहिए, क्योंकि यह सरल और अधिक विश्वसनीय दोनों है।


चूंकि कैनवास हमेशा पूरे पृष्ठ के सापेक्ष नहीं होता है, इसलिए canvas.offsetLeft/Topहमेशा वह नहीं लौटता है जिसकी आपको आवश्यकता होती है। यह अपने ऑफ़सेटपैरेंट तत्व के सापेक्ष ऑफसेट किए गए पिक्सेल की संख्या को वापस कर देगा, जो कि एक divतत्व के साथ कैनवास की तरह कुछ हो सकता है, जिस पर एक position: relativeशैली लागू है। इसके लिए आपको offsetParentएस की श्रृंखला के माध्यम से लूप करने की आवश्यकता है , शुरुआत कैनवास तत्व के साथ। यह कोड मेरे लिए पूरी तरह से काम करता है, फ़ायरफ़ॉक्स और सफारी में परीक्षण किया गया है लेकिन सभी के लिए काम करना चाहिए।

function relMouseCoords(event){
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do{
        totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
        totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
    }
    while(currentElement = currentElement.offsetParent)

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    return {x:canvasX, y:canvasY}
}
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;

अंतिम पंक्ति एक कैनवास तत्व के सापेक्ष माउस निर्देशांक प्राप्त करने के लिए चीजों को सुविधाजनक बनाती है। उपयोगी निर्देशांक प्राप्त करने के लिए सभी आवश्यक है

coords = canvas.relMouseCoords(event);
canvasX = coords.x;
canvasY = coords.y;

8
नहीं, यह बिल्ट जावास्क्रिप्ट जावास्क्रिप्ट प्रोटोटाइप का उपयोग कर रहा है --- डेवलपर.
mozilla.org/en/…

14
मेरी क्रोम है event.offsetXऔर event.offsetYगुण है, इसलिए मैं जोड़कर अपने समाधान संशोधित if (event.offsetX !== undefined && event.offsetY !== undefined) { return {x:event.offsetX, y:event.offsetY}; }। ऐसा लगता है कि यह काम करता है।
बैकेक

3
Baczek क्रोम के बारे में सही है event.offsetXऔर event.offsetYजो IE9 में भी काम करता है। फ़ायरफ़ॉक्स (परीक्षण w / v13) के लिए आप उपयोग कर सकते हैं event.layerXऔर event.layerY
mafafu

3
मैंने अतिरिक्त रूप से इसे जोड़ा: canvasX = event.pageX - totalOffsetX - document.body.scrollLeft; canvasY = event.pageY - totalOffsetY - document.body.scrollTop;
amirpc

4
जवाब पर यह अंतिम संस्करण मेरे लिए काम नहीं किया। फ़ायरफ़ॉक्स पर, यदि पूरी स्क्रीन स्क्रॉल की जाती है, तो मुझे आउटपुट के रूप में विस्थापित मान मिला। मेरे लिए जो काम किया, वह एक बहुत ही समान समाधान था, जो stackoverflow.com/a/10816667/578749 पर दिया गया था कि Event.pageX / Y के बजाय, यह event.clientX / Y से गणना की गई ऑफसेट घटाया। क्या कोई इसकी समीक्षा कर सकता है और समझा सकता है?
लवेला

33

आधुनिक ब्राउज़र अब आपके लिए इसे संभाल रहा है। क्रोम, IE9, और फ़ायरफ़ॉक्स इस तरह से ऑफसेट / वाई का समर्थन करते हैं, क्लिक हैंडलर से घटना में गुजरते हैं।

function getRelativeCoords(event) {
    return { x: event.offsetX, y: event.offsetY };
}

अधिकांश आधुनिक ब्राउज़र भी लेयरएक्स / वाई का समर्थन करते हैं, हालांकि क्रोम और पैड सहित पेज पर क्लिक के निरपेक्ष ऑफसेट के लिए क्रोम और आईई लेयरएक्स / वाई का उपयोग करते हैं। फ़ायरफ़ॉक्स, लेयरएक्स / वाई और ऑफसेटएक्स / वाई में समतुल्य हैं, लेकिन ऑफ़सेट डीएनएन 't पहले से मौजूद है। इसलिए, थोड़े पुराने ब्राउज़रों के साथ संगतता के लिए, आप इसका उपयोग कर सकते हैं:

function getRelativeCoords(event) {
    return { x: event.offsetX || event.layerX, y: event.offsetY || event.layerY };
}

1
दिलचस्प है कि कैसे लेयरएक्स, लेयरवाई को क्रोम और फ़ायरफ़ॉक्स दोनों पर परिभाषित किया गया है, लेकिन क्रोम पर यह गलत है (या इसका मतलब कुछ और है)।
जूलियन मान

@JulianMann जानकारी के लिए धन्यवाद। मैंने इस उत्तर को अधिक वर्तमान समर्थन के आधार पर अद्यतन किया है। ऐसा लगता है कि आप ऑफसेट / वाई के साथ लगभग सार्वभौमिक रूप से दूर हो सकते हैं।
माफियाफू जूल

18

ताजा Quirksmode के अनुसार clientXऔर clientYतरीके सभी प्रमुख ब्राउज़रों में समर्थित हैं। तो, यहाँ यह जाता है - अच्छा, काम करने वाला कोड जो स्क्रॉलबार वाले पेज पर स्क्रॉलिंग डिव में काम करता है:

function getCursorPosition(canvas, event) {
var x, y;

canoffset = $(canvas).offset();
x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft - Math.floor(canoffset.left);
y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop - Math.floor(canoffset.top) + 1;

return [x,y];
}

इसके लिए भी jQuery की आवश्यकता होती है $(canvas).offset()


@ N4ppeL उत्तर के बराबर।
पवेल सजगुर

13

मैंने एक पूर्ण डेमोस्ट्रेशन बनाया जो इस समस्या के समाधान के पूर्ण स्रोत कोड के साथ हर ब्राउज़र में काम करता है: एक माउस के निर्देशांक जावास्क्रिप्ट में कैनवास पर क्लिक करते हैं । डेमो की कोशिश करने के लिए, कोड को कॉपी करें और इसे टेक्स्ट एडिटर में पेस्ट करें। फिर इसे example.html के रूप में सेव करें और आखिर में फाइल को ब्राउजर के साथ खोलें।


11

यहाँ एक चर (%) चौड़ाई के साथ कैनवस के लिए रयान आर्टकोना के उत्तर का एक छोटा संशोधन है :

 HTMLCanvasElement.prototype.relMouseCoords = function (event) {
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do {
        totalOffsetX += currentElement.offsetLeft;
        totalOffsetY += currentElement.offsetTop;
    }
    while (currentElement = currentElement.offsetParent)

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    // Fix for variable canvas width
    canvasX = Math.round( canvasX * (this.width / this.offsetWidth) );
    canvasY = Math.round( canvasY * (this.height / this.offsetHeight) );

    return {x:canvasX, y:canvasY}
}

7

समन्वय रूपांतरण करते समय सावधान रहें; एक क्लिक ईवेंट में लौटाए गए कई गैर-क्रॉस-ब्राउज़र मान हैं। अगर क्लाइंट विंडो ब्राउजर स्क्रॉल (फ़ायरफ़ॉक्स 3.5 और क्रोम 3.0 में सत्यापित) है तो क्लाइंटएक्स और क्लाइंट का उपयोग करना पर्याप्त नहीं है।

यह quirks मोड आलेख एक अधिक सही फ़ंक्शन प्रदान करता है जो किसी दस्तावेज़ के मूल के सापेक्ष क्लिक समन्वय की गणना करने के लिए document.body.scrollLeft और clientY के साथ पेजएक्स या पेजवाई या क्लाइंटएक्स के संयोजन का उपयोग कर सकता है।

अद्यतन: इसके अतिरिक्त, ऑफसेट लाइट और ऑफसेटटॉप तत्व के गद्देदार आकार के सापेक्ष हैं, न कि आंतरिक आकार के। पैडिंग के साथ एक कैनवास: लागू शैली ऑफसेट सामग्री के रूप में अपने सामग्री क्षेत्र के शीर्ष-बाएं को रिपोर्ट नहीं करेगी। इस समस्या के विभिन्न समाधान हैं; सबसे सरल हो सकता है कि कैनवास पर सभी बॉर्डर, पैडिंग, आदि शैलियों को साफ़ करें और इसके बजाय उन्हें कैनवास वाले बॉक्स पर लागू करें।


7

मुझे यकीन नहीं है कि इन सभी उत्तरों का क्या मतलब है जो मूल तत्वों के माध्यम से लूप करते हैं और सभी प्रकार के अजीब सामान करते हैं

HTMLElement.getBoundingClientRectविधि किसी भी तत्व की वास्तविक स्क्रीन स्थिति को संभालने के लिए बनाया गया है। इसमें स्क्रॉलिंग शामिल है, इसलिए जैसे सामान की scrollTopआवश्यकता नहीं है:

(MDN से) स्क्रॉलिंग की मात्रा जो व्यूपोर्ट क्षेत्र (या किसी अन्य स्क्रॉल करने योग्य तत्व ) से की गई है, बाउंडिंग आयत की गणना करते समय ध्यान में रखा जाता है।

सामान्य छवि

बहुत सरल दृष्टिकोण पहले से ही यहाँ तैनात थे। यह तब तक सही है जब तक कोई जंगली सीएसएस नियम शामिल नहीं होते हैं।

बढ़ाया कैनवास / छवि को संभालना

जब छवि पिक्सेल चौड़ाई सीएसएस चौड़ाई से मेल नहीं खाती है, तो आपको पिक्सेल मूल्यों पर कुछ अनुपात लागू करने की आवश्यकता होगी:

/* Returns pixel coordinates according to the pixel that's under the mouse cursor**/
HTMLCanvasElement.prototype.relativeCoords = function(event) {
  var x,y;
  //This is the current screen rectangle of canvas
  var rect = this.getBoundingClientRect();
  var top = rect.top;
  var bottom = rect.bottom;
  var left = rect.left;
  var right = rect.right;
  //Recalculate mouse offsets to relative offsets
  x = event.clientX - left;
  y = event.clientY - top;
  //Also recalculate offsets of canvas is stretched
  var width = right - left;
  //I use this to reduce number of calculations for images that have normal size 
  if(this.width!=width) {
    var height = bottom - top;
    //changes coordinates by ratio
    x = x*(this.width/width);
    y = y*(this.height/height);
  } 
  //Return as an array
  return [x,y];
}

जब तक कैनवास में कोई सीमा नहीं होती है, तब तक यह स्ट्रेच की गई छवियों (jsFiddle) के लिए काम करता है

सीएसएस सीमाओं को संभालना

यदि कैनवास में मोटी सीमा है, तो चीजें थोड़ी जटिल हो जाती हैं । आपको सचमुच सीमा आयत से सीमा को घटाना होगा। इसे .getComputedStyle का उपयोग करके किया जा सकता है । यह उत्तर प्रक्रिया का वर्णन करता है

फ़ंक्शन तब थोड़ा बढ़ता है:

/* Returns pixel coordinates according to the pixel that's under the mouse cursor**/
HTMLCanvasElement.prototype.relativeCoords = function(event) {
  var x,y;
  //This is the current screen rectangle of canvas
  var rect = this.getBoundingClientRect();
  var top = rect.top;
  var bottom = rect.bottom;
  var left = rect.left;
  var right = rect.right;
  //Subtract border size
  // Get computed style
  var styling=getComputedStyle(this,null);
  // Turn the border widths in integers
  var topBorder=parseInt(styling.getPropertyValue('border-top-width'),10);
  var rightBorder=parseInt(styling.getPropertyValue('border-right-width'),10);
  var bottomBorder=parseInt(styling.getPropertyValue('border-bottom-width'),10);
  var leftBorder=parseInt(styling.getPropertyValue('border-left-width'),10);
  //Subtract border from rectangle
  left+=leftBorder;
  right-=rightBorder;
  top+=topBorder;
  bottom-=bottomBorder;
  //Proceed as usual
  ...
}

मैं इस अंतिम कार्य को भ्रमित करने वाली किसी भी चीज के बारे में नहीं सोच सकता। अपने आप को JsFiddle पर देखें ।

टिप्पणियाँ

यदि आपको देशी prototypeएस को संशोधित करना पसंद नहीं है , तो बस फ़ंक्शन को बदलें और इसे कॉल करें (canvas, event)(और किसी के thisसाथ बदलें canvas)।


6

यहाँ एक बहुत अच्छा ट्यूटोरियल है-

http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/

 <canvas id="myCanvas" width="578" height="200"></canvas>
<script>
  function writeMessage(canvas, message) {
    var context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.font = '18pt Calibri';
    context.fillStyle = 'black';
    context.fillText(message, 10, 25);
  }
  function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: evt.clientX - rect.left,
      y: evt.clientY - rect.top
    };
  }
  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d');

  canvas.addEventListener('mousemove', function(evt) {
    var mousePos = getMousePos(canvas, evt);
    var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
    writeMessage(canvas, message);
  }, false);

उम्मीद है की यह मदद करेगा!


रयान आर्टेकोना का समाधान ज़ूम के साथ टैबलेट ब्राउज़र के लिए काम नहीं करता था। हालांकि यह एक किया था।
एंडी मेयर्स

उन चित्रों के साथ काम नहीं करता जिनके पास CSS width/ heightoverriden है लेकिन फिर भी सबसे अच्छे समाधानों में से एक है।
टॉम ज़ातो -

3

2016 में jQuery का उपयोग करना, कैनवास के सापेक्ष निर्देशांक क्लिक करने के लिए, मैं करता हूं:

$(canvas).click(function(jqEvent) {
    var coords = {
        x: jqEvent.pageX - $(canvas).offset().left,
        y: jqEvent.pageY - $(canvas).offset().top
    };
});

यह कैनवास ऑफसेट () और jqEvent.pageX / Y दोनों के बाद से काम करता है, स्क्रॉल स्थिति की परवाह किए बिना दस्तावेज़ के सापेक्ष हैं।

ध्यान दें कि यदि आपका कैनवास छोटा है, तो ये निर्देशांक कैनवास तार्किक निर्देशांक के समान नहीं हैं । उन पाने के लिए, आप भी करेंगे :

var logicalCoords = {
    x: coords.x * (canvas.width / $(canvas).width()),
    y: coords.y * (canvas.height / $(canvas).height())
}

वाह। J जेकवेंट ’कैसे परिभाषित हो जाता है? या 'कैनवास'? या दूसरे उदाहरण 'कोऑर्डर्स' में? क्या आपको दूसरे से पहले पहला उदाहरण चलाने की आवश्यकता है? उस स्थिति में, आप "उन लोगों को प्राप्त करने के लिए क्यों नहीं लिखेंगे, जो आप भी करेंगे"? क्या यह सब ऑन्कलिक फंक्शन में जाता है या क्या? थोड़ा संदर्भ दो, साथी। और 2008 में पूछे गए मूल प्रश्न पर विचार करते हुए, मुझे लगता है कि आपको उस तकनीक के संदर्भ में जवाब देने की आवश्यकता है जो 2008 में उपलब्ध थी। उस समय (v1.2) उपलब्ध संस्करण से मान्य jQuery का उपयोग करके अपने उत्तर को परिष्कृत करें। ;)
अयिलिस

1
ठीक है, मेरे अनुमान के लिए खेद है। मैं उसे हटाने के लिए संपादन करूंगा। मैंने सबसे हालिया रूपरेखा का उपयोग करके उत्तर प्रदान करने का इरादा किया है। और मेरा मानना ​​है कि एक प्रोग्रामर को यह बताने की जरूरत नहीं होगी कि jqEvent, कैनवस और कोर्ड क्या हैं।
सरसापैरिला

अछा लगता है। आपके सहयोग के लिए धन्यवाद! क्षमा करें, मैंने आपको एक कठिन समय दिया! ;)
अयिलिस

3

तो यह दोनों सरल है लेकिन लगता है की तुलना में थोड़ा अधिक जटिल विषय है।

सबसे पहले आम तौर पर यहाँ भ्रमित प्रश्न हैं

  1. तत्व सापेक्ष माउस निर्देशांक कैसे प्राप्त करें

  2. 2 डी कैनवास एपीआई या वेबजीएल के लिए कैनवास पिक्सेल माउस निर्देशांक कैसे प्राप्त करें

तो, जवाब

तत्व सापेक्ष माउस निर्देशांक कैसे प्राप्त करें

तत्व एक कैनवास हो रहा है या नहीं तत्व सापेक्ष माउस निर्देशांक सभी तत्वों के लिए समान है।

प्रश्न के 2 सरल उत्तर हैं "कैनवास सापेक्ष माउस निर्देशांक कैसे प्राप्त करें"

सरल उत्तर # 1 उपयोग offsetXऔरoffsetY

canvas.addEventListner('mousemove', (e) => {
  const x = e.offsetX;
  const y = e.offsetY;
});

यह उत्तर क्रोम, फ़ायरफ़ॉक्स और सफारी में काम करता है। अन्य सभी ईवेंट मानों के विपरीत offsetXऔर offsetYCSS रूपांतरण को ध्यान में रखें।

2019/05 के साथ सबसे बड़ी समस्या है offsetXऔर offsetYवे टच इवेंट्स में मौजूद नहीं हैं और इसलिए इसका इस्तेमाल iOS सफारी के साथ नहीं किया जा सकता है। वे पॉइंटर घटनाओं पर मौजूद हैं जो क्रोम और फ़ायरफ़ॉक्स में मौजूद हैं, लेकिन सफारी नहीं हैं, हालांकि जाहिर तौर पर सफारी इस पर काम कर रहा है

एक और मुद्दा यह है कि घटनाएँ कैनवास पर ही होनी चाहिए। यदि आप उन्हें किसी अन्य तत्व या खिड़की पर रखते हैं तो आप बाद में कैनवास को अपना संदर्भ बिंदु नहीं चुन सकते हैं।

सरल उत्तर # 2 उपयोग clientX, clientYऔरcanvas.getBoundingClientRect

आप सीएसएस रूपांतरण के बारे में परवाह नहीं है, तो अगले सरल जवाब कॉल करने के लिए है canvas. getBoundingClientRect()से छोड़ दिया और घटाना clientXऔर topसे clientYके रूप में

canvas.addEventListener('mousemove', (e) => {
  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;
});

यह तब तक काम करेगा जब तक कि कोई सीएसएस ट्रांसफॉर्म न हो। यह टच इवेंट्स के साथ भी काम करता है और इसलिए सफारी आईओएस के साथ काम करेगा

canvas.addEventListener('touchmove', (e) => {
  const rect = canvas. getBoundingClientRect();
  const x = e.touches[0].clientX - rect.left;
  const y = e.touches[0].clientY - rect.top;
});

2 डी कैनवास एपीआई के लिए कैनवास पिक्सेल माउस निर्देशांक कैसे प्राप्त करें

इसके लिए हमें उन मूल्यों को लेने की जरूरत है जो हमने ऊपर उठाई हैं और जिस आकार को कैनवास में दिखाया गया है, उससे कैनवास में खुद को बदल दिया है

साथ canvas.getBoundingClientRectऔर clientXऔरclientY

canvas.addEventListener('mousemove', (e) => {
  const rect = canvas.getBoundingClientRect();
  const elementRelativeX = e.clientX - rect.left;
  const elementRelativeY = e.clientY - rect.top;
  const canvasRelativeX = elementRelativeX * canvas.width / rect.width;
  const canvasRelativeY = elementRelativeY * canvas.height / rect.height;
});

या के साथ offsetXऔरoffsetY

canvas.addEventListener('mousemove', (e) => {
  const elementRelativeX = e.offsetX;
  const elementRelativeX = e.offsetY;
  const canvasRelativeX = elementRelativeX * canvas.width / canvas.clientWidth;
  const canvasRelativeY = elementRelativeX * canvas.height / canvas.clientHeight;
});

ध्यान दें: सभी मामलों में कैनवास पर पैडिंग या बॉर्डर न जोड़ें। ऐसा करने से बड़े पैमाने पर कोड जटिल हो जाएगा। इसके बजाय आप चाहते हैं कि एक सीमा या पैडिंग कैनवास को किसी अन्य तत्व में घेर ले और पैडिंग या बॉर्डर को बाहरी तत्व में जोड़ दे।

काम कर उदाहरण event.offsetX,event.offsetY

उदाहरण के कार्य का उपयोग कर canvas.getBoundingClientRectऔर event.clientXऔरevent.clientY


2

मैं इस लिंक की सलाह देता हूं- http://miloq.blogspot.in/2011/05/coordinates-mouse-click-canvas.html

<style type="text/css">

  #canvas{background-color: #000;}

</style>

<script type="text/javascript">

  document.addEventListener("DOMContentLoaded", init, false);

  function init()
  {
    var canvas = document.getElementById("canvas");
    canvas.addEventListener("mousedown", getPosition, false);
  }

  function getPosition(event)
  {
    var x = new Number();
    var y = new Number();
    var canvas = document.getElementById("canvas");

    if (event.x != undefined && event.y != undefined)
    {
      x = event.x;
      y = event.y;
    }
    else // Firefox method to get the position
    {
      x = event.clientX + document.body.scrollLeft +
          document.documentElement.scrollLeft;
      y = event.clientY + document.body.scrollTop +
          document.documentElement.scrollTop;
    }

    x -= canvas.offsetLeft;
    y -= canvas.offsetTop;

    alert("x: " + x + "  y: " + y);
  }

</script>

किस बात का है x = new Number()? उस पुनर्निर्देश के नीचे दिए गए कोड का xअर्थ है कि आवंटित संख्या को तुरंत हटा दिया गया है
gman


1

आप बस कर सकते हैं:

var canvas = yourCanvasElement;
var mouseX = (event.clientX - (canvas.offsetLeft - canvas.scrollLeft)) - 2;
var mouseY = (event.clientY - (canvas.offsetTop - canvas.scrollTop)) - 2;

यह आपको माउस पॉइंटर की सटीक स्थिति देगा।


1

Http://jsbin.com/ApuJOSA/1/edit?html,output पर डेमो देखें ।

  function mousePositionOnCanvas(e) {
      var el=e.target, c=el;
      var scaleX = c.width/c.offsetWidth || 1;
      var scaleY = c.height/c.offsetHeight || 1;

      if (!isNaN(e.offsetX)) 
          return { x:e.offsetX*scaleX, y:e.offsetY*scaleY };

      var x=e.pageX, y=e.pageY;
      do {
        x -= el.offsetLeft;
        y -= el.offsetTop;
        el = el.offsetParent;
      } while (el);
      return { x: x*scaleX, y: y*scaleY };
  }

0

यहाँ ऊपर रयान Artecona के समाधान के कुछ संशोधन दिए गए हैं।

function myGetPxStyle(e,p)
{
    var r=window.getComputedStyle?window.getComputedStyle(e,null)[p]:"";
    return parseFloat(r);
}

function myGetClick=function(ev)
{
    // {x:ev.layerX,y:ev.layerY} doesn't work when zooming with mac chrome 27
    // {x:ev.clientX,y:ev.clientY} not supported by mac firefox 21
    // document.body.scrollLeft and document.body.scrollTop seem required when scrolling on iPad
    // html is not an offsetParent of body but can have non null offsetX or offsetY (case of wordpress 3.5.1 admin pages for instance)
    // html.offsetX and html.offsetY don't work with mac firefox 21

    var offsetX=0,offsetY=0,e=this,x,y;
    var htmls=document.getElementsByTagName("html"),html=(htmls?htmls[0]:0);

    do
    {
        offsetX+=e.offsetLeft-e.scrollLeft;
        offsetY+=e.offsetTop-e.scrollTop;
    } while (e=e.offsetParent);

    if (html)
    {
        offsetX+=myGetPxStyle(html,"marginLeft");
        offsetY+=myGetPxStyle(html,"marginTop");
    }

    x=ev.pageX-offsetX-document.body.scrollLeft;
    y=ev.pageY-offsetY-document.body.scrollTop;
    return {x:x,y:y};
}

0

सबसे पहले, जैसा कि दूसरों ने कहा है, आपको कैनवास तत्व की स्थिति प्राप्त करने के लिए एक फ़ंक्शन की आवश्यकता है । यहां एक विधि है जो इस पृष्ठ (IMHO) के कुछ अन्य लोगों की तुलना में थोड़ी अधिक सुरुचिपूर्ण है। आप इसे किसी भी तत्व को पास कर सकते हैं और दस्तावेज़ में इसकी स्थिति प्राप्त कर सकते हैं :

function findPos(obj) {
    var curleft = 0, curtop = 0;
    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
        return { x: curleft, y: curtop };
    }
    return undefined;
}

अब उस के सापेक्ष कर्सर की वर्तमान स्थिति की गणना करें:

$('#canvas').mousemove(function(e) {
    var pos = findPos(this);
    var x = e.pageX - pos.x;
    var y = e.pageY - pos.y;
    var coordinateDisplay = "x=" + x + ", y=" + y;
    writeCoordinateDisplay(coordinateDisplay);
});

ध्यान दें कि मैंने जेनेरिक findPosफ़ंक्शन को इवेंट हैंडलिंग कोड से अलग कर दिया है । ( जैसा होना चाहिए । हमें अपने कार्यों को प्रत्येक कार्य के लिए रखने की कोशिश करनी चाहिए।)

के मान offsetLeftऔर offsetTopसापेक्ष हैं offsetParent, जो कुछ रैपर divनोड (या उस चीज़ के लिए कुछ और) हो सकते हैं। जब कोई तत्व लपेटते हैं तो canvasवे उसके सापेक्ष होते हैंbody , तो , इसलिए घटाने के लिए कोई ऑफसेट नहीं होता है। यही कारण है कि हमें कुछ और करने से पहले कैनवास की स्थिति निर्धारित करने की आवश्यकता है।

सिमिलरी, e.pageXऔरe.pageY दस्तावेज़ के सापेक्ष कर्सर की स्थिति दें। यही कारण है कि हम सही स्थिति में आने के लिए उन मूल्यों से कैनवास की ऑफसेट को घटाते हैं।

तैनात तत्वों के लिए एक विकल्प सीधे e.layerXऔर के मूल्यों का उपयोग करना है e.layerY। यह दो कारणों से ऊपर की विधि से कम विश्वसनीय है:

  1. ये मान पूरे दस्तावेज़ के सापेक्ष भी होते हैं, जब इवेंट किसी पोस्ट किए गए तत्व के अंदर नहीं होता है
  2. वे किसी भी मानक का हिस्सा नहीं हैं

0

थ्रीजेएस आर 7

var x = event.offsetX == undefined ? event.layerX : event.offsetX;
var y = event.offsetY == undefined ? event.layerY : event.offsetY;

mouse2D.x = ( x / renderer.domElement.width ) * 2 - 1;
mouse2D.y = - ( y / renderer.domElement.height ) * 2 + 1;

कई उपाय आजमाने के बाद। इसने मेरे लिए काम किया। इसलिए पोस्ट करने में किसी और की मदद कर सकते हैं। यहीं से मिला


0

यहाँ एक सरलीकृत समाधान है (यह सीमाओं / स्क्रॉल के साथ काम नहीं करता है):

function click(event) {
    const bound = event.target.getBoundingClientRect();

    const xMult = bound.width / can.width;
    const yMult = bound.height / can.height;

    return {
        x: Math.floor(event.offsetX / xMult),
        y: Math.floor(event.offsetY / yMult),
    };
}

0

मैं एक pdf के ऊपर कैनवास रखने वाला एक एप्लिकेशन बना रहा था , जिसमें कैनवास के बहुत सारे आकार शामिल थे जैसे कि ज़ूम-इन और पीडीएफ को ज़ूम आउट करना और पीडीएफ के प्रत्येक ज़ूम-इन / आउट को चालू करने के लिए मुझे कैनवास को अनुकूलित करना था। pdf का आकार, मैंने स्टैकओवरफ़्लो में बहुत सारे उत्तर दिए, और एक सही समाधान नहीं मिला जो अंततः समस्या का समाधान करेगा।

मैं rxjs और कोणीय 6 का उपयोग कर रहा था , और नवीनतम संस्करण के लिए कोई उत्तर नहीं मिला।

यहां संपूर्ण कोड स्निपेट है जो कैनवास के शीर्ष पर आकर्षित करने के लिए किसी भी rxjs का लाभ उठाने के लिए सहायक होगा ।

  private captureEvents(canvasEl: HTMLCanvasElement) {

    this.drawingSubscription = fromEvent(canvasEl, 'mousedown')
      .pipe(
        switchMap((e: any) => {

          return fromEvent(canvasEl, 'mousemove')
            .pipe(
              takeUntil(fromEvent(canvasEl, 'mouseup').do((event: WheelEvent) => {
                const prevPos = {
                  x: null,
                  y: null
                };
              })),

              takeUntil(fromEvent(canvasEl, 'mouseleave')),
              pairwise()
            )
        })
      )
      .subscribe((res: [MouseEvent, MouseEvent]) => {
        const rect = this.cx.canvas.getBoundingClientRect();
        const prevPos = {
          x: Math.floor( ( res[0].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
          y:  Math.floor( ( res[0].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
        };
        const currentPos = {
          x: Math.floor( ( res[1].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
          y: Math.floor( ( res[1].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
        };

        this.coordinatesArray[this.file.current_slide - 1].push(prevPos);
        this.drawOnCanvas(prevPos, currentPos);
      });
  }

और यहाँ स्निपेट है जो ठीक करता है, माउस कैनवास के आकार के सापेक्ष समन्वयित करता है, भले ही आप कैनवास को ज़ूम-इन / आउट कैसे करें।

const prevPos = {
  x: Math.floor( ( res[0].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
  y:  Math.floor( ( res[0].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
};
const currentPos = {
  x: Math.floor( ( res[1].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
  y: Math.floor( ( res[1].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
};

-1

अरे, यह डोजो में है, बस इसका कारण है कि मेरे पास पहले से ही एक परियोजना के लिए कोड था।

यह काफी स्पष्ट होना चाहिए कि इसे गैर डोजो वेनिला जावास्क्रिप्ट में कैसे परिवर्तित किया जाए।

  function onMouseClick(e) {
      var x = e.clientX;
      var y = e.clientY;
  }
  var canvas = dojo.byId(canvasId);
  dojo.connect(canvas,"click",onMouseClick);

उम्मीद है की वो मदद करदे।


6
clientX / clientY ब्राउज़रों में समान व्यवहार नहीं करता है।
tfwright
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.