7. 椭圆离心率与形状关系

对应章节:3.1 椭圆
功能简介
保持长半轴 aaa 不变,调节离心率 e=c/ae = c/ae=c/a。随着 eee 从 0 接近 1,椭圆从“圆”逐渐变得“扁平”。通过动画直观展示离心率对椭圆“扁圆程度”的影响。
在这里插入图片描述

@Entry
@Component
struct EccentricityDemo {
  @State e: number = 0.5 // 离心率 e
  @State isAnimating: boolean = false // 是否正在动画
  private a: number = 100 // 长半轴 a
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Text('椭圆离心率演示')
        .fontSize(24).fontWeight(FontWeight.Bold).margin({ bottom: 20 })

      Text(`离心率 e = ${this.e.toFixed(2)}`)
        .fontSize(18).margin({ bottom: 10 })

      Text(`长半轴 a = ${this.a}`)
        .fontSize(16).margin({ bottom: 20 })

      Stack() {
        Canvas(this.context)
          .width(400)
          .height(250)
          .onReady(() => this.draw())
      }
      .margin({ bottom: 20 })

      // 控制区域
      Column() {
        Text('调节离心率:')
          .fontSize(16).margin({ bottom: 10 })

        Row() {
          Text('e:')
            .width(30).fontSize(14)
          Slider({
            value: this.e,
            min: 0.01,
            max: 0.99,
            step: 0.01
          })
            .width(200)
            .onChange((value: number) => {
              this.e = value
              this.draw()
            })
          Text(this.e.toFixed(2))
            .width(50).fontSize(14)
        }
        .margin({ bottom: 20 })

        Button(this.isAnimating ? '停止动画' : '播放动画')
          .onClick(() => {
            this.toggleAnimation()
          })
      }

      Text('提示: 调节离心率观察椭圆形状变化')
        .fontSize(12).fontColor('#666')
        .margin({ top: 10 })
    }
  }

  private draw() {
    const width = 400
    const height = 250
    const centerX = width / 2
    const centerY = height / 2

    // 清空画布
    this.context.clearRect(0, 0, width, height)
    this.context.fillStyle = '#F5F5F5'
    this.context.fillRect(0, 0, width, height)

    // 计算椭圆参数
    const c = this.a * this.e // 焦距半长
    const b = Math.sqrt(this.a * this.a - c * c) // 短半轴 b

    // 绘制椭圆
    this.context.strokeStyle = '#3498DB'
    this.context.lineWidth = 2
    this.context.beginPath()
    this.context.ellipse(centerX, centerY, this.a, b, 0, 0, 2 * Math.PI)
    this.context.stroke()

    // 绘制焦点
    this.context.fillStyle = '#E74C3C'
    // 焦点F1
    this.context.beginPath()
    this.context.arc(centerX - c, centerY, 6, 0, 2 * Math.PI)
    this.context.fill()
    // 焦点F2
    this.context.beginPath()
    this.context.arc(centerX + c, centerY, 6, 0, 2 * Math.PI)
    this.context.fill()

    // 绘制焦点标签
    this.context.fillStyle = '#E74C3C'
    this.context.font = '14px sans-serif'
    this.context.textAlign = 'center'
    this.context.fillText('F₁', centerX - c, centerY - 15)
    this.context.fillText('F₂', centerX + c, centerY - 15)

    // 绘制长轴和短轴
    this.context.strokeStyle = '#95A5A6'
    this.context.lineWidth = 1
    this.context.setLineDash([5, 5])

    // 长轴
    this.context.beginPath()
    this.context.moveTo(centerX - this.a, centerY)
    this.context.lineTo(centerX + this.a, centerY)
    this.context.stroke()

    // 短轴
    this.context.beginPath()
    this.context.moveTo(centerX, centerY - b)
    this.context.lineTo(centerX, centerY + b)
    this.context.stroke()

    this.context.setLineDash([])
  }

  private toggleAnimation() {
    if (this.isAnimating) {
      // 停止动画
      this.isAnimating = false
    } else {
      // 开始动画
      this.isAnimating = true
      this.animateEccentricity()
    }
  }

  private animateEccentricity() {
    let direction = 1 // 1 表示增大,-1 表示减小
    let currentE = this.e

    const animate = () => {
      if (!this.isAnimating) return

      // 更新离心率
      currentE += direction * 0.01

      // 边界检查
      if (currentE >= 0.99) {
        direction = -1
      } else if (currentE <= 0.01) {
        direction = 1
      }

      // 更新状态
      this.e = currentE
      this.draw()

      // 继续动画
      setTimeout((): void => animate(), 50)
    }

    animate()
  }
}
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐