1
votes

I have a webpage with an HTML5 canvas which I'm using to display a number of images as well as four 'description boxes' on the canvas.

The intention is that users will be able to drag and drop the images to their matching description boxes, however, I'm having a bit of trouble getting the dragging and dropping working.

I've tried several different ways of enabling drag and drop on the images, but none of them seem to work.

The problem I have is that the content of what is to be displayed on the canvas needs to be dynamic, i.e. the administrator will be able to change what images etc are displayed on the canvas by altering the filenames of the images to be used in an XML file, to whichever images he would rather use.

So basically, I want to add code to the JavaScript that is displaying the images on the canvas to enable them to be dragged and dropped around the canvas.

Does anyone have any suggestions of what is the best way to do this?

My HTML page looks like this:

<!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>
<script src = "dragAndDrop1.js" type = "text/javascript"></script>
<script src = "dragAndDrop2.js" type = "text/javascript"></script>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.0.5.js"></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 = "variables&preloadingImages.js" type = "text/javascript"></script>
</body>

I've tried adding the drag and drop functionality in the three different ways- hence the three drag and drop JS files that I've included, but none of these seem to work.

The JavaScript that I'm using to draw the images to the canvas is simply a number of arrays, with each element holding a single image. There is an array for each category of image that I'm drawing to the canvas, and the number of images in each category is variable.

I've then used the JS concat method to concatenate the arrays, putting all of the images in a single array called allImagesArray.

I have the following function, which draws each image from allImagesArray in a random location on the canvas:

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

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

            }

        }

This function also draws four 'description areas' on the canvas, labelled 'Asset', 'Liability', 'Income' and 'Expenditure'.

What the user is required to do, is drag each image to its corresponding 'description area'. When an image is dragged to the correct description area, it should then disappear from the canvas.

But although I have the images and description areas drawn to the canvas, I can't seem to work out how to add drag & drop functionality to the images.

I've had a look at several examples online, but can't seem to get any of them working- I'm wondering if it's because I'm drawing the images from an array using a while loop? I've also looked at other questions asked on this site, but can't seem to find the answer in any of those.

I've looked at the tutorials at http://www.html5canvastutorials.com/kineticjs/html5-canvas-drag-and-drop-an-image-tutorial/ and http://www.html5canvastutorials.com/labs/html5-canvas-drag-and-drop-multiple-images-with-kineticjs/ but can't seem to make these examples work with my code. Does anyone have any ideas of how I can add drag and drop functionality to each of the images drawn to the canvas using my drawLevelOneElements() function?

1
Or you can use kineticJS -> kineticjs.comMyBoon
Yeah, I've tried using that, but couldn't seem to get it working. I'm not sure if that's just because I wasn't using it correctly though- to use it would I just add a <script src... > to it? Or is there something else I need to do?Noble-Surfer
Kinetic allows drag/drop pretty simply. You just add draggable:true to the properties object passed into the constructor.Shmiddty
I'm not sure I understand how to do this- do you have a JSfiddle or something that you could show me an example of? When you say just add draggable:true to the properties object passed into the constructor... Is the constructor my drawImage method?Noble-Surfer
Take a look at Fabric.js and one of the demos that show how to add objects to canvas (drag drop is already built-in) For example, fabricjs.com/per-pixel-drag-dropkangax

1 Answers

0
votes

cgSceneGraph will easily help you in that case. You can have a look at the example page (source code is included with the demos): http://gwennaelbuchet.github.com/cgSceneGraph/examples.html

I'm the designer of this framework, so I can easily help you to include it into your project :)

To make an object draggable, just like this :

this.img = new CGSGNodeImage(x, y, sourceURL);
this.img.isDraggable = true;
this.img.isCollisionManaged = true;

Then, to know if your image is inside the description area, you can use the collision detection of cgSceneGraph like this:

//detect collision each frame
var bindCheckCollision = this.checkCollision.bind(this);
this.onRenderEnd = function () {
    bindCheckCollision();
};

and the checkCOllision method:

checkCollision: function () {
    var isColliding = this.img.isColliding(this.descriptionNode, 0);
}

No more to do :)

A complete example is on the website. Hope this can help you.

Gwen.