HARMONYOS应用实例252:圆周角定理
·
- 圆周角定理
- 功能:拖动圆周上的点,观察圆周角大小变化,验证同弧所对圆周角是圆心角的一半。
核心功能:
拖动圆周上的点A、B、C,观察角度变化
实时计算圆心角∠AOB和圆周角∠ACB
验证圆周角定理:同弧所对圆周角是圆心角的一半
显示圆周角与圆心角的比值
// 点数据接口
interface CircumferentialPoint {
x: number
y: number
}
@Entry
@Component
struct CircumferentialAngleTheorem {
@State centerX: number = 250
@State centerY: number = 150
@State radius: number = 100
@State pointA: CircumferentialPoint = { x: 250, y: 50 }
@State pointB: CircumferentialPoint = { x: 150, y: 150 }
@State pointC: CircumferentialPoint = { x: 350, y: 150 }
@State centralAngle: number = 0
@State circumferentialAngle: number = 0
@State isDragging: boolean = false
@State draggingPoint: 'A' | 'B' | 'C' = 'C'
build() {
Column({ space: 20 }) {
Text('圆周角定理演示')
.fontSize(26)
.fontWeight(FontWeight.Bold)
Column() {
Text('本应用演示圆周角定理:同弧所对的圆周角是圆心角的一半。用户可以拖动圆周上的点C,观察圆周角∠ACB的大小变化,验证它始终等于圆心角∠AOB的一半。通过直观的交互方式,帮助学生理解圆周角定理的核心内容和几何意义。')
.fontSize(14)
.fontColor('#666666')
.textAlign(TextAlign.Center)
.lineHeight(22)
.padding({ left: 20, right: 20 })
}
.width('100%')
.backgroundColor('#E3F2FD')
.borderRadius(10)
.padding(15)
Canvas(this.canvasContext)
.width(500)
.height(300)
.backgroundColor('#FFFFFF')
.border({ width: 2, color: '#333' })
.borderRadius(10)
.onReady(() => {
this.draw()
})
.gesture(
PanGesture()
.onActionStart((event) => {
this.isDragging = true
this.draggingPoint = this.getDraggingPoint(event.fingerList[0].localX, event.fingerList[0].localY)
})
.onActionUpdate((event) => {
if (this.isDragging) {
this.updatePointPosition(event.fingerList[0].localX, event.fingerList[0].localY)
this.calculateAngles()
this.draw()
}
})
.onActionEnd(() => {
this.isDragging = false
})
)
Column({ space: 10 }) {
Row({ space: 20 }) {
Text('圆心角 ∠AOB')
.fontSize(16)
.fontWeight(FontWeight.Medium)
Text(`${this.centralAngle.toFixed(1)}°`)
.fontSize(16)
.fontColor('#2196F3')
}
Row({ space: 20 }) {
Text('圆周角 ∠ACB')
.fontSize(16)
.fontWeight(FontWeight.Medium)
Text(`${this.circumferentialAngle.toFixed(1)}°`)
.fontSize(16)
.fontColor('#FF9800')
}
Row({ space: 20 }) {
Text('圆周角 / 圆心角')
.fontSize(16)
.fontWeight(FontWeight.Medium)
Text(`${(this.centralAngle > 0 ? (this.circumferentialAngle / this.centralAngle).toFixed(2) : '0.00')}`)
.fontSize(16)
.fontColor('#4CAF50')
}
Row({ space: 20 }) {
Text('定理验证')
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text(this.getTheoremVerification())
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor(this.getVerificationColor())
}
}
.width('90%')
.padding(20)
.backgroundColor('#F5F5F5')
.borderRadius(10)
Row({ space: 20 }) {
Button('重置位置')
.width('30%')
.height(50)
.fontSize(18)
.backgroundColor('#2196F3')
.onClick(() => {
this.resetPosition()
})
Button('随机位置')
.width('30%')
.height(50)
.fontSize(18)
.backgroundColor('#4CAF50')
.onClick(() => {
this.randomPosition()
})
}
.width('90%')
}
.width('100%')
.height('100%')
.padding(20)
.justifyContent(FlexAlign.Start)
}
private canvasContext: CanvasRenderingContext2D = new CanvasRenderingContext2D()
private getDraggingPoint(x: number, y: number): 'A' | 'B' | 'C' {
const distanceA = Math.sqrt((x - this.pointA.x) ** 2 + (y - this.pointA.y) ** 2)
const distanceB = Math.sqrt((x - this.pointB.x) ** 2 + (y - this.pointB.y) ** 2)
const distanceC = Math.sqrt((x - this.pointC.x) ** 2 + (y - this.pointC.y) ** 2)
const minDistance = Math.min(distanceA, distanceB, distanceC)
if (minDistance < 10) {
if (minDistance === distanceA) return 'A'
if (minDistance === distanceB) return 'B'
return 'C'
}
return 'C'
}
private updatePointPosition(x: number, y: number) {
const dx = x - this.centerX
const dy = y - this.centerY
const distance = Math.sqrt(dx * dx + dy * dy)
if (distance > 0) {
const normalizedX = this.centerX + (dx / distance) * this.radius
const normalizedY = this.centerY + (dy / distance) * this.radius
if (this.draggingPoint === 'A') {
this.pointA = { x: normalizedX, y: normalizedY }
} else if (this.draggingPoint === 'B') {
this.pointB = { x: normalizedX, y: normalizedY }
} else {
this.pointC = { x: normalizedX, y: normalizedY }
}
}
}
private calculateAngles() {
this.centralAngle = this.calculateAngle(this.pointA, this.centerX, this.centerY, this.pointB)
this.circumferentialAngle = this.calculateAngle(this.pointA, this.pointC.x, this.pointC.y, this.pointB)
}
private calculateAngle(p1: CircumferentialPoint, centerX: number, centerY: number, p2: CircumferentialPoint): number {
const v1x = p1.x - centerX
const v1y = p1.y - centerY
const v2x = p2.x - centerX
const v2y = p2.y - centerY
const dotProduct = v1x * v2x + v1y * v2y
const magnitude1 = Math.sqrt(v1x * v1x + v1y * v1y)
const magnitude2 = Math.sqrt(v2x * v2x + v2y * v2y)
if (magnitude1 === 0 || magnitude2 === 0) {
return 0
}
let angle = Math.acos(dotProduct / (magnitude1 * magnitude2)) * (180 / Math.PI)
const crossProduct = v1x * v2y - v1y * v2x
if (crossProduct < 0) {
angle = 360 - angle
}
return angle
}
private getTheoremVerification(): string {
if (this.centralAngle < 0.1) {
return '请拖动点C'
}
const ratio = this.circumferentialAngle / this.centralAngle
if (Math.abs(ratio - 0.5) < 0.05) {
return '定理成立!'
} else {
return '验证中...'
}
}
private getVerificationColor(): string {
if (this.centralAngle < 0.1) {
return '#666666'
}
const ratio = this.circumferentialAngle / this.centralAngle
if (Math.abs(ratio - 0.5) < 0.05) {
return '#4CAF50'
} else {
return '#FF9800'
}
}
private draw() {
const ctx = this.canvasContext
ctx.clearRect(0, 0, 500, 300)
ctx.save()
ctx.beginPath()
ctx.arc(this.centerX, this.centerY, this.radius, 0, 2 * Math.PI)
ctx.fillStyle = '#E3F2FD'
ctx.fill()
ctx.strokeStyle = '#2196F3'
ctx.lineWidth = 2
ctx.stroke()
ctx.beginPath()
ctx.arc(this.centerX, this.centerY, 3, 0, 2 * Math.PI)
ctx.fillStyle = '#2196F3'
ctx.fill()
ctx.beginPath()
ctx.moveTo(this.pointA.x, this.pointA.y)
ctx.lineTo(this.centerX, this.centerY)
ctx.lineTo(this.pointB.x, this.pointB.y)
ctx.strokeStyle = '#2196F3'
ctx.lineWidth = 2
ctx.stroke()
ctx.beginPath()
ctx.moveTo(this.pointA.x, this.pointA.y)
ctx.lineTo(this.pointC.x, this.pointC.y)
ctx.lineTo(this.pointB.x, this.pointB.y)
ctx.strokeStyle = '#FF9800'
ctx.lineWidth = 2
ctx.stroke()
ctx.beginPath()
ctx.arc(this.pointA.x, this.pointA.y, 8, 0, 2 * Math.PI)
ctx.fillStyle = '#4CAF50'
ctx.fill()
ctx.strokeStyle = '#333'
ctx.lineWidth = 2
ctx.stroke()
ctx.beginPath()
ctx.arc(this.pointB.x, this.pointB.y, 8, 0, 2 * Math.PI)
ctx.fillStyle = '#4CAF50'
ctx.fill()
ctx.strokeStyle = '#333'
ctx.lineWidth = 2
ctx.stroke()
ctx.beginPath()
ctx.arc(this.pointC.x, this.pointC.y, 8, 0, 2 * Math.PI)
ctx.fillStyle = '#FF9800'
ctx.fill()
ctx.strokeStyle = '#333'
ctx.lineWidth = 2
ctx.stroke()
ctx.font = '16px sans-serif'
ctx.fillStyle = '#333'
ctx.fillText('O', this.centerX + 10, this.centerY - 10)
ctx.fillText('A', this.pointA.x + 10, this.pointA.y - 10)
ctx.fillText('B', this.pointB.x + 10, this.pointB.y - 10)
ctx.fillText('C', this.pointC.x + 10, this.pointC.y - 10)
this.drawArc(this.pointA, this.pointB, '#2196F3', 0.5)
this.drawArc(this.pointA, this.pointB, '#FF9800', 0.3, this.pointC)
ctx.restore()
}
private drawArc(p1: CircumferentialPoint, p2: CircumferentialPoint, color: string, lineWidth: number, center?: CircumferentialPoint) {
const ctx = this.canvasContext
const arcCenter = center || { x: this.centerX, y: this.centerY }
const startAngle = Math.atan2(p1.y - arcCenter.y, p1.x - arcCenter.x)
const endAngle = Math.atan2(p2.y - arcCenter.y, p2.x - arcCenter.x)
ctx.beginPath()
ctx.arc(arcCenter.x, arcCenter.y, this.radius * 0.7, startAngle, endAngle, false)
ctx.strokeStyle = color
ctx.lineWidth = lineWidth
ctx.setLineDash([5, 5])
ctx.stroke()
ctx.setLineDash([])
}
private resetPosition() {
this.pointA = { x: 250, y: 50 }
this.pointB = { x: 150, y: 150 }
this.pointC = { x: 350, y: 150 }
this.calculateAngles()
this.draw()
}
private randomPosition() {
const angleA = Math.random() * Math.PI * 2
const angleB = angleA + Math.random() * Math.PI
const angleC = angleA + Math.random() * Math.PI * 2
this.pointA = {
x: this.centerX + Math.cos(angleA) * this.radius,
y: this.centerY + Math.sin(angleA) * this.radius
}
this.pointB = {
x: this.centerX + Math.cos(angleB) * this.radius,
y: this.centerY + Math.sin(angleB) * this.radius
}
this.pointC = {
x: this.centerX + Math.cos(angleC) * this.radius,
y: this.centerY + Math.sin(angleC) * this.radius
}
this.calculateAngles()
this.draw()
}
}
更多推荐

所有评论(0)