mirror of
https://github.com/konvajs/konva.git
synced 2025-09-19 19:07:59 +08:00
refactored filter API so that transitions can hook into the filter controls. Filter transitons are now working. Filters can now also have an unlimited number of parameters. added _applyFilter flag to ensure that new filters are only applied once, when needed, right before a redraw
This commit is contained in:
2
Thorfile
2
Thorfile
@@ -5,9 +5,9 @@ class Build < Thor
|
||||
# This is the list of files to concatenate. The first file will appear at the top of the final file. All files are relative to the lib directory.
|
||||
FILES = [
|
||||
"src/Global.js", "src/util/Type.js", "src/Canvas.js", "src/util/Tween.js", "src/util/Transform.js", "src/util/Collection.js",
|
||||
"src/filters/Grayscale.js", "src/filters/Brighten.js", "src/filters/Invert.js", "src/filters/Blur.js", "src/filters/Mask.js",
|
||||
"src/Node.js", "src/Animation.js", "src/DragAndDrop.js", "src/Transition.js", "src/Container.js", "src/Shape.js", "src/Stage.js", "src/Layer.js", "src/Group.js",
|
||||
"src/shapes/Rect.js", "src/shapes/Circle.js", "src/shapes/Wedge.js", "src/shapes/Ellipse.js", "src/shapes/Image.js", "src/shapes/Polygon.js", "src/shapes/Text.js", "src/shapes/Line.js", "src/shapes/Spline.js", "src/shapes/Blob.js", "src/shapes/Sprite.js",
|
||||
"src/filters/Grayscale.js", "src/filters/Brighten.js", "src/filters/Invert.js", "src/filters/Blur.js", "src/filters/Mask.js",
|
||||
"src/plugins/Path.js", "src/plugins/TextPath.js", "src/plugins/RegularPolygon.js", "src/plugins/Star.js", "src/plugins/Label.js"
|
||||
]
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
the Gauss filter
|
||||
master repo: https://github.com/pavelpower/kineticjsGaussFilter/
|
||||
*/
|
||||
(function(Kinetic) {
|
||||
(function() {
|
||||
/*
|
||||
|
||||
StackBlur - a fast almost Gaussian Blur For Canvas
|
||||
@@ -111,7 +111,6 @@
|
||||
mul_sum = mul_table[radius],
|
||||
shg_sum = shg_table[radius];
|
||||
|
||||
|
||||
for ( i = 1; i < div; i++ ) {
|
||||
stack = stack.next = new BlurStack();
|
||||
if ( i == radiusPlus1 ) var stackEnd = stack;
|
||||
@@ -323,21 +322,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
Kinetic = Kinetic || {};
|
||||
Kinetic.Filters = Kinetic.Filters || {};
|
||||
|
||||
/**
|
||||
* Blur Filter
|
||||
* @function
|
||||
* @memberOf Kinetic.Filters
|
||||
* @param {Object} imageData
|
||||
* @param {Integer} radius
|
||||
*/
|
||||
Kinetic.Filters.Blur = function(imageData, radius) {
|
||||
radius = radius || 0;
|
||||
Kinetic.Filters.Blur = function(imageData) {
|
||||
var radius = this.getFilterRadius() | 0;
|
||||
|
||||
if (radius > 0) {
|
||||
filterGaussBlurRGBA(imageData, radius);
|
||||
}
|
||||
};
|
||||
|
||||
window['Kinetic'] = Kinetic;
|
||||
Kinetic.Node.addFilterGetterSetter(Kinetic.Image, 'filterRadius', 0);
|
||||
|
||||
})(Kinetic);
|
||||
})();
|
||||
|
@@ -1,13 +1,12 @@
|
||||
(function() {
|
||||
/**
|
||||
* Brighten Filter
|
||||
* Brighten Filter.
|
||||
* @function
|
||||
* @memberOf Kinetic.Filters
|
||||
* @param {Object} imageData
|
||||
* @param {Integer} brightness number from -255 to 255. Positive values increase the brightness and negative values decrease the brightness, making the image darker
|
||||
*/
|
||||
Kinetic.Filters.Brighten = function(imageData, brightness) {
|
||||
var brightness = brightness || 0;
|
||||
Kinetic.Filters.Brighten = function(imageData) {
|
||||
var brightness = this.getFilterBrightness();
|
||||
var data = imageData.data;
|
||||
for(var i = 0; i < data.length; i += 4) {
|
||||
// red
|
||||
@@ -18,4 +17,18 @@
|
||||
data[i + 2] += brightness;
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.Node.addFilterGetterSetter(Kinetic.Image, 'filterBrightness', 0);
|
||||
/**
|
||||
* get filter brightness. The brightness is a number between -255 and 255. Positive values
|
||||
* increase the brightness and negative values decrease the brightness, making the image darker
|
||||
* @name getFilterBrightness
|
||||
* @methodOf Kinetic.Image.prototype
|
||||
*/
|
||||
|
||||
/**
|
||||
* set filter brightness
|
||||
* @name setFilterBrightness
|
||||
* @methodOf Kinetic.Image.prototype
|
||||
*/
|
||||
})();
|
||||
|
@@ -4,9 +4,8 @@
|
||||
* @function
|
||||
* @memberOf Kinetic.Filters
|
||||
* @param {Object} imageData
|
||||
* @param {Object} config
|
||||
*/
|
||||
Kinetic.Filters.Grayscale = function(imageData, config) {
|
||||
Kinetic.Filters.Grayscale = function(imageData) {
|
||||
var data = imageData.data;
|
||||
for(var i = 0; i < data.length; i += 4) {
|
||||
var brightness = 0.34 * data[i] + 0.5 * data[i + 1] + 0.16 * data[i + 2];
|
||||
|
@@ -4,9 +4,8 @@
|
||||
* @function
|
||||
* @memberOf Kinetic.Filters
|
||||
* @param {Object} imageData
|
||||
* @param {Object} config
|
||||
*/
|
||||
Kinetic.Filters.Invert = function(imageData, config) {
|
||||
Kinetic.Filters.Invert = function(imageData) {
|
||||
var data = imageData.data;
|
||||
for(var i = 0; i < data.length; i += 4) {
|
||||
// red
|
||||
|
@@ -1,4 +1,4 @@
|
||||
(function(Kinetic) {
|
||||
(function() {
|
||||
|
||||
function pixelAt(idata, x, y) {
|
||||
var idx = (y * idata.width + x) * 4;
|
||||
@@ -159,9 +159,6 @@
|
||||
return maskResult;
|
||||
}
|
||||
|
||||
Kinetic = Kinetic || {};
|
||||
Kinetic.Filters = Kinetic.Filters || {};
|
||||
|
||||
/**
|
||||
* Mask Filter
|
||||
*
|
||||
@@ -170,11 +167,11 @@
|
||||
* @function
|
||||
* @memberOf Kinetic.Filters
|
||||
* @param {Object} imageData
|
||||
* @param {Integer} threshold The RGB euclidian distance threshold (default : 10)
|
||||
*/
|
||||
Kinetic.Filters.Mask = function(idata, threshold) {
|
||||
Kinetic.Filters.Mask = function(idata) {
|
||||
// Detect pixels close to the background color
|
||||
var mask = backgroundMask(idata, threshold);
|
||||
var threshold = this.getFilterThreshold(),
|
||||
mask = backgroundMask(idata, threshold);
|
||||
if (mask) {
|
||||
// Erode
|
||||
mask = erodeMask(mask, idata.width, idata.height);
|
||||
@@ -194,6 +191,8 @@
|
||||
return idata;
|
||||
};
|
||||
|
||||
window['Kinetic'] = Kinetic;
|
||||
Kinetic.Node.addFilterGetterSetter(Kinetic.Image, 'filterThreshold', 0);
|
||||
|
||||
})(Kinetic);
|
||||
//threshold The RGB euclidian distance threshold (default : 10)
|
||||
|
||||
})();
|
||||
|
@@ -1,7 +1,8 @@
|
||||
(function() {
|
||||
// CONSTANTS
|
||||
var IMAGE = 'Image',
|
||||
CROP = 'crop';
|
||||
CROP = 'crop',
|
||||
SET = 'set';
|
||||
|
||||
/**
|
||||
* Image constructor
|
||||
@@ -33,12 +34,17 @@
|
||||
that = this,
|
||||
context = canvas.getContext(),
|
||||
crop = this.getCrop(),
|
||||
cropX, cropY, cropWidth, cropHeight,
|
||||
filterCanvas = this.filterCanvas,
|
||||
image;
|
||||
cropX, cropY, cropWidth, cropHeight, image;
|
||||
|
||||
if (filterCanvas) {
|
||||
image = filterCanvas.getElement();
|
||||
// if a filter is set, and the filter needs to be updated, reapply
|
||||
if (this.getFilter() && this._applyFilter) {
|
||||
this.applyFilter();
|
||||
this._applyFilter = false;
|
||||
}
|
||||
|
||||
// NOTE: this.filterCanvas may be set by the above code block
|
||||
if (this.filterCanvas) {
|
||||
image = this.filterCanvas.getElement();
|
||||
}
|
||||
else {
|
||||
image = this.getImage();
|
||||
@@ -97,16 +103,13 @@
|
||||
* apply filter
|
||||
* @name applyFilter
|
||||
* @methodOf Kinetic.Image.prototype
|
||||
* @param {Object} config
|
||||
* @param {Function} filter filter function
|
||||
* @param {*} [val] optional val parameter that can be any data type. See the
|
||||
* docs for the filter in question
|
||||
*/
|
||||
applyFilter: function(filter, val) {
|
||||
applyFilter: function() {
|
||||
var image = this.getImage(),
|
||||
that = this,
|
||||
width = this.getWidth(),
|
||||
height = this.getHeight(),
|
||||
filter = this.getFilter(),
|
||||
filterCanvas, context, imageData;
|
||||
|
||||
if (this.filterCanvas){
|
||||
@@ -124,7 +127,7 @@
|
||||
try {
|
||||
this._drawImage(context, [image, 0, 0, width, height]);
|
||||
imageData = context.getImageData(0, 0, filterCanvas.getWidth(), filterCanvas.getHeight());
|
||||
filter(imageData, val);
|
||||
filter.call(this, imageData);
|
||||
context.putImageData(imageData, 0, 0);
|
||||
}
|
||||
catch(e) {
|
||||
@@ -139,6 +142,7 @@
|
||||
*/
|
||||
clearFilter: function() {
|
||||
this.filterCanvas = null;
|
||||
this._applyFilter = false;
|
||||
},
|
||||
/**
|
||||
* set crop
|
||||
@@ -232,6 +236,22 @@
|
||||
};
|
||||
Kinetic.Global.extend(Kinetic.Image, Kinetic.Shape);
|
||||
|
||||
|
||||
Kinetic.Node.addFilterGetterSetter = function(constructor, attr, def) {
|
||||
this.addGetter(constructor, attr, def);
|
||||
this.addFilterSetter(constructor, attr);
|
||||
};
|
||||
|
||||
Kinetic.Node.addFilterSetter = function(constructor, attr) {
|
||||
var that = this,
|
||||
method = SET + Kinetic.Type._capitalize(attr);
|
||||
|
||||
constructor.prototype[method] = function(val) {
|
||||
this.setAttr(attr, val);
|
||||
this._applyFilter = true;
|
||||
};
|
||||
};
|
||||
|
||||
// add getters setters
|
||||
Kinetic.Node.addGetterSetter(Kinetic.Image, 'image');
|
||||
|
||||
@@ -256,4 +276,7 @@
|
||||
* @methodOf Kinetic.Image.prototype
|
||||
*/
|
||||
|
||||
Kinetic.Node.addFilterGetterSetter(Kinetic.Image, 'filter');
|
||||
|
||||
|
||||
})();
|
||||
|
@@ -52,7 +52,6 @@ Test.Modules.TRANSITION = {
|
||||
easing: 'bounce-ease-out'
|
||||
});
|
||||
},
|
||||
|
||||
'all transition types': function(containerId) {
|
||||
document.getElementById(containerId).style.height = '300px';
|
||||
|
||||
@@ -1438,5 +1437,46 @@ Test.Modules.DRAG_AND_DROP = {
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
'transition gaussian blur filter': function(containerId) {
|
||||
var imageObj = new Image();
|
||||
imageObj.onload = function() {
|
||||
var stage = new Kinetic.Stage({
|
||||
container: containerId,
|
||||
width: 578,
|
||||
height: 200
|
||||
});
|
||||
var layer = new Kinetic.Layer();
|
||||
darth = new Kinetic.Image({
|
||||
x: 10,
|
||||
y: 10,
|
||||
image: imageObj,
|
||||
draggable: true,
|
||||
filter: Kinetic.Filters.Blur,
|
||||
filterRadius: 20
|
||||
});
|
||||
|
||||
layer.add(darth);
|
||||
stage.add(layer);
|
||||
|
||||
|
||||
darth.on('mouseover', function() {
|
||||
darth.transitionTo({
|
||||
easing: 'ease-in-out',
|
||||
duration: 0.5,
|
||||
filterRadius: 0
|
||||
});
|
||||
});
|
||||
|
||||
darth.on('mouseout', function() {
|
||||
darth.transitionTo({
|
||||
easing: 'ease-in-out',
|
||||
duration: 0.5,
|
||||
filterRadius: 20
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
imageObj.src = '../assets/darth-vader.jpg';
|
||||
}
|
||||
};
|
||||
|
@@ -218,12 +218,13 @@ Test.Modules.IMAGE = {
|
||||
test(darth.getWidth() === 438, 'image width should be 438');
|
||||
test(darth.getHeight() === 300, 'image height should be 300');
|
||||
|
||||
darth.applyFilter(Kinetic.Filters.Grayscale, null, function() {
|
||||
darth.setFilter(Kinetic.Filters.Grayscale);
|
||||
|
||||
layer.draw();
|
||||
var dataUrl = layer.toDataURL();
|
||||
//console.log(dataUrl);
|
||||
warn(dataUrl === dataUrls['grayscale image'], 'problem with Grayscale filter.');
|
||||
});
|
||||
|
||||
};
|
||||
imageObj.src = '../assets/darth-vader.jpg';
|
||||
},
|
||||
@@ -251,7 +252,7 @@ Test.Modules.IMAGE = {
|
||||
test(darth.getWidth() === 438, 'image width should be 438');
|
||||
test(darth.getHeight() === 300, 'image height should be 300');
|
||||
|
||||
darth.applyFilter(Kinetic.Filters.Invert);
|
||||
darth.setFilter(Kinetic.Filters.Invert);
|
||||
|
||||
layer.draw();
|
||||
var dataUrl = layer.toDataURL();
|
||||
@@ -285,7 +286,8 @@ Test.Modules.IMAGE = {
|
||||
test(darth.getWidth() === 438, 'image width should be 438');
|
||||
test(darth.getHeight() === 300, 'image height should be 300');
|
||||
|
||||
darth.applyFilter(Kinetic.Filters.Brighten, 100);
|
||||
darth.setFilter(Kinetic.Filters.Brighten);
|
||||
darth.setFilterBrightness(100);
|
||||
|
||||
layer.draw();
|
||||
var dataUrl = layer.toDataURL();
|
||||
@@ -302,9 +304,7 @@ Test.Modules.IMAGE = {
|
||||
width: 578,
|
||||
height: 200
|
||||
});
|
||||
var layer = new Kinetic.Layer({
|
||||
throttle: 999
|
||||
});
|
||||
var layer = new Kinetic.Layer();
|
||||
darth = new Kinetic.Image({
|
||||
x: 10,
|
||||
y: 10,
|
||||
@@ -318,8 +318,8 @@ Test.Modules.IMAGE = {
|
||||
test(darth.getWidth() === 438, 'image width should be 438');
|
||||
test(darth.getHeight() === 300, 'image height should be 300');
|
||||
|
||||
darth.applyFilter(Kinetic.Filters.Blur, 10);
|
||||
|
||||
darth.setFilter(Kinetic.Filters.Blur);
|
||||
darth.setFilterRadius(10);
|
||||
layer.draw();
|
||||
var dataUrl = layer.toDataURL();
|
||||
//console.log(dataUrl);
|
||||
@@ -357,7 +357,7 @@ Test.Modules.IMAGE = {
|
||||
test(darth.getWidth() === 438, 'image width should be 438');
|
||||
test(darth.getHeight() === 300, 'image height should be 300');
|
||||
|
||||
darth.applyFilter(Kinetic.Filters.Grayscale);
|
||||
darth.setFilter(Kinetic.Filters.Grayscale);
|
||||
|
||||
layer.draw();
|
||||
//console.log(layer.toDataURL());
|
||||
@@ -428,7 +428,8 @@ Test.Modules.IMAGE = {
|
||||
layer.add(filtered);
|
||||
stage.add(layer);
|
||||
|
||||
filtered.applyFilter(Kinetic.Filters.Mask, 10);
|
||||
filtered.setFilter(Kinetic.Filters.Mask);
|
||||
filtered.setFilterThreshold(10);
|
||||
|
||||
layer.draw();
|
||||
var dataUrl = layer.toDataURL();
|
||||
|
Reference in New Issue
Block a user