html5 canvas kineticjs event

2019-05-11 03:07发布

问题:

I seem to be having an issue with getting events using KineticJS to fire on a Kinetic.Line with a stroke of 1 or less. I thought adding all the lines to a group, and then attaching the event to a group would suffice, but it did not work.

I have simplified the code from what I'm trying to accomplish to shorten the post:

var gridOffsetX = 45, gridHeight = 200, gridWidth = 760, rowHeight = gridHeight / 4;
var stage, baseLayer = new Kinetic.Layer();

// debug message
var debugText = new Kinetic.Text({
    fontStyle: 'bold', fontSize: 12, fill: 'red',
    x: 45, y: gridHeight + 10, text: 'mouseup'
});

window.onload = function () {

    stage = new Kinetic.Stage({
        container: 'canvas',
        width: 800, height: 200 + 22
    });

    var index = 0.5;
    var yPosition = (gridHeight / 4 * index);

    // create the base object
    var text = new Kinetic.Text({
        fontStyle: "bold", fontSize: 10, fill: "black",
        x: 0, y: yPosition, text: "Row A", align: "right"
    });

    // center the text
    text.offsetY(text.height() / 2);
    baseLayer.add(text);
    baseLayer.add(addStatusText(text, ++index, "Row B"));
    baseLayer.add(addStatusText(text, ++index, "Row C"));
    baseLayer.add(addStatusText(text, ++index, "Row D"));

    var gridGroup = new Kinetic.Group();

    drawGrid(gridGroup);
    wireGridEvents(gridGroup);

    baseLayer.add(gridGroup);
    baseLayer.add(debugText);
    stage.add(baseLayer);
};

function addStatusText(control, index, text) {
    var yPosition = (gridHeight / 4 * index);

    control = control.clone({ text: text, y: yPosition });
    control.offsetY(control.height() / 2);

    return control;
}

function drawGrid(gridGroup) {

    var rect = new Kinetic.Rect({
        x: gridOffsetX, y: 0,
        width: gridWidth, height: gridHeight,
        stroke: "black", strokeWidth: 1
    });

    gridGroup.add(rect);

    var t1, t2, index1;

    for (index1 = 1; index1 <= 3; index1++) {
        t2 = (gridHeight / 4 * index1);
        gridGroup.add(drawGridLine(gridOffsetX, t2, gridOffsetX + gridWidth, t2));
    }

    for (index1 = 1; index1 < 48; index1++) {
        t1 = gridOffsetX + (gridWidth / 48) * index1;
        gridGroup.add(drawGridLine(t1, 0, t1, gridHeight));
    }
}

function drawGridLine(startX, startY, endX, endY) {
    return new Kinetic.Line({
        points: [startX, startY, endX, endY],
        stroke: 'black', strokeWidth: 0.5
    });
}

function wireGridEvents(group) {
    group.on('mousedown', function () { writeMessage('mousedown'); });
    group.on('mouseup', function () { writeMessage('mouseup'); });
}

function writeMessage(message) {
    debugText.text(message);
    baseLayer.draw();
}

Fiddle example here: http://jsfiddle.net/uvULx/15/

You'll notice that if you click between the lines the text under the grid will change to "mousedown". If you repeat the same process on top of a line the event will not fire.

I'm pretty sure it's the close to the same thing as this person's question (which was never answered). One comment is to set the stroke to 2, but this is not an option due to dynamically sizing the grid for smaller screen sizes.

Is there an option of laying some sort of "transparent" shape over the whole grid which could catch all events at any location of the grid?

回答1:

This has actually been in bug in KineticJS regarding groups, shapes, mouseevents and aliasing, and was solved by @lavrton just two days ago. See also this issue (and 3 other related issues) on github.

I updated your fiddle to use the code from this latest commit and then it works fine: http://jsfiddle.net/uvULx/17/. So updating your project to use this latest KineticJS 'release', should solve your problem (download it from github here, and not from the kineticjs.com website).

As a side note, the behaviour you describe in your version of the fiddle also happens when the stroke is 2 or larger. Approximately in the center of the line the event wouldn't fire.