-->

kineticjs custom hit region not working

2019-06-12 14:04发布

问题:

I have a draggable line with a stroke width of 2 and want the user to be able to drag the line even if he clicks and drags near the surrounding area. As per my understanding, the way to do that is to define a custom drawHitFunc for the line. I adapted the code from tutorial here: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-custom-hit-function-tutorial/ to define my custom drawHitFunc for the line.

My custom draw hit function is simple--same line but much thicker (25 pixels wide). However, this does not seem to work. The drag only works if I carefully place my mouse pointer right on the line and then drag. Based on the drawHitFunc defined below, it should work even if I click and drag near the line. What am I doing wrong?

Here is the drawHitFunc snippet:

function(canvas) {
var context = canvas.getContext();
context.beginPath();
context.lineWidth = 25;
context.moveTo(this.getPoints()[0].x, this.getPoints()[0].y);
context.lineTo(this.getPoints()[1].x, this.getPoints()[1].y);
context.closePath();
canvas.fillStroke(this);
}

The full failing example is at: http://jsfiddle.net/BwF6K/

Any help pointing out what I missed is appreciated.

Thanks.

回答1:

Yes, it looks like KineticJS doesn’t like custom hit-testing a line.

Instead, this works…rather than using a “fat” line in the custom hittest, just draw a rectangle around the line.

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/twUqx/

  var line = new Kinetic.Line({
        points: [fromX, fromY, toX, toY],
        stroke: drawColor,
        strokeWidth: 2,
        name: 'line',
        draggable:true,
        drawHitFunc: function(canvas) {
          var x1=this.getPoints()[0].x;
          var y1=this.getPoints()[0].y;
          var x2=this.getPoints()[1].x;
          var y2=this.getPoints()[1].y;
          var context = canvas.getContext();
          context.beginPath();
          context.lineWidth = 25;
          context.moveTo(x1-12,y1-12);
          context.lineTo(x2+12,y1-12);
          context.lineTo(x2+12,y2+12);
          context.lineTo(x1-12,y2+12);
          context.closePath();
          canvas.fillStroke(this);
        }
    });

Notice that I drew a horizontal line because I didn’t feel like working out the trig for a rotated line =)



回答2:

You can actually use a line as the hit area for a Line object. And you can achieve this in two ways:

  1. Assign the line's internal colorKey as the strokeStyle and use the native canvas stroke:

    context.lineWidth = 10; context.strokeStyle = this.colorKey; context.stroke();

  2. The other solution is to set the strokeWidth before calling fillStroke, and then setting it back:

    this.setStrokeWidth(10); canvas.fillStroke(this); this.setStrokeWidth(3);



回答3:

In Kinetic 4.7.2 the solution looks like:

  drawHitFunc: function(context) {
    var hitWidth = 50;
    context.beginPath();
    context.moveTo(this.getPoints()[0].x, this.getPoints()[0].y);
    context.lineTo(this.getPoints()[1].x, this.getPoints()[1].y);
    context.closePath();
    var orgWidth = this.getStrokeWidth();
    this.setStrokeWidth(hitWidth);
    context.fillStrokeShape(this);
    this.setStrokeWidth(orgWidth);
  }