Harmonyos应用实例218:复数运算可视化
·
10. 复数运算可视化
功能简介:支持复数的四则运算、模、幅角计算,通过复平面可视化展示复数及其运算结果。帮助学生理解复数的几何意义和运算规则,适用于复数章节的教学。
ArkTS代码:
@Entry
@Component
struct ComplexCalculator {
@State private real1: number = 1
@State private imag1: number = 1
@State private real2: number = 1
@State private imag2: number = -1
@State private operation: string = 'add'
@State private result: string = ''
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
build() {
Column() {
Text('🔢 复数运算可视化')
.fontSize(24).fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
Canvas(this.context)
.width(400).height(400)
.backgroundColor('#f5f5f5')
.onReady(() => this.drawComplex())
Text('运算选择')
.fontSize(18).fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
Row() {
Button('加法')
.width(80)
.onClick(() => { this.operation = 'add'; this.calculate() })
Button('减法')
.width(80)
.onClick(() => { this.operation = 'subtract'; this.calculate() })
Button('乘法')
.width(80)
.onClick(() => { this.operation = 'multiply'; this.calculate() })
Button('除法')
.width(80)
.onClick(() => { this.operation = 'divide'; this.calculate() })
}
Text('复数1: a + bi')
.fontSize(16).fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
Row() {
Text('实部 a: ')
.width(70)
TextInput({
placeholder: '实部',
text: this.real1.toString()
})
.width(100)
.onChange((v: string) => {
this.real1 = parseFloat(v) || 0
this.calculate()
})
Text('虚部 b: ')
.width(70)
TextInput({
placeholder: '虚部',
text: this.imag1.toString()
})
.width(100)
.onChange((v: string) => {
this.imag1 = parseFloat(v) || 0
this.calculate()
})
}
Text('复数2: c + di')
.fontSize(16).fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
Row() {
Text('实部 c: ')
.width(70)
TextInput({
placeholder: '实部',
text: this.real2.toString()
})
.width(100)
.onChange((v: string) => {
this.real2 = parseFloat(v) || 0
this.calculate()
})
Text('虚部 d: ')
.width(70)
TextInput({
placeholder: '虚部',
text: this.imag2.toString()
})
.width(100)
.onChange((v: string) => {
this.imag2 = parseFloat(v) || 0
this.calculate()
})
}
Text('运算结果')
.fontSize(18).fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
Text(this.result)
.fontSize(16).fontColor('#2196F3')
.margin({ bottom: 20 })
Text('复数1信息')
.fontSize(14).fontColor('#666')
Text(this.getComplexInfo(this.real1, this.imag1))
.fontSize(14).fontColor('#666')
Text('复数2信息')
.fontSize(14).fontColor('#666')
Text(this.getComplexInfo(this.real2, this.imag2))
.fontSize(14).fontColor('#666')
}
.padding(20)
}
private calculate() {
let real: number, imag: number
switch (this.operation) {
case 'add':
real = this.real1 + this.real2
imag = this.imag1 + this.imag2
break
case 'subtract':
real = this.real1 - this.real2
imag = this.imag1 - this.imag2
break
case 'multiply':
real = this.real1 * this.real2 - this.imag1 * this.imag2
imag = this.real1 * this.imag2 + this.imag1 * this.real2
break
case 'divide':
const denominator = this.real2 * this.real2 + this.imag2 * this.imag2
real = (this.real1 * this.real2 + this.imag1 * this.imag2) / denominator
imag = (this.imag1 * this.real2 - this.real1 * this.imag2) / denominator
break
default:
real = 0
imag = 0
}
const mod = Math.sqrt(real * real + imag * imag)
const arg = Math.atan2(imag, real) * 180 / Math.PI
this.result = `结果: ${real.toFixed(2)} + ${imag.toFixed(2)}i, 模: ${mod.toFixed(2)}, 幅角: ${arg.toFixed(2)}°`
this.drawComplex()
}
private drawComplex() {
const ctx = this.context
const width = 400
const height = 400
const centerX = width / 2
const centerY = height / 2
const scale = 50 // 缩放因子
// 清空画布
ctx.clearRect(0, 0, width, height)
// 绘制坐标轴
ctx.beginPath()
ctx.moveTo(50, centerY)
ctx.lineTo(width - 50, centerY)
ctx.moveTo(centerX, 50)
ctx.lineTo(centerX, height - 50)
ctx.strokeStyle = '#000'
ctx.lineWidth = 1
ctx.stroke()
// 绘制网格
ctx.strokeStyle = '#ddd'
ctx.lineWidth = 0.5
for (let i = 1; i < 4; i++) {
const x = centerX + i * scale
ctx.beginPath()
ctx.moveTo(x, 50)
ctx.lineTo(x, height - 50)
ctx.stroke()
const x2 = centerX - i * scale
ctx.beginPath()
ctx.moveTo(x2, 50)
ctx.lineTo(x2, height - 50)
ctx.stroke()
const y = centerY + i * scale
ctx.beginPath()
ctx.moveTo(50, y)
ctx.lineTo(width - 50, y)
ctx.stroke()
const y2 = centerY - i * scale
ctx.beginPath()
ctx.moveTo(50, y2)
ctx.lineTo(width - 50, y2)
ctx.stroke()
}
// 计算运算结果
let resultReal: number, resultImag: number
switch (this.operation) {
case 'add':
resultReal = this.real1 + this.real2
resultImag = this.imag1 + this.imag2
break
case 'subtract':
resultReal = this.real1 - this.real2
resultImag = this.imag1 - this.imag2
break
case 'multiply':
resultReal = this.real1 * this.real2 - this.imag1 * this.imag2
resultImag = this.real1 * this.imag2 + this.imag1 * this.real2
break
case 'divide':
const denominator = this.real2 * this.real2 + this.imag2 * this.imag2
resultReal = (this.real1 * this.real2 + this.imag1 * this.imag2) / denominator
resultImag = (this.imag1 * this.real2 - this.real1 * this.imag2) / denominator
break
default:
resultReal = 0
resultImag = 0
}
// 绘制复数1
const x1 = centerX + this.real1 * scale
const y1 = centerY - this.imag1 * scale
ctx.beginPath()
ctx.arc(x1, y1, 6, 0, 2 * Math.PI)
ctx.fillStyle = '#2196F3'
ctx.fill()
ctx.strokeStyle = '#000'
ctx.stroke()
// 绘制复数1的向量
ctx.beginPath()
ctx.moveTo(centerX, centerY)
ctx.lineTo(x1, y1)
ctx.strokeStyle = '#2196F3'
ctx.lineWidth = 2
ctx.stroke()
// 绘制复数2
const x2 = centerX + this.real2 * scale
const y2 = centerY - this.imag2 * scale
ctx.beginPath()
ctx.arc(x2, y2, 6, 0, 2 * Math.PI)
ctx.fillStyle = '#4CAF50'
ctx.fill()
ctx.strokeStyle = '#000'
ctx.stroke()
// 绘制复数2的向量
ctx.beginPath()
ctx.moveTo(centerX, centerY)
ctx.lineTo(x2, y2)
ctx.strokeStyle = '#4CAF50'
ctx.lineWidth = 2
ctx.stroke()
// 绘制结果复数
const x3 = centerX + resultReal * scale
const y3 = centerY - resultImag * scale
ctx.beginPath()
ctx.arc(x3, y3, 6, 0, 2 * Math.PI)
ctx.fillStyle = '#FF5722'
ctx.fill()
ctx.strokeStyle = '#000'
ctx.stroke()
// 绘制结果复数的向量
ctx.beginPath()
ctx.moveTo(centerX, centerY)
ctx.lineTo(x3, y3)
ctx.strokeStyle = '#FF5722'
ctx.lineWidth = 2
ctx.stroke()
// 绘制图例
ctx.font = '12px Arial'
ctx.fillStyle = '#000'
ctx.fillText('复数1', 30, 30)
ctx.fillText('复数2', 100, 30)
ctx.fillText('结果', 170, 30)
ctx.fillStyle = '#2196F3'
ctx.fillRect(25, 15, 10, 10)
ctx.fillStyle = '#4CAF50'
ctx.fillRect(95, 15, 10, 10)
ctx.fillStyle = '#FF5722'
ctx.fillRect(165, 15, 10, 10)
}
private getComplexInfo(real: number, imag: number): string {
const mod = Math.sqrt(real * real + imag * imag)
const arg = Math.atan2(imag, real) * 180 / Math.PI
return `模: ${mod.toFixed(2)}, 幅角: ${arg.toFixed(2)}°`
}
}
更多推荐


所有评论(0)