我正在使用canvas元素生成文本的base64图像。当我点击“ Generate text”按钮时,画布将填充图像,但是直到您第二次点击按钮时,画布才会调整大小。 (而且很奇怪,在我的机器上,我的字体直到第二次单击时才起作用)
我的小提琴在下面,您可以看到该功能在第一次单击时部分起作用,这就是让我感到困惑的地方。
我已经检查了答案here,here和here,但我不是jQuery专家,而且我不知道如何将其中一些解决方案应用于我具体情况。我已经在上面的答案中尝试了一些建议的解决方案,包括:
将我的代码包装在$(document).ready(function() {}
使用$("#addText").click
代替$("#addText").on("click"...
编辑:正如@Barmar在评论中提到的那样,它在第一次尝试时会调整为大约一半的大小。这是因为lineCount()
函数在第一次点击时输出了错误的数字。
$(document).ready(function() {
$("#addText").click(txtimg);
$("#myDownload").click(function() {
var canvas = document.getElementById("myCanvas");
var fullQuality = canvas.toDataURL("image/png", 1.0);
$('#imgURL').val(fullQuality);
});
$("input[type='radio'][name='fontRadios']").click(function() {
console.log($("input[type='radio'][name='fontRadios']:checked").val());
});
$("#colorChooser > label").on("click", function() {
$('#colorPreview').css("background-color", $(this).attr('data-color')),
txtimg();
});
$("#CaptureURL").click(function() {
$("#imgURL").select();
document.execCommand('copy');
});
});
function txtimg() {
var fontSize = parseInt($('#fontSizeValue').html());
var fontColor = $('#colorChooser > label > input:checked').attr('id');
var fontFam = $("input[type='radio'][name='fontRadios']:checked").val();
var canvas = document.getElementById("myCanvas");
var myMessage = $("#myMessage").val();
var maxWidth = 600;
var lineHeight = parseInt($('#lineHeightValue').html());
var ctx = canvas.getContext("2d");
var canvHeight = lineHeight * lineCount(ctx, myMessage, maxWidth);
canvas.height = lineHeight * lineCount(ctx, myMessage, maxWidth);
var x = canvas.width / 2;
var y = canvas.height;
//ctx.clearRect(0, 0, canvas.width, canvas.height);
//ctx.beginPath();
//ctx.moveTo(x, 0);
ctx.font = fontSize + "px " + fontFam;
ctx.fillStyle = fontColor;
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = 'high';
//ctx.fillText(myMessage, x, y);
wrapText(ctx, myMessage, x, 0 + lineHeight, maxWidth, lineHeight);
}
function lineCount(context, text, maxWidth) {
var words = text.split(' ');
var line = '';
var lines = 1;
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 && n > 0) {
line = words[n] + ' ';
lines++;
} else {
line = testLine;
}
}
return lines;
}
function wrapText(context, text, x, y, maxWidth, lineHeight) {
var words = text.split(' ');
var line = '';
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 && n > 0) {
context.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
} else {
line = testLine;
}
}
context.fillText(line, x, y);
}
function fontVal(elem) {
var fv = document.getElementById('fontSizeValue');
if (fv.innerHTML != elem.value) {
fv.innerHTML = elem.value;
console.log(elem.value);
}
}
function lineVal(elem) {
var lv = document.getElementById('lineHeightValue');
if (lv.innerHTML != elem.value) {
lv.innerHTML = elem.value;
console.log(elem.value);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Helloworld!</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.0/css/all.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<link href="https://fonts.googleapis.com/css?family=Oswald|Roboto|Sofia" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="d-flex flex-row align-content-center mb-5">
<div class="d-flex align-self-center mx-auto">
<canvas id="myCanvas" width="600" height="100" style="border: 1px solid #cecece;"></canvas>
</div>
</div>
<form id="myForm">
<div class="form-group">
<label for="myMessage">Message</label>
<input type="text" name="myMessage" id="myMessage" class="form-control" value="Did you ever hear the tragedy of Darth Plagueis the Wise? I thought not. It's not a story the Jedi would tell you. It's a Sith legend. Darth Plagueis was a Dark Lord of the Sith, so powerful and so wise he could use the Force to influence the midichlorians to create life... He had such a knowledge of the dark side that he could even keep the ones he cared about from dying. The dark side of the Force is a pathway to many abilities some consider to be unnatural. He became so powerful... the only thing he was afraid of was losing his power, which eventually, of course, he did. Unfortunately, he taught his apprentice everything he knew, then his apprentice killed him in his sleep. It's ironic he could save others from death, but not himself."
/>
</div>
<hr/>
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label for="fontRange">Font Size: </label><span id="fontSizeValue">32</span><span>px</span>
<input type="range" class="form-control-range" id="fontRange" min="8" max="128" value="32" onChange="fontVal(this)" onMouseMove="fontVal(this)">
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<label for="lineRange">Line Height</label><span id="lineHeightValue">32</span><span>px</span>
<input type="range" class="form-control-range" id="lineRange" min="0" max="128" value="32" onChange="lineVal(this)" onMouseMove="lineVal(this)">
</div>
</div>
</div>
<hr/>
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label for="fontSizeSelect">Typeface</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="fontRadios" id="Oswald" value="Oswald" checked>
<label class="form-check-label" for="WP">
Oswald
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="fontRadios" id="Roboto" value="Roboto">
<label class="form-check-label" for="TG">
Roboto
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="fontRadios" id="Sofia" value="Sofia">
<label class="form-check-label" for="TGB">
Sofia
</label>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="btn-group btn-group-toggle w-100" data-toggle="buttons" id="colorChooser">
<label class="btn rush-red active" data-color="#ed1c24">
<input type="radio" name="colorOptions" id="#ed1c24" autocomplete="off" checked>Red
</label>
<label class="btn rush-gold" data-color="#eeb111">
<input type="radio" name="colorOptions" id="#eeb111" autocomplete="off">Gold
</label>
<label class="btn rush-grey" data-color="#505051">
<input type="radio" name="colorOptions" id="#505051" autocomplete="off">Grey
</label>
<label class="btn rush-black" data-color="#111111">
<input type="radio" name="colorOptions" id="#111111" autocomplete="off">Black
</label>
</div>
<div class="card">
<div id="colorPreview" class="card-body" style="background-color: #ed1c24;">
</div>
</div>
</div>
</div>
<button id="addText" class="btn btn-primary" type="button">
Add Text
</button>
</form>
<hr/>
<button class="btn btn-primary" type="button" id="myDownload">
<i class="fa fa-code pr-2"></i>Generate Image URL
</button>
<button class="btn btn-primary" type="button" id="CaptureURL">
<i class="fa fa-copy pr-2"></i>Copy
</button>
<!--a class="btn disabled float-right" id="linkURL" href="#" target="_blank">
<i class="fa fa-external-link-alt pr-2"></i>Test in Browser
</a-->
<textarea id="imgURL" class="form-control"></textarea>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>
答案 0 :(得分:1)
在第一次调用lineCount()
之前设置画布字体属性。对measureText()
的内部调用使用分配给它们之前的所有默认值。
答案 1 :(得分:0)
我在这里找到了答案: Drawing text to <canvas> with @font-face does not work at the first time
浏览器异步地在后台加载字体,因此我将它们放在要加载的其他文档中。这是在丢掉measureText()函数之后,因此丢掉了行距