2010-07-04 49 views
5

Có thể một số người đã có những trải nghiệm tương tự về tình huống khó xử này và có thể giúp tôi ở đây ...HTML5 canvas: tìm hiểu xem các tọa độ nhấp có nằm trong một hình chữ nhật đã cho không

Về cơ bản, tôi có phần tử canvas tôi vẽ một số hình chữ nhật trong vòng lặp bằng cách sử dụng

context.fillRect (x, y, width, height) 

Bây giờ, tôi muốn một số hình chữ nhật trở thành điểm nóng và phản hồi sự kiện nhấp chuột. Tôi có thể tìm hiểu chính xác (x, y) của sự kiện nhấp bằng cách sử dụng event.layerXevent.layerY.

Cho rằng tôi biết như sau:

  • x chính xác, y của nhấp chuột
  • x, y, chiều rộng và chiều cao của mỗi hình chữ nhật

làm thế nào để tìm thấy ra nếu sự kiện nhấp xảy ra bên trong chu vi một hình chữ nhật nhất định hay không?
và,
hình chữ nhật nào xảy ra sự kiện nhấp chuột 0n?

Có công thức toán học nào không?

Bất kỳ trợ giúp sẽ được nhiều đánh giá cao, và nếu như tôi không đủ rõ ràng, cho tôi biết ...

Cảm ơn

EDIT
Có cách nào tốt hơn để lặp qua tất cả hình chữ nhật và kiểm tra vị trí và kích thước của chúng?

Trả lời

12

Đây là vấn đề cấu trúc liên kết chung thường gặp phải khi sử dụng bản đồ.

Thuật toán cho việc quyết định liệu một điểm nằm trong bất kỳ đa giác (hình chữ nhật, hình tròn, hình dạng bất thường) là như sau:

  • Từ quan điểm được kiểm tra xây dựng bất kỳ dòng theo hướng nào cho đến khi mép diện tích màn hình, trong đó đa giác của bạn đang nằm

  • nếu dòng cắt bất kỳ ranh giới đa giác tại một lẻ số nơi thì nó là trong rằng Polygon

  • nếu đường cắt bất kỳ đường viền đa giác nào thậm chí số địa điểm đó là bên ngoài đa giác đó.

     ------------ 
         |   | 
         |  o--|------------------- 1 intersection: inside 
         |   | 
         ------------- 
         ------------ 
         |   | 
    o------|-----------|------------------- 2 intersections: outside 
         |   | 
         ------------- 
    

Ghi chú:

  • Hướng của dòng là không thích hợp

  • sẽ không hoạt động nếu một đa giác được cắt ở phía bên của màn hình mà không cần đóng cửa

  • Nếu đa giác cắt ngang chính nó thì thuật toán có thể thất bại nếu dòng xảy ra để đi qua các điểm cắt (ví dụ như trong hình 8 được coi là một đa giác đơn nơi dòng đi chính xác thông qua nơi trên và dưới phần kết nối của hình kết nối)

+5

+1 cho nghệ thuật ascii! –

1

đại khái, bạn có thể làm điều đó như thế này:

var click_x = event.layerX; 
var click_y = event.layerY; 

for (var i = 0; i < rects.length; i++) { 
    var rect = rects[i]; 
    if (click_x >= rect.x && click_x <= rect.x + rect.width 
    && click_y >= rect.y && click_y <= rect.y + rect.height) { 
     // The click was inside the rectange 
    } 
} 

Giả sử chúng ta đang làm việc với độ rộng không âm và chiều cao :)

+0

Có không có cách nào tốt hơn không phải là vòng lặp thông qua mỗi hình chữ nhật và kiểm tra kích thước ... (Sigh !!) – ekhaled

+0

Bạn có thể sử dụng thứ gì đó như [phân cấp khối lượng giới hạn (BVH)] (http://en.wikipedia.org/wiki/Bounding_volume_hierarchy) để chia nhỏ không gian và thu hẹp các hình chữ nhật cần được kiểm tra. Điều này sẽ yêu cầu một số tiền xử lý mặc dù. – tomit

1

Đây có thể là quá mức cần thiết, nhưng Bánh JS sẽ thực hiện công việc cho hình chữ nhật và các hình dạng khác. Check out the demo.

+0

Anh ấy có toàn bộ hệ thống xử lý sự kiện, bạn nói đúng, đó là một chút quá mức cần thiết cho nhu cầu của tôi. – ekhaled

5

Tôi ghét phải gửi một tấn mã ở đây, nhưng đây là một lớp học js có thể giúp bạn ...

function Point(x,y){ 
    this.x=x; 
    this.y=y; 
} 

function Polygon(){ 
    this.points=[]; 
    this.x_min=undefined; 
    this.x_max=undefined; 
    this.y_min=undefined; 
    this.y_max=undefined; 

    this.add = function(p){ 
     this.points=this.points.concat(p); 
     if (p.x<this.x_min){this.x_min=p.x;} 
     if (p.x>this.x_max){this.x_max=p.x;} 
     if (p.y<this.y_min){this.y_min=p.y;} 
     if (p.y>this.y_min){this.y_max=p.y;} 
    } 

    this.pointInPoly = function(p){ 
     var j=(this.points.length-1); //start by testing the link from the last point to the first point 
     var isOdd=false; 

     //check the bounding box conditions 
     if (p.x < this.x_min || p.x > this.x_max || p.y < this.y_min || p.y > this.y_max){ 
      return false; 
     } 

     //if necessary use the line crossing algorithm 
     for(var i=0; i<this.points.length; i++){ 
      if ((this.points[i].y<p.y && this.points[j].y>=p.y) || 
       (this.points[j].y<p.y && this.points[i].y>=p.y)) { 
        if (this.points[i].x+(p.y-this.points[i].y)/(this.points[j].y- 
         this.points[i].y)*(this.points[j].x-this.points[i].x)<p.x) 
        { isOdd=(!isOdd);} } 
      j=i; 
     } 
     return isOdd; 
    } 
} 

PS: bạn sẽ cần phải chuyển đổi sự kiện click của bạn để tọa độ địa phương sử dụng một cái gì đó giống như hàm sau (trong đó e là sự kiện click của bạn):

function getPosition(e){ 
    var p = new Point(); 
    if (e.pageX != undefined && e.pageY != undefined) { 
     p.x = e.pageX; 
     p.y = e.pageY; 
    } 
    else { 
     p.x = e.clientX + document.body.scrollLeft + 
       document.documentElement.scrollLeft; 
     p.y = e.clientY + document.body.scrollTop + 
       document.documentElement.scrollTop; 
    } 
    p.x -= gCanvas.offsetLeft; 
    p.y -= gCanvas.offsetTop; 


    return p; 
} 
1

Gần đây, tôi đã tạo một API để phát hiện các nhấp chuột trên hình chữ nhật. Nó rất cơ bản nhưng cần giải quyết vấn đề của bạn
Bạn có thể tìm thấy nó here.
Lưu ý: Nó hiện không có một văn bản hỗ trợ cho các nút nhưng nó có hỗ trợ cho một số phong cách cơ bản
Tài liệu: Here Code:

function canvasButton(x, y, w, h, style , text) { 
    this.style = style 
    this.x = x || 0; 
    this.y = y || 0; 
    this.w = w || 1; 
    this.h = h || 1; 
    this.fill = style.default.fill ; 
    this.text = text || undefined; 
    this.onclick = function() {alert("Click! Make sure to add the onclick listener to your button!")} 
    this.mouseup = function() {alert("Mouseup! Make sure to add the mouseup listener to your button!")} 
    this.addListener = function() { 
    var buttonX = this.x; 
    var buttonY = this.y; 
    var buttonWidth = this.w; 
    var buttonHeight = this.h; 
    var onclick = this.onclick 
    var mouseup = this.mouseup 
    var styles = this.style 
    var draw = this.draw 
    var ctx = this.ctx 
    this.ctx.canvas.addEventListener('mousedown',function(e){ 
     var click_x = e.clientX; 
     var click_y = e.clientY; 
     if (click_x >= buttonY && click_x <= buttonX + buttonWidth && click_y >= buttonY && click_y <= buttonY + buttonHeight) { 
      onclick() 
      ctx.fillStyle = style.active.fill 
      ctx.fillRect(buttonX, buttonY, buttonWidth, buttonHeight); 
     } 
    }) 
    this.ctx.canvas.addEventListener('mouseup',function(e) { 
     var click_x = e.clientX; 
     var click_y = e.clientY; 
     if (click_x >= buttonY && click_x <= buttonX + buttonWidth && click_y >= buttonY && click_y <= buttonY + buttonHeight) { 
      mouseup() 
      ctx.fillStyle = style.default.fill 
      ctx.fillRect(buttonX, buttonY, buttonWidth, buttonHeight); 

     } 

    }) 
    } 

} 

// Draws this shape to a given context 
canvasButton.prototype.draw = function(ctx) { 
    this.ctx = ctx 
    ctx.fillStyle = this.fill; 
    ctx.font = this.font 
    ctx.fillRect(this.x, this.y, this.w, this.h); 
    ctx.fillText(this.text,this.x,this.y) 
    this.addListener(); 
} 


//Use it like this: 
var start = new canvasButton(x,y,height,width,{ // Styles 
    "default": { 
     "fill":"#765", 

    }, 
    "active": { 
     "fill":"#876", 

    } 
}) 
//Event Listeners 
start.mousedown = function() { 

} 
start.mouseup = function() { 

} 
start.draw(document.getElementById("canvas").getContext("2d")); // Draw to canvas 
Các vấn đề liên quan