javascript - 如何在带有多个文本字段的画布上显示用户输入和文本换行
问题描述
我正在尝试设置此站点,用户输入的文本将在其中将文本绘制到正在显示的图像的语音气泡中。我有三个问题:
用户可以在画布上输入文本,但是当用户删除字符时,画布上绘制的文本不会更新
文本根本没有用用户输入换行,但是当我直接插入字符串时它会换行。我希望文本与用户输入一起换行
每当用户开始在新输入框中输入内容时,画布中的所有文本都会被删除。
我已经在网上寻找教程和答案,但它们都不是我需要在这里正常工作的确切解决方案。任何其他建议都会有所帮助。
谢谢!
<html>
<input id="input-text" type="text" onkeyup="usertextChange(this.value)"
maxlength="6" />
<input id="input-text2" type="text" onkeyup="usertextChange2(this.value)"
maxlength="5" />
<input id="input-text3" type="text" onkeyup="usertextChange3(this.value)"
maxlength="12" />
<input id="input-text4" type="text" onkeyup="usertextChange4(this.value)"
maxlength="18" />
<div class="art-container">
<canvas id="canvas" width="576" height="576">
Canvas requires a browser that supports HTML5.
</canvas>
<img crossOrigin="Anonymous" id="no-crying"
src="https://cdn.glitch.com/4ed5f9d8-97ad-4c53-b855-3e8d508ba2f3%2FDVSN-
FUTURE-NO-CRYIN-FINAL-NoText.jpg?v=1572122142300"/>
</div>
</html>
<style>
#input-text, #input-text2, #input-text3, #input-text4 {
width: 90%;
font-size: 18px;
height: 24px;
text-transform: uppercase;
padding: 0 8px;
background-color: transparent;
color: red;
border: 2px solid black;
outline: none;
border-radius: 4px;
margin-bottom: 12px;
margin-left: auto;
margin-right: auto;
font-weight: 500;
font-family: bubblegum;
}
#no-crying {
display: none;
}
</style>
<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var maxWidth = 90;
var lineHeight = 45;
var x = 35;
var y = 315;
var text = document.getElementById('input-text1').value;
var text2 = document.getElementById('input-text2').value;
var text3 = document.getElementById('input-text3').value;
var text4 = document.getElementById('input-text4').value;
function drawImage(text) {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var img = document.getElementById('no-crying');
context.drawImage(img, 0, 0, canvas.width, canvas.height);
}
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);
}
window.onload = function() {
drawImage();
}
// USER IMPUT FUNCTIONS
window.usertextChange = function(val){
context.clearRect(0, 0, canvas.width, canvas.height);
context.restore();
drawImage();
context.font = '26px Bubblegum';
context.fillStyle = "#000000";
context.fillText(val, 39, 315);
context.save();
wrapText(context, text, x, y, maxWidth, lineHeight);
}
window.usertextChange2 = function(val){
context.restore();
context.font = '22px Bubblegum';
context.fillStyle = "#000000";
context.fillText(val, 45, 370);
context.save();
wrapText(context, text, x, y, maxWidth, lineHeight);
}
window.usertextChange3 = function(val){
context.restore();
context.font = '26px Bubblegum';
context.fillStyle = "#000000";
context.fillText(val, 25, 420);
context.save();
wrapText(context, text, x, y, maxWidth, lineHeight);
}
window.usertextChange4 = function(val){
context.restore();
context.font = '24px Bubblegum';
context.fillStyle = "#000000";
context.fillText(val, 48, 360);
wrapText(context, text, x, y, maxWidth, lineHeight);
}
</script>
编辑 我还希望在添加用户输入文本后下载图像。什么是最好的实施方式。这是我根据最近的回复得出的结论
function init() {
text1 = '';
text2 = '';
text3 = '';
text4 = '';
backgroundImg = new Image();
backgroundImg.src = 'https://cdn.glitch.com/4ed5f9d8-97ad-4c53-b855-
3e8d508ba2f3%2FDVSN-FUTURE-NO-CRYIN-FINAL-NoText.jpg?v=1572122142300';
backgroundImg.setAttribute('crossOrigin', 'anonymous');
function addLink() {
var link = document.createElement('a');
link.innerHTML = 'Download!';
link.addEventListener('click', function(e) {
link.href = canvas.toDataURL();
link.download = "salt-bae.png";
}, false);
link.className = "instruction";
document.getElementById('input-container').appendChild(link);
}
window.onload = function() {
drawImage();
addLink();
}
解决方案
几点评论:
您使用var text = document.getElementById('input-text1').value;
id input-text1而在您的 HTML 中,您的 id 是input-text。
drawImage(text)
您使用从未使用过的text
参数定义函数。在此函数中,您再次创建canvas
和context
变量。
您在 DOM 中插入一个您隐藏的图像,以便稍后在画布上绘制它。我认为创建一个新Image
对象更容易。
功能wrapText()
有点模糊。它是否格式化文本?它显示什么吗?您可以将其重命名为displayWrapText()
或getWrappedText()
。
然后,关于你的问题:
当用户删除字符时,文本不会更新,因为除了输入 #1,当用户键入时,它不会清除气泡,而是在前一个文本上绘制新文本(它变得越来越暗)。这就是为什么你看不出有什么不同。删除适用于第一个输入,因为您清除气泡并再次绘制全文。
Tbh,我在尝试时忘记了这个问题,现在它运行良好......无论如何,提供一个适合
maxWidth
该wrapText()
功能的:有小气泡和大气泡。但是,如果字符串不包含任何空格,它不会换行。当用户输入第一个输入时,它会清除画布但仅在第一个气泡内再次显示文本,因此其他显示为空。您需要清除画布并重新绘制所有相应气泡中的文本。
我所做的是应用我之前告诉你的内容,并改进事件处理(请参阅冒泡),因为每个输入的代码几乎相同。为了能够在每次更新后重绘所有气泡,我在每次更新时存储它们的值。
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
const lineHeight = 30;
let backgroundImg;
let text1;
let text2;
let text3;
let text4;
init();
function init() {
text1 = '';
text2 = '';
text3 = '';
text4 = '';
backgroundImg = new Image();
backgroundImg.src = 'https://cdn.glitch.com/4ed5f9d8-97ad-4c53-b855-3e8d508ba2f3%2FDVSN-FUTURE-NO-CRYIN-FINAL-NoText.jpg?v=1572122142300';
context.drawImage(backgroundImg, 0, 0, canvas.width, canvas.height);
document.querySelector('#input-container').addEventListener('keyup', function(e) {
const num = parseInt(e.target.getAttribute('data-bubble'), 10);
const text = e.target.value;
saveText(num, text);
draw(canvas, context, backgroundImg);
}, false);
}
function draw(canvas, context, backgroundImg) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(backgroundImg, 0, 0, canvas.width, canvas.height);
drawBubble(canvas, context, getTextFrom(1), 39, 315, '26px Bubblegum', '#000000', 110, lineHeight); // bubble 1
drawBubble(canvas, context, getTextFrom(2), 45, 370, '22px Bubblegum', '#000000', 70, lineHeight); // bubble 2
drawBubble(canvas, context, getTextFrom(3), 20, 425, '26px Bubblegum', '#000000', 120, lineHeight); // bubble 3
drawBubble(canvas, context, getTextFrom(4), 20, 515, '24px Bubblegum', '#000000', 120, lineHeight); // bubble 4
}
function getTextFrom(num) {
switch(num) {
case 1: return text1;
case 2: return text2;
case 3: return text3;
case 4: return text4;
default: '';
}
}
function saveText(num, text) {
switch(num) {
case 1: text1 = text; break;
case 2: text2 = text; break;
case 3: text3 = text; break;
case 4: text4 = text; break;
}
}
function displayWrappedText(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 drawBubble(canvas, context, text, x, y, font, color, maxWidth, lineHeight) {
context.font = font;
context.fillStyle = color;
//context.fillText(text, x, y);
displayWrappedText(context, text, x, y, maxWidth, lineHeight);
}
#input-container > input {
width: 90%;
font-size: 18px;
height: 24px;
text-transform: uppercase;
padding: 0 8px;
background-color: transparent;
color: red;
border: 2px solid black;
outline: none;
border-radius: 4px;
margin-bottom: 12px;
margin-left: auto;
margin-right: auto;
font-weight: 500;
font-family: bubblegum;
}
<div id="input-container">
<input class="js-input-text" data-bubble="1" type="text" maxlength="6" />
<input class="js-input-text" data-bubble="2" type="text" maxlength="5" />
<input class="js-input-text" data-bubble="3" type="text" maxlength="12" />
<input class="js-input-text" data-bubble="4" type="text" maxlength="18" />
</div>
<div class="art-container">
<canvas id="canvas" width="576" height="576">
Canvas requires a browser that supports HTML5.
</canvas>
</div>
推荐阅读
- c# - 如何通过文本文件在控制台上显示学生的姓名和平均成绩?
- python-3.x - 将张量分成两组的最快方法,对于每组,随机将一个分配给 0,另一个分配给 1
- swift - '不能用'UIImagePickerController.Infokey'类型的索引为'[NSObject:AnyObject]'类型的值下标
- sql - PostgreSQL查询检查是否从多个表中引用了一行
- botframework - QnA Maker 知识库返回“在 KB 中找不到好的匹配项”以获取后续提示
- python - 如何从python子目录中的多个文件中读取特定的文本文件
- azure-devops - 构建管道 - 获取触发管道的签入标题
- node.js - 如何解析来自 Slack 的交互消息?
- c - 如何在 Windows 文本编辑器上阻止打印功能(CTRL + P)?
- excel - 如何从 excel 数据透视表中选择数据?