Harmonyos应用实例205:椭圆离心率与形状关系
·
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()
}
}
更多推荐



所有评论(0)