HTML5 редактировать текст на холсте

Я пытаюсь создать что-то похожее на http://www.listhings.com/ где вы можете редактировать текст на холсте.

Я прочитал другой пост HTML5 Canvas Text Edit. Но я не хочу редактировать текст за пределами холста. Я хочу редактировать текст на холсте.

Буду признателен, если кто-нибудь может указать мне правильное направление.
Спасибо

2 ответа

Во-первых, Мохсен правильно указывает, что когда вы делаете context.fillText, вы фактически "рисуете изображение букв" на холсте. Это не похоже на текстовый процессор!

Вы можете захватить ключевые события в окне, а затем записать нажатия клавиш на свой холст.

Вот код и скрипка: http://jsfiddle.net/m1erickson/7tXd4/

В этом примере вводятся только строчные буквы z (без прописных букв, пробелов, пробелов и т. Д.)

Возможно, вы захотите сделать больше улучшений, таких как эти:

  • Добавление дополнительных клавиш (AZ, 0-9 и т. Д.).
  • Отвечайте на командные клавиши, такие как backspace, чтобы удалить буквы из истории ключей.
  • Поместите курсор, чтобы пользователи знали, где они находятся в строке при вводе (подсказка: http://www.html5canvastutorials.com/tutorials/html5-canvas-text-metrics/)
  • Если вы разрешаете многострочный текст, обработайте клавишу [enterkey] и перейдите к новой строке.
  • Так далее

Вот код, который поможет вам начать:

<!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>

fillText() не создавайте объект или текстовый узел, который вы можете редактировать впоследствии. Он будет заполнять текст на холсте, это означает, что он оставит пиксели на холсте.

Вы можете использовать библиотеки Canvas, такие как http://kineticjs.com/ чтобы иметь один слой для этого текста, чтобы вы могли стереть слой и заново ввести текст. Kinect позволяет привязывать значения к слоям, чтобы вы могли сохранить свой текст в слое в значении, связанном со слоем.

Попробуйте это решение 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>
Другие вопросы по тегам