最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I drag a piece of user generated text around the HTML5 canvas? - Stack Overflow

programmeradmin2浏览0评论

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

    }

}

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

    }

}
Share Improve this question asked Apr 1, 2014 at 12:11 Formula 1Formula 1 1833 gold badges3 silver badges9 bronze badges 2
  • 1 Please add JFiddle or show html – Dean Meehan Commented Apr 1, 2014 at 12:13
  • The example code is annotated in the above. – Formula 1 Commented Apr 1, 2014 at 13:29
Add a comment  | 

4 Answers 4

Reset to default 14

Dragging text is largely responding to mouse events.

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

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>

Create a transparent div over canvas and position it such a way that it cover only area you filled with text. Make this div draggable. On div position change clear canvas and redraw text on canvas based on new position of div.

You should repeat all fillText stuff when mouse is down, also clear the screen before every draw

function drawText() {
    ctx.clearRect(0, 0, 500, 400);
    ctx.fillStyle = "black";
    ctx.strokeStyle = "black";
    ctx.font = "35px Arial";
    ctx.fillText(fname, canvasX, canvasY);
    ctx.stroke();
}

Here's a jsfiddle

Okay so I just want to point out one problem in the following jsfiddle solution by markE

Dragging text is largely responding to mouse events

the problem is that if your page doesn't fit the window and is scrollable if you have scrolled your page and now you are dragging the text, it won't work because the mouse event will return clientY that couldn't calculate the saved coordinates.

Reproduce by giving height as

<canvas id="canvas" width=300 height=3000></canvas>

and drag text after scrolling.

发布评论

评论列表(0)

  1. 暂无评论