텍스트에 “\ n”이 포함되어 있으면 캔버스에 텍스트를 추가 할 수없는 것 같습니다. 내 말은, 줄 바꿈이 표시되지 않거나 작동하지 않습니다.
ctxPaint.fillText("s ome \n \\n <br/> thing", x, y);
위의 코드는 "s ome \n <br/> thing"
한 줄에 를 그립니다 .
이것이 fillText의 제한입니까 아니면 내가 잘못하고 있습니까? “\ n”이 있고 인쇄되지 않지만 작동하지 않습니다.
답변
Canvas의 한계 인 것 같습니다 fillText
. 여러 줄 지원이 없습니다. 설상가상으로 선 높이를 측정하는 내장 된 방법이없고 너비 만 측정 할 수 있으므로 직접 수행하기가 더 어려워집니다!
많은 사람들이 자신의 다중 라인 지원을 작성했으며 아마도 가장 주목할만한 프로젝트는 Mozilla Skywriter 입니다.
해야 할 일의 요점은 fillText
매번 y 값에 텍스트 높이를 추가하면서 여러 번 호출하는 것입니다. (M의 너비를 측정하는 것은 스카이 라이터 사람들이 텍스트를 근사화하기 위해하는 일입니다.)
답변
텍스트에서 개행 문자를 처리하고 싶다면 개행에서 텍스트를 분할하고 여러 번 호출하여 시뮬레이션 할 수 있습니다. fillText()
http://jsfiddle.net/BaG4J/1/ 와 같은 것
var c = document.getElementById('c').getContext('2d');
c.font = '11px Courier';
console.log(c);
var txt = 'line 1\nline 2\nthird line..';
var x = 30;
var y = 30;
var lineheight = 15;
var lines = txt.split('\n');
for (var i = 0; i<lines.length; i++)
c.fillText(lines[i], x, y + (i*lineheight) );
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>
방금 http://jsfiddle.net/BaG4J/2/ 에서 개념 증명 ( 지정된 너비에서 절대 줄 바꿈. 단어 분리 처리 없음 )
예제를 만들었습니다 .
var c = document.getElementById('c').getContext('2d');
c.font = '11px Courier';
var txt = 'this is a very long text to print';
printAt(c, txt, 10, 20, 15, 90 );
function printAt( context , text, x, y, lineHeight, fitWidth)
{
fitWidth = fitWidth || 0;
if (fitWidth <= 0)
{
context.fillText( text, x, y );
return;
}
for (var idx = 1; idx <= text.length; idx++)
{
var str = text.substr(0, idx);
console.log(str, context.measureText(str).width, fitWidth);
if (context.measureText(str).width > fitWidth)
{
context.fillText( text.substr(0, idx-1), x, y );
printAt(context, text.substr(idx-1), x, y + lineHeight, lineHeight, fitWidth);
return;
}
}
context.fillText( text, x, y );
}
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>
그리고 단어 줄 바꿈 ( 공백에서 나누기 ) 개념 증명. http://jsfiddle.net/BaG4J/5/의
예
var c = document.getElementById('c').getContext('2d');
c.font = '11px Courier';
var txt = 'this is a very long text. Some more to print!';
printAtWordWrap(c, txt, 10, 20, 15, 90 );
function printAtWordWrap( context , text, x, y, lineHeight, fitWidth)
{
fitWidth = fitWidth || 0;
if (fitWidth <= 0)
{
context.fillText( text, x, y );
return;
}
var words = text.split(' ');
var currentLine = 0;
var idx = 1;
while (words.length > 0 && idx <= words.length)
{
var str = words.slice(0,idx).join(' ');
var w = context.measureText(str).width;
if ( w > fitWidth )
{
if (idx==1)
{
idx=2;
}
context.fillText( words.slice(0,idx-1).join(' '), x, y + (lineHeight*currentLine) );
currentLine++;
words = words.splice(idx-1);
idx = 1;
}
else
{idx++;}
}
if (idx > 0)
context.fillText( words.join(' '), x, y + (lineHeight*currentLine) );
}
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>
두 번째 및 세 번째 예제 measureText()
에서는 인쇄 할 때 문자열이 얼마나 길지 ( 픽셀 단위 ) 를 보여주는 방법을 사용하고 있습니다.
답변
이 파티에 조금 늦게 올지도 모르지만 캔버스에 텍스트를 완벽하게 감싸는 다음 자습서를 찾았습니다.
http://www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial/
그로부터 나는 다중 라인이 작동한다고 생각할 수있었습니다 (죄송합니다 Ramirez, 당신은 나를 위해 작동하지 않았습니다!). 캔버스에서 텍스트를 래핑하는 전체 코드는 다음과 같습니다.
<script type="text/javascript">
// http: //www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial/
function wrapText(context, text, x, y, maxWidth, lineHeight) {
var cars = text.split("\n");
for (var ii = 0; ii < cars.length; ii++) {
var line = "";
var words = cars[ii].split(" ");
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + " ";
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth) {
context.fillText(line, x, y);
line = words[n] + " ";
y += lineHeight;
}
else {
line = testLine;
}
}
context.fillText(line, x, y);
y += lineHeight;
}
}
function DrawText() {
var canvas = document.getElementById("c");
var context = canvas.getContext("2d");
context.clearRect(0, 0, 500, 600);
var maxWidth = 400;
var lineHeight = 60;
var x = 20; // (canvas.width - maxWidth) / 2;
var y = 58;
var text = document.getElementById("text").value.toUpperCase();
context.fillStyle = "rgba(255, 0, 0, 1)";
context.fillRect(0, 0, 600, 500);
context.font = "51px 'LeagueGothicRegular'";
context.fillStyle = "#333";
wrapText(context, text, x, y, maxWidth, lineHeight);
}
$(document).ready(function () {
$("#text").keyup(function () {
DrawText();
});
});
</script>
c
내 캔버스의 ID는 어디에 있고 text
내 텍스트 상자의 ID는 어디에 있습니까 ?
보시다시피 비표준 글꼴을 사용하고 있습니다. 캔버스를 조작하기 전에 일부 텍스트에 글꼴을 사용한 경우 @ font-face를 사용할 수 있습니다. 그렇지 않으면 캔버스가 글꼴을 선택하지 않습니다.
이것이 누군가를 돕기를 바랍니다.
답변
텍스트를 선으로 분할하고 각각 개별적으로 그립니다.
function fillTextMultiLine(ctx, text, x, y) {
var lineHeight = ctx.measureText("M").width * 1.2;
var lines = text.split("\n");
for (var i = 0; i < lines.length; ++i) {
ctx.fillText(lines[i], x, y);
y += lineHeight;
}
}
답변
여기에 이미 제시된 인기있는 wrapText () 함수를 수정하는 솔루션이 있습니다. 캔버스 컨텍스트에서 함수를 호출 할 수 있도록 JavaScript의 프로토 타이핑 기능을 사용하고 있습니다.
CanvasRenderingContext2D.prototype.wrapText = function (text, x, y, maxWidth, lineHeight) {
var lines = text.split("\n");
for (var i = 0; i < lines.length; i++) {
var words = lines[i].split(' ');
var line = '';
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = this.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
this.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
}
else {
line = testLine;
}
}
this.fillText(line, x, y);
y += lineHeight;
}
}
기본 사용법 :
var myCanvas = document.getElementById("myCanvas");
var ctx = myCanvas.getContext("2d");
ctx.fillStyle = "black";
ctx.font = "12px sans-serif";
ctx.textBaseline = "top";
ctx.wrapText("Hello\nWorld!",20,20,160,16);
다음은 제가 함께 모은 데모입니다.
http://jsfiddle.net/7RdbL/
답변
방금 CanvasRenderingContext2D를 확장하여 mlFillText와 mlStrokeText라는 두 가지 함수를 추가했습니다.
GitHub 에서 마지막 버전을 찾을 수 있습니다 .
이 기능을 사용하면 상자에서 miltiline 텍스트를 채우거나 칠할 수 있습니다. 텍스트를 세로 및 가로로 맞출 수 있습니다. (\ n을 고려하고 텍스트를 정당화 할 수도 있습니다).
프로토 타입은 다음과 같습니다.
function mlFillText (text, x, y, w, h, vAlign, hAlign, lineheight); function mlStrokeText (텍스트, x, y, w, h, vAlign, hAlign, lineheight);
vAlign은 “top”, “center”또는 “button”이 될 수 있으며 hAlign은 “left”, “center”, “right”또는 “justify”가 될 수 있습니다.
여기에서 lib를 테스트 할 수 있습니다 : http://jsfiddle.net/4WRZj/1/
다음은 라이브러리 코드입니다.
// Library: mltext.js
// Desciption: Extends the CanvasRenderingContext2D that adds two functions: mlFillText and mlStrokeText.
//
// The prototypes are:
//
// function mlFillText(text,x,y,w,h,vAlign,hAlign,lineheight);
// function mlStrokeText(text,x,y,w,h,vAlign,hAlign,lineheight);
//
// Where vAlign can be: "top", "center" or "button"
// And hAlign can be: "left", "center", "right" or "justify"
// Author: Jordi Baylina. (baylina at uniclau.com)
// License: GPL
// Date: 2013-02-21
function mlFunction(text, x, y, w, h, hAlign, vAlign, lineheight, fn) {
text = text.replace(/[\n]/g, " \n ");
text = text.replace(/\r/g, "");
var words = text.split(/[ ]+/);
var sp = this.measureText(' ').width;
var lines = [];
var actualline = 0;
var actualsize = 0;
var wo;
lines[actualline] = {};
lines[actualline].Words = [];
i = 0;
while (i < words.length) {
var word = words[i];
if (word == "\n") {
lines[actualline].EndParagraph = true;
actualline++;
actualsize = 0;
lines[actualline] = {};
lines[actualline].Words = [];
i++;
} else {
wo = {};
wo.l = this.measureText(word).width;
if (actualsize === 0) {
while (wo.l > w) {
word = word.slice(0, word.length - 1);
wo.l = this.measureText(word).width;
}
if (word === "") return; // I can't fill a single character
wo.word = word;
lines[actualline].Words.push(wo);
actualsize = wo.l;
if (word != words[i]) {
words[i] = words[i].slice(word.length, words[i].length);
} else {
i++;
}
} else {
if (actualsize + sp + wo.l > w) {
lines[actualline].EndParagraph = false;
actualline++;
actualsize = 0;
lines[actualline] = {};
lines[actualline].Words = [];
} else {
wo.word = word;
lines[actualline].Words.push(wo);
actualsize += sp + wo.l;
i++;
}
}
}
}
if (actualsize === 0) lines[actualline].pop();
lines[actualline].EndParagraph = true;
var totalH = lineheight * lines.length;
while (totalH > h) {
lines.pop();
totalH = lineheight * lines.length;
}
var yy;
if (vAlign == "bottom") {
yy = y + h - totalH + lineheight;
} else if (vAlign == "center") {
yy = y + h / 2 - totalH / 2 + lineheight;
} else {
yy = y + lineheight;
}
var oldTextAlign = this.textAlign;
this.textAlign = "left";
for (var li in lines) {
var totallen = 0;
var xx, usp;
for (wo in lines[li].Words) totallen += lines[li].Words[wo].l;
if (hAlign == "center") {
usp = sp;
xx = x + w / 2 - (totallen + sp * (lines[li].Words.length - 1)) / 2;
} else if ((hAlign == "justify") && (!lines[li].EndParagraph)) {
xx = x;
usp = (w - totallen) / (lines[li].Words.length - 1);
} else if (hAlign == "right") {
xx = x + w - (totallen + sp * (lines[li].Words.length - 1));
usp = sp;
} else { // left
xx = x;
usp = sp;
}
for (wo in lines[li].Words) {
if (fn == "fillText") {
this.fillText(lines[li].Words[wo].word, xx, yy);
} else if (fn == "strokeText") {
this.strokeText(lines[li].Words[wo].word, xx, yy);
}
xx += lines[li].Words[wo].l + usp;
}
yy += lineheight;
}
this.textAlign = oldTextAlign;
}
(function mlInit() {
CanvasRenderingContext2D.prototype.mlFunction = mlFunction;
CanvasRenderingContext2D.prototype.mlFillText = function (text, x, y, w, h, vAlign, hAlign, lineheight) {
this.mlFunction(text, x, y, w, h, hAlign, vAlign, lineheight, "fillText");
};
CanvasRenderingContext2D.prototype.mlStrokeText = function (text, x, y, w, h, vAlign, hAlign, lineheight) {
this.mlFunction(text, x, y, w, h, hAlign, vAlign, lineheight, "strokeText");
};
})();
그리고 다음은 사용 예입니다.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var T = "This is a very long line line with a CR at the end.\n This is the second line.\nAnd this is the last line.";
var lh = 12;
ctx.lineWidth = 1;
ctx.mlFillText(T, 10, 10, 100, 100, 'top', 'left', lh);
ctx.strokeRect(10, 10, 100, 100);
ctx.mlFillText(T, 110, 10, 100, 100, 'top', 'center', lh);
ctx.strokeRect(110, 10, 100, 100);
ctx.mlFillText(T, 210, 10, 100, 100, 'top', 'right', lh);
ctx.strokeRect(210, 10, 100, 100);
ctx.mlFillText(T, 310, 10, 100, 100, 'top', 'justify', lh);
ctx.strokeRect(310, 10, 100, 100);
ctx.mlFillText(T, 10, 110, 100, 100, 'center', 'left', lh);
ctx.strokeRect(10, 110, 100, 100);
ctx.mlFillText(T, 110, 110, 100, 100, 'center', 'center', lh);
ctx.strokeRect(110, 110, 100, 100);
ctx.mlFillText(T, 210, 110, 100, 100, 'center', 'right', lh);
ctx.strokeRect(210, 110, 100, 100);
ctx.mlFillText(T, 310, 110, 100, 100, 'center', 'justify', lh);
ctx.strokeRect(310, 110, 100, 100);
ctx.mlFillText(T, 10, 210, 100, 100, 'bottom', 'left', lh);
ctx.strokeRect(10, 210, 100, 100);
ctx.mlFillText(T, 110, 210, 100, 100, 'bottom', 'center', lh);
ctx.strokeRect(110, 210, 100, 100);
ctx.mlFillText(T, 210, 210, 100, 100, 'bottom', 'right', lh);
ctx.strokeRect(210, 210, 100, 100);
ctx.mlFillText(T, 310, 210, 100, 100, 'bottom', 'justify', lh);
ctx.strokeRect(310, 210, 100, 100);
ctx.mlStrokeText("Yo can also use mlStrokeText!", 0 , 310 , 420, 30, 'center', 'center', lh);
답변
자바 스크립트를 사용하여 솔루션을 개발했습니다. 아름답지는 않지만 나를 위해 일했습니다.
function drawMultilineText(){
// set context and formatting
var context = document.getElementById("canvas").getContext('2d');
context.font = fontStyleStr;
context.textAlign = "center";
context.textBaseline = "top";
context.fillStyle = "#000000";
// prepare textarea value to be drawn as multiline text.
var textval = document.getElementByID("textarea").value;
var textvalArr = toMultiLine(textval);
var linespacing = 25;
var startX = 0;
var startY = 0;
// draw each line on canvas.
for(var i = 0; i < textvalArr.length; i++){
context.fillText(textvalArr[i], x, y);
y += linespacing;
}
}
// Creates an array where the <br/> tag splits the values.
function toMultiLine(text){
var textArr = new Array();
text = text.replace(/\n\r?/g, '<br/>');
textArr = text.split("<br/>");
return textArr;
}
도움이 되었기를 바랍니다.