合理的文字
此示例呈現對齊文字。它通過擴充套件原型或作為全域性物件 justifiedText
為 CanvasRenderingContext2D
增加了額外的功能(可選參見注釋 A)。
示例渲染
用於呈現此影象的程式碼位於底部的用法示例中。
這個例子
該函式作為匿名立即呼叫函式。
(function(){
const FILL = 0; // const to indicate filltext render
const STROKE = 1;
const MEASURE = 2;
var renderType = FILL; // used internal to set fill or stroke text
var maxSpaceSize = 3; // Multiplier for max space size. If greater then no justificatoin applied
var minSpaceSize = 0.5; // Multiplier for minimum space size
var renderTextJustified = function(ctx,text,x,y,width){
var words, wordsWidth, count, spaces, spaceWidth, adjSpace, renderer, i, textAlign, useSize, totalWidth;
textAlign = ctx.textAlign; // get current align settings
ctx.textAlign = "left";
wordsWidth = 0;
words = text.split(" ").map(word => {
var w = ctx.measureText(word).width;
wordsWidth += w;
return {
width : w,
word : word,
};
});
// count = num words, spaces = number spaces, spaceWidth normal space size
// adjSpace new space size >= min size. useSize Resulting space size used to render
count = words.length;
spaces = count - 1;
spaceWidth = ctx.measureText(" ").width;
adjSpace = Math.max(spaceWidth * minSpaceSize, (width - wordsWidth) / spaces);
useSize = adjSpace > spaceWidth * maxSpaceSize ? spaceWidth : adjSpace;
totalWidth = wordsWidth + useSize * spaces
if(renderType === MEASURE){ // if measuring return size
ctx.textAlign = textAlign;
return totalWidth;
}
renderer = renderType === FILL ? ctx.fillText.bind(ctx) : ctx.strokeText.bind(ctx); // fill or stroke
switch(textAlign){
case "right":
x -= totalWidth;
break;
case "end":
x += width - totalWidth;
break;
case "center": // intentional fall through to default
x -= totalWidth / 2;
default:
}
if(useSize === spaceWidth){ // if space size unchanged
renderer(text,x,y);
} else {
for(i = 0; i < count; i += 1){
renderer(words[i].word,x,y);
x += words[i].width;
x += useSize;
}
}
ctx.textAlign = textAlign;
}
// Parse vet and set settings object.
var justifiedTextSettings = function(settings){
var min,max;
var vetNumber = (num, defaultNum) => {
num = num !== null && num !== null && !isNaN(num) ? num : defaultNum;
if(num < 0){
num = defaultNum;
}
return num;
}
if(settings === undefined || settings === null){
return;
}
max = vetNumber(settings.maxSpaceSize, maxSpaceSize);
min = vetNumber(settings.minSpaceSize, minSpaceSize);
if(min > max){
return;
}
minSpaceSize = min;
maxSpaceSize = max;
}
// define fill text
var fillJustifyText = function(text, x, y, width, settings){
justifiedTextSettings(settings);
renderType = FILL;
renderTextJustified(this, text, x, y, width);
}
// define stroke text
var strokeJustifyText = function(text, x, y, width, settings){
justifiedTextSettings(settings);
renderType = STROKE;
renderTextJustified(this, text, x, y, width);
}
// define measure text
var measureJustifiedText = function(text, width, settings){
justifiedTextSettings(settings);
renderType = MEASURE;
return renderTextJustified(this, text, 0, 0, width);
}
// code point A
// set the prototypes
CanvasRenderingContext2D.prototype.fillJustifyText = fillJustifyText;
CanvasRenderingContext2D.prototype.strokeJustifyText = strokeJustifyText;
CanvasRenderingContext2D.prototype.measureJustifiedText = measureJustifiedText;
// code point B
// optional code if you do not wish to extend the CanvasRenderingContext2D prototype
/* Uncomment from here to the closing comment
window.justifiedText = {
fill : function(ctx, text, x, y, width, settings){
justifiedTextSettings(settings);
renderType = FILL;
renderTextJustified(ctx, text, x, y, width);
},
stroke : function(ctx, text, x, y, width, settings){
justifiedTextSettings(settings);
renderType = STROKE;
renderTextJustified(ctx, text, x, y, width);
},
measure : function(ctx, text, width, settings){
justifiedTextSettings(settings);
renderType = MEASURE;
return renderTextJustified(ctx, text, 0, 0, width);
}
}
to here*/
})();
注意 - 答: 如果你不想擴充套件
CanvasRenderingContext2D
原型從示例中刪除// code point A
和// code point B
之間的所有程式碼並取消註釋標記為/* Uncomment from here to the closing comment
的程式碼
如何使用
CanvasRenderingContext2D
中新增了三個函式,可用於建立的所有 2D 上下文物件。
- ctx.fillJustifyText(text,x,y,width,[settings]);
- ctx.strokeJustifyText(text,x,y,width,[settings]);
- ctx.measureJustifiedText(text,width,[settings]);
填充和描邊文字功能填充或描邊文字並使用相同的引數。measureJustifiedText
將返回文字將呈現的實際寬度。根據當前設定,這可能等於,小於或大於引數 width
。
注意:
[
和]
中的引數是可選的。
函式引數
-
text: 包含要呈現的文字的字串。
-
x,y: 用於渲染文字的座標。
-
width: 對齊文字的寬度。文字將增加/減少單詞之間的空格以適合寬度。如果單詞之間的空格大於
maxSpaceSize
(預設值= 6),則將使用正常間距,文字將不會填充所需的寬度。如果間距小於minSpaceSize
(預設值= 0.5)時間正常間距,則使用最小空間大小,文字將超出請求的寬度 -
設定: 可選。包含最小和最大空間大小的物件。
settings
引數是可選的,如果不包括在內,文字渲染將使用最後定義的設定或預設值(如下所示)。
min 和 max 都是分隔單詞的[space]字元的最小和最大尺寸。預設的 maxSpaceSize = 6
表示當字元之間的空格大於 63 * ctx.measureText(“”)時 .with text 文字將不合理。如果要對齊的文字的空格小於 minSpaceSize = 0.5
(預設值 0.5)* ctx.measureText(" ").width
,則間距將設定為 minSpaceSize * ctx.measureText(" ").width
,結果文字將超出對齊寬度。
應用以下規則,min 和 max 必須是數字。如果不是,則不會更改關聯值。如果 minSpaceSize
大於 maxSpaceSize
,則兩個輸入設定均無效,最大最大值不會改變。
具有預設值的示例設定物件
settings = {
maxSpaceSize : 6; // Multiplier for max space size.
minSpaceSize : 0.5; // Multiplier for minimum space size
};
注意: 這些文字函式為 2D 上下文的
textAlign
屬性引入了微妙的行為更改。 ’left’,‘right’,‘center’和’start’表現得像預期的那樣,但’end’不會從函式引數x
的右邊開始,而是從x + width
的右邊開始對齊
注意: 設定(最小和最大空間大小)對所有 2D 上下文物件都是全域性的。
用法示例
var i = 0;
text[i++] = "This text is aligned from the left of the canvas.";
text[i++] = "This text is near the max spacing size";
text[i++] = "This text is way too short.";
text[i++] = "This text is too long for the space provied and will overflow#";
text[i++] = "This text is aligned using 'end' and starts at x + width";
text[i++] = "This text is near the max spacing size";
text[i++] = "This text is way too short.";
text[i++] = "#This text is too long for the space provied and will overflow";
text[i++] = "This is aligned with 'center' and is placed from the center";
text[i++] = "This text is near the max spacing size";
text[i++] = "This text is way too short.";
text[i++] = "This text is just too long for the space provied and will overflow";
// ctx is the 2d context
// canvas is the canvas
ctx.clearRect(0,0,w,h);
ctx.font = "25px arial";
ctx.textAlign = "center"
var left = 20;
var center = canvas.width / 2;
var width = canvas.width-left*2;
var y = 40;
var size = 16;
var i = 0;
ctx.fillText("Justified text examples.",center,y);
y+= 40;
ctx.font = "14px arial";
ctx.textAlign = "left"
var ww = ctx.measureJustifiedText(text[0], width);
var setting = {
maxSpaceSize : 6,
minSpaceSize : 0.5
}
ctx.strokeStyle = "red"
ctx.beginPath();
ctx.moveTo(left,y - size * 2);
ctx.lineTo(left, y + size * 15);
ctx.moveTo(canvas.width - left,y - size * 2);
ctx.lineTo(canvas.width - left, y + size * 15);
ctx.stroke();
ctx.textAlign = "left";
ctx.fillStyle = "red";
ctx.fillText("< 'left' aligned",left,y - size)
ctx.fillStyle = "black";
ctx.fillJustifyText(text[i++], left, y, width, setting); // settings is remembered
ctx.fillJustifyText(text[i++], left, y+=size, width);
ctx.fillJustifyText(text[i++], left, y+=size, width);
ctx.fillJustifyText(text[i++], left, y+=size, width);
y += 2.3*size;
ctx.fillStyle = "red";
ctx.fillText("< 'end' aligned from x plus the width -------------------->",left,y - size)
ctx.fillStyle = "black";
ctx.textAlign = "end";
ctx.fillJustifyText(text[i++], left, y, width);
ctx.fillJustifyText(text[i++], left, y+=size, width);
ctx.fillJustifyText(text[i++], left, y+=size, width);
ctx.fillJustifyText(text[i++], left, y+=size, width);
y += 40;
ctx.strokeStyle = "red"
ctx.beginPath();
ctx.moveTo(center,y - size * 2);
ctx.lineTo(center, y + size * 5);
ctx.stroke();
ctx.textAlign = "center";
ctx.fillStyle = "red";
ctx.fillText("'center' aligned",center,y - size)
ctx.fillStyle = "black";
ctx.fillJustifyText(text[i++], center, y, width);
ctx.fillJustifyText(text[i++], center, y+=size, width);
ctx.fillJustifyText(text[i++], center, y+=size, width);
ctx.fillJustifyText(text[i++], center, y+=size, width);