349 lines
10 KiB
JavaScript
349 lines
10 KiB
JavaScript
|
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
import eve from './eve.js'
|
||
|
import { Snap } from './svg.js'
|
||
|
|
||
|
Snap.plugin(function (Snap, Element, Paper, glob) {
|
||
|
var elproto = Element.prototype,
|
||
|
pproto = Paper.prototype,
|
||
|
rgurl = /^\s*url\((.+)\)/,
|
||
|
Str = String,
|
||
|
$ = Snap._.$
|
||
|
Snap.filter = {}
|
||
|
/*\
|
||
|
* Paper.filter
|
||
|
[ method ]
|
||
|
**
|
||
|
* Creates a `<filter>` element
|
||
|
**
|
||
|
- filstr (string) SVG fragment of filter provided as a string
|
||
|
= (object) @Element
|
||
|
* Note: It is recommended to use filters embedded into the page inside an empty SVG element.
|
||
|
> Usage
|
||
|
| var f = paper.filter('<feGaussianBlur stdDeviation="2"/>'),
|
||
|
| c = paper.circle(10, 10, 10).attr({
|
||
|
| filter: f
|
||
|
| });
|
||
|
\*/
|
||
|
pproto.filter = function (filstr) {
|
||
|
var paper = this
|
||
|
if (paper.type != 'svg') {
|
||
|
paper = paper.paper
|
||
|
}
|
||
|
var f = Snap.parse(Str(filstr)),
|
||
|
id = Snap._.id(),
|
||
|
width = paper.node.offsetWidth,
|
||
|
height = paper.node.offsetHeight,
|
||
|
filter = $('filter')
|
||
|
$(filter, {
|
||
|
id: id,
|
||
|
filterUnits: 'userSpaceOnUse'
|
||
|
})
|
||
|
filter.appendChild(f.node)
|
||
|
paper.defs.appendChild(filter)
|
||
|
return new Element(filter)
|
||
|
}
|
||
|
|
||
|
eve.on('snap.util.getattr.filter', function () {
|
||
|
eve.stop()
|
||
|
var p = $(this.node, 'filter')
|
||
|
if (p) {
|
||
|
var match = Str(p).match(rgurl)
|
||
|
return match && Snap.select(match[1])
|
||
|
}
|
||
|
})
|
||
|
eve.on('snap.util.attr.filter', function (value) {
|
||
|
if (value instanceof Element && value.type == 'filter') {
|
||
|
eve.stop()
|
||
|
var id = value.node.id
|
||
|
if (!id) {
|
||
|
$(value.node, { id: value.id })
|
||
|
id = value.id
|
||
|
}
|
||
|
$(this.node, {
|
||
|
filter: Snap.url(id)
|
||
|
})
|
||
|
}
|
||
|
if (!value || value == 'none') {
|
||
|
eve.stop()
|
||
|
this.node.removeAttribute('filter')
|
||
|
}
|
||
|
})
|
||
|
/*\
|
||
|
* Snap.filter.blur
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns an SVG markup string for the blur filter
|
||
|
**
|
||
|
- x (number) amount of horizontal blur, in pixels
|
||
|
- y (number) #optional amount of vertical blur, in pixels
|
||
|
= (string) filter representation
|
||
|
> Usage
|
||
|
| var f = paper.filter(Snap.filter.blur(5, 10)),
|
||
|
| c = paper.circle(10, 10, 10).attr({
|
||
|
| filter: f
|
||
|
| });
|
||
|
\*/
|
||
|
Snap.filter.blur = function (x, y) {
|
||
|
if (x == null) {
|
||
|
x = 2
|
||
|
}
|
||
|
var def = y == null ? x : [x, y]
|
||
|
return Snap.format('<feGaussianBlur stdDeviation="{def}"/>', {
|
||
|
def: def
|
||
|
})
|
||
|
}
|
||
|
Snap.filter.blur.toString = function () {
|
||
|
return this()
|
||
|
}
|
||
|
/*\
|
||
|
* Snap.filter.shadow
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns an SVG markup string for the shadow filter
|
||
|
**
|
||
|
- dx (number) #optional horizontal shift of the shadow, in pixels
|
||
|
- dy (number) #optional vertical shift of the shadow, in pixels
|
||
|
- blur (number) #optional amount of blur
|
||
|
- color (string) #optional color of the shadow
|
||
|
- opacity (number) #optional `0..1` opacity of the shadow
|
||
|
* or
|
||
|
- dx (number) #optional horizontal shift of the shadow, in pixels
|
||
|
- dy (number) #optional vertical shift of the shadow, in pixels
|
||
|
- color (string) #optional color of the shadow
|
||
|
- opacity (number) #optional `0..1` opacity of the shadow
|
||
|
* which makes blur default to `4`. Or
|
||
|
- dx (number) #optional horizontal shift of the shadow, in pixels
|
||
|
- dy (number) #optional vertical shift of the shadow, in pixels
|
||
|
- opacity (number) #optional `0..1` opacity of the shadow
|
||
|
= (string) filter representation
|
||
|
> Usage
|
||
|
| var f = paper.filter(Snap.filter.shadow(0, 2, .3)),
|
||
|
| c = paper.circle(10, 10, 10).attr({
|
||
|
| filter: f
|
||
|
| });
|
||
|
\*/
|
||
|
Snap.filter.shadow = function (dx, dy, blur, color, opacity) {
|
||
|
if (opacity == null) {
|
||
|
if (color == null) {
|
||
|
opacity = blur
|
||
|
blur = 4
|
||
|
color = '#000'
|
||
|
} else {
|
||
|
opacity = color
|
||
|
color = blur
|
||
|
blur = 4
|
||
|
}
|
||
|
}
|
||
|
if (blur == null) {
|
||
|
blur = 4
|
||
|
}
|
||
|
if (opacity == null) {
|
||
|
opacity = 1
|
||
|
}
|
||
|
if (dx == null) {
|
||
|
dx = 0
|
||
|
dy = 2
|
||
|
}
|
||
|
if (dy == null) {
|
||
|
dy = dx
|
||
|
}
|
||
|
color = Snap.color(color)
|
||
|
return Snap.format(
|
||
|
'<feGaussianBlur in="SourceAlpha" stdDeviation="{blur}"/><feOffset dx="{dx}" dy="{dy}" result="offsetblur"/><feFlood flood-color="{color}"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="{opacity}"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>',
|
||
|
{
|
||
|
color: color,
|
||
|
dx: dx,
|
||
|
dy: dy,
|
||
|
blur: blur,
|
||
|
opacity: opacity
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
Snap.filter.shadow.toString = function () {
|
||
|
return this()
|
||
|
}
|
||
|
/*\
|
||
|
* Snap.filter.grayscale
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns an SVG markup string for the grayscale filter
|
||
|
**
|
||
|
- amount (number) amount of filter (`0..1`)
|
||
|
= (string) filter representation
|
||
|
\*/
|
||
|
Snap.filter.grayscale = function (amount) {
|
||
|
if (amount == null) {
|
||
|
amount = 1
|
||
|
}
|
||
|
return Snap.format(
|
||
|
'<feColorMatrix type="matrix" values="{a} {b} {c} 0 0 {d} {e} {f} 0 0 {g} {b} {h} 0 0 0 0 0 1 0"/>',
|
||
|
{
|
||
|
a: 0.2126 + 0.7874 * (1 - amount),
|
||
|
b: 0.7152 - 0.7152 * (1 - amount),
|
||
|
c: 0.0722 - 0.0722 * (1 - amount),
|
||
|
d: 0.2126 - 0.2126 * (1 - amount),
|
||
|
e: 0.7152 + 0.2848 * (1 - amount),
|
||
|
f: 0.0722 - 0.0722 * (1 - amount),
|
||
|
g: 0.2126 - 0.2126 * (1 - amount),
|
||
|
h: 0.0722 + 0.9278 * (1 - amount)
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
Snap.filter.grayscale.toString = function () {
|
||
|
return this()
|
||
|
}
|
||
|
/*\
|
||
|
* Snap.filter.sepia
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns an SVG markup string for the sepia filter
|
||
|
**
|
||
|
- amount (number) amount of filter (`0..1`)
|
||
|
= (string) filter representation
|
||
|
\*/
|
||
|
Snap.filter.sepia = function (amount) {
|
||
|
if (amount == null) {
|
||
|
amount = 1
|
||
|
}
|
||
|
return Snap.format(
|
||
|
'<feColorMatrix type="matrix" values="{a} {b} {c} 0 0 {d} {e} {f} 0 0 {g} {h} {i} 0 0 0 0 0 1 0"/>',
|
||
|
{
|
||
|
a: 0.393 + 0.607 * (1 - amount),
|
||
|
b: 0.769 - 0.769 * (1 - amount),
|
||
|
c: 0.189 - 0.189 * (1 - amount),
|
||
|
d: 0.349 - 0.349 * (1 - amount),
|
||
|
e: 0.686 + 0.314 * (1 - amount),
|
||
|
f: 0.168 - 0.168 * (1 - amount),
|
||
|
g: 0.272 - 0.272 * (1 - amount),
|
||
|
h: 0.534 - 0.534 * (1 - amount),
|
||
|
i: 0.131 + 0.869 * (1 - amount)
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
Snap.filter.sepia.toString = function () {
|
||
|
return this()
|
||
|
}
|
||
|
/*\
|
||
|
* Snap.filter.saturate
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns an SVG markup string for the saturate filter
|
||
|
**
|
||
|
- amount (number) amount of filter (`0..1`)
|
||
|
= (string) filter representation
|
||
|
\*/
|
||
|
Snap.filter.saturate = function (amount) {
|
||
|
if (amount == null) {
|
||
|
amount = 1
|
||
|
}
|
||
|
return Snap.format('<feColorMatrix type="saturate" values="{amount}"/>', {
|
||
|
amount: 1 - amount
|
||
|
})
|
||
|
}
|
||
|
Snap.filter.saturate.toString = function () {
|
||
|
return this()
|
||
|
}
|
||
|
/*\
|
||
|
* Snap.filter.hueRotate
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns an SVG markup string for the hue-rotate filter
|
||
|
**
|
||
|
- angle (number) angle of rotation
|
||
|
= (string) filter representation
|
||
|
\*/
|
||
|
Snap.filter.hueRotate = function (angle) {
|
||
|
angle = angle || 0
|
||
|
return Snap.format('<feColorMatrix type="hueRotate" values="{angle}"/>', {
|
||
|
angle: angle
|
||
|
})
|
||
|
}
|
||
|
Snap.filter.hueRotate.toString = function () {
|
||
|
return this()
|
||
|
}
|
||
|
/*\
|
||
|
* Snap.filter.invert
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns an SVG markup string for the invert filter
|
||
|
**
|
||
|
- amount (number) amount of filter (`0..1`)
|
||
|
= (string) filter representation
|
||
|
\*/
|
||
|
Snap.filter.invert = function (amount) {
|
||
|
if (amount == null) {
|
||
|
amount = 1
|
||
|
}
|
||
|
// <feColorMatrix type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" color-interpolation-filters="sRGB"/>
|
||
|
return Snap.format(
|
||
|
'<feComponentTransfer><feFuncR type="table" tableValues="{amount} {amount2}"/><feFuncG type="table" tableValues="{amount} {amount2}"/><feFuncB type="table" tableValues="{amount} {amount2}"/></feComponentTransfer>',
|
||
|
{
|
||
|
amount: amount,
|
||
|
amount2: 1 - amount
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
Snap.filter.invert.toString = function () {
|
||
|
return this()
|
||
|
}
|
||
|
/*\
|
||
|
* Snap.filter.brightness
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns an SVG markup string for the brightness filter
|
||
|
**
|
||
|
- amount (number) amount of filter (`0..1`)
|
||
|
= (string) filter representation
|
||
|
\*/
|
||
|
Snap.filter.brightness = function (amount) {
|
||
|
if (amount == null) {
|
||
|
amount = 1
|
||
|
}
|
||
|
return Snap.format(
|
||
|
'<feComponentTransfer><feFuncR type="linear" slope="{amount}"/><feFuncG type="linear" slope="{amount}"/><feFuncB type="linear" slope="{amount}"/></feComponentTransfer>',
|
||
|
{
|
||
|
amount: amount
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
Snap.filter.brightness.toString = function () {
|
||
|
return this()
|
||
|
}
|
||
|
/*\
|
||
|
* Snap.filter.contrast
|
||
|
[ method ]
|
||
|
**
|
||
|
* Returns an SVG markup string for the contrast filter
|
||
|
**
|
||
|
- amount (number) amount of filter (`0..1`)
|
||
|
= (string) filter representation
|
||
|
\*/
|
||
|
Snap.filter.contrast = function (amount) {
|
||
|
if (amount == null) {
|
||
|
amount = 1
|
||
|
}
|
||
|
return Snap.format(
|
||
|
'<feComponentTransfer><feFuncR type="linear" slope="{amount}" intercept="{amount2}"/><feFuncG type="linear" slope="{amount}" intercept="{amount2}"/><feFuncB type="linear" slope="{amount}" intercept="{amount2}"/></feComponentTransfer>',
|
||
|
{
|
||
|
amount: amount,
|
||
|
amount2: 0.5 - amount / 2
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
Snap.filter.contrast.toString = function () {
|
||
|
return this()
|
||
|
}
|
||
|
})
|