h5中坐标系的实践

546 阅读1分钟

描述

有一个页面,跑道是水平垂直居中,且跑道有多条。有一个运动员他跑了x米,如果他在跑道1(从里到外依次是1,2,3,4......),此时他应该在跑道上的哪个位置?

示意图

示意图的解释

  1. x,y坐标系(原点是ox,oy),px,py坐标系(原点是0,0)。
  2. 跑道里面的宽度w,长度h。
  3. 跑道和跑道之间的间距gap。
  4. 运动员的坐标(x,y)。
  5. 跑道起点start。

代码实现

class Runway {
  /**
   * @param w 虚拟跑道的宽度
   * @param h 虚拟跑道的长度
   * @param gap 虚拟跑道之间的距离
   * @param ox,oy 虚拟跑道中心坐标
   * @param d 最里面的跑道的真实距离
   * 注意:
   * 1,w, h, gap, n, x, y都是虚拟数值,d是真实数值 不明白问我
   * 2,运动员是逆时针跑动
   */
  constructor(w, h, gap, ox, oy, d) {
    this.w = w
    this.h = h
    this.gap = gap
    this.ox = ox
    this.oy = oy
    this.d = d
  }

  /**
   * @function 求余
   * @param num1
   * @param num2
   * @returns {rest}
   */
  getRest(num1, num2) {
    let num11 = num1
    let num22 = num2
    let rest
    if (num11 / num22 < 1) {
      rest = num11
    } else {
      while (true) {
        if (num11 / num22 < 1) {
          rest = num11
          break
        } else {
          num11 = num11 - num22
        }
      }
    }
    return rest
  }

  /**
   * @function 获取运动员的在页面上的位置坐标
   * @param distance 跑了多少距离
   * @param which 在哪一个跑道 从里到外依次是 1 2 3 4 ...
   * @return {x:x,y:y} 跑道上某一点的坐标
   */
  getCoordinate(distance, which = 1) {
    let x, y
    let w = this.w
    let h = this.h
    let d = this.d
    let gap = this.gap
    let PI = Math.PI
    let r = w / 2
    let r0 = r + (which - 1) * gap//半径
    let a = 2 * h + 2 * PI * r0//虚拟跑道的距离
    let unit = d / a //实际跑道的距离除以虚拟跑道的距离
    let c = distance / unit//运动员实际运动的距离distance转成虚拟跑道上的距离
    let l = this.getRest(c, a)//一圈半,两圈半,坐标点在同一个位置
    if (l >= 0 && l <= h / 2) {
      x = r0
      y = h / 2 - l
    } else if (l > h / 2 && l < h) {
      x = r0
      y = l - h / 2
    } else if (l >= h && l < h + PI * r0) {
      let hudu = (l - h) / r0
      x = r0 * Math.cos(hudu)
      y = h / 2 + r0 * Math.sin(hudu)
    } else if (l >= h + PI * r0 && l <= 3 * h / 2 + PI * r0) {
      x = -r0
      y = h / 2 - (l - h - PI * r0)
    } else if (l > 3 * h / 2 + PI * r0 && l <= 2 * h + PI * r0) {
      x = -r0
      y = -(l - 3 * h / 2 - PI * r0)
    } else {
      let hudu = (PI + (l - 2 * h - PI * r0)) / r0
      x = r0 * Math.cos(hudu)
      y = -h / 2 + r0 * Math.sin(hudu)
    }

    return {
      x: x + this.ox,
      y: y + this.oy
    }
  }
}​
​
let w = 600
let h = 1200
let r = w / 2
let p = new Runway(w, h, 30, 375, 800, 2 * Math.PI * r + 2 * h)
let coordinate = p.getCoordinate(h / 2, 1)
console.log(coordinate)//{x:675,y:800}

注意: 以上的代码不可避免的还会有有一定的计算误差,原因是js中数字计算的精度有点问题。

谢谢阅读!