【问题标题】:How to drag images / objects within Canvas?如何在 Canvas 中拖动图像/对象?
【发布时间】:2013-08-21 02:18:50
【问题描述】:

1) 在 Canvas 上,我正在使用 drawSvg (canvg) 绘制 SVG 文件 (awesome_tiger.svg)。

2) 在该 SVG 文件上,我正在绘制图像*(green1.png 和 pink.png)*,其坐标来自 JSON。

var dataJSON = data || [];
var dataJSON2 = data2 || [];

3) 所以我可以平移我正在用 draw1(scaleValue) 绘制的完整绘图。

4) 当我点击 green.png 和 pink.png 时,它们各自的工具提示可以查看在 tooltipFunc 函数中完成的操作。

5) 我想要做的是,当点击 green.png / pink.png 并拖动它时,我应该只能拖动那些图像而不是 Svg 文件。如果我点击 svg 文件并拖动它,那么正常的平移应该可以正常工作。

有人可以帮忙吗?

“我的问题的其他参考:” 下面提到的这个主题的内容,我在 stackoverflow 链接上得到了这个。有了这个帮助,任何人都可以帮助我解决我的项目需求问题吗?

以下是我的源代码:

JSON 数据:

data = [  
        {   "id" :["first"],        
            "x": ["195"],
            "y": ["150"],
            "tooltiptxt": ["Region 1"]

        },  
        {
            "id" :["second"],
            "x": ["255"],
            "y": ["180"],
            "tooltiptxt": ["Region 2"]      
        },
        {
            "id" :["third"],
            "x": ["200"],
            "y": ["240"],
            "tooltiptxt": ["Region 3"]      
        }       

    ];

data2 = [  
        {   "id" :["first2"],       
            "x": ["225"],
            "y": ["150"],
            "tooltiptxt": ["Region 21"]

        },  
        {
            "id" :["second2"],
            "x": ["275"],
            "y": ["180"],
            "tooltiptxt": ["Region 22"]     
        },
        {
            "id" :["third3"],
            "x": ["300"],
            "y": ["240"],
            "tooltiptxt": ["Region 23"]     
        }       

    ];


Javascript Code:        

var dataJSON = data || [];
var dataJSON2 = data2 || [];
window.onload = function(){ 
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext('2d');      
    var tooltip = null,
            timer;

    //svg file and png files are collected in files.
    var files = ["/static/images/awesome_tiger.svg", "/static/images/green1.png", "/static/images/pink.png"],
    images = [],
    numOfFiles = files.length,
    count = numOfFiles;

    /// function to load all images in one go
    function loadImages() {
        /// go through array of file names
        for(var i = 0; i < numOfFiles; i++) {
            /// create an image element
            var img = document.createElement('img');
            /// use common loader as we need to count files
            img.onload = imageLoaded;

            //img.onerror = ... handle errors
            img.src = files[i];                 
            /// push image onto array in the same order as file names
            images.push(img);

        }
    }
    loadImages();
    function imageLoaded(e) {
        /// for each successful load we count down
        count--;            
        if (count === 1)            
        start(); //start when nothing more to count
    }
    function start() {      
        context.drawSvg(files[0], 0, 0, 400*scaleValue, 400*scaleValue);    

       for(var i = 0, pos; pos = dataJSON[i]; i++) {         
           /// as we know the alpha ball has index 1 we use that here for images
           context.drawImage(images[1], pos.x, pos.y, 20/scaleValue, 20/scaleValue);
       }
        for(var i = 0, pos; pos = dataJSON2[i]; i++) {             
           context.drawImage(images[2], pos.x, pos.y, 20/scaleValue, 20/scaleValue);
       }
    }
    //Drawing the svg file with drawSvg and images with drawImage(dataJSON and dataJSON2 are JSON through with will get the x an y co-ordinates for those images to draw)

    function draw1(scaleValue){             
        context.save();     
        context.setTransform(1,0,0,1,0,0)   
        context.globalAlpha = 0.5;                      
        context.clearRect(0, 0, canvas.width, canvas.height);   
        context.restore();          
        context.save(); 
        context.drawSvg(files[0], 0, 0, 400*scaleValue, 400*scaleValue)
        context.scale(scaleValue, scaleValue);
        for(var i = 0, pos; pos = dataJSON[i]; i++) {
               /// as we know the alpha ball has index 1 we use that here for images
               context.drawImage(images[1], pos.x, pos.y, 20/scaleValue, 20/scaleValue);
           }    
        for(var i = 0, pos; pos = dataJSON2[i]; i++) {
               /// as we know the alpha ball has index 1 we use that here for images
               context.drawImage(images[2], pos.x, pos.y, 20/scaleValue, 20/scaleValue);
           }
        context.restore();
    }; 

//Code for Zoom In and Zoom Out
    var scaleValue = 1;
    var scaleMultiplier = 0.8;
    draw1(scaleValue);
    var startDragOffset = {};
    var mouseDown = false;          
    // add button event listeners
    document.getElementById("plus").addEventListener("click", function(){           
        scaleValue /= scaleMultiplier;                          
        draw1(scaleValue);              
    }, false);
     document.getElementById("minus").addEventListener("click", function(){
        scaleValue *= scaleMultiplier;              
        draw1(scaleValue);      
    }, false);
    document.getElementById("original_size").addEventListener("click", function(){
        scaleValue = 1;                 
        draw1(scaleValue);  
    }, false);

    //Code for panning on canvas

    var isDown = false;
    var startCoords = [];
    var transX, transY;
    var last = [0, 0];

    canvas.onmousedown = function(e){
        clearTooltip();
        isDown = true;          
        startCoords = [
            e.offsetX - last[0],
            e.offsetY - last[1]
       ];
    };

    canvas.onmouseup  = function(e){        
        isDown = false;         
        last = [
            e.offsetX - startCoords[0], // set last coordinates
            e.offsetY - startCoords[1]
        ];
    };

    canvas.onmousemove = function(e){   
            var x = e.offsetX;              
            var y = e.offsetY;

            transX = parseInt(parseInt(x) - parseInt(startCoords[0]));
            transY = parseInt(parseInt(y) - parseInt(startCoords[1]));

            if(!isDown) return; 
            context.setTransform(1, 0, 0, 1, transX, transY);                                   
            draw1(scaleValue);  
    }


    canvas.addEventListener('click', function(e) {          
        var x = e.offsetX;              
        var y = e.offsetY;

        transX = parseInt(parseInt(x) - parseInt(startCoords[0]));
        transY = parseInt(parseInt(y) - parseInt(startCoords[1]));

        tooltipFunc(e, transX, transY); 

    }, false);


    //tooptip function
    function tooltipFunc(e, transX, transY){
        //document.body.style.cursor = 'default';
        var translationX, translationY;
        var r = canvas.getBoundingClientRect(),
                    x = e.clientX - r.left,
                    y = e.clientY - r.top,
                    i = 0,
                    r,
                    inTooltip = false;

        if((typeof startCoords[0] == 'undefined' || startCoords[0] === 'NaN') && (typeof startCoords[1] === 'undefined' || startCoords[1] === 'NaN')){  
            console.log('if');
                for (; r = dataJSON[i]; i++) {              
                    if (x >= parseInt(dataJSON[i].x[0] * scaleValue) + parseInt(scaleValue) && x <= parseInt(dataJSON[i].x[0] * scaleValue) + parseInt(20/scaleValue) && y >= parseInt(dataJSON[i].y[0] * scaleValue) && y <= parseInt(dataJSON[i].y[0] * scaleValue) + parseInt(20/scaleValue)) {
                        //clearTooltip();
                        showTooltip(e.clientX, e.clientY, i);
                        inTooltip = true;
                    }
                }
        }
        else {
            console.log('else');                                    
        for (var i = 0; r = dataJSON[i]; i++) { 
                    console.log('else for');                    
                    if(x >= parseInt(parseInt(dataJSON[i].x[0] * scaleValue) + parseInt(scaleValue) + parseInt(transX)) && x <= parseInt(parseInt(dataJSON[i].x[0] * scaleValue) + parseInt(scaleValue) + parseInt(transX) + parseInt(20)) && y >= parseInt(parseInt(dataJSON[i].y[0] * scaleValue) + parseInt(scaleValue) + parseInt(transY)) && y <= parseInt(parseInt(dataJSON[i].y[0] * scaleValue) + parseInt(scaleValue) + parseInt(transY) + parseInt(20))) {                        
                        clearTooltip();                                             
                        showTooltip(e.clientX, e.clientY, i);
                        inTooltip = true;
                    }
            }
            for (var i = 0; r = dataJSON2[i]; i++) {    
                    console.log('else for');                    
                    if(x >= parseInt(parseInt(dataJSON2[i].x[0] * scaleValue) + parseInt(scaleValue) + parseInt(transX)) && x <= parseInt(parseInt(dataJSON2[i].x[0] * scaleValue) + parseInt(scaleValue) + parseInt(transX) + parseInt(20)) && y >= parseInt(parseInt(dataJSON2[i].y[0] * scaleValue) + parseInt(scaleValue) + parseInt(transY)) && y <= parseInt(parseInt(dataJSON2[i].y[0] * scaleValue) + parseInt(scaleValue) + parseInt(transY) + parseInt(20))) {                        
                        clearTooltip();                         
                        showTooltip2(e.clientX, e.clientY, i);
                        inTooltip = true;
                    }
            }
        }
    }


}           

我的问题的其他参考:

<html>
<head>
<title>Test Page</title>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>

<canvas id="c" width = "500" height = "500" ></canvas>    

<script type="text/javascript">
var canvas = $("#c");
var c = canvas[0].getContext("2d");

//var path = "http://wonderfl.net/images/icon/e/ec/ec3c/ec3c37ba9594a7b47f1126b2561efd35df2251bfm";
var path = "blue.jpg";
var path2 = "purple.jpg";
var image1 = new DragImage(path, 200, 100);
var image2 = new DragImage(path2, 300, 100);

var loop = setInterval(function() {

    c.fillStyle = "gray";
    c.fillRect(0, 0, 500, 500);

    image1.update();
    image2.update();
}, 30);

var mouseX = 0,
    mouseY = 0;
var mousePressed = false;
var dragging = false;
canvas.mousemove(function(e) {
    mouseX = e.offsetX;
    mouseY = e.offsetY;
})

$(document).mousedown(function() {
    mousePressed = true;
}).mouseup(function() {
    mousePressed = false;
    dragging = false;
});

function DragImage(src, x, y) {
    var that = this;
    var startX = 0,
        startY = 0;
    var drag = false;

    this.x = x;
    this.y = y;
    var img = new Image();
    img.src = src;
    this.update = function() {
        if (mousePressed ) {

                var left = that.x;
                var right = that.x + img.width;
                var top = that.y;
                var bottom = that.y + img.height;
                if (!drag) {
                    startX = mouseX - that.x;
                    startY = mouseY - that.y;
                }
                if (mouseX < right && mouseX > left && mouseY < bottom && mouseY > top) {
                    if (!dragging){
            dragging = true;
                        drag = true;
                    }

                }

        } else {

            drag = false;
        }
        if (drag) {
            that.x = mouseX - startX;
            that.y = mouseY - startY;
        }
        c.drawImage(img, that.x, that.y);
    }
}
</script>
</body>
</html>

【问题讨论】:

    标签: javascript jquery canvas 3d 2d


    【解决方案1】:

    希望我能理解你的问题...!

    以下是平移画布和在画布上拖动对象的方法

    这说明了任何拖动或平移之前的画布:

    请注意绿色矩形在老虎的左眼上方。

    这说明了绿色矩形被拖到右眼后的画布:

    这说明了平移后的画布。

    tiger 和所有 rects 将同时平移。

    大部分重要的代码都在 mousedown 和 mousemove 事件处理程序中

    鼠标按下时:

    • 如果鼠标位于 1+ 个彩色图像上,则拖动图像。
    • 如果鼠标不在任何彩色图像上,则平移画布。

    这是鼠标按下的代码:

    function handleMouseDown(e){
    
      // get mouse coordinates
    
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
    
      // set the starting drag position 
      // this is needed in mousemove to determine how far we have dragged
      lastX=mouseX;
      lastY=mouseY;
    
      // test if we're over any of the images
      // if yes, put those image(s) in an array called dragging
      dragging=imagesHitTests(mouseX,mouseY);
    
      // set the dragging flag
      isDown=true;
    
    }
    

    鼠标移动时:

    • 确定我们是在拖动还是平移。
    • 如果 dragging[] 数组不为空,我们正在拖动。
    • 如果 dragging[] 数组为空,我们正在平移。
    • 拖动时,将每个拖动图像的 XY 更改为我们拖动的量。
    • 平移时,将老虎的位置更改为我们拖动的量。

    鼠标移动代码如下:

    function handleMouseMove(e){
    
      // if we're not dragging, exit
      if(!isDown){return;}
    
      //get mouse coordinates
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
    
      // calc how much the mouse has moved since we were last here
      var dx=mouseX-lastX;
      var dy=mouseY-lastY;
    
      // set the lastXY for next time we're here
      lastX=mouseX;
      lastY=mouseY;
    
      // handle drags/pans
      if(dragging.length>0){
          // we're dragging images
          // move all affected images by how much the mouse has moved
          for(var i=0;i<dragging.length;i++){
              img=images[dragging[i]];
              img.x+=dx;
              img.y+=dy;
          }
      }else{
          // we're panning the tiger
          // set the panXY by how much the mouse has moved
          panX+=dx;
          panY+=dy;
      }
      draw();
    }
    

    这里是确定哪些彩色图像在鼠标下方的代码 - 并将被拖动。

    鼠标下的任何彩色图像都会添加到一个名为“拖动”的数组中。

    此 dragging[] 数组用于 mousemove 以拖动适当的彩色图像。

      // create an array of any "hit" colored-images
      function imagesHitTests(x,y){
          // adjust for panning
          x-=panX;
          y-=panY;
          // create var to hold any hits
          var hits=[];
          // hit-test each image
          // add hits to hits[]
          for(var i=0;i<images.length;i++){
              var img=images[i];
              if(x>img.x && x<img.x+img.width && y>img.y && y<img.y+img.height){
                  hits.push(i);
              }
          }
          return(hits);
      }
    

    这是完整的代码和小提琴:http://jsfiddle.net/m1erickson/pbRq2/

    <!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.strokeStyle="red";
        ctx.lineWidth=5;
    
        var canvasOffset=$("#canvas").offset();
        var offsetX=canvasOffset.left;
        var offsetY=canvasOffset.top;
    
        var lastX=0;
        var lastY=0;
        var panX=0;
        var panY=0;
        var dragging=[];
        var isDown=false;
    
    
        // create green & pink "images" (we just use rects instead of images)
        var images=[];
        images.push({x:200,y:150,width:25,height:25,color:"green"});
        images.push({x:80,y:235,width:25,height:25,color:"pink"});
    
        // load the tiger image
        var tiger=new Image();
        tiger.onload=function(){
            draw();
        }
        tiger.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tiger.png";
    
    
        function draw(){
    
            ctx.clearRect(0,0,canvas.width,canvas.height);
    
            // draw tiger
            ctx.globalAlpha=0.25;
            ctx.drawImage(tiger,panX,panY,tiger.width,tiger.height);
    
            // draw color images
            ctx.globalAlpha=1.00;
            for(var i=0;i<images.length;i++){
                var img=images[i];
                ctx.beginPath();
                ctx.rect(img.x+panX,img.y+panY,img.width,img.height);
                ctx.fillStyle=img.color;
                ctx.fill();
                ctx.stroke();
            }
        }
    
        // create an array of any "hit" colored-images
        function imagesHitTests(x,y){
            // adjust for panning
            x-=panX;
            y-=panY;
            // create var to hold any hits
            var hits=[];
            // hit-test each image
            // add hits to hits[]
            for(var i=0;i<images.length;i++){
                var img=images[i];
                if(x>img.x && x<img.x+img.width && y>img.y && y<img.y+img.height){
                    hits.push(i);
                }
            }
            return(hits);
        }
    
    
        function handleMouseDown(e){
    
          // get mouse coordinates
          mouseX=parseInt(e.clientX-offsetX);
          mouseY=parseInt(e.clientY-offsetY);
          // set the starting drag position
          lastX=mouseX;
          lastY=mouseY;
          // test if we're over any of the images
          dragging=imagesHitTests(mouseX,mouseY);
          // set the dragging flag
          isDown=true;
        }
    
        function handleMouseUp(e){
          // clear the dragging flag
          isDown=false;
        }
    
    
        function handleMouseMove(e){
    
          // if we're not dragging, exit
          if(!isDown){return;}
    
          //get mouse coordinates
          mouseX=parseInt(e.clientX-offsetX);
          mouseY=parseInt(e.clientY-offsetY);
    
          // calc how much the mouse has moved since we were last here
          var dx=mouseX-lastX;
          var dy=mouseY-lastY;
    
          // set the lastXY for next time we're here
          lastX=mouseX;
          lastY=mouseY;
    
          // handle drags/pans
          if(dragging.length>0){
              // we're dragging images
              // move all affected images by how much the mouse has moved
              for(var i=0;i<dragging.length;i++){
                  img=images[dragging[i]];
                  img.x+=dx;
                  img.y+=dy;
              }
          }else{
              // we're panning the tiger
              // set the panXY by how much the mouse has moved
              panX+=dx;
              panY+=dy;
          }
          draw();
        }
    
        // use jQuery to handle mouse events
        $("#canvas").mousedown(function(e){handleMouseDown(e);});
        $("#canvas").mousemove(function(e){handleMouseMove(e);});
        $("#canvas").mouseup(function(e){handleMouseUp(e);});
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <canvas id="canvas" width=300 height=300></canvas>
    </body>
    </html>
    

    【讨论】:

    • 非常感谢您的回答。让我在我的代码中实现这一点。非常感谢。
    • 在我的代码中实现了上述内容。现在它正在工作。谢谢
    猜你喜欢
    • 2023-03-03
    • 2014-03-16
    • 2012-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 2014-03-18
    • 2014-09-15
    相关资源
    最近更新 更多