improve docs

This commit is contained in:
2020-10-05 20:51:21 +08:00
parent ff12497673
commit 744874d591
8 changed files with 304 additions and 17 deletions
+5 -3
View File
@@ -1,6 +1,8 @@
# TextFrame # TextFrame
一个通过canvas将长文本分成若干页渲染的js工具,处理排版禁则,支持辅助平面Unicode字符。目前仅工作于浏览器环境。 一个通过canvas将长文本分成若干页渲染的js工具,处理排版禁则,支持辅助平面Unicode字符。目前仅工作于浏览器环境。
[中文版](https://github.com/mattuylee/text-frame) | [English](https://github.com/mattuylee/text-frame/blob/master/docs/en/README-EN.md)
## 项目介绍 ## 项目介绍
在浏览器中,尽管css有分栏布局,但却很难实现“分页”。浏览器没有提供计算一个盒子可以显示多少文本的API,只有Canvas的上下文提供了一个`measureText()`方法,但它只能简单的计算一段文本的渲染宽度,当文本不止一行时就无法计算了。由于不同字体不同字符有不同的宽度,再加上各浏览器对排版禁则的处理不一致,基本杜绝了计算浏览器原生DOM元素能够显示多少文本的可能。 在浏览器中,尽管css有分栏布局,但却很难实现“分页”。浏览器没有提供计算一个盒子可以显示多少文本的API,只有Canvas的上下文提供了一个`measureText()`方法,但它只能简单的计算一段文本的渲染宽度,当文本不止一行时就无法计算了。由于不同字体不同字符有不同的宽度,再加上各浏览器对排版禁则的处理不一致,基本杜绝了计算浏览器原生DOM元素能够显示多少文本的可能。
@@ -31,11 +33,11 @@
| 破折号 | ── | | 破折号 | ── |
| 省略号 | …… | | 省略号 | …… |
本项目默认按照上述禁则处理排版禁则,但可以通过[选项](https://mattuylee.github.io/text-frame/zh/options.md)控制排版禁则。 本项目默认按照上述禁则处理排版禁则,但可以通过[选项](https://github.com/mattuylee/text-frame/blob/master/docs/zh/options.md)控制排版禁则。
草案中规定,当碰到行首为(行首禁则中的)标点时,应遵守「先挤进,后推出」原则,即先尝试压缩当前行的标点,无法挤压再取前一行的最后一个字至下一行。考虑到标点符号压缩的复杂性,本项目暂未实现该特性,而是直接尝试取上一行的最后一字到下一行,如果直到上一行首都没找到允许出现在行首的字符,则采取不处理的方式。 草案中规定,当碰到行首为(行首禁则中的)标点时,应遵守「先挤进,后推出」原则,即先尝试压缩当前行的标点,无法挤压再取前一行的最后一个字至下一行。考虑到标点符号压缩的复杂性,本项目暂未实现该特性,而是直接尝试取上一行的最后一字到下一行,如果直到上一行首都没找到允许出现在行首的字符,则采取不处理的方式。
## 功能 ## 功能
本项目定义了文本片段(text fragment)的概念。通过在选项中指定一个文本片段数组,可以对每一个片段设置不同的样式,如字体、颜色、对齐方式等,具体请参考[配置项](https://mattuylee.github.io/text-frame/zh/options.md)。一般来说,一个文本片段即一个文本段落,虽然文本片段内也支持换行,但不会有段间距和行缩进。在本项目文档中文本片段和文本段落等价,都是指`FragmentOptions`定义的文本片段。 本项目定义了文本片段(text fragment)的概念。通过在选项中指定一个文本片段数组,可以对每一个片段设置不同的样式,如字体、颜色、对齐方式等,具体请参考[配置项](https://github.com/mattuylee/text-frame/blob/master/docs/zh/options.md)。一般来说,一个文本片段即一个文本段落,虽然文本片段内也支持换行,但不会有段间距和行缩进。在本项目文档中文本片段和文本段落等价,都是指`FragmentOptions`定义的文本片段。
本项目支持以下特性: 本项目支持以下特性:
* 每个段落单独设置字体、缩进、边距、字体颜色等; * 每个段落单独设置字体、缩进、边距、字体颜色等;
@@ -109,7 +111,7 @@ renderFrame(canvas.getContext('2d'), frames[0]);
</script> </script>
``` ```
配置说明请参考[配置项](https://mattuylee.github.io/text-frame/zh/options.md)。 配置说明请参考[配置项](https://github.com/mattuylee/text-frame/blob/master/docs/zh/options.md)。
## 源码编译 ## 源码编译
+3 -3
View File
@@ -1,6 +1,6 @@
# TextFrame # TextFrame
[中文版](https://github.com/mattuylee/text-frame) | [English](https://github.com/mattuylee/text-frame/docs/en/README-EN.md) [中文版](https://github.com/mattuylee/text-frame) | [English](https://github.com/mattuylee/text-frame/blob/master/docs/en/README-EN.md)
A javascript tool to split long text into frames, with typesetting prohibition processed and unicode full support. A javascript tool to split long text into frames, with typesetting prohibition processed and unicode full support.
@@ -34,7 +34,7 @@ refering to [W3C draft](https://www.w3.org/TR/2020/WD-clreq-20201001/#prohibitio
| Em dash and long dash | ── | | Em dash and long dash | ── |
| Ellipsis | …… | | Ellipsis | …… |
This library take the above as default rules, but it can be configued with [options](https://mattuylee.github.io/text-frame/en/options.md). This library take the above as default rules, but it can be configued with [options](https://github.com/mattuylee/text-frame/blob/master/docs/en/options.md).
Here is an online [demo](https://mattuylee.github.io/text-frame/en/example.html). Here is an online [demo](https://mattuylee.github.io/text-frame/en/example.html).
@@ -100,7 +100,7 @@ renderFrame(canvas.getContext('2d'), frames[0], true);
// ...render // ...render
</script> </script>
``` ```
Option reference sits [here](https://mattuylee.github.io/text-frame/en/options.md). Option reference sits [here](https://github.com/mattuylee/text-frame/blob/master/docs/en/options.md).
## Build from Source ## Build from Source
+138
View File
@@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test</title>
<style>
.example-container {
display: flex;
min-width: 360px;
flex-wrap: wrap;
justify-content: center;
max-width: 1024px;
margin: auto;
}
.example-item {
box-sizing: border-box;
min-width: 300px;
width: 300px;
margin: 16px;
}
.example-item:first-child {
flex-grow: 1;
}
#source {
width: 100%;
box-sizing: border-box;
font-size: 16px;
height: 360px;
padding: 1em;
}
#canvas {
width: 100%;
height: 360px;
border: 1px solid darkgray;
}
</style>
<script src="../../dist/umd/text-frame.js"></script>
</head>
<body>
<div class="example-container">
<div class="example-item">
<textarea id="source" oninput="refresh()" spellcheck="false">
options = {
viewWidth: 300,
viewHeight: 360,
fontSize: 16,
margin: 16,
fragments: [
{
color: 'green',
fontSize: 20,
margin: 32,
textAlign: 'center',
text: "Caption"
},
{
fontFamily: 'serif',
margin: { bottom: 32 },
marginCollapse: true,
textAlign: 'justify',
text: "This is a multi-line text."
}
]
}
</textarea>
<a href="https://github.com/mattuylee/text-frame/blob/master/docs/en/options.md"><button>Option Reference</button></a>
</div>
<div class="example-item">
<canvas id="canvas"></canvas>
<button onclick="setPagination(-1)">Previous</button>
<button onclick="setPagination(1)">Next</button>
<span id="pagination" style="float: right;">0 / 0</span>
</div>
</div>
<script>
var options
, pagination = document.getElementById('pagination')
, canvas = document.getElementById('canvas')
, ctx = canvas.getContext('2d')
, pageIndex = 0
, frames = []
, defaultOptions = {
viewWidth: 300,
viewHeight: 360,
fontWeight: '700',
fontSize: 20,
color: 'red',
fragments: [
{
textAlign: 'center',
margin: 16,
marginCollapse: false,
text: "bad input"
},
]
}
canvas.width = 300 * devicePixelRatio;
canvas.height = 360 * devicePixelRatio;
window.onresize = refresh;
refresh();
function refresh() {
try {
var src = document.getElementById('source').value;
new Function(src)();
frames = TextFrame.computeTextFrames(options);
}
catch (e) {
console.error(e);
frames = TextFrame.computeTextFrames(defaultOptions);
}
pageIndex = 0;
setPagination(0)
}
function setPagination(delta) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
if (!frames.length) {
pagination.textContent = '0 / 0';
return;
}
pageIndex += delta;
if (pageIndex < 0) { pageIndex = 0; }
else if (pageIndex >= frames.length) {
pageIndex = frames.length - 1;
}
TextFrame.renderFrame(ctx, frames[pageIndex]);
pagination.textContent = pageIndex + 1 + ' / ' + frames.length;
}
</script>
</body>
</html>
+1 -1
View File
@@ -24,7 +24,7 @@ export function renderFrame(context: CanvasRenderingContext2D, frame: TextFrame,
### canvasHeight ### canvasHeight
* Type: `number` * Type: `number`
* Default: 根据`viewHeight`计算。 * Default: compute with `viewHeight`
* Description: canvas.height is `viewHeight * window.devicePixelRatio` * Description: canvas.height is `viewHeight * window.devicePixelRatio`
### margin ### margin
+139
View File
@@ -0,0 +1,139 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test</title>
<style>
.example-container {
display: flex;
min-width: 360px;
flex-wrap: wrap;
justify-content: center;
max-width: 1024px;
margin: auto;
}
.example-item {
box-sizing: border-box;
min-width: 300px;
width: 300px;
margin: 16px;
}
.example-item:first-child {
flex-grow: 1;
}
#source {
width: 100%;
box-sizing: border-box;
font-size: 16px;
height: 360px;
padding: 1em;
}
#canvas {
width: 100%;
height: 360px;
border: 1px solid darkgray;
}
</style>
<script src="../../dist/umd/text-frame.js"></script>
</head>
<body>
<div class="example-container">
<div class="example-item">
<textarea id="source" oninput="refresh()" spellcheck="false">
options = {
viewWidth: 300,
viewHeight: 360,
fontSize: 16,
margin: 16,
fragments: [
{
color: 'green',
fontSize: 20,
margin: 32,
textAlign: 'center',
text: "标题"
},
{
textIndent: 32,
fontFamily: 'serif',
margin: { bottom: 32 },
marginCollapse: true,
textAlign: 'justify',
text: "这是一个多行文本。"
}
]
}
</textarea>
<a href="https://github.com/mattuylee/text-frame/blob/master/docs/zh/options.md"><button>配置项</button></a>
</div>
<div class="example-item">
<canvas id="canvas"></canvas>
<button onclick="setPagination(-1)">上一页</button>
<button onclick="setPagination(1)">下一页</button>
<span id="pagination" style="float: right;">0 / 0</span>
</div>
</div>
<script>
var options
, pagination = document.getElementById('pagination')
, canvas = document.getElementById('canvas')
, ctx = canvas.getContext('2d')
, pageIndex = 0
, frames = []
, defaultOptions = {
viewWidth: 300,
viewHeight: 360,
fontWeight: '700',
fontSize: 20,
color: 'red',
fragments: [
{
textAlign: 'center',
margin: 16,
marginCollapse: false,
text: "bad input"
},
]
}
canvas.width = 300 * devicePixelRatio;
canvas.height = 360 * devicePixelRatio;
window.onresize = refresh;
refresh();
function refresh() {
try {
var src = document.getElementById('source').value;
new Function(src)();
frames = TextFrame.computeTextFrames(options);
}
catch (e) {
console.error(e);
frames = TextFrame.computeTextFrames(defaultOptions);
}
pageIndex = 0;
setPagination(0)
}
function setPagination(delta) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
if (!frames.length) {
pagination.textContent = '0 / 0';
return;
}
pageIndex += delta;
if (pageIndex < 0) { pageIndex = 0; }
else if (pageIndex >= frames.length) {
pageIndex = frames.length - 1;
}
TextFrame.renderFrame(ctx, frames[pageIndex]);
pagination.textContent = pageIndex + 1 + ' / ' + frames.length;
}
</script>
</body>
</html>
+16 -7
View File
@@ -38,7 +38,7 @@
border: 1px solid darkgray; border: 1px solid darkgray;
} }
</style> </style>
<script src="../dist/umd/text-frame.js"></script> <script src="../../dist/umd/text-frame.js"></script>
</head> </head>
<body> <body>
@@ -51,15 +51,24 @@
fontSize: 16, fontSize: 16,
margin: 16, margin: 16,
fragments: [ fragments: [
{ {
margin: { left: 16, right: 16, top: 32 }, color: 'green',
marginCollapse: false, fontSize: 20,
text: "在这里输入文本。" margin: 32,
}, textAlign: 'center',
text: "Caption"
},
{
fontFamily: 'serif',
margin: { bottom: 32 },
marginCollapse: true,
textAlign: 'justify',
text: "This is a multi-line text."
}
] ]
} }
</textarea> </textarea>
<button>Options Refrence</button> <a href="https://github.com/mattuylee/text-frame/blob/master/docs/en/options.md"><button>Option Reference</button></a>
</div> </div>
<div class="example-item"> <div class="example-item">
<canvas id="canvas"></canvas> <canvas id="canvas"></canvas>
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"name": "text-frame", "name": "@mattuy/text-frame",
"version": "0.0.1", "version": "0.0.1",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
+1 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@mattuy/text-frame", "name": "@mattuy/text-frame",
"version": "0.0.1", "version": "0.0.4",
"private": false, "private": false,
"description": "a javascript tool to split long text into pages, with typesetting prohibition processed and unicode full support.\n一个将长文本分成若干页的js工具,处理排版禁则,支持Unicode", "description": "a javascript tool to split long text into pages, with typesetting prohibition processed and unicode full support.\n一个将长文本分成若干页的js工具,处理排版禁则,支持Unicode",
"main": "index.js", "main": "index.js",
@@ -11,7 +11,6 @@
"build": "rollup -c rollup.config.js --environment NODE_ENV:development", "build": "rollup -c rollup.config.js --environment NODE_ENV:development",
"dist": "rollup -c rollup.config.js --environment NODE_ENV:production", "dist": "rollup -c rollup.config.js --environment NODE_ENV:production",
"debug": "rollup -c rollup.config.js --environment NODE_ENV:development --watch", "debug": "rollup -c rollup.config.js --environment NODE_ENV:development --watch",
"install": "npm run build && npm run dist",
"example": "rollup -c rollup.config.js --environment NODE_ENV:development --environment SERVE" "example": "rollup -c rollup.config.js --environment NODE_ENV:development --environment SERVE"
}, },
"repository": { "repository": {