189 lines
6.1 KiB
JavaScript
189 lines
6.1 KiB
JavaScript
/**
|
|
* {}
|
|
* @author yutent<yutent.io@gmail.com>
|
|
* @date 2024/03/07 16:04:23
|
|
*/
|
|
|
|
import eve from './eve.js'
|
|
import { select, SnapElement } from './svg.js'
|
|
import { $, url } from './utils.js'
|
|
import { parseColor } from './lib/color.js'
|
|
|
|
let rgurl = /^\s*url\((.+)\)/,
|
|
Str = String
|
|
|
|
eve.on('snap.util.getattr.filter', function () {
|
|
eve.stop()
|
|
let p = $(this.node, 'filter')
|
|
if (p) {
|
|
let match = Str(p).match(rgurl)
|
|
return match && select(match[1])
|
|
}
|
|
})
|
|
eve.on('snap.util.attr.filter', function (value) {
|
|
if (value instanceof SnapElement && value.type == 'filter') {
|
|
eve.stop()
|
|
let id = value.node.id
|
|
if (!id) {
|
|
$(value.node, { id: value.id })
|
|
id = value.id
|
|
}
|
|
$(this.node, {
|
|
filter: url(id)
|
|
})
|
|
}
|
|
if (!value || value == 'none') {
|
|
eve.stop()
|
|
this.node.removeAttribute('filter')
|
|
}
|
|
})
|
|
|
|
export const filter = {
|
|
/**
|
|
* 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
|
|
| let f = paper.filter(filter.blur(5, 10)),
|
|
| c = paper.circle(10, 10, 10).attr({
|
|
| filter: f
|
|
| });
|
|
*/
|
|
blur(x, y) {
|
|
if (x == null) {
|
|
x = 2
|
|
}
|
|
let def = y == null ? x : [x, y]
|
|
return `<feGaussianBlur stdDeviation="${def}"/>`
|
|
},
|
|
|
|
/**
|
|
* 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
|
|
let f = paper.filter(filter.shadow(0, 2, .3)),
|
|
c = paper.circle(10, 10, 10).attr({
|
|
filter: f
|
|
});
|
|
*/
|
|
shadow(dx = 0, dy = 2, blur = 4, color = '#000', opacity = 1) {
|
|
color = parseColor(color)
|
|
return `<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>`
|
|
},
|
|
|
|
/**
|
|
* Returns an SVG markup string for the grayscale filter
|
|
**
|
|
- amount (number) amount of filter (`0..1`)
|
|
= (string) filter representation
|
|
*/
|
|
grayscale(amount = 1) {
|
|
let a = 0.2126 + 0.7874 * (1 - amount)
|
|
let b = 0.7152 - 0.7152 * (1 - amount)
|
|
let c = 0.0722 - 0.0722 * (1 - amount)
|
|
let d = 0.2126 - 0.2126 * (1 - amount)
|
|
let e = 0.7152 + 0.2848 * (1 - amount)
|
|
let f = 0.0722 - 0.0722 * (1 - amount)
|
|
let g = 0.2126 - 0.2126 * (1 - amount)
|
|
let h = 0.0722 + 0.9278 * (1 - amount)
|
|
|
|
return `<feColorMatrix type="matrix" values="${a} ${b} ${c} 0 0 ${d} ${e} ${f} 0 0 ${g} ${b} ${h} 0 0 0 0 0 1 0"/>`
|
|
},
|
|
|
|
/**
|
|
* Returns an SVG markup string for the sepia filter
|
|
**
|
|
- amount (number) amount of filter (`0..1`)
|
|
= (string) filter representation
|
|
*/
|
|
sepia(amount = 1) {
|
|
let a = 0.393 + 0.607 * (1 - amount)
|
|
let b = 0.769 - 0.769 * (1 - amount)
|
|
let c = 0.189 - 0.189 * (1 - amount)
|
|
let d = 0.349 - 0.349 * (1 - amount)
|
|
let e = 0.686 + 0.314 * (1 - amount)
|
|
let f = 0.168 - 0.168 * (1 - amount)
|
|
let g = 0.272 - 0.272 * (1 - amount)
|
|
let h = 0.534 - 0.534 * (1 - amount)
|
|
let i = 0.131 + 0.869 * (1 - amount)
|
|
|
|
return `<feColorMatrix type="matrix" values="${a} ${b} ${c} 0 0 ${d} ${e} ${f} 0 0 ${g} ${h} ${i} 0 0 0 0 0 1 0"/>`
|
|
},
|
|
|
|
/**
|
|
* Returns an SVG markup string for the saturate filter
|
|
**
|
|
- amount (number) amount of filter (`0..1`)
|
|
= (string) filter representation
|
|
*/
|
|
saturate(amount = 1) {
|
|
return `<feColorMatrix type="saturate" values="${1 - amount}"/>`
|
|
},
|
|
|
|
/**
|
|
* Returns an SVG markup string for the hue-rotate filter
|
|
**
|
|
- angle (number) angle of rotation
|
|
= (string) filter representation
|
|
*/
|
|
hueRotate(angle) {
|
|
angle = angle || 0
|
|
return `<feColorMatrix type="hueRotate" values="${angle}"/>`
|
|
},
|
|
|
|
/**
|
|
* Returns an SVG markup string for the invert filter
|
|
**
|
|
- amount (number) amount of filter (`0..1`)
|
|
= (string) filter representation
|
|
*/
|
|
invert(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 `<feComponentTransfer><feFuncR type="table" tableValues="${amount} ${
|
|
1 - amount
|
|
}"/><feFuncG type="table" tableValues="${amount} ${
|
|
1 - amount
|
|
}"/><feFuncB type="table" tableValues="${amount} ${
|
|
1 - amount
|
|
}"/></feComponentTransfer>`
|
|
},
|
|
|
|
/**
|
|
* Returns an SVG markup string for the brightness filter
|
|
**
|
|
- amount (number) amount of filter (`0..1`)
|
|
= (string) filter representation
|
|
*/
|
|
brightness(amount = 1) {
|
|
return `<feComponentTransfer><feFuncR type="linear" slope="${amount}"/><feFuncG type="linear" slope="${amount}"/><feFuncB type="linear" slope="${amount}"/></feComponentTransfer>`
|
|
},
|
|
|
|
/**
|
|
* Returns an SVG markup string for the contrast filter
|
|
**
|
|
- amount (number) amount of filter (`0..1`)
|
|
= (string) filter representation
|
|
*/
|
|
contrast(amount = 1) {
|
|
let amount2 = 0.5 - amount / 2
|
|
return `<feComponentTransfer><feFuncR type="linear" slope="${amount}" intercept="${amount2}"/><feFuncG type="linear" slope="${amount}" intercept="${amount2}"/><feFuncB type="linear" slope="${amount}" intercept="${amount2}"/></feComponentTransfer>`
|
|
}
|
|
}
|