Question

In my application, I draw an image to the canvas, then add circles and text for labels. I moved my extra drawing code to the load method of drawImage and have discovered that the same code is called repeatedly when moving the mouse over the canvas. I've tried to selectively comment out different blocks to pinpoint the issue but have not really narrowed it down.

This block is the main code that draws the image. Many of the variables are self explanatory. The different IDs used are for database identification. I've noticed that "callback" gets printed repeatedly when moving the mouse over the canvas.

canvasObject.drawImage({
        layer: true,
        name: 'image',
        source: imageSize.url,
        x: (600-imageSize.width)/2,
        y: 0,
        fromCenter: false,
        data: {
            id : image.id
        },
        load: function() {
            // now draw the labels and stuff on top
            console.log("callback")
            for (var imageLabelIndex in image.image_label_locations) {
                var labelLocation = image.image_label_locations[imageLabelIndex]
                console.log("draw " + imageLabelIndex)

                drawLabelLine(canvasObject, {
                    index : imageLabelIndex,
                    from : {
                        x : labelLocation.location_x,
                        y : labelLocation.location_y
                    },
                    to : {
                        x : labelLocation.label.location_x,
                        y : labelLocation.label.location_y
                    }
                })
                drawSmallLabel(canvasObject, {
                    index : imageLabelIndex,
                    x : labelLocation.location_x,
                    y : labelLocation.location_y,
                    id : labelLocation.id
                })
                drawLargeLabel(canvasObject, {
                    index : imageLabelIndex,
                    x : labelLocation.label.location_x,
                    y : labelLocation.label.location_y,
                    id : labelLocation.label.id
                })
            }
        },
        click: function(layer) {
            console.log("click")

            // check whether the mouse is on an existing object
            var canvasObject = $(layer.canvas)
            var parentOffset = canvasObject.offset();
            var canvasWidth = canvasObject.attr("width")
            var space = 24

            mouseDownPosition = {"x" : layer.eventX, "y" : layer.eventY }

            var labelPosition = { "x" : (mouseDownPosition.x < canvasWidth/2) ? space : canvasWidth-space, "y" : mouseDownPosition.y }
            drawLabelLine(canvasObject, {
                index : countAnswers(),
                from: {
                    x : labelPosition.x,
                    y : labelPosition.y
                },
                to: {
                    x : mouseDownPosition.x,
                    y : mouseDownPosition.y
                }
            })

            drawSmallLabel(canvasObject, {
                index : countAnswers(),
                x : mouseDownPosition.x,
                y : mouseDownPosition.y
            })

            drawLargeLabel(canvasObject, {
                index : countAnswers(),
                x : labelPosition.x,
                y : labelPosition.y
            })

            // also add an answer to the question page
            addLabelAnswer(countAnswers(), mouseDownPosition, labelPosition)
        }
    })
Was it helpful?

Solution

The code runs as you move the mouse because jCanvas is redrawing the canvas on mousemove. This is due to the presence of a draggable layer or a layer with a mousemove callback defined somewhere. Additionally, the load() callback runs whenever the image is drawn or redrawn (not just when it is initially drawn).

The fix is actually quite simple:

Store a boolean property (initially set to false) in the data object of your image layer. Then, in your load() callback, wrap your code in an if statement which checks if the property's value is false then. If so, set its value to true and run the code. If not, then you know the callback has already run, and therefore you don't do anything.

canvasObject.drawImage({
    layer: true,
    name: 'image',
    source: imageSize.url,
    x: (600-imageSize.width)/2,
    y: 0,
    fromCenter: false,
    data: {
        id : image.id,
        loaded: false
    },
    load: function(layer) {
        if (layer.data.loaded === false) {
            layer.data.loaded = true;
            // now draw the labels and stuff on top
            console.log("callback")
            for (var imageLabelIndex in image.image_label_locations) {
                var labelLocation = image.image_label_locations[imageLabelIndex]
                console.log("draw " + imageLabelIndex)

                drawLabelLine(canvasObject, {
                    index : imageLabelIndex,
                    from : {
                        x : labelLocation.location_x,
                        y : labelLocation.location_y
                    },
                    to : {
                        x : labelLocation.label.location_x,
                        y : labelLocation.label.location_y
                    }
                })
                drawSmallLabel(canvasObject, {
                    index : imageLabelIndex,
                    x : labelLocation.location_x,
                    y : labelLocation.location_y,
                    id : labelLocation.id
                })
                drawLargeLabel(canvasObject, {
                    index : imageLabelIndex,
                    x : labelLocation.label.location_x,
                    y : labelLocation.label.location_y,
                    id : labelLocation.label.id
                })
            }
        }
    },
    click: function(layer) {
        console.log("click")

        // check whether the mouse is on an existing object
        var canvasObject = $(layer.canvas)
        var parentOffset = canvasObject.offset();
        var canvasWidth = canvasObject.attr("width")
        var space = 24

        mouseDownPosition = {"x" : layer.eventX, "y" : layer.eventY }

        var labelPosition = { "x" : (mouseDownPosition.x < canvasWidth/2) ? space : canvasWidth-space, "y" : mouseDownPosition.y }
        drawLabelLine(canvasObject, {
            index : countAnswers(),
            from: {
                x : labelPosition.x,
                y : labelPosition.y
            },
            to: {
                x : mouseDownPosition.x,
                y : mouseDownPosition.y
            }
        })

        drawSmallLabel(canvasObject, {
            index : countAnswers(),
            x : mouseDownPosition.x,
            y : mouseDownPosition.y
        })

        drawLargeLabel(canvasObject, {
            index : countAnswers(),
            x : labelPosition.x,
            y : labelPosition.y
        })

        // also add an answer to the question page
        addLabelAnswer(countAnswers(), mouseDownPosition, labelPosition)
    }
})
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top