【问题标题】:HTML5: Get click position from canvas arcHTML5:从画布弧中获取点击位置
【发布时间】:2013-09-26 10:07:47
【问题描述】:

查看此jsFiddle 帖子以获取工作弧图;感谢Simon Sarris 修复了我之前的问题。

我正在使用KineticJS 插件来创建形状并使用事件处理程序。假设您单击了弧上的某个位置并且弧知道您单击的位置(xy),那么这两个坐标如何用于确定百分比?

当您点击任意位置时,总百分比始终为 100%。

插件

为了更简单,我可以对 (x, y) 做些什么来虚拟弯曲对象,使 x 从 0 变为最大 x

【问题讨论】:

    标签: html canvas click position geometric-arc


    【解决方案1】:

    简单的三角函数。 sin(angle) = opposite / adjacentoppositey 值,adjacentx 值。所以Math.asin((xx - x) / (yy - y)) 其中 xx 和 yy 是圆弧中心的坐标。这为您提供了角度,然后您可以将其除以 2 * Math.PI

    我不记得负数会发生什么。您可能需要获取参数的Math.abs 值,然后计算出点击在哪个象限(使用<> 很容易做到)并为每个象限添加Math.PI / 2

    【讨论】:

      【解决方案2】:

      这包括检查鼠标是否在弧内:

      // Return range is 0 to Math.PI * 2
      function get_mouse_circle_angle(origin_x, origin_y, mouse_x, mouse_y) {
          var mouse_angle = Math.atan2(mouse_y - origin_y, mouse_x - origin_x);
          if (mouse_angle < 0) {
              mouse_angle = (Math.PI * 2) + mouse_angle;
          }
          return mouse_angle;
      }
      
      // Return range is [0, 1)
      // 0/1 is 3 oclock
      function get_mouse_circle_percent(origin_x, origin_y, mouse_x, mouse_y) {
          var mouse_angle = get_mouse_circle_angle(origin_x, origin_y, mouse_x, mouse_y);
          return mouse_angle / (2 * Math.PI);
      }
      
      function get_mouse_arc_pos(origin_x, origin_y, mouse_x, mouse_y, radius, thickness) {
          var mouse_angle = Math.atan2(mouse_y - origin_y, mouse_x - origin_x);
          if (mouse_angle < 0) {
              mouse_angle = (Math.PI * 2) + mouse_angle;
          }
          var mouse_percent = mouse_angle / (2 * Math.PI);
      
          var circle_edge_x = origin_x + (radius + thickness / 2) * Math.cos(mouse_angle);
          var circle_edge_y = origin_y + (radius + thickness / 2) * Math.sin(mouse_angle);
      
          var arc_inside_x = origin_x + (radius - thickness / 2) * Math.cos(mouse_angle);
          var arc_inside_y = origin_y + (radius - thickness / 2) * Math.sin(mouse_angle);
      
          var is_in_circle = true;
      
          if (mouse_angle <= (2 * Math.PI) * 0.25) {
              if (mouse_x > circle_edge_x || mouse_y > circle_edge_y)
                  is_in_circle = false;
          }
          else if (mouse_angle <= (2 * Math.PI) * 0.5) {
              if (mouse_x < circle_edge_x || mouse_y > circle_edge_y)
                  is_in_circle = false;
          }
          else if (mouse_angle <= (2 * Math.PI) * 0.75) {
              if (mouse_x < circle_edge_x || mouse_y < circle_edge_y)
                  is_in_circle = false;
          }
          else {
              if (mouse_x > circle_edge_x || mouse_y < circle_edge_y)
                  is_in_circle = false;
          }
      
          var is_in_arc = is_in_circle;
          if (is_in_circle) {
              if (mouse_angle <= (2 * Math.PI) * 0.25) {
                  if (mouse_x < arc_inside_x || mouse_y < arc_inside_y)
                      is_in_arc = false;
              }
              else if (mouse_angle <= (2 * Math.PI) * 0.5) {
                  if (mouse_x > arc_inside_x || mouse_y < arc_inside_y)
                      is_in_arc = false;
              }
              else if (mouse_angle <= (2 * Math.PI) * 0.75) {
                  if (mouse_x > arc_inside_x || mouse_y > arc_inside_y)
                      is_in_arc = false;
              }
              else {
                  if (mouse_x < arc_inside_x || mouse_y > arc_inside_y)
                      is_in_arc = false;
              }
          }
      
          return {
              angle: mouse_angle,
              percent: mouse_percent,
              is_in_circle: is_in_circle,
              is_in_arc: is_in_arc
          };
      }
      

      【讨论】:

        【解决方案3】:

        没有真正测试过,但从技术上讲,它应该可以工作:

        // Where x1 and y1 should be the coordinates of the arc's center
        function angle(x1, y1, x2, y2) {
            // Calculate a · b
            var nominator = x1 * x2 + y1 * y2;
        
            // Calculate ||a|| ||b||
            var denominator = Math.sqrt(x1*x1 + y1*y1) * Math.sqrt(x2*x2 + y2*y2);
            if (denominator == 0) return 0; // Indifinite angle
        
            // Return the angle
            return Math.acos(nominator / denominator);
        }
        
        // Returns a percent, might be negative
        var percent = angle(0, 0, mouseX, mouseY) / (2*Math.PI);
        

        编辑

        对于负数,您可以尝试加 1,因为它在 [-1, 1] 范围内

        if (percent < 0) percent += 1;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-03-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-06
          • 2017-03-17
          • 2011-10-28
          • 1970-01-01
          相关资源
          最近更新 更多