【问题标题】:HTML5 edit text on the canvasHTML5 在画布上编辑文本
【发布时间】:2019-11-10 16:23:02
【问题描述】:

我正在尝试创建类似于http://www.listhings.com 的内容,您可以在其中编辑画布中的文本。

我已阅读另一篇帖子 HTML5 Canvas Text Edit 。但我不想在画布之外编辑文本。我想编辑画布中的文本。

如果有人能指出我正确的方向,我将不胜感激。
谢谢

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    首先,Mohsen 正确地指出,当您执行 context.fillText 时,您实际上是在画布上“绘制字母图片”。它不像文字处理器!

    您可以捕捉窗口上的按键事件,然后将击键写到您的画布上。

    这是代码和小提琴:http://jsfiddle.net/m1erickson/7tXd4/

    这个例子只输入小写字母 a-z(没有大写、空格、退格等)

    您可能想要进行更多的增强,例如:

    这里的代码只是为了让你开始:

    <!doctype html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    
    <style>
        body{ background-color: ivory; padding:20px; }
        canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
    
        ctx.font="18px Arial";
    
        var keyHistory="";
    
        window.addEventListener("keyup", keyUpHandler, true);
    
        function addletter(letter){
            keyHistory+=letter;
            ctx.clearRect(0,0,300,300);
            ctx.fillText(keyHistory,20,20);
        }
    
        function keyUpHandler(event){
            var letters="abcdefghijklmnopqrstuvwxyz";
            var key=event.keyCode;
            if(key>64 && key<91){
                var letter=letters.substring(key-64,key-65);
                addletter(letter);
            }
        }
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <p>First click in the red canvas below</p><br/>
        <p>Then type any lowercase letters from a-z</p><br/>
        <canvas id="canvas" width=300 height=100></canvas>
    </body>
    </html>
    

    【讨论】:

    • @albertxing:很好!感谢分享。我特别喜欢你用作介绍的“代码输入”。
    • 谢谢,感谢您的反馈。我怎么不能@提及你?
    • 不仅有英文字母,还有更好的键处理解决方案: function keyPressHandler(event) { addletter(String.fromCharCode(event.charCode)); }
    • 以上评论更正:String.fromCharCode(event.keyCode)
    【解决方案2】:

    fillText() 不要创建以后可以编辑的对象或文本节点。它将在画布上填充文本,这意味着它将在画布上留下像素。

    您可以使用 http://kineticjs.com/ 之类的 Canvas 库为该文本创建一个图层,这样您就可以擦除该图层并在其中重新键入文本。Kinect 允许您将值绑定到图层,这样您就可以将文本保存在layer 在绑定到图层的值中。

    【讨论】:

      【解决方案3】:

      试试这个解决方案https://jsfiddle.net/tabvn/zjyoexf1/

      <!DOCTYPE html>
      <html>
      <head>
          <meta charset="utf-8"/>
          <title>Canvas Input Element</title>
      </head>
      <body>
          <canvas id="draw" width="500" height="500"></canvas>
      <script type="text/javascript">
          var canvas = document.getElementById("draw");
          var ctx = canvas.getContext("2d");
          canvas.width = window.innerWidth;
          canvas.height = window.innerHeight;
          ctx.beginPath();
      
          function Input(text = "", options = {}){
              this.text = text;
              this.options = Object.assign({width: 250, height: 40, font: "17px Arial", borderWidth: 1, borderColor: "#ccc", padding: 5}, options);
              this.position = {x: 10, y: 10};
              this.isFocus = false;
              this.focusIndex = text.length;
              this.isCommandKey = false;
              this.selected = false;
      
              this.render = function(){
                  ctx.clearRect(this.position.x, this.position.y, this.options.width, this.options.height);
                  ctx.font = this.options.font;
                  ctx.lineWidth = this.options.borderWidth;
                  ctx.strokeStyle = this.options.borderColor;
                  if(this.isFocus){
                      ctx.strokeStyle = "#000";
                  }
                  ctx.rect(this.position.x, this.position.y, this.options.width, this.options.height);
                  ctx.stroke();
      
                  // write text
                  var str = "";
                  for(var i = 0; i < this.text.length; i++){
                      if(!this.selected && this.isFocus && this.focusIndex === i){
                          str += "|";
                      }
                      str += this.text[i];
                  }
                  if(!this.selected && this.isFocus && this.focusIndex === this.text.length){
                      str += "|";
                  }
      
                  if(this.selected){
                          var _width = ctx.measureText(this.text).width;
                          ctx.fillStyle = 'rgba(0,0,0,0.5)';
                          ctx.fillRect(this.position.x + this.options.padding, this.position.y + this.options.padding, _width, parseInt(this.options.font, 17));
      
                  }
      
                  ctx.fillStyle = "#000";
                  ctx.fillText(str, this.position.x + this.options.padding,  this.position.y + (this.options.height / 2) + this.options.padding);
      
              }
      
              this.handleOnClick = function(e){
                  let clientX = e.clientX;
                  let clientY = e.clientY;
                  if(clientX <= this.position.x + this.options.width && clientX >= this.position.x && clientY <= this.position.y + this.options.height && clientY >= this.position.y){
                      if(!this.isFocus){
                          this.isFocus = true;
                          this.focusIndex = this.text.length;
                          this.render();
                      }
                  }else{
                      if(this.isFocus){
                          this.selected = false;
                          this.isFocus = false;
                          this.render();
                      }
      
                  }
              }
      
              this.handleOnKeyUp = function(e){
                  this.isCommandKey = false;
                  this.render();
              }
      
              this.handleOnKeyDown = function(e){
                  if(e.key === "Meta" || e.key === "Control"){
                      this.isCommandKey = true;
                  }
                  if(this.isFocus){
                      e.preventDefault();
                  }
                  if(this.isCommandKey && e.key === "a"){
                      this.selected = true;
                      this.render(); 
                      return 
                  }
                  if(this.isFocus && e.key === "Backspace"){
                      if(this.selected){
                          this.focusIndex = 0;
                          this.text = "";
                          this.selected = false;
                          this.render();
                      }
                      var str = "";
                      for(var i =0; i < this.text.length; i++){
                          if(i !== this.focusIndex - 1){
                              str += this.text[i];
                          }
                      }
      
                      this.text = str;
      
                      this.focusIndex --;
                      if(this.focusIndex <0){
                          this.focusIndex = 0;
                      }
                      this.render();
                  }
                  if(this.isFocus && e.key === "ArrowLeft"){
                      this.focusIndex --;
                      if(this.focusIndex < 0){
                          this.focusIndex = 0;
                      }
                      this.render();
                  }
                  if(this.isFocus && e.key === "ArrowRight"){
                      this.focusIndex ++;
                      if(this.focusIndex > this.text.length){
                          this.focusIndex = this.text.length;
                      }
                      this.render();
                  }
                  if(!this.isCommandKey && this.isFocus && (e.keyCode == 32 || (e.keyCode >= 65))){
                      this.text += e.key;
                      this.focusIndex = this.text.length;
                      this.render();
                  }
      
      
              }
          }
      
          var input = new Input("I 'm an input");
          input.render();
      
          window.addEventListener("click", function(event){
                  input.handleOnClick(event);
          });
          window.addEventListener("keydown", function(event){
                  input.handleOnKeyDown(event);
          });
          window.addEventListener("keyup", function(event){
                  input.handleOnKeyUp(event);
          });
      
      </script>
      
      </body>
      </html>
      

      【讨论】:

      • 欢迎来到 SO,请在您的答案中添加一些解释,简单描述您的解决方案如何解决问题并避免仅发布代码答案。
      • :) 我注意到了
      • @Toan,是否允许以 CC0 方式重用您上面的代码示例?
      • @Simeon 没关系
      猜你喜欢
      • 2018-03-06
      • 2011-04-11
      • 1970-01-01
      • 2012-11-20
      • 2014-10-06
      • 2016-06-19
      • 2011-03-11
      • 1970-01-01
      相关资源
      最近更新 更多