Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I drag a piece of user generated text around the HTML5 canvas?

Basically what I have coded is the ability to type a word into a text box. When a button is pressed to submit it that word is then posted to the HTML5 canvas so people can see it. What I want to do now is to have the ability to drag that word around the HTML5 canvas. I'm having slightly difficulty in achieving this and was wondering if someone could help me with this please? Here's my code what I've done so far:

var fname;
var canvas;
var ctx;
var canvasX;
var canvasY;
var mouseIsDown;

function addTitle2() {

    canvas = document.getElementById("canvas");
    ctx = canvas.getContext("2d");

    canvas.addEventListener("mousedown", mouseDown, false);
    canvas.addEventListener("mousemove", mouseXY, false);
    document.body.addEventListener("mouseup", mouseUp, false);

    var fname = document.forms[0].fname.value;

    ctx.fillStyle = "black";
    ctx.strokeStyle = "black";
    ctx.font = "35px Arial";
    ctx.fillText(fname, Math.random() * 500, Math.random() * 400);
    ctx.stroke();

}

function mouseUp() {

    mouseIsDown = 0;
    mouseXY();

}

function mouseDown() {

    mouseIsDown = 1;
    mouseXY();

}

function mouseXY(e) {

    e.preventDefault();

    canvasX = e.pageX - canvas.offsetLeft;
    canvasY = e.pageY - canvas.offsetTop;

    ShowPos();

}

function ShowPos() {

    if(mouseIsDown) {

        ctx.fillText(fname, canvasX, canvasY);

    }

}
like image 793
Formula 1 Avatar asked Apr 01 '14 12:04

Formula 1


People also ask

How do I put text on a canvas in HTML?

To add a text to the HTML <canvas> element, you need to use the fillText() or strokeText() methods, or you can use the combination of the two. You can also give color to your text, define the font and size, and even add gradients.

How do I align text in canvas?

To align HTML5 Canvas text, we can use the textAlign property of the canvas context, which can be set to start, end, left, center, or right. The alignment is relative to an imaginary vertical line at the x position of the text defind by fillText() or strokeText().

What is the method to draw filled text on a canvas?

The fillText() method draws filled text on the canvas. The default color of the text is black. Tip: Use the font property to specify font and font size, and use the fillStyle property to render the text in another color/gradient.


1 Answers

Dragging text is largely responding to mouse events.

A Demo: http://jsfiddle.net/m1erickson/9xAGa/

enter image description hereenter image description here

First create text objects to refer to

// some text objects
var texts=[];

// some test texts
texts.push({text:"Hello",x:20,y:20});
texts.push({text:"World",x:20,y:70});

In mousedown

Iterate through each text object and see if the mouse is inside.

// handle mousedown events
// iterate through texts[] and see if the user
// mousedown'ed on one of them
// If yes, set the selectedText to the index of that text
function handleMouseDown(e){
  e.preventDefault();
  startX=parseInt(e.clientX-offsetX);
  startY=parseInt(e.clientY-offsetY);
  // Put your mousedown stuff here
  for(var i=0;i<texts.length;i++){
      if(textHittest(startX,startY,i)){
          selectedText=i;
      }
  }
}

// test if x,y is inside the bounding box of texts[textIndex]
function textHittest(x,y,textIndex){
    var text=texts[textIndex];
    return(x>=text.x && 
        x<=text.x+text.width &&
        y>=text.y-text.height && 
        y<=text.y);
}

In mousemove

Change the selected text's x,y by the distance the mouse has been dragged:

    // handle mousemove events
    // calc how far the mouse has been dragged since
    // the last mousemove event and move the selected text
    // by that distance
    function handleMouseMove(e){
      if(selectedText<0){return;}
      e.preventDefault();
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // Put your mousemove stuff here
      var dx=mouseX-startX;
      var dy=mouseY-startY;
      startX=mouseX;
      startY=mouseY;

      var text=texts[selectedText];
      text.x+=dx;
      text.y+=dy;
      draw();
    }

In mouseup

The drag is over:

// done dragging
function handleMouseUp(e){
  e.preventDefault();
  selectedText=-1;
}

Annotated Code:

<!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; }
    #canvas{border:1px solid red;}
    #theText{width:10em;}
</style>
<script>
$(function(){

    // canvas related variables
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    // variables used to get mouse position on the canvas
    var $canvas=$("#canvas");
    var canvasOffset=$canvas.offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;
    var scrollX=$canvas.scrollLeft();
    var scrollY=$canvas.scrollTop();

    // variables to save last mouse position
    // used to see how far the user dragged the mouse
    // and then move the text by that distance
    var startX;
    var startY;

    // an array to hold text objects
    var texts=[];

    // this var will hold the index of the hit-selected text
    var selectedText=-1;

    // clear the canvas & redraw all texts
    function draw(){
        ctx.clearRect(0,0,canvas.width,canvas.height);
        for(var i=0;i<texts.length;i++){
            var text=texts[i];
            ctx.fillText(text.text,text.x,text.y);
        }
    }

    // test if x,y is inside the bounding box of texts[textIndex]
    function textHittest(x,y,textIndex){
        var text=texts[textIndex];
        return(x>=text.x && 
            x<=text.x+text.width &&
            y>=text.y-text.height && 
            y<=text.y);
    }

    // handle mousedown events
    // iterate through texts[] and see if the user
    // mousedown'ed on one of them
    // If yes, set the selectedText to the index of that text
    function handleMouseDown(e){
      e.preventDefault();
      startX=parseInt(e.clientX-offsetX);
      startY=parseInt(e.clientY-offsetY);
      // Put your mousedown stuff here
      for(var i=0;i<texts.length;i++){
          if(textHittest(startX,startY,i)){
              selectedText=i;
          }
      }
    }

    // done dragging
    function handleMouseUp(e){
      e.preventDefault();
      selectedText=-1;
    }

    // also done dragging
    function handleMouseOut(e){
      e.preventDefault();
      selectedText=-1;
    }

    // handle mousemove events
    // calc how far the mouse has been dragged since
    // the last mousemove event and move the selected text
    // by that distance
    function handleMouseMove(e){
      if(selectedText<0){return;}
      e.preventDefault();
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // Put your mousemove stuff here
      var dx=mouseX-startX;
      var dy=mouseY-startY;
      startX=mouseX;
      startY=mouseY;

      var text=texts[selectedText];
      text.x+=dx;
      text.y+=dy;
      draw();
    }

    // listen for mouse events
    $("#canvas").mousedown(function(e){handleMouseDown(e);});
    $("#canvas").mousemove(function(e){handleMouseMove(e);});
    $("#canvas").mouseup(function(e){handleMouseUp(e);});
    $("#canvas").mouseout(function(e){handleMouseOut(e);});

    $("#submit").click(function(){

        // calc the y coordinate for this text on the canvas
        var y=texts.length*20+20;

        // get the text from the input element
        var text={text:$("#theText").val(),x:20,y:y};

        // calc the size of this text for hit-testing purposes
        ctx.font="16px verdana";
        text.width=ctx.measureText(text.text).width;
        text.height=16;

        // put this new text in the texts array
        texts.push(text);

        // redraw everything
        draw();

    });


}); // end $(function(){});
</script>
</head>
<body>
    <input id="theText" type="text">
    <button id="submit">Draw text on canvas</button><br>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
like image 181
markE Avatar answered Nov 14 '22 21:11

markE