FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Improved text component · N8python/enable3d@406685c · GitHub

Commit 406685c

Browse files
committed
Improved text component
1 parent 7d3ca80 commit 406685c

3 files changed

Lines changed: 189 additions & 22 deletions

File tree

‎packages/dev/src/game.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import startPhaserGame from './phaserGame'
22
import startProject from './threeScene'
3+
import startProjectFlatDev0 from './threeSceneFlatDev0'
34
import startProjectFlatDev1 from './threeSceneFlatDev1'
45
import startProjectFlatDev2 from './threeSceneFlatDev2'
56
import startPhysics from './physics'
@@ -13,5 +14,6 @@ import startHeadless from './headless'
1314
// startHeadless() // @enable3d/ammo-physics (headless)
1415

1516
// flat_EXPERIMENTAL
16-
startProjectFlatDev1()
17+
startProjectFlatDev0()
18+
// startProjectFlatDev1()
1719
// startProjectFlatDev2()
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Project, Scene3D, PhysicsLoader, FLAT } from 'enable3d'
2+
3+
import { Camera, LinearFilter, LinearMipMapLinearFilter, NearestFilter, Scene } from 'three'
4+
5+
class MainScene extends Scene3D {
6+
ui: {
7+
camera: Camera
8+
scene: Scene
9+
}
10+
11+
matter = new FLAT.MatterPhysics()
12+
ball: FLAT.SimpleSprite
13+
14+
async create() {
15+
this.warpSpeed()
16+
17+
this.renderer.autoClear = false // To allow render overlay on top of the 3d camera
18+
const width = window.innerWidth
19+
const height = window.innerHeight
20+
this.ui = {
21+
// {x: 0, y: 0} is bottomLeft
22+
camera: this.cameras.orthographicCamera({ left: 0, right: width, bottom: 0, top: height }),
23+
scene: new Scene()
24+
}
25+
}
26+
27+
preRender() {
28+
this.renderer.clear()
29+
}
30+
31+
postRender() {
32+
if (this.ui && this.ui.scene && this.ui.camera) {
33+
this.renderer.clearDepth()
34+
this.renderer.render(this.ui.scene, this.ui.camera)
35+
36+
FLAT.render(this.ui.camera)
37+
}
38+
}
39+
}
40+
41+
const startProject = () => {
42+
PhysicsLoader('/lib', () => new Project({ scenes: [MainScene] }))
43+
}
44+
45+
export default startProject

‎packages/threeGraphics/src/flat/text.ts‎

Lines changed: 141 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,38 @@ import { LinearFilter, Texture } from 'three'
1010
import { SimpleSprite, canvas } from './index'
1111
import { createNewTexture } from './_misc'
1212

13+
export interface TextConfig {
14+
align?: 'center' | 'left' | 'right'
15+
background?: string | CanvasGradient | CanvasPattern
16+
baseline?: CanvasTextBaseline
17+
borderColor?: string
18+
borderRadius?: number
19+
borderWidth?: number
20+
fillStyle?: string | CanvasGradient | CanvasPattern
21+
fontFamily?: string
22+
fontSize?: number
23+
fontWeight?: string
24+
lineHeight?: number
25+
lineWidth?: number
26+
offset?: { x?: number; y?: number }
27+
padding?: number | { x?: number; y?: number }
28+
strokeStyle?: string | CanvasGradient | CanvasPattern
29+
}
30+
31+
// https://stackoverflow.com/a/7838871
32+
const roundRect = (ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, r: number) => {
33+
if (w < 2 * r) r = w / 2
34+
if (h < 2 * r) r = h / 2
35+
36+
ctx.beginPath()
37+
ctx.moveTo(x + r, y)
38+
ctx.arcTo(x + w, y, x + w, y + h, r)
39+
ctx.arcTo(x + w, y + h, x, y + h, r)
40+
ctx.arcTo(x, y + h, x, y, r)
41+
ctx.arcTo(x, y, x + w, y, r)
42+
ctx.closePath()
43+
}
44+
1345
const fontHeightCache: Map<string, number> = new Map()
1446

1547
const calcHeight = (text: string, fontSize: number, fontFamily: string, lineHeight: number = 1) => {
@@ -42,23 +74,54 @@ const calcWidth = (ctx: CanvasRenderingContext2D, lines: string[]) => {
4274
return Math.max(...lines.map(line => Math.ceil(ctx.measureText(line).width)))
4375
}
4476

45-
const createTextImage = (text: string, color: string) => {
77+
const createTextImage = (text: string, config: TextConfig) => {
78+
const {
79+
align = 'center',
80+
background = 'gray',
81+
baseline = 'middle',
82+
borderColor = 'yellow',
83+
borderRadius = 20,
84+
borderWidth = 20,
85+
fillStyle = 'DarkSlateBlue',
86+
fontFamily = 'Arial',
87+
fontSize = 96,
88+
fontWeight = 'bold',
89+
lineHeight = 1,
90+
lineWidth = 8,
91+
padding = 12,
92+
strokeStyle = 'Red'
93+
} = config
94+
95+
// get offset
96+
const { offset: { x: offsetX = 0, y: offsetY = 0 } = {} } = config
97+
98+
// get padding
99+
let paddingX
100+
let paddingY
101+
if (typeof padding !== 'number') {
102+
paddingX = padding.x || 0
103+
paddingY = padding.y || 0
104+
} else {
105+
paddingX = padding
106+
paddingY = padding
107+
}
108+
109+
const font = `${fontWeight} ${fontSize}px ${fontFamily}`
110+
46111
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
47112

48113
// clean up
49114
ctx.clearRect(0, 0, canvas.width, canvas.height)
50115

51-
const fontSize = 72
52-
const fontFamily = 'Arial'
53-
const lineHeight = 1
54116
const lines = text.split('\n')
55117

56-
ctx.font = `bold ${fontSize}px ${fontFamily}`
118+
ctx.font = font
57119

58-
let line_Height = calcHeight(text, fontSize, fontFamily, lineHeight)
120+
let line_height = calcHeight(text, fontSize, fontFamily, lineHeight)
121+
let line_width = fillStyle ? lineWidth * 2 : lineWidth
59122

60-
let height = line_Height * lines.length
61-
let width = calcWidth(ctx, lines)
123+
let height = line_height * lines.length + paddingY * 2 + borderWidth * 2
124+
let width = calcWidth(ctx, lines) + line_width + paddingX * 2 + borderWidth * 2
62125

63126
// adjust to PowerOfTwo (WebGL1 only)
64127
// width = Math.max(2, MathUtils.ceilPowerOfTwo(width))
@@ -67,20 +130,77 @@ const createTextImage = (text: string, color: string) => {
67130
canvas.height = height
68131
canvas.width = width
69132

133+
// border
134+
if (borderColor) {
135+
ctx.strokeStyle = borderColor
136+
roundRect(
137+
ctx,
138+
borderWidth / 2,
139+
borderWidth / 2,
140+
canvas.width - borderWidth,
141+
canvas.height - borderWidth,
142+
borderRadius
143+
)
144+
ctx.lineWidth = borderWidth
145+
ctx.stroke()
146+
}
147+
70148
// background
71-
// ctx.fillStyle = '#c4c4c4'
72-
// ctx.fillRect(0, 0, canvas.width, canvas.height)
149+
if (background) {
150+
ctx.fillStyle = background
151+
roundRect(
152+
ctx,
153+
borderWidth,
154+
borderWidth,
155+
canvas.width - borderWidth * 2,
156+
canvas.height - borderWidth * 2,
157+
borderColor ? borderRadius / 2 : borderRadius
158+
)
159+
ctx.fill()
160+
161+
// if (borderColor && borderWidth)
162+
// ctx.fillRect(borderWidth, borderWidth, canvas.width - borderWidth * 2, canvas.height - borderWidth * 2)
163+
// else ctx.fillRect(0, 0, canvas.width, canvas.height)
164+
}
73165

74166
// text
75-
ctx.font = `bold ${fontSize}px ${fontFamily}`
76-
ctx.textAlign = 'left'
77-
ctx.textBaseline = 'middle'
78-
ctx.fillStyle = color
167+
ctx.font = font
168+
ctx.textAlign = align
169+
ctx.textBaseline = baseline
170+
171+
if (strokeStyle && lineWidth) {
172+
ctx.strokeStyle = strokeStyle
173+
ctx.lineWidth = line_width
174+
}
175+
176+
if (fillStyle) ctx.fillStyle = fillStyle
79177

80178
for (var i = 0; i < lines.length; i++) {
81-
const top = i * line_Height + line_Height / 2
82-
const left = 0
83-
ctx.fillText(lines[i], left, top)
179+
let top = i * line_height + line_height / 2
180+
let left = 0
181+
182+
if (align === 'left') {
183+
left = line_width / 2
184+
left += paddingX
185+
left += borderWidth
186+
}
187+
if (align === 'center') {
188+
left = width / 2
189+
}
190+
if (align === 'right') {
191+
left = width - line_width / 2
192+
left -= paddingX
193+
left -= borderWidth
194+
}
195+
196+
top += paddingY
197+
top += borderWidth
198+
199+
top += offsetY
200+
left += offsetX
201+
202+
if (strokeStyle && lineWidth) ctx.strokeText(lines[i], left, top)
203+
if (fillStyle) ctx.fillText(lines[i], left, top)
84204
}
85205

86206
// https://github.com/makc/Edelweiss/blob/c3e63135f2f57f1a422c30abbeca35e579b84f02/docs/js/AssetManager.js#L245
@@ -105,8 +225,8 @@ export class TextTexture extends Texture {
105225
return new this.constructor(this._text).copy(this)
106226
}
107227

108-
constructor(text: string, color: string = '#00ff00') {
109-
const { imageData, width, height } = createTextImage(text, color)
228+
constructor(text: string, config: TextConfig = {}) {
229+
const { imageData, width, height } = createTextImage(text, config)
110230
super(imageData)
111231

112232
this.width = width
@@ -130,14 +250,14 @@ export class TextSprite extends SimpleSprite {
130250
this._text = texture.getText()
131251
}
132252

133-
setText(text: string, color: string = '#00ff00') {
253+
setText(text: string, config: TextConfig = {}) {
134254
this._text = text
135255

136256
// dispose
137257
this.texture.dispose()
138258

139259
// create
140-
this.texture = this.material.map = createNewTexture(createTextImage(text, color).imageData)
260+
this.texture = this.material.map = createNewTexture(createTextImage(text, config).imageData)
141261

142262
// update size
143263
this.height = this.texture.image.height

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL