Trong API Trang trình bày, văn bản có thể nằm trong các hình dạng hoặc trong các ô của bảng. Trước khi có thể thao tác và tạo kiểu cho văn bản, bạn cần hiểu cấu trúc và cách hoạt động của kiểu văn bản.
Trang này mô tả cách trình bày văn bản trong API Trang trình bày.
Trình tự các phần tử văn bản
Văn bản chứa trong một hình dạng hoặc ô trong bảng được tạo thành từ một chuỗi các cấu trúc TextElement. Trình tự này thể hiện cấu trúc của văn bản, theo thứ tự xuất hiện từ đầu đến cuối.
Ví dụ: hãy xem xét nội dung của trang trình bày này — tất cả nằm trong một hộp văn bản:
Trang trình bày ở trên có một hộp văn bản, trong đó trường text
chứa một trình tự các phần tử văn bản như minh hoạ trong sơ đồ sau:
Cụ thể hơn, chuỗi văn bản này được biểu thị trong API Trang trình bày như sau:
"textElements": [ {
"endIndex": 224,
"paragraphMarker": { "style": {} }
}, {
"endIndex": 130,
"textRun": { "content": "Li lingues differe in li grammatica e li vocabules. Omnicos directe al desirabilite de un nov ", "style": {} }
}, {
"endIndex": 143,
"startIndex": 130,
"textRun": { "content": "lingua franca", "style": { "italic": True } }
}, {
"endIndex": 224,
"startIndex": 143,
"textRun": { "content": ": solmen va esser necessi far:\n", "style": {} }
}, {
"endIndex": 243,
"startIndex": 224,
"paragraphMarker": {
"style": { "indentStart": { "magnitude": 36, "unit": "PT" }, "direction": "LEFT_TO_RIGHT", "indentFirstLine": { "magnitude": 18, "unit": "PT" }, "spacingMode": "COLLAPSE_LISTS" },
"bullet": { "listId": "foo123", "glyph": "\u25cf" }
}
}, {
"endIndex": 243,
"startIndex": 224,
"textRun": { "content": "uniform grammatica\n", "style": {} }
}, {
"endIndex": 257,
"startIndex": 243,
"paragraphMarker": {
"style": { "indentStart": { "magnitude": 36, "unit": "PT" }, "direction": "LEFT_TO_RIGHT", "indentFirstLine": { "magnitude": 18, "unit": "PT" }, "spacingMode": "COLLAPSE_LISTS" },
"bullet": { "listId": "foo123", "glyph": "\u25cf" }
}
}, {
"endIndex": 257,
"startIndex": 243,
"textRun": { "content": "Pronunciation\n", "style": {} }
}, {
"endIndex": 277,
"startIndex": 257,
"paragraphMarker": {
"style": { "indentStart": { "magnitude": 36, "unit": "PT" }, "indentFirstLine": { "magnitude": 18, "unit": "PT" }, "spacingMode": "COLLAPSE_LISTS" },
"bullet": { "listId": "foo123", "glyph": "\u25cf" }
}
}, {
"endIndex": 277,
"startIndex": 257,
"textRun": { "content": "plu sommun paroles.\n", "style": {} }
}, {
"endIndex": 500,
"startIndex": 277,
"paragraphMarker": { "style": {} }
}, {
"endIndex": 500,
"startIndex": 277,
"textRun": { "content": "Ka swu thefognay, tay waddeant varpa u inzo.\n", "style": {} }
}]
Nội dung TextElement
Mỗi thành phần văn bản đều chứa chỉ mục bắt đầu và chỉ mục kết thúc dựa trên 0. Chỉ mục này mô tả vị trí của thành phần trong văn bản đầy đủ của thành phần trang, cùng với một trong các loại đối tượng văn bản sau:
Loại văn bản | Nội dung mô tả |
---|---|
ParagraphMarker | Phần tử văn bản này đại diện cho phần đầu của một đoạn mới. Chỉ mục đầu và cuối của thành phần văn bản thể hiện toàn bộ đoạn, bao gồm cả ký tự dòng mới kết thúc đoạn. Một đoạn văn không bao giờ chồng lên một đoạn khác. Đoạn luôn kết thúc bằng ký tự dòng mới, do đó luôn có một dòng mới ở cuối nội dung văn bản của một hình dạng hoặc ô trong bảng. Đoạn văn có thể thuộc danh sách có dấu đầu dòng hoặc được đánh số. Nếu có, nội dung của trường ParagraphMarker.bullet sẽ bao gồm một mã nhận dạng danh sách. Mã nhận dạng này tham chiếu đến một phần tử danh sách tồn tại bên trong TextContent cùng với trình tự TextElement . Các đoạn trong cùng một danh sách logic sẽ tham chiếu đến cùng một mã danh sách. |
TextRun | Phần tử văn bản này đại diện cho một chuỗi văn bản liền kề và tất cả đều có cùng một kiểu văn bản. Văn bản chạy không bao giờ vượt qua ranh giới đoạn: ngay cả khi văn bản kết thúc một đoạn có cùng kiểu với văn bản bắt đầu đoạn tiếp theo, nội dung sẽ được tách sau ký tự dòng mới để tạo thành các lần chạy văn bản riêng biệt. Nếu bạn cần xử lý chuỗi văn bản đầy đủ trong một phần tử trang, hãy lặp lại qua tất cả các phần tử văn bản, nối các chuỗi tìm được trong tất cả các lần chạy văn bản. |
AutoText | Văn bản tự động dùng để chỉ những vị trí trong văn bản tự động thay đổi tuỳ thuộc vào ngữ cảnh. Trong Trang trình bày, số này dùng để biểu thị số trang trình bày hiện tại bên trong văn bản. |
Sửa đổi nội dung văn bản
Khi cần sửa đổi văn bản bằng API Trang trình bày, bạn không cần phải tạo tất cả các thành phần văn bản thích hợp một cách rõ ràng. Thay vào đó, bạn có thể thao tác trên văn bản như trong trình chỉnh sửa Trang trình bày: bằng cách chèn văn bản, xoá dải ô và cập nhật kiểu trên dải ô. Các thao tác này ngầm tạo các phần tử ParagraphMarker
và TextRun
nếu cần để phản ánh các thay đổi của bạn.
Chèn văn bản
Bạn có thể chèn văn bản vào một chỉ mục bằng cách sử dụng yêu cầu InsertTextRequest trong lệnh gọi đến batchUpdate. Trường insertionIndex
của phương thức này chỉ định vị trí chèn văn bản; bạn có thể tính toán chỉ mục này bằng cách sử dụng các trường chỉ mục bắt đầu và kết thúc bên trong phần tử văn bản.
Tính năng chèn văn bản có một số tác dụng phụ phản ánh hành vi của trình chỉnh sửa Trang trình bày:
- Việc chèn ký tự dòng mới ngầm tạo một đoạn văn bản mới, tạo thành phần văn bản
ParagraphMarker
bắt đầu tại chỉ mục của dòng mới và kết thúc ở dòng mới sau. Kiểu đoạn văn bản (bao gồm cả dấu đầu dòng và thông tin chi tiết về danh sách) sẽ được sao chép từ đoạn hiện tại sang đoạn mới. - Kiểu của các ký tự được chèn được xác định tự động, thường giữ cùng một kiểu văn bản đã tồn tại ở chỉ mục chèn. Do đó, văn bản thường được chèn vào
TextRun
hiện có tại chỉ mục đó. Bạn có thể cập nhật kiểu này sau bằng cách sử dụng yêu cầu UpdateTextStyle.
Đang xoá văn bản
Bạn có thể xoá một dải văn bản bằng cách sử dụng thông báo DeleteTextRequest trong lệnh gọi đến batchUpdate. Việc xoá văn bản có một số vấn đề tinh vi:
- Thao tác xoá vượt quá một ranh giới của đoạn sẽ hợp nhất hai đoạn văn bản bằng cách xoá thành phần văn bản
ParagraphMarker
phân tách. - Đoạn mới được hợp nhất sẽ sử dụng kiểu đoạn kết hợp, khớp với hành vi trong trình chỉnh sửa Trang trình bày.
- Thao tác xoá có phạm vi bao gồm một lần chạy văn bản sẽ xoá toàn bộ nội dung khỏi một lần chạy văn bản, đồng thời cũng sẽ xoá chính lần chạy văn bản đó.
- Thao tác xoá có phạm vi bao gồm một phần tử
AutoText
sẽ xoá phần tửAutoText
.
Đang cập nhật kiểu văn bản
Giao diện kết xuất của văn bản trong một trang trình bày được xác định bởi các thuộc tính kiểu văn bản:
- Các kiểu đoạn như thụt lề, căn chỉnh và dấu đầu dòng được xác định theo các thuộc tính trên điểm đánh dấu đoạn.
- Các kiểu ký tự như in đậm, in nghiêng và gạch dưới được xác định theo các thuộc tính khi chạy văn bản riêng lẻ.
Đang cập nhật kiểu nhân vật
Bạn có thể cập nhật kiểu ký tự bằng cách sử dụng thông báo UpdateTextStyleRequest trong lệnh gọi đến gói batchUpdate.
Giống như các thao tác văn bản khác, kiểu ký tự được áp dụng cho một loạt văn bản và ngầm tạo đối tượng TextRun
mới khi cần.
Việc đặt một số kiểu ký tự ngầm cập nhật các kiểu liên quan khác để phù hợp với hành vi trong Trình chỉnh sửa Trang trình bày. Ví dụ: việc thêm một đường liên kết sẽ tự động thay đổi các thuộc tính gạch chân và màu nền trước của văn bản. Hãy xem tài liệu tham khảo về TextStyle để biết thêm thông tin chi tiết.
Đang cập nhật kiểu đoạn
Bạn có thể cập nhật kiểu đoạn văn bản bằng cách sử dụng thông báo UpdateParagraphStyleRequest trong lệnh gọi tới batchUpdate.
API Trang trình bày hỗ trợ CreateParagraphBulletsRequest phản ánh chức năng của giá trị đặt trước cho dấu đầu dòng trong trình chỉnh sửa Trang trình bày để tạo danh sách có dấu đầu dòng và được đánh số. Tương tự, DeleteParagraphBulletsRequest xoá mọi dấu đầu dòng hiện có trên đoạn.
Kiểu kế thừa
Một số hình dạng, còn gọi là placeholders, có thể kế thừa kiểu văn bản của các hình dạng mẹ khác: xem placeholders để tìm hiểu thêm về tính kế thừa của hình dạng nói chung.
Phần này tập trung vào cách hoạt động của tính kế thừa kiểu để tạo kiểu văn bản được kết xuất cuối cùng hiển thị trong trang trình bày.
Biểu thị kiểu trong phần giữ chỗ
Phần trong placeholders mô tả cách tính kế thừa hoạt động giữa hình dạng mẹ và hình dạng con. Việc kế thừa kiểu văn bản được xử lý bằng các tính năng bổ sung trong mô hình kế thừa:
- Thuộc tính của các phần tử văn bản ParagraphMaker xác định định dạng đoạn.
- Thuộc tính của các phần tử văn bản TextRun xác định định dạng ký tự.
- Nội dung của phần giữ chỗ mẹ chứa 8 cặp ParagraphMarker/TextRun như vậy (để hỗ trợ 8 cấp độ lồng danh sách).
- Phần giữ chỗ con kế thừa các thuộc tính văn bản mặc định từ các phần tử văn bản này trong nội dung văn bản của phần tử mẹ.
Biểu đồ sau đây cho thấy một cách trực quan hoá các mối quan hệ này:
ParagraphMarker/TextRun đầu tiên trong hình dạng mẹ xác định hầu hết kiểu văn bản kế thừa; kiểu trong 7 cặp còn lại chỉ ảnh hưởng đến các đoạn ở cấp độ dấu đầu dòng lồng nhau sâu hơn:
Cặp thành phần văn bản gốc | Định dạng con mà chế độ này kiểm soát |
---|---|
ParagraphMarker TextRun đầu tiên |
Kiểu văn bản của các đoạn danh sách cấp 0 (ngoài cùng) và tất cả các đoạn không nằm trong danh sách. |
2 ParagraphMarker thứ 2 TextRun |
Kiểu văn bản của các cấp danh sách còn lại (lồng nhau) từ 1 đến 7 |
Thứ ba ParagraphMarker Thứ ba TextRun |
|
Thứ tư ParagraphMarker Thứ tư TextRun |
|
Thứ năm ParagraphMarker thứ năm TextRun |
|
Thứ sáu ParagraphMarker Thứ sáu TextRun |
|
Thứ bảy ParagraphMarker Thứ bảy TextRun |
|
Phần 8 ParagraphMarker Phần 8 TextRun |
Để truy cập các cặp thành phần văn bản này, hãy sử dụng chỉ mục rõ ràng trong trường textElements
như minh hoạ trong đoạn mã bên dưới. Đoạn mã này cho biết cách thiết lập kiểu mặc định (kế thừa) cho cấp 0 và đoạn không phải trong danh sách:
"text": {
"textElements": [ {
"startIndex": 0,
"endIndex": 1,
"paragraphMarker": {
"style": { "alignment": "START", ... },
"bullet": { "nestingLevel": 0, ... }
}
},{
"startIndex": 0,
"endIndex": 1,
"textRun": {
"content": "\n",
"style": { "foregroundColor": { "opaqueColor": { "themeColor": "DARK1" } }, }
}
},{
...
} ]
}
Lưu ý rằng trường content
của TextRun
của hình dạng mẹ luôn bao gồm một ký tự dòng mới.
Kiểu kế thừa có thể được ghi đè
Hình dạng con có thể chỉ định các thuộc tính định kiểu trên các phần tử ParagraphMarker và TextRun trong nội dung. Các thuộc tính được chỉ định cục bộ này sẽ ghi đè mọi thuộc tính kế thừa trong phạm vi cục bộ của chúng. Các phần tử không chỉ định kiểu nào sẽ sử dụng kiểu tương ứng kế thừa từ kiểu gốc.
Việc xoá thuộc tính kiểu rõ ràng khỏi một hình dạng con để thuộc tính này không còn được đặt nữa, sẽ làm cho thuộc tính này kế thừa từ hình dạng mẹ.
Ví dụ:
Theo tính kế thừa hiển thị trong sơ đồ trên, giả sử hình dạng ParentPlaceholder
có nội dung văn bản sau:
"text": {
"textElements": [
{ "startIndex": 0, "endIndex": 1,
"paragraphMarker": {
"style": {"alignment": "START", ...},
"bullet": {"nestingLevel": 0, ...}
}
},
{ "startIndex": 0, "endIndex": 1,
"textRun": {
"content": "\n",
"style": {"foregroundColor": {"opaqueColor": {"themeColor": "DARK1"} }, }
...
}
},
{ "startIndex": 1, "endIndex": 2,
"paragraphMarker": {
"style": {"alignment": "END", ...},
"bullet": {"nestingLevel": 1, ...}
}
},
{ "startIndex": 1, "endIndex": 2,
"textRun": {
"content": "\n",
"style": {"foregroundColor": {"opaqueColor": {"themeColor": "LIGHT1"} }, ...}
}
},
...
]
}
Và giả sử hình dạng ChildPlaceholder
có nội dung văn bản sau:
"text": {
"textElements": [
{ "startIndex": 0, "endIndex": 1,
"paragraphMarker": {
"style": {},
}
},
{ "startIndex": 0, "endIndex": 1,
"textRun": {
"content": "This is my first paragraph\n",
"style": {},
}
...
},
{ "startIndex": 1, "endIndex": 2,
"paragraphMarker": {
"style": {},
"bullet": {
"nestingLevel": 1,
"listId": "someListId",
"glyph": "●"
}
}
},
{ "startIndex": 1, "endIndex": 2,
"textRun": {
"content": "This paragraph is in a list\n",
"style": {},
...
}
}
]
}
Điều này dẫn đến những kết quả được mô tả trong các đoạn sau.
Kế thừa kiểu cho một đoạn văn bản thuần tuý
Đoạn đầu tiên của hình dạng con, bao gồm văn bản "Đây là đoạn đầu tiên của tôi", là một đoạn văn đơn giản (không nằm trong danh sách). Không có phần tử nào trong nội dung văn bản chỉ định bất kỳ thuộc tính kiểu nào, vì vậy, thành phần này kế thừa tất cả các kiểu ký tự và đoạn văn bản từ thành phần mẹ. Điều này dẫn đến việc hiển thị sau:
- Văn bản: "Đây là đoạn đầu tiên của tôi" là văn bản được hiển thị. Bản thân văn bản không bao giờ được kế thừa.
- Căn chỉnh: Văn bản được hiển thị với cách căn chỉnh
START
, kế thừa từParagraphMarker
đầu tiên của thành phần mẹ. - Màu nền trước: Văn bản được hiển thị bằng màu nền trước
DARK1
, kế thừa từTextRun
đầu tiên của thành phần mẹ.
Kế thừa kiểu của một đoạn trong danh sách
Đoạn tiếp theo, bao gồm cả văn bản "Đoạn này nằm trong danh sách", nằm trong danh sách có dấu đầu dòng ở cấp độ lồng ghép 1, vì ParagraphMarker
tương ứng của đoạn văn bản đó có trường bullet
được đặt ở cấp này. Do đó, lớp này sẽ kế thừa kiểu văn bản và đoạn văn bản từ cấp độ lồng nhau 1 trong thành phần mẹ. Điều này dẫn đến quá trình hiển thị như sau:
- Văn bản: "Đoạn văn bản này nằm trong danh sách" là văn bản được hiển thị. Bản thân văn bản không bao giờ được kế thừa.
- Căn chỉnh: Văn bản hiển thị với cách căn chỉnh "END", kế thừa từ
ParagraphMarker
thứ hai của thành phần mẹ. - Màu nền trước: Văn bản được hiển thị bằng màu nền trước của văn bản
LIGHT1
, kế thừa từTextRun
thứ hai của thành phần mẹ.
Tương tác giữa việc cập nhật và kế thừa kiểu văn bản và đoạn văn
Kiểu văn bản không được đặt theo hình dạng con sẽ kế thừa các giá trị từ thành phần mẹ. Kiểu văn bản được đặt trong thành phần con sẽ "ghi đè" các giá trị mẹ trong một số phạm vi cục bộ.
Bạn có thể sử dụng UpdateTextStyleRequest để huỷ thiết lập kiểu văn bản của hình dạng con để hình dạng đó không còn có chế độ ghi đè cục bộ nữa và do đó kế thừa các dấu gạch đứng từ hình dạng mẹ. Ngoài ra, việc cập nhật kiểu văn bản của thành phần con để khớp với giá trị kế thừa từ thành phần mẹ sẽ ngầm thiết lập kiểu đó để sử dụng giá trị kế thừa.
Điều này không ảnh hưởng đến giao diện trực quan của văn bản ngay sau khi cập nhật. Tuy nhiên, nếu sau đó bạn cập nhật một đoạn hoặc kiểu văn bản trong phần giữ chỗ gốc thì có thể sẽ quan trọng. Hành vi kế thừa này khớp với hành vi của trình chỉnh sửa Trang trình bày, vì vậy, bạn có thể thử nghiệm kết quả của việc thay đổi kiểu trước khi làm việc với API.
Ví dụ:
Hãy xem xét các định nghĩa trong ví dụ trước cho ChildPlaceholder
và ParentPlaceholder
.
Bây giờ, giả sử bạn gửi UpdateTextStyleRequest sau:
{ "updateTextStyle": {
"objectId": "ChildPlaceholder",
"style": {"foregroundColor": {"opaqueColor": {"themeColor": "DARK1"} }, },
"textRange": { "type": "ALL" },
"fields": "foregroundColor"
}
}
Yêu cầu này cố gắng đặt DARK1
foregroundColor cho tất cả văn bản của phần giữ chỗ cho trẻ em bằng cách sử dụng mặt nạ trường để chỉ định rằng chỉ màu nền trước của phần tử mới thay đổi. Yêu cầu này có các kết quả sau:
- Đoạn đầu tiên:
foregroundColor
mới khớp vớiforegroundColor
kế thừa, vì vậy kiểu này không thay đổi và vẫn kế thừa. - Đoạn thứ hai:
foregroundColor
mới không khớp vớiforegroundColor
kế thừa, vì vậy màu nền trước của đoạn thứ hai được cập nhật thànhDARK1
.
Nội dung văn bản của Trình giữ chỗ con hiện là:
"text": {
"textElements": [
{ "startIndex": 0, "endIndex": 1,
"paragraphMarker": {
"style": {},
}
},
{ "startIndex": 0, "endIndex": 1,
"textRun": {
"content": "This is my first paragraph\n",
"style": {},
}
...
},
{ "startIndex": 1, "endIndex": 2,
"paragraphMarker": {
"style": {},
"bullet": {"nestingLevel": 1, "listId": "someListId", "glyph": "●" }
}
},
{ "startIndex": 1, "endIndex": 2,
"textRun": {
"content": "This paragraph is in a list\n",
"style": {"foregroundColor": {"opaqueColor": {"themeColor": "DARK1"} }, },
...
}
}
]
}
Kiểu văn bản dạng ký tự trong dấu đầu dòng
Giống như văn bản thông thường, ký tự gạch đầu dòng có kiểu văn bản kiểm soát cách hiển thị ký tự. Bạn không thể trực tiếp sửa đổi các kiểu văn bản này bằng API Trang trình bày. Tuy nhiên, nếu bạn sử dụng UpdateTextStyleRequest để cập nhật một đoạn hoàn chỉnh có dấu đầu dòng, thì API Trang trình bày sẽ cập nhật kiểu văn bản của dấu đầu dòng cho phù hợp.
Kiểu văn bản dùng dấu đầu dòng tuân theo hệ thống phân cấp kế thừa hơi khác so với kiểu văn bản thông thường.
- Dấu đầu dòng ở cấp độ lồng nhất nhất định kế thừa từ
TextStyle
được đặt trong trườngNestingLevel.bullet_style
bên trong đối tượngList
của dấu đầu dòng. - Tiếp theo, thành phần này kế thừa từ
NestingLevel.bullet_style
tương ứng trongList
của phần giữ chỗ gốc. - Cuối cùng, lớp này tìm cách kế thừa từ các đối tượng phần giữ chỗ mẹ còn lại.