আমি ক্যানভাস উপাদানটিতে মাউস ক্লিকের স্থানাঙ্কগুলি কীভাবে পেতে পারি?


276

কোনও ক্যানভাস উপাদানটিতে ক্লিক ইভেন্ট হ্যান্ডলার যুক্ত করার সহজ উপায় কী যা ক্লিকের x এবং y স্থানাঙ্ক ফেরত দেবে (ক্যানভাস উপাদানটির সাথে সম্পর্কিত)?

কোনও লিগ্যাসি ব্রাউজারের সামঞ্জস্যতা প্রয়োজন নেই, সাফারি, অপেরা এবং ফায়ারফক্স করবে।


এটি সাধারণ ডোম উপাদানগুলির থেকে মাউস ইভেন্টগুলি পাওয়ার থেকে আলাদা হওয়া উচিত নয়। quirksmode একটি ভাল রেফারেন্স আছে।
এয়ারপোর্ট

4
আপনি উপরে তালিকাভুক্ত কোডটি কেবল তখনই কাজ করে যখন ক্যানভাস অন্য পাত্রে গভীর না থাকে। সাধারণভাবে আপনাকে jquery অফসেট ফাংশন [var testDiv = $ ('# টেস্টডিভ') এর মতো কিছু ব্যবহার করতে হবে; ক্রস ব্রাউজার উপায়ে সঠিক অফসেট পেতে var offset = 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 এখন উপস্থিত এবং আরও মার্জিত।
গেমএলকেমিস্ট

192

আপনি যদি সরলতা পছন্দ করেন তবে তবুও ক্রস ব্রাউজার কার্যকারিতা চান তবে আমার কাছে এই সমাধানটি সবচেয়ে ভাল কাজ করেছে। এটি @ অ্যালডেকাইনের সমাধানের সরলিকরণ যা 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)
})

পৃষ্ঠাটি যদি নীচে স্ক্রোল করা থাকে তবে আমার ধারণা, যে কোনওটিকে নথির স্ক্রোলটিকে অফসেট বিবেচনায় নেওয়া উচিত।
পেপে এলজি

8
@ পেপেল-জি বাউন্ডিং ক্লায়েন্টের আয়তক্ষেত্রটি আপনার জন্য এটি গণনা করে। আপনি কোনও মন্তব্য পোস্ট করার আগে আপনি সহজেই এটি কনসোলে পরীক্ষা করতে পারেন (এটি আমিই করেছি)।
টোমা জ্যাটো - মনিকা

1
@ টম্যাজাটো, ওহ, getBoundingClientRectভিউ বন্দরের তুলনায় অবস্থানগুলি ফেরত দেবে? তখন আমার অনুমানটি ভুল ছিল was আমি কখনই এটি পরীক্ষা করে দেখিনি যেহেতু এটি আমার পক্ষে কখনও সমস্যা ছিল না, এবং আমি দয়া করে অন্য পাঠকদেরকে দেখলাম এমন একটি সম্ভাব্য সমস্যা সম্পর্কে সতর্ক করতে চেয়েছিলাম, তবে আপনার স্পষ্টতার জন্য আপনাকে ধন্যবাদ।
পেপে এলজি

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নিজের ক্যানভাস উপাদান দিয়ে শুরু করে s এর চেইনটি দিয়ে লুপ করতে হবে । এই কোডটি আমার পক্ষে নিখুঁতভাবে কাজ করে, ফায়ারফক্স এবং সাফারিতে পরীক্ষিত তবে সবার জন্য কাজ করা উচিত।

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
না, এটি বিল্টিন জাভাস্ক্রিপ্ট প্রোটোটাইপ অবজেক্টটি ব্যবহার করছে --- বিকাশকারী.মোজিলা.আর
//২

14
আমার ক্রোমের রয়েছে event.offsetXএবং event.offsetYবৈশিষ্ট্য, তাই আমি যুক্ত করে আপনার সমাধানটি পরিবর্তন করেছি if (event.offsetX !== undefined && event.offsetY !== undefined) { return {x:event.offsetX, y:event.offsetY}; }। দেখে মনে হচ্ছে এটি কাজ করে।
ব্যাকজেক

3
Baczek Chrome এর সম্পর্কে সঠিক event.offsetXএবং event.offsetYযা IE9 কাজ করে। ফায়ারফক্সের জন্য (পরীক্ষিত ডাব্লু / ভি 13) আপনি event.layerXএবং ব্যবহার করতে পারেন event.layerY
মাফাফু

3
আমি অতিরিক্ত এটি যোগ করেছি: canvasX = event.pageX - totalOffsetX - document.body.scrollLeft; canvasY = event.pageY - totalOffsetY - document.body.scrollTop;
amirpc

4
উত্তরের এই চূড়ান্ত সংস্করণটি আমার পক্ষে কার্যকর হয়নি। ফায়ারফক্সে, যদি পুরো স্ক্রিনটি স্ক্রোল করা হয় তবে আমি আউটপুট হিসাবে স্থানচ্যুত মূল্য পেয়েছি। কি আমার জন্য কাজ অনুরূপ একটি সমাধান ছিল, দেওয়া stackoverflow.com/a/10816667/578749 যে event.pageX / ওয়াই পরিবর্তে, এটা event.clientX / ওয়াই থেকে অফসেট গণনা বিয়োগ। কেউ এই পর্যালোচনা এবং ব্যাখ্যা করতে পারে?
lvella

33

আধুনিক ব্রাউজারটি এখন আপনার জন্য এটি পরিচালনা করে। ক্লিক হ্যান্ডলার থেকে ইভেন্টটি পেরিয়ে ক্রোম, আইই 9 এবং ফায়ারফক্স এইভাবে অফসেটএক্স / ওয়াই সমর্থন করে।

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

বেশিরভাগ আধুনিক ব্রাউজারগুলি লেয়ারএক্স / ওয়াই সমর্থন করে, তবে ক্রোম এবং আইই ফায়ারফক্সে লেয়ারএক্স / ওয়াই এবং অফসেটএক্স / ওয়াই সমতুল্য পাতায় মার্জিন, প্যাডিং সহ পৃষ্ঠায় ক্লিকের নিখুঁত অফসেটের জন্য লেয়ারএক্স / ওয়াই ব্যবহার করে তবে অফসেট করা হয়নি এর আগে উপস্থিত ছিল না। সুতরাং, সামান্য পুরানো ব্রাউজারগুলির সাথে সামঞ্জস্যের জন্য, আপনি এটি ব্যবহার করতে পারেন:

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

1
আকর্ষণীয় কিভাবে লেয়ারএক্স, লেয়ারওয়াই ক্রোম এবং ফায়ারফক্স উভয় ক্ষেত্রে সংজ্ঞায়িত করা হয়েছে তবে ক্রোমে এটি সঠিক নয় (বা এর অর্থ অন্য কিছু)।
জুলিয়ান মান

@ জুলিয়ানম্যান তথ্যের জন্য ধন্যবাদ। আমি আরও বর্তমান সমর্থন উপর ভিত্তি করে এই উত্তর আপডেট করেছি। দেখে মনে হচ্ছে আপনি এখন সর্বজনীনভাবে অফসেটএক্স / ওয়াই দিয়ে চলে যেতে পারেন।
মাফাফু

18

তাজা মতে QuirksmodeclientX এবং 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()


@ এন 4ppeL উত্তরের সমান।
পাওয়ে স্জাকুর

13

আমি একটি সম্পূর্ণ ডিমেস্টেরেশন তৈরি করেছি যা প্রতিটি ব্রাউজারে এই সমস্যার সমাধানের সম্পূর্ণ উত্স কোড সহ কাজ করে: জাভাস্ক্রিপ্টে ক্যানভাসে মাউসের ক্লিকের সমন্বয়কারী । ডেমো চেষ্টা করার জন্য, কোডটি অনুলিপি করুন এবং এটি একটি পাঠ্য সম্পাদকের মধ্যে আটকান। তারপরে এটিকে উদাহরণ। 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 এবং Chrome 3.0 এ যাচাই করা হয়েছে) ক্লায়েন্টএক্স এবং ক্লায়েন্টওয়াই একা ব্যবহার করা যথেষ্ট নয়।

এই quirks মোড নিবন্ধটি আরও সঠিক ফাংশন সরবরাহ করে যা ডকুমেন্টের মূল সাথে সম্পর্কিত ক্লিক স্থানাঙ্ক গণনা করতে ডকুমেন্ট.body.scrolLeft এবং ক্লায়েন্টওয়্যারের সাথে পেজএক্স বা পেজওয়াই বা ক্লায়েন্টএক্সের সংমিশ্রণ ব্যবহার করতে পারে।

আপডেট: অতিরিক্তভাবে, অফসেট লেফট এবং অফসেটটপ উপাদানটির প্যাডযুক্ত আকারের সাথে সম্পর্কিত, অভ্যন্তরের আকার নয়। প্যাডিং সহ একটি ক্যানভাস: শৈলী প্রয়োগ করা হয়েছে এটির সামগ্রীর অঞ্চলের উপরের-বামটিকে অফসেট লেফট হিসাবে প্রতিবেদন করবে না। এই সমস্যার বিভিন্ন সমাধান রয়েছে; সবচেয়ে সহজ হতে পারে ক্যানভাসে সমস্ত বর্ডার, প্যাডিং ইত্যাদি স্টাইলগুলি সাফ করা এবং পরিবর্তে ক্যানভাসযুক্ত বাক্সে এগুলি প্রয়োগ করা।


7

আমি নিশ্চিত নই যে এই সমস্ত উত্তরের মূল বিষয়টি যা পিতামাতার উপাদানগুলির মধ্য দিয়ে লুপ করে দেয় এবং সমস্ত ধরণের অদ্ভুত স্টাফ করে

HTMLElement.getBoundingClientRectপদ্ধতি কোনো উপাদান প্রকৃত পর্দা অবস্থান হ্যান্ডেল করতে ডিজাইন করা হয়েছে। এর মধ্যে স্ক্রোলিং অন্তর্ভুক্ত রয়েছে, সুতরাং এর মতো জিনিসগুলির scrollTopপ্রয়োজন হয় না:

(এমডিএন থেকে) সীমাবদ্ধ আয়তক্ষেত্রটি গণনা করার সময়ভিউপোর্ট অঞ্চল (বা অন্য কোনও স্ক্রোলযোগ্য উপাদান )দিয়ে স্ক্রলিংয়ের পরিমাণটি বিবেচনায় নেওয়া হয়

সাধারণ চিত্র

খুব সহজ পদ্ধতির ইতিমধ্যে এখানে পোস্ট করা হয়েছে। যতক্ষণ কোনও বুনো সিএসএসের বিধি জড়িত না হয় এটি সঠিক ।

প্রসারিত ক্যানভাস / চিত্র পরিচালনা করা

চিত্রের পিক্সেলের প্রস্থ এটির সিএসএস প্রস্থের সাথে মিলে না গেলে, আপনাকে পিক্সেল মানগুলিতে কিছু অনুপাত প্রয়োগ করতে হবে:

/* 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];
}

যতক্ষণ না ক্যানভাসের কোনও সীমানা নেই, এটি প্রসারিত চিত্রগুলির জন্য কাজ করে (জেএসফিডাল)

সিএসএস সীমানা পরিচালনা করছে

ক্যানভাসের ঘন সীমানা থাকলে জিনিসগুলি কিছুটা জটিল হয়ে যায় । আক্ষরিকভাবে আপনাকে সীমানাটি আয়তক্ষেত্র থেকে বিয়োগ করতে হবে। এটি .getComputesStyle ব্যবহার করে করা যেতে পারে । এই উত্তর প্রক্রিয়া বর্ণনা করে

ফাংশনটি তখন কিছুটা বড় হয়:

/* 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
  ...
}

আমি এই চূড়ান্ত ফাংশনকে বিভ্রান্ত করবে এমন কোনও কিছুই ভাবতে পারি না। জেএসফিডেলে নিজেকে দেখুন ।

মন্তব্য

আপনি নেটিভ পরিবর্তন পছন্দ না হয় 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);

আশাকরি এটা সাহায্য করবে!


রায়ান আরটেকোনার সমাধানটি জুম সহ ট্যাবলেট ব্রাউজারগুলির জন্য কাজ করে না। তবে এই এক করেছে।
অ্যান্ডি মায়ার্স

সিএসএস width/ heightওভারডিডেনযুক্ত চিত্রগুলির সাথে কাজ করে না তবে এখনও সেরা সমাধানগুলির মধ্যে একটি।
টোমা জ্যাটো - মনিকা

3

ক্যানভাসের তুলনায় ২০১ coord সালে 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())
}

কি দারুন. কিভাবে 'jqEvent' সংজ্ঞায়িত হয়? নাকি 'ক্যানভাস'? নাকি দ্বিতীয় উদাহরণে 'সমন্বয়'? দ্বিতীয়টির আগে আপনার কি প্রথম উদাহরণ চালানো দরকার? সেক্ষেত্রে আপনি কেন সেগুলি লেখার জন্য লিখবেন না, আপনি কী করবেন? এই সবগুলি একটি অন্লিক ফাংশনে যায় বা কী? একটু প্রসঙ্গ দিন, সাথী। এবং আসল প্রশ্নটি ২০০৮ সালে জিজ্ঞাসা করা হয়েছিল বলে বিবেচনা করে আমার মনে হয় যে আপনি যে প্রযুক্তিটি ২০০৮ সালে উপলভ্য ছিল তার প্রসঙ্গে উত্তর দেওয়া দরকার। সেই সময়ে যে সংস্করণটি পাওয়া গিয়েছিল (v1.2) থেকে বৈধ jQuery ব্যবহার করে আপনার উত্তরটি পরিমার্জন করুন। ;)
আইয়েলিস

1
ঠিক আছে, আমার অহংকারের জন্য দুঃখিত এটি মুছে ফেলার জন্য আমি সম্পাদনা করব। আমি সর্বাধিক সাম্প্রতিক ফ্রেমওয়ার্কগুলি ব্যবহার করে উত্তর সরবরাহ করার লক্ষ্য নিয়েছিলাম। এবং আমি বিশ্বাস করি যে প্রোগ্রামারকে jqEvent, ক্যানভাস এবং কর্ডগুলি কী তা ব্যাখ্যা করার দরকার নেই।
সরসপরিলা

ভাল লাগছে। আপনার ইনপুট জন্য ধন্যবাদ! দুঃখিত আমি আপনাকে একটি কঠিন সময় দিয়েছি! ;)
আইয়েলিস

3

সুতরাং এটি উভয়ই সহজ তবে এটি মনে হচ্ছে কিছু জটিল বিষয়।

প্রথমে এখানে সাধারণত বিবাদযুক্ত প্রশ্নগুলি রয়েছে

  1. উপাদান সম্পর্কিত আপেক্ষিক মাউস স্থানাঙ্কগুলি কীভাবে পাবেন

  2. 2D ক্যানভাস এপিআই বা ওয়েবজিএলের জন্য ক্যানভাস পিক্সেল মাউস স্থানাঙ্কগুলি কীভাবে পাবেন

সুতরাং, উত্তর

উপাদান সম্পর্কিত আপেক্ষিক মাউস স্থানাঙ্কগুলি কীভাবে পাবেন

উপাদানটি একটি ক্যানভাসের উপাদান সম্পর্কিত মাউস স্থানাঙ্কগুলি পেতে কিনা তা সমস্ত উপাদানগুলির জন্য একই।

"ক্যানভাস আপেক্ষিক মাউস স্থানাঙ্ক কিভাবে পাবেন" প্রশ্নের 2 টি সহজ উত্তর রয়েছে

সহজ উত্তর # 1 ব্যবহার offsetXএবংoffsetY

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

এই উত্তরটি ক্রোম, ফায়ারফক্স এবং সাফারিতে কাজ করে। অন্যান্য ইভেন্ট ইভেন্টের মতো নয় offsetXএবং offsetYসিএসএস রূপান্তরগুলি অ্যাকাউন্টে নিন।

সঙ্গে সবচেয়ে বড় সমস্যা offsetXএবং offsetY2019/05 এর হিসাবে তারা স্পর্শ ইভেন্টের উপস্থিত না থাকার এবং তাই আইওএস সাফারি সঙ্গে ব্যবহার করা যেতে পারে। এটি পয়েন্টার ইভেন্টগুলিতে রয়েছে যা ক্রোম এবং ফায়ারফক্সে বিদ্যমান তবে সাফারি নয় যদিও দৃশ্যত সাফারি এতে কাজ করছে

আরেকটি বিষয় হ'ল ঘটনাগুলি ক্যানভাসে থাকা উচিত। আপনি যদি এগুলিকে অন্য কোনও উপাদান বা উইন্ডোতে রাখেন তবে পরে আপনার রেফারেন্স হিসাবে আপনি ক্যানভাসটি বেছে নিতে পারবেন না।

সহজ উত্তর # 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;
});

2D ক্যানভাস এপিআইয়ের জন্য ক্যানভাস পিক্সেল মাউস স্থানাঙ্কগুলি কীভাবে পাবেন

এর জন্য আমাদের আমাদের যে মানগুলি পেয়েছে সেগুলি গ্রহণ করতে হবে এবং ক্যানভাসটি যে আকার থেকে ক্যানভাস প্রদর্শিত হবে তা থেকে ক্যানভাসের পিক্সেলের সংখ্যায় রূপান্তর করতে হবে

সঙ্গে 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 , আউটপুট

  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

উপরের রায়ান আর্তেকোনার সমাধানের কিছু পরিবর্তন এখানে দেওয়া হল।

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

প্রথমত, অন্যরা যেমন বলেছে, ক্যানভাস উপাদানটির অবস্থান পেতে আপনার একটি ফাংশন প্রয়োজন । এই পৃষ্ঠার অন্য কিছু (আইএমএইচও) এর চেয়ে কিছুটা মার্জিত একটি পদ্ধতি এখানে। আপনি এটিকে যে কোনও উপাদানটি পাস করতে পারেন এবং নথিতে তার অবস্থান পেতে পারেন :

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ফাংশনটিকে ইভেন্ট হ্যান্ডলিং কোড থেকে আলাদা করেছি । ( যেমনটি হওয়া উচিত) We আমাদের প্রতিটি কাজকে একটি করে রাখার চেষ্টা করা উচিত))

এর মানগুলি offsetLeftএবং offsetTopএর সাথে সম্পর্কিত offsetParent, যা কিছু মোড়কের divনোড (বা অন্য কোনও কিছু, সে ক্ষেত্রে হতে পারে )। যখন কোনও উপাদান মোড়ানো না থাকে canvasসেগুলি তারা সম্পর্কিত হয় body, তাই বিয়োগ করার কোনও অফসেট নেই। এ কারণেই আমাদের অন্য কিছু করার আগে আমাদের ক্যানভাসের অবস্থান নির্ধারণ করা দরকার।

অনুরূপ, e.pageXএবং e.pageYনথির সাথে সম্পর্কিত কার্সারের অবস্থান দিন। সে কারণেই আমরা সত্য অবস্থানে পৌঁছানোর জন্য ক্যানভাসের অফসেটটি সেই মানগুলি থেকে বিয়োগ করে।

একটা বিকল্প স্থান উপাদান সরাসরি মান ব্যবহার করা e.layerXএবং e.layerY। এটি দুটি কারণের জন্য উপরের পদ্ধতির চেয়ে কম নির্ভরযোগ্য:

  1. ইভেন্টটি কোনও অবস্থানগত উপাদানের অভ্যন্তরে না নিলে এই মানগুলি পুরো ডকুমেন্টের সাথেও আপেক্ষিক
  2. এগুলি কোনও মানের অংশ নয়

0

থ্রিজেএস আর 77

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

আমি একটি পিডিএফ-এর উপর ক্যানভাসযুক্ত একটি অ্যাপ্লিকেশন তৈরি করছিলাম , এতে পিডিএফ-ইন এবং আউট জুম করার মতো ক্যানভাসের অনেক আকার পরিবর্তন করা হয়েছিল এবং পিডিএফ-এর প্রতিটি জুম-ইন / আউট চালু করার জন্য আমাকে ক্যানভাসটির আকার পরিবর্তন করতে হয়েছিল পিডিএফ আকার, আমি স্ট্যাকওভারফ্লোতে প্রচুর উত্তর দিয়েছি, এবং একটি নিখুঁত সমাধান খুঁজে পাইনি যা শেষ পর্যন্ত সমস্যার সমাধান করবে।

আমি rxjs এবং কৌণিক 6 ব্যবহার করছিলাম , এবং নতুন সংস্করণে নির্দিষ্ট কোনও উত্তর খুঁজে পাইনি found

ক্যানভাসের শীর্ষে আঁকতে 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
ক্লায়েন্টএক্স / ক্লায়েন্টওয়াই ব্রাউজারগুলিতে একই রকম আচরণ করে না।
tfwright
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.