html5画布添加拖放到绘制到画布的图像

时间:2012-12-03 13:31:50

标签: javascript drag-and-drop html5-canvas

我有一个带有HTML5画布的网页,我用它来在画布上显示多个图像以及四个“描述框”。

目的是用户可以将图像拖放到匹配的描述框中,但是,我在拖放工作时遇到了一些麻烦。

我编写的用于添加拖放功能的函数基于我在此页面上找到的教程:http://simonsarris.com/blog/510-making-html5-canvas-useful

显然,我稍微修改了代码,因为我不想做教程中建议的所有内容,因为我正在向画布绘制图像(而不是形状)。但是,虽然所有图像都显示在画布上,但在浏览器中查看我的页面时,拖放功能还没有与我根据该教程编写的新JavaScript文件一起添加。

我没有在Firebug控制台中收到任何错误,并且页面的显示与添加新JS函数之前完全一样。

有人能发现我失踪的东西吗?

我的HTML是:

<!DOCTYPE html>
<html>
<head>
<script src = "kinetic.js" type = "text/javascript"></script>
<title>Home</title>

<script src = "drawLevelOneElements.js" type = "text/javascript"></script>
<script src = "layers&analytics.js" type = "text/javascript"></script>
<script src = "startGameDrawGameElementsDrawStartButton.js" type = "text/javascript"></script>
<script src = "interaction.js" type = "text/javascript"></script>
<script src = "dragAndDrop.js" type = "text/javascript"></script>


</head>

<body onLoad="startGame()">

<section hidden>
<img id="StartButton" src="StartButton.png" alt="Start Button" width="179" height="180" href="javascript:drawLevelOneElements();"/>
</section>

    <h1>Home</h1>
    <p>The purpose of this website is to teach users the basic principles of running a business by playing the game below. <br /><br /></p>

    <canvas id="gameCanvas" width="1000" height="500" style="border:1px solid">
    Your browser does not support the canvas element.
    </canvas>

    <br /><br />
    <p>Use this paragraph to enter text that provides the user with instructions for how to play the game. <br />
        Update the instructions so that they're appropriate to whatever level the user is currently playing.</p>

<script src = "layers&analytics.js" type = "text/javascript"></script>
<script src = "startGameDrawGameElementsDrawStartButton.js" type = "text/javascript"></script>
<script src = "variables&preloadingImages.js" type = "text/javascript"></script>
<script src = "drawLevelOneElements.js" type = "text/javascript"></script>
<script src = "interaction.js" type = "text/javascript"></script>-->
    <script src = "variables&preloadingImages.js" type = "text/javascript"></script>
</body>

页面底部的所有脚本标签(最后一个除外)实际上已在我的文件中注释掉了,我只需删除注释即可在此处的代码块中显示它。

我为拖放功能添加的javaScript是:

function canvasState(myGameCanvas){

var bounding_box = myGameCanvas.getBoundingClientRect();
var mouseX = (mouse_event.clientX-bounding_box.left) * (myGameCanvas.width/bouding_box.width);
var mouseY = (mouse_event.clientY-bounding_box.top) * (myGameCanvas.height/bounding_box.height);
var pixels = context.getImageData(mouseX, mouseY, 1, 1);

this.valid = false; /*When set to true, the canvas will redraw everything */
this.allImagesArray; /*This is the array holding all of the images to be drawn */
this.dragging = false; /*Keep track of when the current selected object is being dragged */
this.selection = null;
this.dragOffX = 0; /*See mousedown and mousemove events for explanation */
this.dragOffY = 0;

this.interval = 30; /*This variable will be used to determine how often the draw method is called. */

/*Save a reference to the canvasState so that I'm still using this particular canvasState. */
var myState = this;

/*This stops double clicking on the canvas selecting text on the canvas */
myGameCanvas.addEventListener('selectstart', function(e) {e.preventDefault(); return false; }, false);
/*Up, down and move are for dragging */
myGameCanvas.addEventListener('mousedown', function(e){
    var mouse = myState.getMouse(e);
    var mX = mouse.x;
    var mY = mouse.y;
    var allImages = myState.allImagesArray;
    var NoOfImages = allImages.length;
    for (var i = 1-1; i >= 0; i--){
        if(allImages[i].contains(mX, mY)){
            var mySelection = allImages[i];
            /*Keep track of where in the object was clicked, so that it can be 
                moved smoothly (see mousemove) */
            myState.dragOffX = mX - mySelection.x;
            myState.dragOffY = mY - mySelection.y;
            myState.dragging = true;
            myState.selection = mySelection;
            myState.valid = false;
            return;
        }
    }
    /*If the code hasn't returned, it means that nothing has been selected.
    If there was an object selected, then deselect it. */
    if (myState.selection){
        myState.selection = null;
        myState.valid = false; /*Need to clear the old selection border */

    }
}, true);

/*This event checks to see if the dragging flag has been set to true. If it has, it gets the
current mouse position and moves the selected object to that position, remembering the offset
where it was selected. If the dragging flag is false, the event does nothing. */
myGameCanvas.addEventListener('mousemove', function(e){
    if(myState.dragging){
        var mouse = myState.getMouse(e);
        /*I don't want to drag the object by its top left corner, I want to drag from where the
        object was clicked. That's why I saved the offset and use it here. */
        myState.selection.x = mouse.x - myState.dragOffX;
        myState.selection.y = mouse.y - myState.dragOffY;
        myState.valid = false; /*Something's dragging, so I must redraw */
    }
}, true);

/*All the mouseup event has to do is update the canvas state so that it is no longer dragging.
So, once the mouse button is lifted, the mousemove event should be back to doing nothing. */
myGameCanvas.addEventListener('mouseup', function(e){
    myState.dragging = false;
}, true);

setInterval(function(){ myState.draw(); }, myState.interval);

canvasState.prototype.draw = function(){
    /*If the state is invalid,redraw and validate. */
    if (!this.valid){
        var context = this.context;
        var images = this.images;
        this.clear();

        /*Redraw the game elements here */
        drawLevelOneElements();
    }
}


}

dragAndDrop.js代码:

function canvasState(myGameCanvas){

var bounding_box = myGameCanvas.getBoundingClientRect();
var mouseX = (mouse_event.clientX-bounding_box.left) * (myGameCanvas.width/bouding_box.width);
var mouseY = (mouse_event.clientY-bounding_box.top) * (myGameCanvas.height/bounding_box.height);
var pixels = context.getImageData(mouseX, mouseY, 1, 1);

this.valid = false; /*When set to true, the canvas will redraw everything */
this.allImagesArray; /*This is the array holding all of the images to be drawn */
this.dragging = false; /*Keep track of when the current selected object is being dragged */
this.selection = null;
this.dragOffX = 0; /*See mousedown and mousemove events for explanation */
this.dragOffY = 0;

this.interval = 30; /*This variable will be used to determine how often the draw method is called. */

/*Save a reference to the canvasState so that I'm still using this particular canvasState. */
var myState = this;

/*This stops double clicking on the canvas selecting text on the canvas */
myGameCanvas.addEventListener('selectstart', function(e) {e.preventDefault(); return false; }, false);
console.log("Event Listener 'selectstart' added to canvas.");
/*Up, down and move are for dragging */
myGameCanvas.addEventListener('mousedown', function(e){
    console.log("Event Listener 'mousedown' added to canvas");
    var mouse = myState.getMouse(e);
    var mX = mouse.x;
    var mY = mouse.y;
    var allImages = myState.allImagesArray;
    var NoOfImages = allImages.length;
    for (var i = 1-1; i >= 0; i--){
        if(allImages[i].contains(mX, mY)){
            var mySelection = allImages[i];
            /*Keep track of where in the object was clicked, so that it can be 
                moved smoothly (see mousemove) */
            myState.dragOffX = mX - mySelection.x;
            myState.dragOffY = mY - mySelection.y;
            myState.dragging = true;
            myState.selection = mySelection;
            myState.valid = false;
            return;
        }
    }
    /*If the code hasn't returned, it means that nothing has been selected.
    If there was an object selected, then deselect it. */
    if (myState.selection){
        myState.selection = null;
        myState.valid = false; /*Need to clear the old selection border */

    }
}, true);

/*This event checks to see if the dragging flag has been set to true. If it has, it gets the
current mouse position and moves the selected object to that position, remembering the offset
where it was selected. If the dragging flag is false, the event does nothing. */
myGameCanvas.addEventListener('mousemove', function(e){
    console.log("Event listener 'mousemove' added to canvas.");
    if(myState.dragging){
        var mouse = myState.getMouse(e);
        /*I don't want to drag the object by its top left corner, I want to drag from where the
        object was clicked. That's why I saved the offset and use it here. */
        myState.selection.x = mouse.x - myState.dragOffX;
        myState.selection.y = mouse.y - myState.dragOffY;
        myState.valid = false; /*Something's dragging, so I must redraw */
    }
}, true);

/*All the mouseup event has to do is update the canvas state so that it is no longer dragging.
So, once the mouse button is lifted, the mousemove event should be back to doing nothing. */
myGameCanvas.addEventListener('mouseup', function(e){
    console.log("Event listener 'mouseup' added to canvas.");
    myState.dragging = false;
}, true);

setInterval(function(){ myState.draw(); }, myState.interval);

canvasState.prototype.draw = function(){
    /*If the state is invalid,redraw and validate. */
    if (!this.valid){
        var context = this.context;
        var images = this.images;
        this.clear();

        /*Redraw the game elements here */
        drawLevelOneElements();
    }
}


}

drawLevelOneElements.js的代码:(现在包括对canvasState()的调用;)

function drawLevelOneElements(){
            /*First, clear the canvas */ 
            context.clearRect(0, 0, myGameCanvas.width, myGameCanvas.height);
            /*This line clears all of the elements that were previously drawn on the canvas. */
            /*Then redraw the game elements */
            drawGameElements(); 
            /*Call the function to enable drag and drop */
            canvasState(document.getElementById('gameCanvas'));

            /*Create the four description areas, and place them near the bottom of the canvas */
            /*Create boxes with rounded corners for the description areas */
            CanvasRenderingContext2D.prototype.drawDescriptionArea = function(x, y, width, height, radius, stroke){
                if(typeof stroke == "undefined" ){
                    stroke = true;
                }
                if(typeof radius === "undefined"){
                    radius = 5;
                }
                this.beginPath();
                this.moveTo(x + radius, y);
                this.lineTo(x + width - radius, y);
                this.quadraticCurveTo(x + width, y, x + width, y + radius);
                this.lineTo(x + width, y + height - radius);
                this.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
                this.lineTo(x + radius, y + height);
                this.quadraticCurveTo(x, y + height, x, y + height - radius);
                this.lineTo(x, y + radius);
                this.quadraticCurveTo(x, y, x + radius, y);
                this.closePath();
                if(stroke){
                    context.stroke();
                }
            }

            context.drawDescriptionArea(70, 400, 120, 70);
            context.font = '25pt Calibri';
            context.strokeText('Asset', 90, 440);

            context.drawDescriptionArea(300, 400, 120, 70);
            context.strokeText('Liability', 310, 440);

            context.drawDescriptionArea(540, 400, 120, 70);
            context.strokeText('Income', 550, 440);

            context.drawDescriptionArea(750, 400, 180, 70);
            context.strokeText('Expenditure', 760, 440);

            /*Now draw the images to the canvas */
            /*First, create variables for the x & y coordinates of the image that will be drawn.
                the x & y coordinates should hold random numbers, so that the images will be 
                drawn in random locations on the canvas.*/
                var imageX = Math.floor(Math.random()*100);
                var imageY = Math.floor(Math.random()*100);

                /*Create a 'table' of positions that the images will be drawn to */
                var imagePositionsX = [20, 80, 140, 200, 260, 320, 380, 440, 500, 560];
                var imagePositionsY = [20, 60, 100, 140, 180, 220, 260, 300, 340, 380];

            /*Draw all images from assetsImageArray */
            /*Use a while loop to loop through the array, get each item and draw it. */
            var arrayIteration = 0;
            console.log('All Images Array length: ' + allImagesArray.length); /*Display the length of the array in the console, to check it's holding the correct number of images. */
            while(arrayIteration < allImagesArray.length){
                var randomPositionX = Math.floor(Math.random()*10);
                var randomPositionY = Math.floor(Math.random()*10);
                context.drawImage(allImagesArray[arrayIteration], imageX, imageY, 50, 50);
                console.log(arrayIteration); /*Display the current array position that's being drawn */
                arrayIteration = arrayIteration+1;
                /*Now try changing the values of imageX & imageY so that the next image is drawn to a 
                    different location*/
                imageX = imagePositionsX[randomPositionX];  /* imageX+(Math.floor(Math.random()*100)); */
                imageY = imagePositionsY[randomPositionY];  /* imageY+(Math.floor(Math.random()*100));  */

            }

        }

1 个答案:

答案 0 :(得分:0)

在评论结束时,我可以回答你:在代码中的某个地方,你必须调用canvasState()函数,仅仅定义它是不够的。您必须在何处调用它主要取决于您何时需要它的功能。例如,如果要在页面加载时设置拖放功能,则会为主体的加载事件设置事件处理程序:

<body onLoad="startGame()">

在startGame()函数的代码中,您可以调用canvasState()。如果在按下StartButton时需要它,则应该从drawLevelOneElements()函数中调用它。由于您正在学习教程,因此事情发生的顺序可能很重要,因此可能存在需要调用函数的特定位置。

还有一条建议。因为你似乎在学习,从基础知识入手,深入了解你到目前为止所学到的知识,不要只是按照随机的教程。