mirror of
https://github.com/konvajs/konva.git
synced 2025-09-19 19:07:59 +08:00
cleaned up isListening API. introduced new enableHitGraph config that can be used to disable the hit graph
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var SPACE = '',
|
||||
var SPACE = ' ',
|
||||
TRANSFORM_CHANGE_STR = [
|
||||
'xChange.kinetic',
|
||||
'yChange.kinetic',
|
||||
@@ -291,6 +291,7 @@
|
||||
hitCanvas;
|
||||
|
||||
if(this.shouldDrawHit()) {
|
||||
|
||||
if (hasClip) {
|
||||
hitCanvas = this.getLayer().hitCanvas;
|
||||
hitCanvas.getContext()._clip(this);
|
||||
@@ -309,6 +310,24 @@
|
||||
|
||||
return this;
|
||||
}
|
||||
/*
|
||||
_isListeningEnabled: function() {
|
||||
var ret;
|
||||
|
||||
if (this._listeningEnabled) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
ret = false;
|
||||
this.children.each(function(child) {
|
||||
if (child.isListeningEnabled()) {
|
||||
ret = true;
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
*/
|
||||
});
|
||||
|
||||
Kinetic.Util.extend(Kinetic.Container, Kinetic.Node);
|
||||
|
@@ -174,6 +174,12 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// listening is required for drag and drop
|
||||
/*
|
||||
this._listeningEnabled = true;
|
||||
this._clearSelfAndAncestorCache('listeningEnabled');
|
||||
*/
|
||||
};
|
||||
|
||||
Kinetic.Node.prototype._dragChange = function() {
|
||||
|
@@ -48,6 +48,7 @@ var Kinetic = {};
|
||||
traceArrMax: 100,
|
||||
dblClickWindow: 400,
|
||||
pixelRatio: undefined,
|
||||
enableHitGraph: true,
|
||||
|
||||
// user agent
|
||||
UA: (function() {
|
||||
|
120
src/Node.js
120
src/Node.js
@@ -17,6 +17,7 @@
|
||||
ID = 'id',
|
||||
KINETIC = 'kinetic',
|
||||
LISTENING = 'listening',
|
||||
//LISTENING_ENABLED = 'listeningEnabled',
|
||||
MOUSEENTER = 'mouseenter',
|
||||
MOUSELEAVE = 'mouseleave',
|
||||
NAME = 'name',
|
||||
@@ -62,20 +63,21 @@
|
||||
this.attrs = {};
|
||||
this.cache = {};
|
||||
this.setAttrs(config);
|
||||
//this._listeningEnabled = false;
|
||||
|
||||
// event bindings for cache handling
|
||||
this.on(TRANSFORM_CHANGE_STR, function() {
|
||||
this._clearCache(TRANSFORM);
|
||||
that._clearSelfAndChildrenCache(ABSOLUTE_TRANSFORM);
|
||||
that._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
|
||||
});
|
||||
this.on('visibleChange.kinetic', function() {
|
||||
that._clearSelfAndChildrenCache(VISIBLE);
|
||||
that._clearSelfAndDescendantCache(VISIBLE);
|
||||
});
|
||||
this.on('listeningChange.kinetic', function() {
|
||||
that._clearSelfAndChildrenCache(LISTENING);
|
||||
that._clearSelfAndDescendantCache(LISTENING);
|
||||
});
|
||||
this.on('opacityChange.kinetic', function() {
|
||||
that._clearSelfAndChildrenCache(ABSOLUTE_OPACITY);
|
||||
that._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -103,16 +105,34 @@
|
||||
|
||||
return this.cache[attr];
|
||||
},
|
||||
_clearSelfAndChildrenCache: function(attr) {
|
||||
/*
|
||||
* when the logic for a cached result depends on ancestor propagation, use this
|
||||
* method to clear self and children cache
|
||||
*/
|
||||
_clearSelfAndDescendantCache: function(attr) {
|
||||
var that = this;
|
||||
this._clearCache(attr);
|
||||
|
||||
if (this.children) {
|
||||
this.getChildren().each(function(node) {
|
||||
node._clearSelfAndChildrenCache(attr);
|
||||
node._clearSelfAndDescendantCache(attr);
|
||||
});
|
||||
}
|
||||
},
|
||||
/*
|
||||
* when the logic for a cached result depends on descendant propagation, use this
|
||||
* method to clear self and ancestor cache
|
||||
*/
|
||||
/*
|
||||
_clearSelfAndAncestorCache: function(attr) {
|
||||
var parent = this.getParent();
|
||||
|
||||
this._clearCache(attr);
|
||||
if (parent) {
|
||||
parent._clearSelfAndAncestorCache(attr);
|
||||
}
|
||||
},
|
||||
*/
|
||||
/**
|
||||
* bind events to the node. KineticJS supports mouseover, mousemove,
|
||||
* mouseout, mouseenter, mouseleave, mousedown, mouseup, click, dblclick, touchstart, touchmove,
|
||||
@@ -177,7 +197,19 @@
|
||||
name: name,
|
||||
handler: handler
|
||||
});
|
||||
|
||||
// NOTE: this flag is set to true when any event handler is added, even non
|
||||
// mouse or touch gesture events. This improves performance for most
|
||||
// cases where users aren't using events, but is still very light weight.
|
||||
// To ensure perfect accuracy, devs can explicitly set listening to false.
|
||||
/*
|
||||
if (name !== KINETIC) {
|
||||
this._listeningEnabled = true;
|
||||
this._clearSelfAndAncestorCache(LISTENING_ENABLED);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
/**
|
||||
@@ -241,12 +273,12 @@
|
||||
}
|
||||
|
||||
// every cached attr that is calculated via node tree
|
||||
// treversal must be cleared when removing a node
|
||||
this._clearSelfAndChildrenCache(STAGE);
|
||||
this._clearSelfAndChildrenCache(ABSOLUTE_TRANSFORM);
|
||||
this._clearSelfAndChildrenCache(VISIBLE);
|
||||
this._clearSelfAndChildrenCache(LISTENING);
|
||||
this._clearSelfAndChildrenCache(ABSOLUTE_OPACITY);
|
||||
// traversal must be cleared when removing a node
|
||||
this._clearSelfAndDescendantCache(STAGE);
|
||||
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
|
||||
this._clearSelfAndDescendantCache(VISIBLE);
|
||||
this._clearSelfAndDescendantCache(LISTENING);
|
||||
this._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
|
||||
|
||||
return this;
|
||||
},
|
||||
@@ -345,11 +377,23 @@
|
||||
return this;
|
||||
},
|
||||
/**
|
||||
* determine if node is listening for events. The node is listening only
|
||||
* if it's listening and all of its ancestors are listening. If an ancestor
|
||||
* is listening, this means that the node is also listening
|
||||
* determine if node is listening for events by taking into account ancestors.
|
||||
*
|
||||
* Parent | Self | isListening
|
||||
* listening | listening |
|
||||
* ----------+-----------+------------
|
||||
* T | T | T
|
||||
* T | F | F
|
||||
* F | T | T
|
||||
* F | F | F
|
||||
* ----------+-----------+------------
|
||||
* T | I | T
|
||||
* F | I | F
|
||||
* I | I | T
|
||||
*
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
isListening: function() {
|
||||
return this._getCache(LISTENING, this._isListening);
|
||||
@@ -358,10 +402,34 @@
|
||||
var listening = this.getListening(),
|
||||
parent = this.getParent();
|
||||
|
||||
if(listening && parent && !parent.isListening()) {
|
||||
return false;
|
||||
// the following conditions are a simplification of the truth table above.
|
||||
// please modify carefully
|
||||
if (listening === 'inherit') {
|
||||
if (parent) {
|
||||
return parent.isListening();
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return listening;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* determine if listening is enabled by taking into account descendants. If self or any children
|
||||
* have _isListeningEnabled set to true, than self also has listening enabled.
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
/*
|
||||
isListeningEnabled: function() {
|
||||
return this._getCache(LISTENING_ENABLED, this._isListeningEnabled);
|
||||
},
|
||||
*/
|
||||
shouldDrawHit: function() {
|
||||
return Kinetic.enableHitGraph && /*this.isListeningEnabled() &&*/ this.isListening() && this.isVisible() && !Kinetic.isDragging();
|
||||
},
|
||||
/**
|
||||
* determine if node is visible or not. Node is visible only
|
||||
@@ -550,7 +618,7 @@
|
||||
}
|
||||
|
||||
this._clearCache(TRANSFORM);
|
||||
this._clearSelfAndChildrenCache(ABSOLUTE_TRANSFORM);
|
||||
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
|
||||
},
|
||||
_clearTransform: function() {
|
||||
var trans = {
|
||||
@@ -576,7 +644,7 @@
|
||||
this.attrs.skewY = 0;
|
||||
|
||||
this._clearCache(TRANSFORM);
|
||||
this._clearSelfAndChildrenCache(ABSOLUTE_TRANSFORM);
|
||||
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
|
||||
|
||||
return trans;
|
||||
},
|
||||
@@ -1239,9 +1307,6 @@
|
||||
this.drawHit();
|
||||
return this;
|
||||
},
|
||||
shouldDrawHit: function() {
|
||||
return this.isListening() && this.isVisible() && !Kinetic.isDragging();
|
||||
},
|
||||
isDraggable: function() {
|
||||
return false;
|
||||
},
|
||||
@@ -1586,21 +1651,22 @@
|
||||
* @param {Number} height
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'listening', true);
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'listening', 'inherit');
|
||||
|
||||
/**
|
||||
* listen or don't listen to events
|
||||
* listen or don't listen to events. can be true, false, or 'inherit'
|
||||
* @name setListening
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Boolean} listening
|
||||
* @param {Boolean|String} listening
|
||||
*/
|
||||
|
||||
/**
|
||||
* determine if node is listening or not. Node can be listening even if its ancestors
|
||||
* are not listening
|
||||
* determine if node is listening or not.
|
||||
* @name getListening
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @returns {Boolean|String}
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'visible', true);
|
||||
|
@@ -296,6 +296,11 @@
|
||||
this.setDrawHitFunc(this.drawHitFunc);
|
||||
}
|
||||
}
|
||||
/*
|
||||
_isListeningEnabled: function() {
|
||||
return this._listeningEnabled;
|
||||
},
|
||||
*/
|
||||
});
|
||||
Kinetic.Util.extend(Kinetic.Shape, Kinetic.Node);
|
||||
|
||||
|
@@ -70,7 +70,7 @@ suite('Manual', function() {
|
||||
100, 10
|
||||
],
|
||||
easing: Kinetic.Easings.BackEaseOut,
|
||||
yoyo: true
|
||||
yoyo: false
|
||||
});
|
||||
|
||||
// stage.getContent().addEventListener('mouseover', function() {
|
||||
|
@@ -50,7 +50,7 @@ function init() {
|
||||
}
|
||||
}
|
||||
|
||||
addStats();
|
||||
//addStats();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1356,7 +1356,7 @@ suite('Container', function() {
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('Kinetic.enableNestedTransforms flag', function(){
|
||||
test('stage._enableNestedTransforms flag', function(){
|
||||
var stage = addStage();
|
||||
|
||||
var layer = new Kinetic.Layer();
|
||||
|
@@ -24,6 +24,13 @@ suite('DragAndDrop', function() {
|
||||
//change properties
|
||||
circle.setDraggable(true);
|
||||
|
||||
|
||||
//circle.on('click', function(){});
|
||||
|
||||
layer.draw();
|
||||
|
||||
showHit(layer);
|
||||
|
||||
// test new properties
|
||||
assert.equal(circle.getDraggable(), true);
|
||||
});
|
||||
|
@@ -222,10 +222,14 @@ suite('Node', function() {
|
||||
stage.add(layer);
|
||||
|
||||
// listening cache
|
||||
|
||||
// prime the cache
|
||||
circle.isListening();
|
||||
|
||||
assert.equal(circle.cache.listening, true);
|
||||
circle.setListening(false);
|
||||
assert.equal(circle.cache.listening, undefined);
|
||||
layer.draw();
|
||||
circle.isListening();
|
||||
assert.equal(circle.cache.listening, false);
|
||||
|
||||
});
|
||||
@@ -303,8 +307,8 @@ suite('Node', function() {
|
||||
layer.add(rect).add(rect2);
|
||||
stage.add(layer);
|
||||
|
||||
assert.equal(rect.getListening(), true);
|
||||
// test alias
|
||||
assert.equal(rect.getListening(), 'inherit');
|
||||
|
||||
assert.equal(rect.isListening(), true);
|
||||
rect.setListening(false);
|
||||
assert.equal(rect.getListening(), false);
|
||||
@@ -1645,17 +1649,26 @@ suite('Node', function() {
|
||||
rect.setListening(false);
|
||||
assert.equal(rect.isListening(), false);
|
||||
|
||||
rect.setListening(true);
|
||||
rect.setListening('inherit');
|
||||
assert.equal(rect.isListening(), true);
|
||||
|
||||
layer.setListening(false);
|
||||
|
||||
assert.equal(rect.isListening(), false);
|
||||
|
||||
layer.setListening(true);
|
||||
assert.equal(rect.isListening(), true);
|
||||
|
||||
// even though we set stage listening to false, since the layer
|
||||
// listening is set to try, rect listening will be true
|
||||
stage.setListening(false);
|
||||
assert.equal(rect.isListening(), true);
|
||||
|
||||
// setting layer listening to inherit means that the layer listening
|
||||
// will inherit the stage listening, which is false
|
||||
layer.setListening('inherit');
|
||||
assert.equal(rect.isListening(), false);
|
||||
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
@@ -2605,4 +2618,40 @@ suite('Node', function() {
|
||||
// TODO: stage hide() fails. also need to find a good way to test this
|
||||
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
test('Kinetic.enableHitGraph, listening, & shouldDrawHit', function(){
|
||||
var stage = addStage();
|
||||
|
||||
var layer = new Kinetic.Layer();
|
||||
|
||||
var rect = new Kinetic.Rect({
|
||||
x: 100,
|
||||
y: 50,
|
||||
width: 100,
|
||||
height: 50,
|
||||
fill: 'green',
|
||||
stroke: 'blue'
|
||||
});
|
||||
|
||||
layer.add(rect);
|
||||
stage.add(layer);
|
||||
|
||||
|
||||
// test enableHitGraph default
|
||||
assert.equal(Kinetic.enableHitGraph, true);
|
||||
|
||||
assert.equal(rect.isListening(), true);
|
||||
assert.equal(rect.shouldDrawHit(), true);
|
||||
|
||||
// disable hit graph
|
||||
Kinetic.enableHitGraph = false;
|
||||
|
||||
assert.equal(rect.isListening(), true);
|
||||
assert.equal(rect.shouldDrawHit(), false);
|
||||
|
||||
// set the flag back for future tests
|
||||
Kinetic.enableHitGraph = true;
|
||||
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user