如何在Canvas和JS中旋转来自输入的动态文本? [英] How to rotate dynamic text from input in Canvas and JS?

查看:107
本文介绍了如何在Canvas和JS中旋转来自输入的动态文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Canvas和Javascript进行盒子样式设计,但是我无法按照想要的方式旋转文本(从下到上书写).


(来源: hostpic.xyz )

我遵循了一个教程( https://newspaint.wordpress.com/2014/05/22/writing-rotated-text-on-a-javascript-canvas/),并尝试在我的代码中对其进行调整,但我无法做到.

您可以在下面的JSFiddle链接上找到代码,这里有一个输入,您可以在其中键入文本,并且应该在JSFiddle示例中将其写为"brand"一词.

https://jsfiddle.net/ParkerIndustries/mgne9x5u/5/

一切都在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);

除此之外,我建议进行一轮代码清理,以避免变量名和硬编码数字不一致(请尝试使所有内容与img.widthimg.height成比例,然后避免使用文字值.这样可以更轻松地动态调整代码无需重新输入所有值.您可以在img.onload函数触发后访问img.widthimg.height.

另一个有用的功能是 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> 

I'm working on a box styling project with Canvas and Javascript, and I can't rotate the text the way I want (written from bottom to the top).


(source: hostpic.xyz)

I followed a tutorial (https://newspaint.wordpress.com/2014/05/22/writing-rotated-text-on-a-javascript-canvas/) and tried to adapt it in my code, but I couldn't make it.

You can find the code on the JSFiddle link below, there's an input where you can type your text and it should be written as the "brand" word in the JSFiddle example.

https://jsfiddle.net/ParkerIndustries/mgne9x5u/5/

Everything is in the init() function:

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();

I tried a lot a values in the context.rotate() function but in any way my text is upside down.


(source: hostpic.xyz)

解决方案

You're pretty close here. I suggest performing the canvas translation to the middle of the screen (width / 2, height / 2) and then rotating by 270 degrees:

context.translate(canvas.width / 2, canvas.height / 2);
context.rotate(270 * Math.PI / 180);

Beyond that, I recommend a round of code cleanup to avoid inconsistent variable names and hardcoded numbers (try to make everything proportional to img.width and img.height, then avoid literal values. This makes it easier to adjust your code dynamically without having to re-type all of the values. You can access img.width and img.height after the img.onload function fires.

Another useful function is context.measureText(text), which makes it simpler to proportionally scale text size.

Full example:

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>


With that proof-of-concept working, one problem is that scaling the image on canvas causes visual artifacts. This problem can be overcome with JS or by scaling down the source image itself, but at this point, it's best to make the image as an element and circumvent the entire problem.

Similarly, there's no obvious reason to render text on canvas either; we can make an element for this as well. Moving text to HTML/CSS gives more power over how it looks (I didn't do much with style here, so it's an exercise to make it blend more naturally into the image).

Here's a rewrite without canvas that looks much cleaner and should be more maintainable:

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>

这篇关于如何在Canvas和JS中旋转来自输入的动态文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆