From 81a93c59542fc1694b8d27c10852741a4f1c5038 Mon Sep 17 00:00:00 2001 From: Acbox <850625057@qq.com> Date: Mon, 17 Jun 2024 14:45:20 +0800 Subject: [PATCH] feat(70%)(mod-math): `PolarPlane` --- mods/mod-math/src/widgets/numberAxis.ts | 26 +++++++++++-- mods/mod-math/src/widgets/polarPlane.ts | 50 ++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/mods/mod-math/src/widgets/numberAxis.ts b/mods/mod-math/src/widgets/numberAxis.ts index a2165d7bd..a52d6cfee 100644 --- a/mods/mod-math/src/widgets/numberAxis.ts +++ b/mods/mod-math/src/widgets/numberAxis.ts @@ -126,8 +126,16 @@ export class NumberAxis extends Widget { }) changed(this.style.ticks, (v) => { if (v.value) { - for (const tick of this.ticks) - tick.show() + for (let x = this.length[0] + (this.length[1] - this.length[0]) % this.division; x <= this.length[1]; x += this.division) { + this.ticks.push( + new Line([x, -5], [x, 5], { + style: { + color: this.style.tickColor, + }, + progress: this.progress.value, + }), + ) + } } else { for (const tick of this.ticks) @@ -136,8 +144,18 @@ export class NumberAxis extends Widget { }) changed(this.style.texts, (v) => { if (v.value) { - for (const text of this.texts) - text.show() + for (let x = this.length[0] + (this.length[1] - this.length[0]) % this.division; x <= this.length[1]; x += this.division) { + this.texts.push(new Text(this.trend(x).toString(), { + x: x - (this.style.textSize.value / 2), + y: 10, + style: { + fontSize: this.style.textSize.value, + fillColor: this.style.textColor, + // Note: the rotation is reversed because the canvas is flipped + rotation: -this.style.rotation.value, + }, + })) + } } else { for (const text of this.texts) diff --git a/mods/mod-math/src/widgets/polarPlane.ts b/mods/mod-math/src/widgets/polarPlane.ts index 5efcf474f..fe59d9081 100644 --- a/mods/mod-math/src/widgets/polarPlane.ts +++ b/mods/mod-math/src/widgets/polarPlane.ts @@ -1,32 +1,48 @@ -import { Circle, Line } from '@newcar/basic' -import { Widget, changed, ref } from '@newcar/core' +import { Circle, Line, Text } from '@newcar/basic' +import { Widget, changed, reactive, ref } from '@newcar/core' import type { ConvertToProp, Ref, WidgetOptions, WidgetStyle } from '@newcar/core' +import { Color } from '@newcar/utils' +import type { Trend } from './numberAxis' export interface PolarPlaneOptions extends WidgetOptions { style?: PolarPlaneStyle radiusInterval?: number radianInterval?: number levelInterval?: number + trend?: Trend } -export interface PolarPlaneStyle extends WidgetStyle { } +export interface PolarPlaneStyle extends WidgetStyle { + textsOnAxis?: boolean + textsOnCircle?: boolean + textSize?: number + textColor?: Color +} export class PolarPlane extends Widget { radius: Ref radiusInterval: Ref radianInterval: Ref + trend: Ref declare style: ConvertToProp private axisX: Line private axisY: Line private axisR: Array = [] private circles: Array = [] + private textsOnAxis: Array = [] + private textsOnCircle: Array = [] constructor(radius: number, options?: PolarPlaneOptions) { super(options) this.radius = ref(radius) this.radiusInterval = ref(options.radiusInterval ?? 50) - this.radianInterval = ref(options.radianInterval ?? 30) + this.radianInterval = ref(options.radianInterval ?? 360 / 16) + this.trend = ref(options.trend ?? (x => x / 50)) + this.style.textColor = reactive(options.style?.textColor ?? Color.WHITE) + this.style.textSize = ref(options.style?.textSize ?? 20) + this.style.textsOnAxis = ref(options.style?.textsOnAxis ?? true) + this.style.textsOnCircle = ref(options.style?.textsOnCircle ?? true) this.axisX = new Line([-this.radius.value, 0], [this.radius.value, 0]) this.axisY = new Line([0, -this.radius.value], [0, this.radius.value]) @@ -43,9 +59,20 @@ export class PolarPlane extends Widget { }, }), ) + if (this.style.textsOnAxis.value) { + this.textsOnAxis.push( + new Text(this.trend.value(r).toString(), { + x: r, + y: 5, + style: { + fontSize: this.style.textSize.value, + }, + }), + ) + } } - for (let i = 0; i <= 360; i += this.radianInterval.value) { + for (let i = 0; i < 360; i += this.radianInterval.value) { this.axisR.push( new Line([0, 0], [this.radius.value, 0], { style: { @@ -54,9 +81,20 @@ export class PolarPlane extends Widget { }, }), ) + if (this.style.textsOnCircle) { + this.textsOnCircle.push( + new Text(`${(i / 180).toFixed(2)}π`, { + x: this.radius.value * Math.sin(i * Math.PI / 180), + y: this.radius.value * Math.cos(i * Math.PI / 180), + style: { + fontSize: this.style.textSize.value, + }, + }), + ) + } } - this.add(...this.circles, ...this.axisR) + this.add(...this.circles, ...this.axisR, ...this.textsOnAxis, ...this.textsOnCircle) changed(this.radius, (_) => { this.axisX.to.value = [this.radius.value, 0]