Bluescape has a few inconsistencies with text fontSize that require clarification to help developers understand how Bluescape deals with fonts and fontSize.
1. Font Point and Pixel units
In our UI the font size is displayed as font POINT size, and the API uses fontSize in Pixels.
For example, when in the web client UI and selecting text, it shows 12 point.
However, when using an API to query the fontSize of the text element, it returns fontSize = 16 in pixels
{
"data": {
"elements": [
{
"__typename": "Text",
"id": "652fe5d61230370e47f723bc",
"traits": null,
"pinned": false,
"transform": {
"scaleX": 1,
"scaleY": 1,
"x": -195.53751,
"y": -207.554938
},
"text": "My Text",
"style": {
"textTransform": "none",
"fontSize": 16,
"fontFamily": "Source Sans Pro",
"verticalAlign": "top",
"width": 58.53751,
"height": 20
},
"blocks": [
{
"align": "left",
"content": [
{
"text": "My Text"
}
]
}
]
}
]
}
}
2. Known Issue: fontSize can be returned as Float
The graphQL schema shows element query text fontSize should return fontSize pixels as INT, but it can sometimes return a FLOAT. Additionally, fontSize for element mutation input requires INT only. If a float is used as the input, an error is returned.
The issue with float is due to Point to Pixel conversion.
For example:
6 pixel is 6 * (72/96) = 4.5 point
7 pixel is 7 * (72/96) = 5.25 point
Or point to pixels:
5pt * (96/72) = 6.66667px
Expected result:
- fontSize should never be a FLOAT. It is defined by graphQL schema as INT
Actual result:
- fontSize can return as a FLOAT rather than an INT under certain scenarios
Workaround: When using fontSize from a query response in an element input, round the output fontSize to ensure you do not pass a float as the mutation fontSize input.
3. Global text style fontSize vs span fontSize
We have a fontSize that is used for the entire text element which is found in style.fontSize
, but we can also have fontSize in a text block as span.fontSize
. If there is ever a span.fontSize
, it is used. If there isn’t a span.fontSize
, the style.fontSize
is used.
For Example
We have one line of text, “My Text” at 112 point font size:
When we query this text element, we can see both style.fontSize:16
and span.fontSize:149.3333
(note the known issue of Float returned as fontSize). You would use the span.fontSize
rather than the style.fontSize
, due to span.fontSize
always being given priority over style.fontSize
.
{
"type": "Text",
"id": "65255aad8906e1844913b42c",
"transform": {
"x": 153.76057433936785,
"y": -2425,
"scaleX": 1,
"scaleY": 1,
"rotateZ": 0
},
"text": "My Text",
"style": {
"textTransform": "none",
"fontSize": 16,
"fontFamily": "Source Sans Pro",
"verticalAlign": "top",
"width": 608,
"height": 188
},
"myTextBlock": [
{
"align": "left",
"content": [
{
"span": {
"fontSize": 149.3333,
"content": [
{
"text": "My Text"
}
]
}
}
]
}
]
}
4. Scaling text does not change API fontSize pixels
It is possible to scale text elements in both the workspace UI and API. If a user is in the webUI and scales the text by dragging the corner of the element, the font point size also increases in the webUI.
WebUI shows 21 point without scale, width = 97 and height = 37:
API query returns fontSize pixels as fontSize:28
and both scaleX:1
and scaleY:1
{
"data": {
"elements": [
{
"__typename": "Text",
"id": "652ff386f0060266cfbb8cc0",
"transform": {
"scaleX": 1,
"scaleY": 1,
"x": -735,
"y": -2098.909905
},
"boundingBox": {
"width": 97,
"height": 35,
"x": -735,
"y": -2098.909905
},
"text": "My Text",
"style": {
"textTransform": "none",
"fontSize": 28,
"fontFamily": "Source Sans Pro",
"verticalAlign": "top",
"width": 97,
"height": 35
},
"blocks": [
{
"align": "left",
"content": [
{
"text": "My Text"
}
]
}
]
}
]
}
}
After scaling up the text from 21pt in the web UI to 113pt:
Note: The text API query returns original fontSize, width/height. You can calculate the fontSize px by multiplying fontSize by scaleX/scaleY. To get the size of the text element on screen use the boundingBox
object.
{
"data": {
"elements": [
{
"__typename": "Text",
"id": "652ff386f0060266cfbb8cc0",
"transform": {
"scaleX": 5.360824742268041,
"scaleY": 5.360824742857143,
"x": -735,
"y": -2098.909905
},
"boundingBox": {
"width": 520,
"height": 187.62886600000002,
"x": -735,
"y": -2098.909905
},
"text": "My Text",
"style": {
"textTransform": "none",
"fontSize": 28,
"fontFamily": "Source Sans Pro",
"verticalAlign": "top",
"width": 97,
"height": 35
},
"blocks": [
{
"align": "left",
"content": [
{
"text": "My Text"
}
]
}
]
}
]
}
}
For Example: You can use the query output to recreate scaled text with the following createText mutation:
mutation createTextScaledText($ws: String! $textInput:CreateTextInput!) {
createText(
workspaceId: $ws
input:$textInput
){
id
text
transform {x, y}
boundingBox{x, y, width, height}
}
}
Variables with query output from above:
{
"ws": "{{workspaceID}}",
"textInput": {
"transform": {
"scaleX": 5.360824742268041,
"scaleY": 5.360824742857143,
"x": -135,
"y": -2098.909905
},
"style": {
"textTransform": "none",
"fontSize": 28,
"fontFamily": "Source Sans Pro",
"verticalAlign": "top",
"width": 97,
"height": 35
},
"blocks": [{
"block":{
"align": "left",
"content": [
{
"text": "My Text"
}]
}
}]
}
}
Known Issue: There are some edge cases where using the query output params when creating a new text can have point size in the webUI off by 1pt due to math rounding.