added clipping functionality to containers. Currently, the clipping function can only be applied to layers and groups. The clipping region is also subject to the containers transforms, which means that you can also create transformed clipping regions.

This commit is contained in:
Eric Rowell
2013-02-15 18:20:34 -08:00
parent b739d6edf7
commit 46f71d283f
8 changed files with 80 additions and 0 deletions

View File

@@ -146,6 +146,7 @@ class Build < Thor
content.gsub!("{{version}}", version)
content.sub!("{{date}}", date)
content.gsub!("{{NodeParams}}", IO.read("configParams/NodeParams.txt"))
content.gsub!("{{ContainerParams}}", IO.read("configParams/ContainerParams.txt"))
content.gsub!("{{ShapeParams}}", IO.read("configParams/ShapeParams.txt"))
return content

View File

@@ -0,0 +1 @@
@param {Function} [config.clipFunc] clipping function

View File

@@ -204,6 +204,15 @@
var t = no.getTransform(), m = t.getMatrix();
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
}, true);
},
_clip: function(container) {
var context = this.getContext();
context.save();
this._applyAncestorTransforms(container);
context.beginPath();
container.getClipFunc()(this);
context.clip();
context.setTransform(1, 0, 0, 1, 0, 0);
}
};

View File

@@ -5,6 +5,7 @@
* @augments Kinetic.Node
* @param {Object} config
* {{NodeParams}}
* {{ContainerParams}}
*/
Kinetic.Container = function(config) {
this._containerInit(config);
@@ -203,21 +204,56 @@
this.drawHit();
},
drawScene: function(canvas) {
var clip = !!this.getClipFunc() && canvas;
if (clip) {
canvas._clip(this);
}
if(this.isVisible()) {
var children = this.children, len = children.length;
for(var n = 0; n < len; n++) {
children[n].drawScene(canvas);
}
}
if (clip) {
canvas.getContext().restore();
}
},
drawHit: function() {
var clip = !!this.getClipFunc() && this.nodeType !== 'Stage',
hitCanvas;
if (clip) {
hitCanvas = this.getLayer().hitCanvas;
hitCanvas._clip(this);
}
if(this.isVisible() && this.isListening()) {
var children = this.children, len = children.length;
for(var n = 0; n < len; n++) {
children[n].drawHit();
}
}
if (clip) {
hitCanvas.getContext().restore();
}
}
};
Kinetic.Global.extend(Kinetic.Container, Kinetic.Node);
// add getters setters
Kinetic.Node.addGettersSetters(Kinetic.Container, ['clipFunc']);
/**
* set clipping function
* @name setClipFunc
* @methodOf Kinetic.Container.prototype
* @param {Number} deg
*/
/**
* get clipping function
* @name getClipFunc
* @methodOf Kinetic.Container.prototype
*/
})();

View File

@@ -5,6 +5,7 @@
* @augments Kinetic.Container
* @param {Object} config
* {{NodeParams}}
* {{ContainerParams}}
*/
Kinetic.Group = function(config) {
this._initGroup(config);

View File

@@ -8,6 +8,7 @@
* @param {Boolean} [config.clearBeforeDraw] set this property to false if you don't want
* to clear the canvas before each layer draw. The default value is true.
* {{NodeParams}}
* {{ContainerParams}}
*/
Kinetic.Layer = function(config) {
this._initLayer(config);

View File

@@ -6,6 +6,7 @@
* @param {Object} config
* @param {String|DomElement} config.container Container id or DOM element
* {{NodeParams}}
* {{ContainerParams}}
*/
Kinetic.Stage = function(config) {
this._initStage(config);

View File

@@ -1,4 +1,34 @@
Test.Modules.CONTAINER = {
'use clipping function': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200,
draggable: true
});
var layer = new Kinetic.Layer({
clipFunc: function(canvas) {
var context = canvas.getContext();
context.rect(0, 0, 400, 100);
}
});
var group = new Kinetic.Group();
var circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
name: 'myCircle',
draggable: true
});
stage.add(layer);
layer.add(group);
group.add(circle);
layer.draw();
},
'add layer then group then shape': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,