svg.filter.js
A plugin for svg.js adding filter functionality.
svg.filter.js is licensed under the terms of the MIT License.
Usage
Npm
npm i @svgdotjs/svg.filter.js
Yarn
yarn add @svgdotjs/svg.filter.js
Include this plugin after including the svg.js library in your html document.
Here is how each filter effect on the example page is achieved.
Examples
original
var image = draw.image('path/to/image.jpg').size(300, 300)
gaussian blur
image.filterWith(function(add) {
add.gaussianBlur(30)
})
horizontal blur
image.filterWith(function(add) {
add.gaussianBlur(30, 0)
})
desaturate
image.filterWith(function(add) {
add.colorMatrix('saturate', 0)
})
contrast
image.filterWith(function(add) {
var amount = 1.5
add.componentTransfer({
type: 'linear',
slope: amount,
intercept: -(0.3 * amount) + 0.3
})
})
sepiatone
image.filterWith(function(add) {
add.colorMatrix('matrix', [ .343, .669, .119, 0, 0
, .249, .626, .130, 0, 0
, .172, .334, .111, 0, 0
, .000, .000, .000, 1, 0 ])
})
hue rotate 180
image.filterWith(function(add) {
add.colorMatrix('hueRotate', 180)
})
luminance to alpha
image.filterWith(function(add) {
add.colorMatrix('luminanceToAlpha')
})
colorize
image.filterWith(function(add) {
add.colorMatrix('matrix', [ 1.0, 0, 0, 0, 0
, 0, 0.2, 0, 0, 0
, 0, 0, 0.2, 0, 0
, 0, 0, 0, 1.0, 0 ])
})
posterize
image.filterWith(function(add) {
add.componentTransfer({
type: 'discrete',
tableValues: [0, 0.2, 0.4, 0.6, 0.8, 1]
})
})
darken
image.filterWith(function(add) {
add.componentTransfer({
type: 'linear',
slope: 0.2
})
})
lighten
image.filterWith(function(add) {
add.componentTransfer({
type: 'linear',
slope: 1.5,
intercept: 0.2
})
})
invert
image.filterWith(function(add) {
add.componentTransfer({
type: 'table'
tableValues: [1, 0]
})
})
gamma correct 1
image.filterWith(function(add) {
add.componentTransfer({
g: { type: 'gamma', amplitude: 1, exponent: 0.5 }
})
})
gamma correct 2
image.filterWith(function(add) {
add.componentTransfer({
g: { type: 'gamma', amplitude: 1, exponent: 0.5, offset: -0.1 }
})
})
drop shadow
You will notice that all the effect descriptions have a drop shadow. Here is how this drop shadow can be achieved:
var text = draw.text('SVG text with drop shadow').fill('#fff')
text.filterWith(function(add) {
var blur = add.offset(0, 1).in(add.$sourceAlpha).gaussianBlur(1)
add.blend(add.$source, blur)
})
This technique can be achieved on any other shape of course:
var rect = draw.rect(100,100).fill('#f09').stroke({ width: 3, color: '#0f9' }).move(10,10)
rect.filterWith(function(add) {
var blur = add.offset(20, 20).in(add.$sourceAlpha).gaussianBlur(5)
add.blend(add.$source, blur)
this.size('200%','200%').move('-50%', '-50%')
})
If the drop shadow should get the colour of the shape so it appears like coloured glass:
var rect = draw.rect(100,100).fill('#f09').stroke({ width: 3, color: '#0f9' }).move(10,10)
rect.filterWith(function(add) {
var blur = add.offset(20, 20).gaussianBlur(5)
add.blend(add.$source, blur)
this.size('200%','200%').move('-50%', '-50%')
})
extrude
image.filterWith(function(add){
var matrix = add.convolveMatrix([
1,0,0,0,0,0,
0,1,0,0,0,0,
0,0,1,0,0,0,
0,0,0,1,0,0,
0,0,0,0,1,0,
0,0,0,0,0,1
]).attr({
devisor: '2',
preserveAlpha: 'false'
}).in(add.$sourceAlpha)
var color = add.composite(add.flood('#ff2222'),matrix,'in');
add.merge(color,add.$source);
})
Furthermore
Some more features you should know about.
unfilter
The unfilter
method removes the filter attribute from the node:
image.unfilter()
creating a reusable filter
its also posible to create a filter by using the new
keyword
NOTE: when creating a filter this way, it can take an optional attr object
var filter = new SVG.Filter();
filter.offset(20, 20).gaussianBlur(5);
filter.blend(filter.$source, blur);
filter.size('200%','200%').move('-50%', '-50%')
then once you have created the filter you can use it one multiple elements
var image = new SVG.Image();
var shape = new SVG.Rect(10, 10);
image.filterWith(filter);
shape.filterWith(filter);
referencing the filter node
An internal reference to the filter node is made in the element:
image.filterer()
This can also be very useful to reuse an existing filter on various elements:
otherimage.filterWith(image.filterer())
Animating filter values
Every filter value can be animated as well:
var hueRotate
image.filterWith(function(add) {
hueRotate = add.colorMatrix('hueRotate', 0)
})
hueRotate.animate(3000).attr('values', 360)
Chaining Effects
Method chaining is a programing style where each function returns the object it belongs to, for an example look at JQuery.
it's possible to chain the effects on a filter when you are creating them, for example:
image.filterWith(function(add){
add.flood('black',0.5).composite(add.$sourceAlpha,'in').offset(10).merge(add.$source)
})
this would create a basic shadow filter where the first input on the composite
effect would be the flood
effect, and the input on the offset effect would be the composite
effect.
same with the merge
effect, its first input would be the offset
effect, and its second input would be add.$source
some effects like Merge, Blend, Composite, DisplacementMap have thier arguments changed when they are chained, for example
image.filterWith(function(add){
add.flood('black',0.5).composite(add.$sourceAlpha,'in')
})
the composite
effects first input is set to the flood
effect and its second input becomes the first argument, this is the same for the merge, blend, composite, and displacmentMap effect.
for more details check out each effects doc below
Effect Classes
Base Effect Class
in(effect)
gets or sets the in
attribute of the effect
in2(effect)
gets or sets the in2
attribute of the effect
this function works the same as the in method.
it's only on effects (Blend, Composite, and DisplacementMap)
result(string)
gets or sets the result
attribute of the effect
- string: if a string is provided it will set the value of the
result
attribute.
if no arguments are provided it will act as a getter and return the value of the result
attribute
Blend
W3 doc
filter.blend(in1, in2, mode)
new SVG.BlendEffect({in1, in2, mode})
- in1: an effect or the result of effect
- in2: same as in1
- mode: "normal | multiply | screen | darken | lighten" defaults to "normal"
chaining when this effect is called right after another effect, for example:
filter.offset(10).blend(filter.$source)
the first input is set to the offset
effect and the second input is set to filter.$source
or what ever was passed as the first argument, and the second input becomes the mode
ColorMatrix
W3 doc
filter.colorMatrix(type, values);
new SVG.ColorMatrixEffect({type, values});
- type: "matrix | saturate | hueRotate | luminanceToAlpha"
- values
- type="matrix": values would be a matrix the size of 4x5
- type="saturate": number (0 to 1)
- type="hueRotate": number (0 to 360) deg
- type="luminanceToAlpha": value not needed
ComponentTransfer
W3 doc
filter.componentTransfer(components);
filter.componentTransfer(function (add) { add.funcA({ type... }) });
new SVG.ComponentTransferEffect();
- components: an object which is set for all chanels or
r
, g
, b
, a
properties for each chanel
type: "identity | table | discrete | linear | gamma",
tableValues: "0 0.5 2 1",
slope: 1,
intercept: 3,
amplitude: 0,
exponent: 0,
offset: 0
}
Composite
W3 doc
filter.composite(in1, in2, operator);
new SVG.CompositeEffect({in1, in2, operator});
- in1: an effect or the result of an effect
- in2: same as in1
- operator: "over | in | out | atop | xor | arithmetic" defaults to "over"
chaining when this effect is called right after another effect, for example:
filter.flood('black',0.5).composite(filter.$sourceAlpha,'in')
the first input is set to the flood
effect and the second input is set to filter.$sourceAlpha
or what ever was passed as the first argument.
also the second argument becomes the operator
ConvolveMatrix
W3 doc
filter.convolveMatrix(matrix);
new SVG.ConvolveMatrixEffect({matrix});
- matrix: a square matrix of numbers that will be applied to the image
[
1,0,0,
0,1,0,
0,0,1
]
DiffuseLighting
W3 doc
filter.diffuseLighting(surfaceScale, lightingColor, diffuseConstant, kernelUnitLength);
new SVG.DiffuseLightingEffect({surfaceScale, lightingColor, diffuseConstant, kernelUnitLength});
very complicated, just check out the W3 doc
DisplacementMap
W3 doc
filter.displacementMap(in1, in2, scale, xChannelSelector, yChannelSelector);
new SVG.DisplacementMapEffect({in1, in2, scale, xChannelSelector, yChannelSelector});
very complicated, just check out the W3 doc
chaining when this effect is called right after another effect, for example:
filter.offset(20,50).displacementMap(filter.$source,2)
the first input is set to the offset
effect and the second input is set to filter.$source
or what ever was passed as the first argument.
also the second argument becomes the scale, and the third argument is the xChannelSelector and so on
Flood
W3 doc
filter.flood(color,opacity);
new SVG.FloodEffect(color,opacity);
- color: a named or hex color in string format
- opacity: number form 0 to 1
GaussianBlur
W3 doc
filter.gaussianBlur(x, y);
new SVG.GaussianBlurEffect({x, y});
- x: blur on the X
- y: blur on the y, will default to the x if not provided
Image
W3 doc
filter.image(src);
new SVG.ImageEffect({src});
Merge
W3 doc
filter.merge();
new SVG.MergeEffect();
- Array: an Array of effects or effect results
filter.merge([effectOne,"result-two",another_effect])
- chaining you can also chain the merge effect
filter.offset(10).merge(anotherEffect)
which will result in a merge effect with its first input set to the offset
effect and its second input set to anotherEffect
Morphology
W3 doc
filter.morphology(operator, radius);
new SVG.MorphologyEffect({operator, radius});
- operator: "erode | dilate"
- radius: a single number or a string of two numbers separated by a space
- the first number is the X
- the second number is the Y, if no second number was provided it will default to the first number
Offset
W3 doc
filter.offset(x, y);
new SVG.OffsetEffect({x, y});
- x: move on the X
- y: move on the y, will default to the x if not provided
SpecularLighting
W3 doc
filter.specularLighting(surfaceScale, lightingColor, diffuseConstant, specularExponent, kernelUnitLength);
new SVG.SpecularLightingEffect(surfaceScale, lightingColor, diffuseConstant, specularExponent, kernelUnitLength);
very complicated, just check out the W3 doc
Tile
W3 doc
filter.tile();
new SVG.TileEffect();
no arguments, but if you want to find out what it does check out the W3 doc
Turbulence
W3 doc
filter.turbulence(baseFrequency, numOctaves, seed, stitchTiles, type);
new SVG.TurbulenceEffect({baseFrequency, numOctaves, seed, stitchTiles, type});
very complicated, just check out the W3 doc