我正在使用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>
最佳答案
第一次调用lineCount()
之前,请设置画布字体属性。对measureText()
的内部调用使用分配给它们之前的任何默认值。