javascript - 如何从 Canvas 和 JS 中的输入中旋转动态文本?
问题描述
我正在使用 Canvas 和 Javascript 开发一个框样式项目,但我无法按照我想要的方式旋转文本(从下到上写)。
(来源:hostpic.xyz)
我遵循了一个教程(https://newspaint.wordpress.com/2014/05/22/writing-rotated-text-on-a-javascript-canvas/)并尝试在我的代码中进行调整,但我不能做了。
您可以在下面的 JSFiddle 链接上找到代码,您可以在其中输入文本,并且在 JSFiddle 示例中应将其写为“品牌”字样。
一切都在 init() 函数中:
function init() {
var elem = document.getElementById('elem');
var circle_canvas = document.createElement("canvas");
var context = circle_canvas.getContext("2d");
var img = new Image();
img.src = "https://unblast.com/wp-content/uploads/2018/11/Vertical-Product-Box-Mockup-1.jpg";
context.drawImage(img, 0, 0, 500, 650);
circle_canvas.width = 500;
circle_canvas.height = 650;
context.fillStyle = "#000000";
//context.textAlign = 'center';
var UserInput = document.getElementById("UserInput");
context.save();
context.translate( circle_canvas.width - 1, 0 );
UserInput.oninput = function() {
context.clearRect(0, 0, 500, 650);
context.drawImage(img, 0, 0, 500, 650);
var text = UserInput.value;
console.log(text);
if (text.length < 12) {
context.rotate(3*Math.PI/2);
console.log("-12");
context.font = "50px Righteous";
context.fillText(text, -350, -170);
context.restore();
} else {
context.rotate(3*Math.PI/2);
context.font = "25px Righteous";
context.fillText(text, -350, -170);
context.restore();
}
}
elem.appendChild(circle_canvas);
}
init();
我在 context.rotate() 函数中尝试了很多值,但无论如何我的文本是颠倒的。
(来源:hostpic.xyz)
解决方案
你离这里很近。我建议将画布平移到屏幕中间 ( width / 2, height / 2
),然后旋转 270 度:
context.translate(canvas.width / 2, canvas.height / 2);
context.rotate(270 * Math.PI / 180);
除此之外,我建议进行一轮代码清理,以避免变量名称和硬编码数字不一致(尝试使所有内容都与 and 成比例img.width
,img.height
然后避免使用文字值。这样可以更轻松地动态调整代码,而无需重新键入所有值。您可以在函数触发后访问img.width
和。img.height
img.onload
另一个有用的功能是context.measureText(text)
,它可以更简单地按比例缩放文本大小。
完整示例:
function init() {
var userInput = document.getElementById("user-input");
var elem = document.getElementById("elem");
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var img = new Image();
img.onload = function () {
canvas.width = img.width / 3;
canvas.height = img.height / 3;
context.drawImage(img, 0, 0, canvas.width, canvas.height);
context.fillStyle = "#000000";
context.textAlign = "center";
elem.appendChild(canvas);
userInput.oninput = function () {
var text = userInput.value;
var textSizePx = 50 - context.measureText(text).width / 10;
context.font = textSizePx + "px Righteous";
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(img, 0, 0, canvas.width, canvas.height);
context.save();
context.translate(canvas.width / 2, canvas.height / 2);
context.rotate(270 * Math.PI / 180);
context.fillText(text, 0, -canvas.width / 20);
context.restore();
}
};
img.src = "https://unblast.com/wp-content/uploads/2018/11/Vertical-Product-Box-Mockup-1.jpg";
}
init();
<div id="elem">
<input type="text" id="user-input" maxlength="15">
</div>
通过这种概念验证工作,一个问题是在画布上缩放图像会导致视觉伪影。这个问题可以通过JS或者通过缩小源图片本身来解决,但是此时最好将图片作为一个元素来规避整个问题。
同样,也没有明显的理由在画布上渲染文本。我们也可以为此制作一个元素。将文本移动到 HTML/CSS 可以更好地控制它的外观(我在这里没有对样式做太多,所以这是一个让它更自然地融入图像的练习)。
这是一个没有画布的重写,看起来更干净,应该更易于维护:
function init() {
var userInput = document.querySelector("#user-input");
var img = document.querySelector("#product-img");
var imgRect = img.getBoundingClientRect();
var overlayText = document.querySelector("#overlay-text");
var overlay = document.querySelector("#overlay");
overlay.style.width = (imgRect.width * 0.86) + "px";
overlay.style.height = imgRect.height + "px";
userInput.addEventListener("input", function () {
overlayText.innerText = userInput.value;
overlayText.style.fontSize = (50 - userInput.value.length * 2) + "px";
});
}
init();
#product-img {
position: absolute;
}
#overlay {
position: absolute;
display: flex;
}
#overlay-text {
font-family: Verdana, sans-serif;
color: #333;
transform: rotate(270deg);
margin: auto;
cursor: default;
}
<div>
<input type="text" id="user-input" maxlength="15">
</div>
<div id="product-container">
<img id="product-img" src="https://unblast.com/wp-content/uploads/2018/11/Vertical-Product-Box-Mockup-1.jpg" width=666 height=500 />
<div id="overlay">
<div id="overlay-text"></div>
</div>
</div>
推荐阅读
- tensorflow - 如何在 Tensorflow 1.14.0 中打印冻结推理模型的节点名称?
- c# - Xamarin TimeSpan 使用时间小于 1 毫秒
- python - 如何在文件中找到最大的多位数字并对文件进行排序(Python)
- javascript - 我尝试使用按钮下载本地文件,但找不到该文件
- laravel - 无法修复 laravel 上的顺风组件下拉菜单
- python - 强制数字的正则表达式小于 1000 并且如果有小数点
- javascript - 是否可以动态解构返回?
- excel - 使用多个标签获取元素
- .net - Blazor dll 多次加载 => chrome 资源不足
- python - 如何检查触发器用户的特定角色?(discord.py)