मैं कैनवास का उपयोग करके एक छोटा पेंटिंग ऐप बनाना चाहता हूं। इसलिए मुझे कैनवास पर माउस की स्थिति खोजने की आवश्यकता है।
मैं कैनवास का उपयोग करके एक छोटा पेंटिंग ऐप बनाना चाहता हूं। इसलिए मुझे कैनवास पर माउस की स्थिति खोजने की आवश्यकता है।
जवाबों:
JQuery का उपयोग करने वाले लोगों के लिए:
कभी-कभी, जब आपके पास नेस्टेड तत्व होते हैं, तो उनमें से एक घटना के साथ संलग्न होता है, यह समझने में भ्रमित हो सकता है कि आपका ब्राउज़र माता-पिता के रूप में क्या देखता है। यहां, आप निर्दिष्ट कर सकते हैं कि कौन सा मूल।
आप माउस स्थिति लेते हैं, और फिर मूल तत्व की ऑफसेट स्थिति से इसे घटाते हैं।
var x = evt.pageX - $('#element').offset().left;
var y = evt.pageY - $('#element').offset().top;
यदि आप स्क्रॉलिंग फलक के अंदर पृष्ठ पर माउस की स्थिति प्राप्त करने का प्रयास कर रहे हैं:
var x = (evt.pageX - $('#element').offset().left) + self.frame.scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + self.frame.scrollTop();
या पृष्ठ के सापेक्ष स्थिति:
var x = (evt.pageX - $('#element').offset().left) + $(window).scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
निम्नलिखित प्रदर्शन अनुकूलन पर ध्यान दें:
var offset = $('#element').offset();
// Then refer to
var x = evt.pageX - offset.left;
इस तरह, JQuery को #elementप्रत्येक पंक्ति के लिए नहीं देखना पड़ता है ।
GetBoundingClientRect () का समर्थन करने वाले ब्राउज़रों के लिए नीचे @anytimecoder द्वारा एक नया, केवल-जावास्क्रिप्ट संस्करण है ।
var y = (evt.pageY - $('#element').offset().left) + $(window).scrollTop();करने के लिए याद रखेंvar y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
जैसा कि मुझे एक jQuery- मुक्त उत्तर नहीं मिला, जिसे मैं कॉपी / पेस्ट कर सकता हूं, यहां मैंने जो समाधान इस्तेमाल किया है वह है:
function clickEvent(e) {
// e = Mouse click event.
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left; //x position within the element.
var y = e.clientY - rect.top; //y position within the element.
}
e.currentTarget, नहीं e.target। अन्यथा, बच्चों के तत्व इसे प्रभावित करेंगे
निम्नलिखित कैनवास तत्व से संबंधित माउस पोजीशन की गणना करता है:
var example = document.getElementById('example');
example.onmousemove = function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
}
इस उदाहरण में, thisको संदर्भित करता है exampleतत्व है, और eहै onmousemoveघटना।
var example = document.getElementById('example'); example.onmousemove = function(e) { var X = e.pageX - this.offsetLeft; var Y = e.pageY - this.offsetTop; }
thisकरने के लिए e.currentTarget, कि आप तत्व है कि आप करने के लिए घटना श्रोता जोड़ा सापेक्ष स्थिति मिल जाएगा।
शुद्ध जावास्क्रिप्ट में कोई जवाब नहीं है जो सापेक्ष निर्देशांक लौटाता है जब संदर्भ तत्व दूसरों के अंदर निहित होता है जो पूर्ण स्थिति के साथ हो सकता है। यहाँ इस परिदृश्य का हल है:
function getRelativeCoordinates (event, referenceElement) {
const position = {
x: event.pageX,
y: event.pageY
};
const offset = {
left: referenceElement.offsetLeft,
top: referenceElement.offsetTop
};
let reference = referenceElement.offsetParent;
while(reference){
offset.left += reference.offsetLeft;
offset.top += reference.offsetTop;
reference = reference.offsetParent;
}
return {
x: position.x - offset.left,
y: position.y - offset.top,
};
}
htmlतत्व ऑफसेट
while(reference !== undefined)साथ : के साथ बदलें while(reference)। क्रोम में कम से कम, ऑफसेटपार्टेंट होने के नाते समाप्त नहीं होता है undefined, लेकिन null। बस देखना हो referenceहै truthy यह दोनों के साथ काम करता सुनिश्चित करेगा undefinedऔर null।
offsetParentसंपत्ति है, जो अन्य स्थितियों में भी बहुत उपयोगी साबित होती है!
scrollLeftऔर scrollTopक्षतिपूर्ति करना होगा।
इस समस्या की कठिनाई का एक अच्छा लेखन यहाँ पाया जा सकता है: http://www.quirksmode.org/js/events_properties.html#position
वहां वर्णित तकनीक का उपयोग करके आप दस्तावेज़ में पति-पत्नी की स्थिति पा सकते हैं। फिर आप बस यह देखने के लिए जांचें कि क्या यह आपके तत्व के बाउंडिंग बॉक्स के अंदर है, जिसे आप कॉल करके पा सकते हैं element.getBoundingClientRect()जो निम्नलिखित गुणों के साथ एक वस्तु वापस करेगा { bottom, height, left, right, top, width }:। वहाँ से यह पता लगाना तुच्छ है कि क्या आपके तत्व के अंदर भी हुआ था या नहीं।
मैंने इन सभी समाधानों की कोशिश की और एक मैट्रिक्स रूपांतरित कंटेनर (पैनज़ूम लाइब्रेरी) के साथ मेरे विशेष सेटअप के कारण काम नहीं किया। यह सही मान लौटाता है, भले ही ज़ूम और पैन किया गया हो:
mouseevent(e) {
const x = e.offsetX,
y = e.offsetY
}
लेकिन केवल अगर रास्ते में कोई बाल तत्व नहीं हैं। सीएसएस का उपयोग करके, उन्हें घटना के लिए 'अदृश्य' बनाकर इसे दरकिनार किया जा सकता है:
.child {
pointer-events: none;
}
मैं इस सवाल में आए, लेकिन इसे मेरे मामले के लिए काम करने के लिए में (एक डोम तत्व पर dragover का उपयोग कर (नहीं मेरे मामले में कैनवास) किया जा रहा है), मैंने पाया है कि आप केवल उपयोग करने के लिए है कि offsetXऔर offsetYdragover माउस घटना पर ।
onDragOver(event){
var x = event.offsetX;
var y = event.offsetY;
}
I +1 'मार्क वैन वाइक का जवाब, क्योंकि यह मुझे सही दिशा में मिला, लेकिन मेरे लिए इसे बहुत हल नहीं किया। मैं अभी भी एक और तत्व के भीतर निहित तत्वों में पेंटिंग पर एक ऑफसेट था।
फोलोइंग ने इसे मेरे लिए हल किया:
x = e.pageX - this.offsetLeft - $(elem).offset().left;
y = e.pageY - this.offsetTop - $(elem).offset().top;
दूसरे शब्दों में - मैं बस नेस्टेड सभी तत्वों से सभी ऑफसेट को ढेर कर दिया
उपर्युक्त उत्तरों में से कोई भी संतोषजनक IMO नहीं है, इसलिए यहाँ मेरा क्या उपयोग है:
// Cross-browser AddEventListener
function ael(e, n, h){
if( e.addEventListener ){
e.addEventListener(n, h, true);
}else{
e.attachEvent('on'+n, h);
}
}
var touch = 'ontouchstart' in document.documentElement; // true if touch device
var mx, my; // always has current mouse position IN WINDOW
if(touch){
ael(document, 'touchmove', function(e){var ori=e;mx=ori.changedTouches[0].pageX;my=ori.changedTouches[0].pageY} );
}else{
ael(document, 'mousemove', function(e){mx=e.clientX;my=e.clientY} );
}
// local mouse X,Y position in element
function showLocalPos(e){
document.title = (mx - e.getBoundingClientRect().left)
+ 'x'
+ Math.round(my - e.getBoundingClientRect().top);
}
और अगर आपको कभी पृष्ठ की वर्तमान Y स्क्रॉल स्थिति जानने की आवश्यकता है:
var yscroll = window.pageYOffset
|| (document.documentElement && document.documentElement.scrollTop)
|| document.body.scrollTop; // scroll Y position in page
आपमें से जो नियमित वेबसाइट या PWAs (प्रोग्रेसिव वेब ऐप्स) विकसित कर रहे हैं, मोबाइल उपकरणों और / या लैपटॉप / टच स्क्रीन के साथ मॉनिटर के लिए, तो आप यहाँ आ गए हैं क्योंकि आप माउस इवेंट में उपयोग किए जा सकते हैं और टच के कभी-कभी दर्दनाक अनुभव के लिए नए हैं। घटनाओं ... याय!
सिर्फ 3 नियम हैं:
mousemoveया touchmoveघटनाओं के दौरान जितना संभव हो उतना कम करें ।mousedownया touchstartइवेंट्स के दौरान ज्यादा से ज्यादा करें ।कहने की जरूरत नहीं है, चीजें touchघटनाओं से अधिक जटिल हैं क्योंकि एक से अधिक हो सकते हैं और वे माउस घटनाओं की तुलना में अधिक लचीले (जटिल) हैं। मैं यहाँ केवल एक ही स्पर्श को कवर करने जा रहा हूँ। हां, मैं आलसी हो रहा हूं, लेकिन यह सबसे आम प्रकार का स्पर्श है, इसलिए वहां।
var posTop;
var posLeft;
function handleMouseDown(evt) {
var e = evt || window.event; // Because Firefox, etc.
posTop = e.target.offsetTop;
posLeft = e.target.offsetLeft;
e.target.style.background = "red";
// The statement above would be better handled by CSS
// but it's just an example of a generic visible indicator.
}
function handleMouseMove(evt) {
var e = evt || window.event;
var x = e.offsetX; // Wonderfully
var y = e.offsetY; // Simple!
e.target.innerHTML = "Mouse: " + x + ", " + y;
if (posTop)
e.target.innerHTML += "<br>" + (x + posLeft) + ", " + (y + posTop);
}
function handleMouseOut(evt) {
var e = evt || window.event;
e.target.innerHTML = "";
}
function handleMouseUp(evt) {
var e = evt || window.event;
e.target.style.background = "yellow";
}
function handleTouchStart(evt) {
var e = evt || window.event;
var rect = e.target.getBoundingClientRect();
posTop = rect.top;
posLeft = rect.left;
e.target.style.background = "green";
e.preventDefault(); // Unnecessary if using Vue.js
e.stopPropagation(); // Same deal here
}
function handleTouchMove(evt) {
var e = evt || window.event;
var pageX = e.touches[0].clientX; // Touches are page-relative
var pageY = e.touches[0].clientY; // not target-relative
var x = pageX - posLeft;
var y = pageY - posTop;
e.target.innerHTML = "Touch: " + x + ", " + y;
e.target.innerHTML += "<br>" + pageX + ", " + pageY;
e.preventDefault();
e.stopPropagation();
}
function handleTouchEnd(evt) {
var e = evt || window.event;
e.target.style.background = "yellow";
// Yes, I'm being lazy and doing the same as mouseout here
// but obviously you could do something different if needed.
e.preventDefault();
e.stopPropagation();
}
div {
background: yellow;
height: 100px;
left: 50px;
position: absolute;
top: 80px;
user-select: none; /* Disable text selection */
-ms-user-select: none;
width: 100px;
}
<div
onmousedown="handleMouseDown()"
onmousemove="handleMouseMove()"
onmouseout="handleMouseOut()"
onmouseup="handleMouseUp()"
ontouchstart="handleTouchStart()"
ontouchmove="handleTouchMove()"
ontouchend="handleTouchEnd()">
</div>
Move over box for coordinates relative to top left of box.<br>
Hold mouse down or touch to change color.<br>
Drag to turn on coordinates relative to top left of page.
Vue.js का उपयोग करना पसंद करते हैं ? मैं करता हूँ! तब आपका HTML इस तरह दिखाई देगा:
<div @mousedown="handleMouseDown"
@mousemove="handleMouseMove"
@mouseup="handleMouseUp"
@touchstart.stop.prevent="handleTouchStart"
@touchmove.stop.prevent="handleTouchMove"
@touchend.stop.prevent="handleTouchEnd">
आप इसे प्राप्त कर सकते हैं
var element = document.getElementById(canvasId);
element.onmousemove = function(e) {
var xCoor = e.clientX;
var yCoor = e.clientY;
}
इस ट्यूटोरियल से लिया गया , सुधार के साथ शीर्ष टिप्पणी के लिए धन्यवाद:
function getMousePos( canvas, evt ) {
var rect = canvas.getBoundingClientRect();
return {
x: Math.floor( ( evt.clientX - rect.left ) / ( rect.right - rect.left ) * canvas.width ),
y: Math.floor( ( evt.clientY - rect.top ) / ( rect.bottom - rect.top ) * canvas.height )
};
}
एक कैनवास पर इस प्रकार प्रयोग करें:
var canvas = document.getElementById( 'myCanvas' );
canvas.addEventListener( 'mousemove', function( evt ) {
var mousePos = getMousePos( canvas, evt );
} );
मुझे पता है कि मुझे थोड़ी देर हो गई है, लेकिन यह PURE जावास्क्रिप्ट के साथ काम करता है, और यह आपको तत्व के भीतर पॉइंटर के निर्देशांक भी देता है यदि तत्व व्यूपोर्ट से बड़ा है और उपयोगकर्ता ने स्क्रॉल किया है।
var element_offset_x ; // The distance from the left side of the element to the left of the content area
....// some code here (function declaration or element lookup )
element_offset_x = element.getBoundingClientRect().left - document.getElementsByTagName("html")[0].getBoundingClientRect().left ;
....// code here
function mouseMoveEvent(event)
{
var pointer_location = (event.clientX + window.pageXOffset) - element_offset_x ;
}
यह काम किस प्रकार करता है।
पहली चीज़ जो हम करते हैं उसे वर्तमान तत्व के सापेक्ष HTML तत्व (सामग्री क्षेत्र) का स्थान मिलता है। यदि पृष्ठ में स्क्रॉलबार है और स्क्रॉल किया गया है, तो वह संख्या वापस आ जाएगीgetBoundingClientRect().left html टैग के लिए ऋणात्मक होगा। हम इस संख्या का उपयोग तत्व और सामग्री क्षेत्र के बाईं ओर की दूरी की गणना करने के लिए करते हैं। साथ मेंelement_offset_x = element.getBoundingClientRect().left......;
सामग्री क्षेत्र से तत्व की दूरी जानना। event.clientXहमें व्यूपोर्ट से पॉइंटर की दूरी देता है। यह समझना महत्वपूर्ण है कि व्यूपोर्ट और कंटेंट क्षेत्र दो अलग-अलग इकाइयाँ हैं, अगर पेज स्क्रॉल हो जाए तो व्यूपोर्ट आगे बढ़ सकता है। इसलिए, अगर पेज स्क्रॉल किया जाता है, तब भी क्लाइंट X वही नंबर वापस करेगा।
इसकी भरपाई करने के लिए, हमें पॉइंटर (व्यूपोर्ट के सापेक्ष) की स्थिति, व्यूपोर्ट की एक्स स्थिति (सामग्री क्षेत्र के सापेक्ष) में जोड़ने की जरूरत है। व्यूपोर्ट के X स्थान के साथ पाया जाता है window.pageXOffset.
स्पाइडर के समाधान के आधार पर, मेरा गैर JQuery संस्करण यह है:
// Get the container element's bounding box
var sides = document.getElementById("container").getBoundingClientRect();
// Apply the mouse event listener
document.getElementById("canvas").onmousemove = (e) => {
// Here 'self' is simply the current window's context
var x = (e.clientX - sides.left) + self.pageXOffset;
var y = (e.clientY - sides.top) + self.pageYOffset;
}
यह स्क्रॉलिंग और जूमिंग (जिस स्थिति में कभी-कभी यह लौटाता है) के साथ काम करता है।
एक कैनवास के अंदर माउस निर्देशांक को event.offsetX और event.offsetY के लिए धन्यवाद प्राप्त किया जा सकता है। यहाँ मेरी बात साबित करने के लिए थोड़ा स्निपेट दिया गया है:
c=document.getElementById("c");
ctx=c.getContext("2d");
ctx.fillStyle="black";
ctx.fillRect(0,0,100,100);
c.addEventListener("mousemove",function(mouseEvt){
// the mouse's coordinates on the canvas are just below
x=mouseEvt.offsetX;
y=mouseEvt.offsetY;
// the following lines draw a red square around the mouse to prove it
ctx.fillStyle="black";
ctx.fillRect(0,0,100,100);
ctx.fillStyle="red";
ctx.fillRect(x-5,y-5,10,10);
});
body {
background-color: blue;
}
canvas {
position: absolute;
top: 50px;
left: 100px;
}
<canvas id="c" width="100" height="100"></canvas>
canvas.onmousedown = function(e) {
pos_left = e.pageX - e.currentTarget.offsetLeft;
pos_top = e.pageY - e.currentTarget.offsetTop;
console.log(pos_left, pos_top)
}
HTMLElement.offsetLeft
HTMLElement.offsetLeftकेवल पढ़ने के लिए संपत्ति विवरणी पिक्सेल की संख्या को वर्तमान तत्व के ऊपरी बाएँ कोने में बाईं ओर ऑफसेट हैHTMLElement.offsetParent नोड।
ब्लॉक स्तर तत्वों के लिए, offsetTop, offsetLeft, offsetWidth, और offsetHeightकरने के लिए एक तत्व रिश्तेदार की सीमा बॉक्स का वर्णन offsetParent।
हालांकि, (जैसे इनलाइन स्तर के तत्वों के लिए span) है कि एक लाइन से दूसरी में लपेट कर सकते हैं, offsetTopऔर offsetLeftपहले सीमा बॉक्स की स्थिति का वर्णन (उपयोग Element.getClientRects()अपनी चौड़ाई और ऊंचाई पाने के लिए) है, जबकि offsetWidthऔर offsetHeightसीमांकन सीमा बॉक्स के आयामों का वर्णन ( Element.getBoundingClientRect()इसके स्थान पाने के लिए उपयोग करें)। इसलिए, बाएं, ऊपर, चौड़ाई और ऊंचाई के साथ एक बॉक्स offsetLeft, offsetTop, offsetWidthऔर offsetHeightनहीं लिपटे पाठ के साथ एक अवधि के लिए एक बाउंडिंग बॉक्स हो जाएगा।
HTMLElement.offsetTop
HTMLElement.offsetTopकेवल पढ़ने के लिए संपत्ति के शीर्ष करने के लिए वर्तमान तत्व रिश्तेदार की दूरी रिटर्न offsetParentनोड।
MouseEvent.pageX
pageXकेवल पढ़ने के लिए संपत्ति रिटर्न एक्स (क्षैतिज) पूरे दस्तावेज़ को घटना रिश्तेदार के पिक्सल में समन्वय। यह गुण पृष्ठ के किसी भी क्षैतिज स्क्रॉलिंग को ध्यान में रखता है।
MouseEvent.pageY
MouseEvent.pageYकेवल पढ़ने के लिए संपत्ति विवरणी वाई (ऊर्ध्वाधर) पूरे दस्तावेज़ को घटना रिश्तेदार के पिक्सल में समन्वय। यह गुण पृष्ठ के किसी भी ऊर्ध्वाधर स्क्रॉल को ध्यान में रखता है।
आगे की व्याख्या के लिए, कृपया मोज़िला डेवलपर नेटवर्क देखें:
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageX https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/3Y https: // developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetLeft https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop
pageऔर offsetमेरे बीच के संबंधों के बारे में अधिक जानना मेरे लिए बहुत उपयोगी होगा। इस अनुरोध पर विचार करने के लिए धन्यवाद!
मैंने एक अन्य समाधान लागू किया है जो मुझे लगता है कि बहुत सरल है इसलिए मैंने सोचा कि मैं आप लोगों के साथ साझा करूंगा।
तो, मेरे लिए समस्या यह थी कि घसीट दिया हुआ माउस माउस कर्सर के लिए 0,0 में कूद जाएगा । इसलिए मुझे div पर स्थिति को पकड़ने के लिए div को नई स्थिति को समायोजित करने की आवश्यकता थी।
मैंने divs PageX और PageY को पढ़ा और उसके अनुसार सबसे ऊपर और बाईं ओर सेट किया और फिर निर्देश प्राप्त करने के लिए कि मैं div पर एक प्रारंभिक स्थिति में कर्सर रखने के लिए निर्देशांक समायोजित करने के लिए एक onDragStart श्रोता का उपयोग करता हूं और e.nativeEvent को स्टोर करता हूं .layerX और e.nativeEvent.layerY है कि केवल शुरुआती ट्रिगर में आपको ड्रैग करने योग्य डिव के भीतर पति - पत्नी की स्थिति मिलती है।
उदाहरण कोड:
onDrag={(e) => {
let newCoords;
newCoords = { x: e.pageX - this.state.correctionX, y: e.pageY - this.state.correctionY };
this.props.onDrag(newCoords, e, item.id);
}}
onDragStart={
(e) => {
this.setState({
correctionX: e.nativeEvent.layerX,
correctionY: e.nativeEvent.layerY,
});
}
मुझे आशा है कि यह किसी को उसी समस्या से गुजरने में मदद करेगा जो मैं गया था :)
आपको अपने पृष्ठ की संरचना को जानना होगा, क्योंकि यदि आपका कैनवास एक div का एक बच्चा है, जो बदले में एक अन्य div का बच्चा है ... तो कहानी अधिक जटिल हो जाती है। यहाँ एक कैनवास के लिए मेरा कोड है जो div s के 2 स्तरों के अंदर है:
canvas.addEventListener("click", function(event) {
var x = event.pageX - (this.offsetLeft + this.parentElement.offsetLeft);
var y = event.pageY - (this.offsetTop + this.parentElement.offsetTop);
console.log("relative x=" + x, "relative y" + y);
});
मूल उत्तर ने कहा कि यह एक iframe में डाल दिया। बेहतर समाधान यह है कि घटनाओं को एक कैनवस पर ऑफसेट एक्सएक्सएक्स और ऑफसेट का उपयोग किया जाए जिसमें 0px पर पैडिंग सेट है।
<html>
<body>
<script>
var main=document.createElement('canvas');
main.width="200";
main.height="300";
main.style="padding:0px;margin:30px;border:thick dashed red";
document.body.appendChild(main);
// adding event listener
main.addEventListener('mousemove',function(e){
var ctx=e.target.getContext('2d');
var c=Math.floor(Math.random()*0xFFFFFF);
c=c.toString(16); for(;c.length<6;) c='0'+c;
ctx.strokeStyle='#'+c;
ctx.beginPath();
ctx.arc(e.offsetX,e.offsetY,3,0,2*Math.PI);
ctx.stroke();
e.target.title=e.offsetX+' '+e.offsetY;
});
// it worked! move mouse over window
</script>
</body>
</html>
आप माता-पिता getBoudingClientRect()का उपयोग कर सकते हैं relative।
document.addEventListener("mousemove", (e) => {
let xCoord = e.clientX - e.target.getBoundingClientRect().left + e.offsetX
let yCoord = e.clientY - e.target.getBoundingClientRect().top + e.offsetY
console.log("xCoord", xCoord, "yCoord", yCoord)
})