Skip to content

Commit aad88c4

Browse files
author
Bryan Parker
committed
Text colors and scaling
1 parent 27f0b6c commit aad88c4

File tree

8 files changed

+126
-122
lines changed

8 files changed

+126
-122
lines changed

src/canvas.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Colors, rgbaToString } from '@/colors';
1+
import { Colors, rgbaToString, parseColor } from '@/colors';
22
import { config } from '@/config';
33
import { Shape } from '@/shapes/shape';
44
import { PointShape } from '@/shapes/primitives/point_shape';
@@ -165,7 +165,7 @@ class HtmlCanvas implements Canvas {
165165
this._ctx.font = `${text.fontSize() * text.currentScale()}px ${text.fontFamily()}`;
166166
this._ctx.textBaseline = 'top';
167167
this._ctx.textAlign = 'left';
168-
this._ctx.fillStyle = rgbaToString(styles.color ?? styles.lineColor ?? Colors.black() )
168+
this._ctx.fillStyle = rgbaToString(parseColor(styles.color ?? styles.lineColor ?? Colors.black()));
169169

170170
this._ctx.fillText(text.text(), ...this.t.translateRelative([xDraw, yDraw]));
171171
}
@@ -295,15 +295,14 @@ class HtmlCanvas implements Canvas {
295295
}
296296

297297
private setContextStyles(shape: Shape): void {
298-
// const styles = isShape(shape) ? shape.styles() : shape;
299298
const styles = shape.styles();
300299

301300
if (styles.color) {
302-
this._ctx.fillStyle = rgbaToString(styles.color);
301+
this._ctx.fillStyle = rgbaToString(parseColor(styles.color));
303302
}
304303

305304
if (styles.lineColor) {
306-
this._ctx.strokeStyle = rgbaToString(styles.lineColor);
305+
this._ctx.strokeStyle = rgbaToString(parseColor(styles.lineColor));
307306
}
308307

309308
if (styles.lineWidth) {

src/colors.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function parseColor(color: string | RGBA): Readonly<RGBA> {
3232
* @param color The RGBA color
3333
* @returns the rgba string
3434
*/
35-
function rgbaToString(color: RGBA): string {
35+
function rgbaToString(color: RGBA | Readonly<RGBA>): string {
3636
return `rgba(${color[0]}, ${color[1]}, ${color[2]}, ${color[3]})`;
3737
}
3838

src/shapes/derived/triangle.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ type TriangleArgs = { x?: number; y?: number; center?: Locatable; width?: number
77

88

99
class Triangle extends PointShape {
10-
constructor({ x = 0, y = 0, center = undefined, width = 1, height = 1, ...styleArgs }: TriangleArgs = {}) {
10+
constructor({ x = 0, y = 0, center = undefined, width = 2, height = 2, ...styleArgs }: TriangleArgs = {}) {
1111
super({ points: Triangle.trianglePoints(x, y, width, height), ...styleArgs });
1212
}
1313

src/shapes/primitives/text.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ class Text implements Shape {
6464
}
6565

6666
this._textMeasurement = new TextMeasurement(config.canvasInstance!, this._tex);
67-
this._textWidth = this._textMeasurement.textWidth(this._text, this._size, this._font);
68-
this._textHeight = this._textMeasurement.textHeight(this._text, this._size, this._font);
67+
[this._textWidth, this._textHeight] = this.updateDimensions();
6968
}
7069

7170
center(): Point {
@@ -121,6 +120,7 @@ class Text implements Shape {
121120

122121
scale(factor: number): this {
123122
this._scale += factor;
123+
this.updateDimensions();
124124
return this;
125125
}
126126

@@ -270,8 +270,7 @@ class Text implements Shape {
270270

271271
changeFontSize(size: number): this {
272272
this._size = size;
273-
this._textWidth = this._textMeasurement.textWidth(this._text, this._size, this._font);
274-
this._textHeight = this._textMeasurement.textHeight(this._text, this._size, this._font);
273+
this.updateDimensions();
275274
return this;
276275
}
277276

@@ -299,9 +298,7 @@ class Text implements Shape {
299298
changeText(text: string): this {
300299
this._text = text;
301300

302-
this._textMeasurement = new TextMeasurement(config.canvasInstance!, this._tex);
303-
this._textWidth = this._textMeasurement.textWidth(this._text, this._size, this._font);
304-
this._textHeight = this._textMeasurement.textHeight(this._text, this._size, this._font);
301+
this.updateDimensions();
305302

306303
return this;
307304
}
@@ -317,6 +314,15 @@ class Text implements Shape {
317314
maxY: top + this._textHeight
318315
};
319316
}
317+
318+
private updateDimensions(): [number, number] {
319+
const { width, height } = this._textMeasurement.textDimensions(this._text, this._size, this._font, this._scale);
320+
this._textWidth = width;
321+
this._textHeight = height;
322+
323+
return [this._textWidth, this._textHeight];
324+
}
320325
}
321326

327+
322328
export { Text, type TextBaseline, type TextAlign, type TextArgs };

src/shapes/primitives/text_measurement.ts

+27-39
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ class TextMeasurement {
1515
this._tex = tex;
1616
}
1717

18-
textWidth(text: string, size: number, font: string): number {
18+
textWidth(text: string, size: number, font: string, scale: number = 1): number {
1919
return this._tex
20-
? this.texTextDimensions(text, size).width
21-
: this.textDimensions(text, size, font).width;
20+
? this.texTextDimensions(text, size, scale).width
21+
: this.textDimensions(text, size, font, scale).width;
2222
}
2323

24-
textHeight(text: string, size: number, font: string): number {
24+
textHeight(text: string, size: number, font: string, scale: number = 1): number {
2525
return this._tex
26-
? this.texTextDimensions(text, size).height
27-
: this.textDimensions(text, size, font).height;
26+
? this.texTextDimensions(text, size, scale).height
27+
: this.textDimensions(text, size, font, scale).height;
2828
}
2929

30-
textDimensions(text: string, size: number, font: string): { width: number; height: number; } {
30+
textDimensions(text: string, size: number, font: string, scale: number = 1): { width: number; height: number; } {
3131
if (this._tex) {
32-
return this.texTextDimensions(text, size);
32+
return this.texTextDimensions(text, size, scale);
3333
} else {
3434
const ctx = this._canvas.getContext('2d')!;
35-
ctx.font = `${size}px ${font}`;
35+
ctx.font = `${size * scale}px ${font}`;
3636

3737
const tm = ctx.measureText(text);
3838

@@ -48,7 +48,7 @@ class TextMeasurement {
4848
return { minX: 0, maxX: 0, minY: 0, maxY: 0, width: 0, height: 0 };
4949
} else {
5050
const ctx = this._canvas.getContext('2d')!;
51-
ctx.font = `${text.fontSize()}px ${text.fontFamily()}`;
51+
ctx.font = `${text.fontSize() * text.currentScale()}px ${text.fontFamily()}`;
5252
ctx.textAlign = text.align();
5353
ctx.textBaseline = text.baseline();
5454

@@ -63,37 +63,25 @@ class TextMeasurement {
6363

6464
return { minX, maxX, minY, maxY, height: maxY - minY, width: tm.width };
6565
}
66-
67-
// const { x, y } = text;
68-
// const { width, height } = text.size;
69-
// const { width: textWidth, height: textHeight } = text.size;
70-
// const { baseline } = text;
71-
72-
// const minX = x;
73-
// const maxX = x + width;
74-
// const minY = y - height;
75-
// const maxY = y;
76-
77-
// return { minX, maxX, minY, maxY };
7866
}
7967

80-
textDimensionWithCss(text: string, size: number, font: string) {
81-
const div = document.createElement('div');
82-
div.style.font = `${size}px ${font}`;
83-
div.style.position = 'absolute';
84-
div.style.visibility = 'hidden';
85-
// div.style.height = 'auto';
86-
// div.style.width = 'auto';
87-
div.style.whiteSpace = 'nowrap';
88-
div.textContent = text;
89-
document.body.appendChild(div);
90-
const height = div.clientHeight;
91-
const width = div.clientWidth;
92-
// const cssInfo = window.getComputedStyle(div, null);
93-
94-
document.body.removeChild(div);
95-
return { width, height };
96-
}
68+
// textDimensionWithCss(text: string, size: number, font: string) {
69+
// const div = document.createElement('div');
70+
// div.style.font = `${size}px ${font}`;
71+
// div.style.position = 'absolute';
72+
// div.style.visibility = 'hidden';
73+
// // div.style.height = 'auto';
74+
// // div.style.width = 'auto';
75+
// div.style.whiteSpace = 'nowrap';
76+
// div.textContent = text;
77+
// document.body.appendChild(div);
78+
// const height = div.clientHeight;
79+
// const width = div.clientWidth;
80+
// // const cssInfo = window.getComputedStyle(div, null);
81+
82+
// document.body.removeChild(div);
83+
// return { width, height };
84+
// }
9785

9886
private texTextDimensions(text: string, size: number, scale: number = 1): { width: number; height: number; } {
9987
const { width, height } = TexGenerator.getImage({ text, size, scale });

src/tex_generator.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class TexGenerator {
3333
const height = parseFloat(adaptor.getAttribute(svgNode, 'height'));
3434

3535
const pixelsPerEx = 2;
36-
const scaleFactor = size / pixelsPerEx;
36+
const scaleFactor = size * scale / pixelsPerEx;
3737

3838
const adjustedWidth = width * scaleFactor;
3939
const adjustedHeight = height * scaleFactor;

test/script_test.ts

+70-59
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class TestAnimation extends BaseAnimation {
3939

4040
class TestScene extends Scene {
4141
compose() {
42-
this.add(new GridLines());
42+
// this.add(new GridLines());
4343

4444
// const a = this.add(new Axes({
4545
// xRange: [-1, 5],
@@ -432,68 +432,79 @@ class TestScene extends Scene {
432432
// l.changeendpoints(d1, d2);
433433
// }, { duration: 3000, easing: easing.linear, repeat: true, yoyo: true, }));
434434

435-
const axes = new Axes({
436-
xLength: 8,
437-
yLength: 6,
438-
xRange: [0, 1],
439-
xStep: 0.25,
440-
yRange: [0, 35],
441-
yStep: 5,
442-
showLabels: false,
443-
showTicks: false,
444-
xLabel: 'time (h)',
445-
yLabel: 'distance (miles)'
446-
});
435+
// const axes = new Axes({
436+
// xLength: 8,
437+
// yLength: 6,
438+
// xRange: [0, 1],
439+
// xStep: 0.25,
440+
// yRange: [0, 35],
441+
// yStep: 5,
442+
// showLabels: false,
443+
// showTicks: false,
444+
// xLabel: 'time (h)',
445+
// yLabel: 'distance (miles)'
446+
// });
447447

448-
const fn = x => Math.pow(Math.E, 12 * x * x - 2.5);
449-
const plot = axes.plot(fn).changeLineColor(Colors.green());
450-
451-
const p = axes.point([0.5, fn(0.5)]);
452-
const q = axes.point([0.69, fn(0.69)]);
453-
454-
const pText = new Tex({ text: 'P' }).nextTo(p, [-1, 1]);
455-
const qText = new Tex({ text: 'Q' }).nextTo(q, RIGHT(1.5));
456-
const qDot = new Dot({ center: q, color: Colors.blue() });
457-
const secant = new Line({ from: p, to: q, length: 6, lineColor: Colors.blue() });
458-
const tangent = new TangentLine({ plot, x: 0.5, length: 4, color: Colors.pink() });
459-
const tangentText = new Tex(`m`).changeColor(Colors.pink()).nextTo(tangent.to());
460-
const secantText = new Tex(`m_{\sec} = `).nextTo(secant.to()).changeColor(Colors.blue());
461-
const secantSlope = new Text('').changeColor(Colors.blue()).nextTo(secantText, RIGHT());
462-
// const secantText = new Text(`m_{\\sec}`).nextTo(secant.to()).changeColor(Colors.blue());
463-
464-
this.add(
465-
axes, plot,
448+
// const fn = x => Math.pow(Math.E, 12 * x * x - 2.5);
449+
// const plot = axes.plot(fn).changeLineColor(Colors.green());
450+
451+
// const p = axes.point([0.5, fn(0.5)]);
452+
// const q = axes.point([0.69, fn(0.69)]);
453+
454+
// const pText = new Tex({ text: 'P' }).nextTo(p, [-1, 1]);
455+
// const qText = new Tex({ text: 'Q' }).nextTo(q, RIGHT(1.5));
456+
// const qDot = new Dot({ center: q, color: Colors.blue() });
457+
// const secant = new Line({ from: p, to: q, length: 6, lineColor: Colors.blue() });
458+
// const tangent = new TangentLine({ plot, x: 0.5, length: 4, color: Colors.pink() });
459+
// const tangentText = new Tex(`m`).changeColor(Colors.pink()).nextTo(tangent.to());
460+
// const secantText = new Tex(`m_{\sec} = `).nextTo(secant.to()).changeColor(Colors.blue());
461+
// const secantSlope = new Text('').changeColor(Colors.blue()).nextTo(secantText, RIGHT());
462+
// // const secantText = new Text(`m_{\\sec}`).nextTo(secant.to()).changeColor(Colors.blue());
463+
464+
// this.add(
465+
// axes, plot,
466466

467-
secant,
468-
tangent,
469-
new Dot({ center: p, color: Colors.pink() }),
467+
// secant,
468+
// tangent,
469+
// new Dot({ center: p, color: Colors.pink() }),
470470

471-
qDot,
472-
pText, qText,
473-
tangentText,
474-
secantText,
475-
secantSlope,
476-
);
477-
478-
// Need to throttle how quickly tex is updated since an image is being generated and rendered
479-
const updateText = utils.throttle(text => secantText.changeText(text), 200);
480-
481-
this.add(new Updater((pctComplete: number, starting: boolean) => {
482-
const rx = math.lerp(0.5, 0.75, 1 - pctComplete);
483-
const m = (25 * rx * rx - 25 * 0.5 * 0.5) / (rx - 0.5);
484-
485-
const x = math.lerp(0.51, 0.69, 1 - pctComplete);
486-
qDot.moveTo(plot.pointAtX(x));
487-
secant.changeEndpoints(p, qDot, true);
488-
qText.nextTo(qDot.center(), RIGHT(), 0.3);
489-
secantText.nextTo(secant.to()) //.changeText(`m_{\\sec} = ${m.toFixed(2)}`);
490-
491-
// console.log(m, pctComplete)
492-
// updateText(`m_{\\sec} = ${m.toFixed(2)}`);
493-
secantSlope.nextTo(secantText, RIGHT()).changeText(`${m.toFixed(2)}`);
494-
495-
}, { duration: 5000, easing: Easing.linear, repeat: true, yoyo: true, }));
471+
// qDot,
472+
// pText, qText,
473+
// tangentText,
474+
// secantText,
475+
// secantSlope,
476+
// );
477+
478+
// // Need to throttle how quickly tex is updated since an image is being generated and rendered
479+
// const updateText = utils.throttle(text => secantText.changeText(text), 200);
480+
481+
// this.add(new Updater((pctComplete: number, starting: boolean) => {
482+
// const rx = math.lerp(0.5, 0.75, 1 - pctComplete);
483+
// const m = (25 * rx * rx - 25 * 0.5 * 0.5) / (rx - 0.5);
484+
485+
// const x = math.lerp(0.51, 0.69, 1 - pctComplete);
486+
// qDot.moveTo(plot.pointAtX(x));
487+
// secant.changeEndpoints(p, qDot, true);
488+
// qText.nextTo(qDot.center(), RIGHT(), 0.3);
489+
// secantText.nextTo(secant.to()) //.changeText(`m_{\\sec} = ${m.toFixed(2)}`);
490+
491+
// // console.log(m, pctComplete)
492+
// // updateText(`m_{\\sec} = ${m.toFixed(2)}`);
493+
// secantSlope.nextTo(secantText, RIGHT()).changeText(`${m.toFixed(2)}`);
494+
495+
// }, { duration: 5000, easing: Easing.linear, repeat: true, yoyo: true, }));
496496
// }, { duration: 5000, easing: x => Easing.easeStep(x, 10), repeat: true, yoyo: true, }));
497+
498+
const v = new Tex({ text: '\\mathbb{V}', color: '#343434' }).scale(7);
499+
v.shift(LEFT(2.25), UP(1.5));
500+
501+
const circle = new Circle({ color: '#87c2a5', lineColor: Colors.transparent() }).shift(LEFT());
502+
const square = new Square({ color: '#525893', lineColor: Colors.transparent() }).shift(UP());
503+
const triangle = new Triangle({ color: '#e07a5f', lineColor: Colors.transparent() }).shift(RIGHT());
504+
505+
const logo = new Group(triangle, square, circle, v);
506+
logo.moveTo(ORIGIN);
507+
this.add(logo);
497508
}
498509
}
499510

0 commit comments

Comments
 (0)