Browse Source

Made developing a little more enjoyable

This commit adds playgrounds and a build:dev mode. Now you
can call npm run build:dev to make the linter warn you about
errors without breaking. Also, we now have playgrounds, where
you can use a built version of svg.js to run your own tests.
tags/3.0.0
Saivan 6 years ago
parent
commit
1cb509f863

+ 33
- 34
bench/svg.bench.js View File

@@ -1,56 +1,55 @@
;( function() {
/* global Snap */

;(function () {
SVG.bench = {
// Initalize test store
_chain: []
, _before: function() {}
, _after: function() {}
, draw: SVG().addTo('#draw')
, snap: Snap(100, 100)
, raw: document.getElementById('native')
_chain: [],
_before: function () {},
_after: function () {},
draw: SVG().addTo('#draw'),
snap: Snap(100, 100),
raw: document.getElementById('native'),

// Add descriptor
, describe: function(name, closure) {
describe: function (name, closure) {
this._chain.push({
name: name
, run: closure
name: name,
run: closure
})

return this
}
},

// Add test
, test: function(name, run) {
test: function (name, run) {
// run test
var start = ( new Date ).getTime()
var start = (new Date()).getTime()
run()
this.write( name, ( new Date ).getTime() - start )
this.write(name, (new Date()).getTime() - start)

// clear everything
this.clear()
}
},

// Skip test
, skip: function(name, run) {
this.write( name, false )
}
skip: function (name, run) {
this.write(name, false)
},

// Run tests
, run: function() {
run: function () {
this.pad()
for (var h, i = 0, il = this._chain.length; i < il; i++) {
var h = document.createElement('h1')
h = document.createElement('h1')
h.innerHTML = this._chain[i].name

this.pad().appendChild(h)

this._chain[i].run(this)
}
}
},
// Write result
, write: function(name, ms) {
write: function (name, ms) {
var test = document.createElement('div')

if (typeof ms === 'number') {
@@ -60,14 +59,14 @@
test.className = 'test skipped'
test.innerHTML = name + ' (skipped)'
}
this.pad().appendChild(test)

return this
}
},

// Reference writable element
, pad: function() {
pad: function () {
var pad = document.getElementById('pad')

if (!pad) {
@@ -76,15 +75,15 @@
}

return pad
}
},

// Clear canvasses
, clear: function() {
while(this.raw.hasChildNodes())
clear: function () {
while (this.raw.hasChildNodes()) {
this.raw.removeChild(this.raw.lastChild)
}
this.draw.clear()
this.snap.clear()
}
}

})();
})()

+ 508
- 375
dist/svg.js
File diff suppressed because it is too large
View File


+ 2
- 2
dist/svg.min.js
File diff suppressed because it is too large
View File


+ 3
- 2
gulpfile.js View File

@@ -98,8 +98,8 @@ gulp.task('unify', ['clean'], function () {
.pipe(standard())
.pipe(standard.reporter('default', {
showRuleNames: true,
breakOnError: true,
quiet: true
breakOnError: process.argv[2] !== "--dont-break",
quiet: true,
}))
.pipe(concat('svg.js', { newLine: '\n' }))
// wrap the whole thing in an immediate function call
@@ -109,6 +109,7 @@ gulp.task('unify', ['clean'], function () {
.pipe(chmod(0o644))
.pipe(gulp.dest('dist'))
.pipe(size({ showFiles: true, title: 'Full' }))
return collection
})
/**

+ 2
- 0
package.json View File

@@ -56,6 +56,7 @@
"scripts": {
"build": "gulp",
"build:test": "gulp unify",
"build:dev": "gulp --dont-break",
"test": "karma start .config/karma.conf.js --single-run",
"test:quick": "karma start .config/karma.quick.js",
"lint": "standard --verbose | snazzy"
@@ -88,6 +89,7 @@
"standard": {
"ignore": [
"/dist",
"/spec",
"/src/umd.js"
],
"globals": [

+ 42
- 0
playgrounds/playground.css View File

@@ -0,0 +1,42 @@

html {
background-color : #f5f6f7;
text-align: center;
}

h1 {
color: #f06;
font-size: 6vh;
margin: 4vh;
font-family: Helvetica;
}

svg {
width: 70vw;
height: 80vh;
background-color: white;
position: fixed;
border-radius: 20px;
border: #f065 1px solid;
left: 15vw;
}

.pink {
fill: #FF0066;
}

.green {
fill: #00ff99;
}

.dark-pink {
fill: #660029;
}

.light-pink {
fill: #FF99C2;
}

.off-white {
fill: #FFCCE0;
}

+ 27
- 0
playgrounds/transforms/transforms.html View File

@@ -0,0 +1,27 @@

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>SVG Playground</title>
<link rel="stylesheet" href="../playground.css">
</head>

<body>

<h1>SVG JS Playground</h1>

<svg viewBox="0 0 1000 1000">

<rect id="old" x=300 y=400 width=200 height=400 class="green"/>
<rect id="new" x=300 y=400 width=200 height=400 class="pink"/>

</svg>

</body>

<script src="../../dist/svg.js" charset="utf-8"></script>
<script src="transforms.js" charset="utf-8"></script>

</html>

+ 7
- 0
playgrounds/transforms/transforms.js View File

@@ -0,0 +1,7 @@

let mover = SVG.select("#new")[0]

console.log(mover.transform());
mover.transform({
position: [30, 50]
})

+ 17
- 18
spec/spec/transformations.js View File

@@ -19,11 +19,11 @@ describe('Transformations:', function() {

describe('SVG.Translate', function() {
var trans
beforeEach(function(){
trans = new SVG.Translate(translated.transform())
})

it('creates an object of type SVG.Transformation', function() {
expect(trans instanceof SVG.Transformation).toBeTruthy()
@@ -51,7 +51,7 @@ describe('Transformations:', function() {
var extracted = (new SVG.Matrix(10,0,0,10,20,20)).extract()
trans.undo(extracted)
expect(trans._undo.toString()).toEqual('matrix(1,0,0,1,-2,-2)')
var extracted = (new SVG.Matrix(10,50,50,30,20,20)).extract()
trans.undo(extracted)
expect(trans._undo.e).toBeCloseTo(-extracted.transformedX)
@@ -78,14 +78,14 @@ describe('Transformations:', function() {
})
})
})
describe('SVG.Rotate', function() {
var trans
beforeEach(function(){
trans = new SVG.Rotate(45, 50, 50)
})

it('creates an object of type SVG.Transformation', function() {
expect(trans instanceof SVG.Transformation).toBeTruthy()
@@ -129,15 +129,15 @@ describe('Transformations:', function() {
})
})
})

describe('SVG.Scale', function() {
var trans
beforeEach(function(){
trans = new SVG.Scale(2,2,50,50)
})

it('creates an object of type SVG.Transformation', function() {
expect(trans instanceof SVG.Transformation).toBeTruthy()
@@ -170,7 +170,7 @@ describe('Transformations:', function() {
expect(trans._undo.d).toBeCloseTo(1/extracted.scaleY)
expect(trans._undo.e).toBeCloseTo(45)
expect(trans._undo.f).toBeCloseTo(45)
var extracted = (new SVG.Matrix(10,50,50,30,20,20)).extract()
trans.undo(extracted)
expect(trans._undo.a).toBeCloseTo(1/extracted.scaleX)
@@ -184,12 +184,12 @@ describe('Transformations:', function() {
})
it('returns the inversed matrix from a specific position when created with inverse flag', function() {
var morphed = (new SVG.Scale(scaled.transform(2,2,50,50), true)).at(0.25)
expect(morphed.a).toBeCloseTo(0.8)
expect(morphed.d).toBeCloseTo(0.8)
})
it('returns the resulting transformation which has to be made to set an absolute translation', function() {
var morphed = trans.undo((new SVG.Matrix(10,0,0,10,0,0)).extract()).at(0.5)

expect(morphed.a).toBeCloseTo(0.6)
@@ -200,15 +200,15 @@ describe('Transformations:', function() {
expect(morphed.f).toBeCloseTo(20)
})
})
})
})

describe('SVG.Skew', function() {
var trans
beforeEach(function(){
trans = new SVG.Skew(30,-30,50,50)
})

it('creates an object of type SVG.Transformation', function() {
expect(trans instanceof SVG.Transformation).toBeTruthy()
@@ -257,7 +257,7 @@ describe('Transformations:', function() {
})
it('returns the inversed matrix from a specific position when created with inverse flag', function() {
var morphed = (new SVG.Scale(skewed.transform(20,-20,50,50), true)).at(0.25)
expect(morphed.a).toBeCloseTo(0.963)
expect(morphed.b).toBeCloseTo(0)
expect(morphed.c).toBeCloseTo(0)
@@ -266,7 +266,7 @@ describe('Transformations:', function() {
expect(morphed.f).toBeCloseTo(0)
})
it('returns the resulting transformation which has to be made to set an absolute translation', function() {
var morphed = trans.undo((new SVG.Matrix(10,0,0,10,0,0)).skew(20, 30, 20, 10).extract()).at(0.5)

expect(morphed.a).toBeCloseTo(1.266)
@@ -278,5 +278,4 @@ describe('Transformations:', function() {
})
})
})

})

+ 94
- 124
src/matrix.js View File

@@ -1,4 +1,4 @@
/* global abcdef, arrayToMatrix, deltaTransformPoint, parseMatrix */
/* global abcdef, arrayToMatrix, parseMatrix, unitCircle, mag */

SVG.Matrix = SVG.invent({
// Initialize
@@ -23,159 +23,130 @@ SVG.Matrix = SVG.invent({
},

// Add methods
, extend: {
extend: {

// Convert an object of affine parameters into a matrix
compose: function (o, cx, cy) {

// Set the defaults
var tx = o.translateX || 0
, ty = o.translateY || 0
, theta = o.theta || 0
, sx = o.scaleX || 1
, sy = o.scaleY || 1
, lam = o.shear || 0
, cx = cx || 0
, cy = cy || 0
var ty = o.translateY || 0
var theta = o.theta || 0
var sx = o.scaleX || 1
var sy = o.scaleY || 1
var lam = o.shear || 0
cx = cx || 0
cy = cy || 0

// Calculate the trigonometric values
var ct = Math.cos(theta * Math.PI / 180)
, st Math.sin(theta * Math.PI / 180)
var st = Math.sin(theta * Math.PI / 180)

// Calculate the matrix components directly
var a = sx * ct
, b = sx * st
, c = lam * sx * ct - sy * st
, d = lam * sx * st + sy * ct
, e = - sx * ct * (cx + cy * lam) + sy * st * cy + tx + cx
, f = - sx * st * (cx + cy * lam) - sy * ct * cy + ty + cy
var b = sx * st
var c = lam * sx * ct - sy * st
var d = lam * sx * st + sy * ct
var e = -sx * ct * (cx + cy * lam) + sy * st * cy + tx + cx
var f = -sx * st * (cx + cy * lam) - sy * ct * cy + ty + cy

// Construct a new matrix and return it
var matrix = new SVG.Matrix([a, b, c, d, e, f])
return matrix
}
},
// Decompose a matrix into the affine parameters needed to form it
, decompose: function (matrix, cx, cy) {

decompose: function (matrix, cx, cy) {
// Get the paramaters of the current matrix
var a = matrix.a
, b = matrix.b
, c = matrix.c
, d = matrix.d
, e = matrix.e
, f = matrix.f
var b = matrix.b
var c = matrix.c
var d = matrix.d
var e = matrix.e
var f = matrix.f

// Project the first basis vector onto the unit circle
var circle = unitCircle (a, b)
, theta = circle.theta
, ct = circle.cos
, st = circle.sin
var circle = unitCircle(a, b)
var theta = circle.theta
var ct = circle.cos
var st = circle.sin

// Work out the transformation parameters
var signX = Math.sign(a * ct + b * st)
, sx = signX * mag (a, b)
, lam = (st * d + ct * c) / (ct * a + st * b)
, signY = Math.sign(- c * st + d * ct)
, sy = mag (lam * a - c, d - lam * b)
, tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy)
, ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy)
var sx = signX * mag(a, b)
var lam = (st * d + ct * c) / (ct * a + st * b)
var sy = mag(lam * a - c, d - lam * b)
var tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy)
var ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy)

// Package and return the parameters
return {

// Bundle the affine parameters
translateX: tx
, translateY: ty
, theta: theta
, scaleX: sx
, scaleY: sy
, shear: lam
translateX: tx,
translateY: ty,
theta: theta,
scaleX: sx,
scaleY: sy,
shear: lam,

// Bundle the matrix parameters
, a: this.a
, b: this.b
, c: this.c
, d: this.d
, e: this.e
, f: this.f

// Return the new origin point
, x: this.e
, y: this.f

// Store the matrix
, matrix: new SVG.Matrix(this)
// translation
x: this.e,
y: this.f,
transformedX: (this.e * Math.cos(skewX * Math.PI / 180) + this.f * Math.sin(skewX * Math.PI / 180)) / Math.sqrt(this.a * this.a + this.b * this.b),
transformedY: (this.f * Math.cos(skewX * Math.PI / 180) + this.e * Math.sin(-skewX * Math.PI / 180)) / Math.sqrt(this.c * this.c + this.d * this.d),
// skew
skewX: -skewX,
skewY: 180 / Math.PI * Math.atan2(py.y, py.x),
// scale
scaleX: Math.sqrt(this.a * this.a + this.b * this.b),
scaleY: Math.sqrt(this.c * this.c + this.d * this.d),
// rotation
rotation: skewX,
a: this.a,
b: this.b,
c: this.c,
d: this.d,
e: this.e,
f: this.f,

// Return the new origin point
x: this.e,
y: this.f,
matrix: new SVG.Matrix(this)
>>>>>>> 3.0.0
}
},
// Clone matrix
, form: function (o) {

// Get all of the parameters required to form the matrix
var flipX = o.flip && (o.flip == "x" || o.flip == "both") ? -1 : 1
, flipY = o.flip && (o.flip == "y" || o.flip == "both") ? -1 : 1
, kX = o.skew.length ? o.skew[0]
form: function (o) {
// Get all of the parameters required to form the matrix
var flipX = o.flip && (o.flip === 'x' || o.flip === 'both') ? -1 : 1
var flipY = o.flip && (o.flip === 'y' || o.flip === 'both') ? -1 : 1
var skewX = o.skew.length ? o.skew[0]
: isFinite(o.skew) ? o.skew
: isFinite(o.skewX) ? o.skewX
: 0
, kY = o.skew.length ? o.skew[1]
var skewY = o.skew.length ? o.skew[1]
: isFinite(o.skew) ? o.skew
: isFinite(o.skewY) ? o.skewY
: 0
, skewX = o.scale.length ? o.scale[0] * flipX
var sx = o.scale.length ? o.scale[0] * flipX
: isFinite(o.scale) ? o.scale * flipX
: isFinite(o.scaleX) ? o.scaleX * flipX
: flipX
, skewY = o.scale.length ? o.scale[1] * flipY
var sy = o.scale.length ? o.scale[1] * flipY
: isFinite(o.scale) ? o.scale * flipY
: isFinite(o.scaleY) ? o.scaleY * flipY
: flipY
, kx = Math.tan(SVG.utils.radians(skewX))
, ky = Math.tan(SVG.utils.radians(skewY))
, lam = o.shear || 0
, theta = SVG.utils.radians(o.rotate || 0)
, st = Math.sin(theta)
, ct = Math.cos(theta)
, ox = o.origin.length ? o.origin[0] : o.ox || 0
, oy = o.origin.length ? o.origin[1] : o.oy || 0
, px = o.position.length ? o.position[0] : o.px || ox
, py = o.position.length ? o.position[1] : o.py || oy
, tx = o.translate.length ? o.translate[0] : o.tx || 0
, ty = o.translate.length ? o.translate[1] : o.ty || 0
var kx = Math.tan(SVG.utils.radians(skewX))
var ky = Math.tan(SVG.utils.radians(skewY))
var lam = o.shear || 0
var theta = SVG.utils.radians(o.rotate || 0)
var st = Math.sin(theta)
var ct = Math.cos(theta)
var ox = o.origin.length ? o.origin[0] : o.ox || 0
var oy = o.origin.length ? o.origin[1] : o.oy || 0
var px = o.position.length ? o.position[0] : o.px || ox
var py = o.position.length ? o.position[1] : o.py || oy
var tx = o.translate.length ? o.translate[0] : o.tx || 0
var ty = o.translate.length ? o.translate[1] : o.ty || 0

// Form the matrix parameters... aka. welcome to wonderland! (used wolfram)
var a = ct*sx + ky*st*sy
, b = ct*ky*sy - st*sx
, c = ct*kx*sx + st*sy + lam*(ct*sx+ky*st*sy)
, d = -kx*st*sx + ct*sy + lam*(-st*sx + ct*ky*sy)
, e = px + tx + cx*(ct*sx+ky*st*sy) + cy*(ct*kx*sx+st*sy+lam*(ct*sx+ky*st*sy))
, f = py + ty + cx*(-st*sx + ct*ky*sy) + cy*(-kx*st*sx + ct*sy + lam*(-st*sx + ct*ky*sy))
, result = new Matrix(a, b, c, d, e, f)
return result
}
, clone: function() {
var a = ct * sx + ky * st * sy
var b = ct * ky * sy - st * sx
var c = ct * kx * sx + st * sy + lam * (ct * sx + ky * st * sy)
var d = -kx * st * sx + ct * sy + lam * (-st * sx + ct * ky * sy)
var e = px + tx + ox * (ct * sx + ky * st * sy) + oy * (ct * kx * sx + st * sy + lam * (ct * sx + ky * st * sy))
var f = py + ty + ox * (-st * sx + ct * ky * sy) + oy * (-kx * st * sx + ct * sy + lam * (-st * sx + ct * ky * sy))
var result = new SVG.Matrix(a, b, c, d, e, f)
return result
},
clone: function () {
>>>>>>> 3.0.0
return new SVG.Matrix(this)
},
// Morph one matrix into another
@@ -211,15 +182,15 @@ SVG.Matrix = SVG.invent({
return new SVG.Matrix(this.native().inverse())
},
// Translate matrix
, translate: function(x, y) {
var translation = new SVG.Matrix(this.native().translate(x || 0, y || 0))
, matrix = this.multiply(translation)
translate: function (x, y) {
var translation = new SVG.Matrix(this.native().translate(x || 0, y || 0))
var matrix = this.multiply(translation)
return matrix
}
},
// Scale matrix
, scale: function(x, y, cx, cy) {
scale: function (x, y, cx, cy) {
// Support uniform scaling
if (arguments.length == 1) {
if (arguments.length === 1) {
y = x
} else if (arguments.length === 3) {
cy = cx
@@ -229,22 +200,21 @@ SVG.Matrix = SVG.invent({

// Rotate the current matrix
var scale = new SVG.Matrix(x, 0, 0, y, 0, 0)
, centered = this.around(cx, cy, rotation)
, matrix = this.multiply(centered)
return scale
}
var centered = this.around(cx, cy, scale)
var matrix = this.multiply(centered)
return matrix
},
// Rotate matrix
, rotate: function(r, cx, cy) {

rotate: function (r, cx, cy) {
// Convert degrees to radians
r = SVG.utils.radians(r)

// Construct the rotation matrix
var rotation = new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0)
, centered = this.around(cx, cy, rotation)
, matrix = this.multiply(centered)
var centered = this.around(cx, cy, rotation)
var matrix = this.multiply(centered)
return matrix
}
},
// Flip matrix on x or y, at a given offset
flip: function (a, o) {
return a === 'x' ? this.scale(-1, 1, o, 0)
@@ -252,13 +222,13 @@ SVG.Matrix = SVG.invent({
: this.scale(-1, -1, a, o != null ? o : a)
},
// Skew
, shear: function(a, cx, cy) {
var shear = new SVG.Matrix(1, a, 0, 1, 0, 0)
, centered = this.around(cx, cy, shear)
, matrix = this.multiply(centered)
return matrix
}
, skew: function(x, y, cx, cy) {
shear: function (a, cx, cy) {
var shear = new SVG.Matrix(1, a, 0, 1, 0, 0)
var centered = this.around(cx, cy, shear)
var matrix = this.multiply(centered)
return matrix
},
skew: function (x, y, cx, cy) {
// support uniformal skew
if (arguments.length === 1) {
y = x
@@ -274,10 +244,10 @@ SVG.Matrix = SVG.invent({

// Construct the matrix
var skew = new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0)
, centered = this.around(cx, cy, skew)
, matrix = this.multiply(centered)
var centered = this.around(cx, cy, skew)
var matrix = this.multiply(centered)
return matrix
}
},
// SkewX
skewX: function (x, cx, cy) {
return this.skew(x, 0, cx, cy)

+ 9
- 9
src/sugar.js View File

@@ -35,17 +35,17 @@ var sugar = {

SVG.extend([SVG.Element, SVG.FX], {
// Map rotation to transform
, rotate: function(angle, cx, cy) {
rotate: function (angle, cx, cy) {
var matrix = new SVG.Matrix().rotate(angle, cx, cy)

return this.transform({ rotation: d, cx: cx, cy: cy })
return this.matrix(matrix, true)
},
// Map skew to transform
, skew: function(x, y, cx, cy) {
return arguments.length == 1 || arguments.length == 3 ?
this.transform({ skew: x, cx: y, cy: cx }) :
this.transform({ skewX: x, skewY: y, cx: cx, cy: cy })
}
skew: function (x, y, cx, cy) {
var matrix = arguments.length === 1 || arguments.length === 3
? new SVG.Matrix().skew(x, x, cx, cy)
: new SVG.Matrix().skew(x, y, cx, cy)
return this.matrix(matrix, true)
},
// Map scale to transform
scale: function (x, y, cx, cy) {
return arguments.length === 1 || arguments.length === 3
@@ -60,7 +60,7 @@ SVG.extend([SVG.Element, SVG.FX], {
flip: function (a, o) {
o = typeof a === 'number' ? a : o
return this.transform({ flip: a || 'both', offset: o })
}
},
// Opacity
opacity: function (value) {
return this.attr('opacity', value)

+ 103
- 301
src/transform.js View File

@@ -1,37 +1,72 @@
/* global ensureCentre, capitalize, arrayToMatrix */
/* global arrayToMatrix */

SVG.extend(SVG.Element, {
// Reset all transformations
untransform: function () {
return this.attr('transform', null)
},

// Add transformations
transform: function (o) {
// merge the whole transformation chain into one matrix and returns it
matrixify: function () {
var matrix = (this.attr('transform') || '')
// split transformations
.split(SVG.regex.transforms).slice(0, -1).map(function (str) {
// generate key => value pairs
var kv = str.trim().split('(')
return [kv[0], kv[1].split(SVG.regex.delimiter).map(function (str) { return parseFloat(str) })]
})
// merge every transformation into one matrix
.reduce(function (matrix, transform) {
if (transform[0] === 'matrix') return matrix.multiply(arrayToMatrix(transform[1]))
return matrix[transform[0]].apply(matrix, transform[1])
}, new SVG.Matrix())

/**
* EXTRACTING PARAMETERS
*/
return matrix
},

// add an element to another parent without changing the visual representation on the screen
toParent: function (parent) {
if (this === parent) return this
var ctm = this.screenCTM()
var pCtm = parent.screenCTM().inverse()

this.addTo(parent).untransform().transform(pCtm.multiply(ctm))

return this
},

// same as above with parent equals root-svg
toDoc: function () {
return this.toParent(this.doc())
}
})

SVG.extend(SVG.Element, {

// Add transformations
transform: function (o) {
// Act as a getter if no object was passed
if (typeof o !== 'object') {
matrix = new SVG.Matrix(this).extract()
var matrix = new SVG.Matrix(this).decompose()
return typeof o === 'string' ? matrix[o] : matrix
}

// Allow the user to define the origin with a string
if (typeof o.origin === "string") {

if (typeof o.origin === 'string') {
// Get the bounding box and string to use in our calculations
var string = o.origin.toLowerCase().trim()
, bbox = this.bbox()
, x = bbox.x
, y = bbox.y
, width = bbox.width
, height = bbox.height
var bbox = this.bbox()
var x = bbox.x
var y = bbox.y
var width = bbox.width
var height = bbox.height

// Set the bounds eg : "bottom-left", "Top right", "middle" etc...
o.ox = string.includes("left") ? x
: string.includes("right") ? x + width
o.ox = string.includes('left') ? x
: string.includes('right') ? x + width
: x + width / 2
o.oy = string.includes("top") ? y
: string.includes("bottom") ? y + height
o.oy = string.includes('top') ? y
: string.includes('bottom') ? y + height
: y + height / 2

// Make sure we only pass ox and oy
@@ -40,71 +75,14 @@ SVG.extend(SVG.Element, {

// Get the resulting matrix and apply it to the element
var result = new SVG.Matrix().form(o)
, matrixString = result.toString()
// get current matrix
matrix = new SVG.Matrix(target)

// ensure relative flag
relative = !!relative || !!o.relative

// act on matrix
if (o.a != null) {
matrix = relative
? matrix.multiply(new SVG.Matrix(o))
: new SVG.Matrix(o)

// act on rotation
} else if (o.rotation != null) {
// ensure centre point
ensureCentre(o, target)

// apply transformation
matrix = relative
? matrix.rotate(o.rotation, o.cx, o.cy)
: matrix.rotate(o.rotation - matrix.extract().rotation, o.cx, o.cy)

// act on scale
} else if (o.scale != null || o.scaleX != null || o.scaleY != null) {
// ensure centre point
ensureCentre(o, target)

// ensure scale values on both axes
o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1
o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1

if (!relative) {
// absolute; multiply inversed values
var e = matrix.extract()
o.scaleX = o.scaleX * 1 / e.scaleX
o.scaleY = o.scaleY * 1 / e.scaleY
}

matrix = matrix.scale(o.scaleX, o.scaleY, o.cx, o.cy)

// act on skew
} else if (o.skew != null || o.skewX != null || o.skewY != null) {
// ensure centre point
ensureCentre(o, target)

// ensure skew values on both axes
o.skewX = o.skew != null ? o.skew : o.skewX != null ? o.skewX : 0
o.skewY = o.skew != null ? o.skew : o.skewY != null ? o.skewY : 0

if (!relative) {
// absolute; reset skew values
var el = matrix.extract()
matrix = matrix.multiply(new SVG.Matrix().skew(el.skewX, el.skewY, el.cx, el.cy).inverse())
}
>>>>>>> 3.0.0
var matrixString = result.toString()

// Apply the result
return this.attr('transform', matrix)
}
}
return this.attr('transform', matrixString)
},

// Map matrix to transform
, matrix: function(m, relative) {

matrix: function (m, relative) {
// Construct a matrix from the first parameter
var matrix = new SVG.Matrix(m)

@@ -120,10 +98,7 @@ SVG.extend(SVG.Element, {
})

SVG.extend(SVG.FX, {
transform: function(o, relative) {



transform: function (o, relative) {

// // get target in case of the fx module, otherwise reference this
// var target = this.target()
@@ -203,90 +178,51 @@ SVG.extend(SVG.FX, {
//
// return this._callStart()
// }
// ensure scale values on both axes
o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1
o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1

matrix = new SVG.Scale(o.scaleX, o.scaleY, o.cx, o.cy)

// act on skew
} else if (o.skewX != null || o.skewY != null) {
// ensure centre point
ensureCentre(o, target)

// ensure skew values on both axes
o.skewX = o.skewX != null ? o.skewX : 0
o.skewY = o.skewY != null ? o.skewY : 0

matrix = new SVG.Skew(o.skewX, o.skewY, o.cx, o.cy)

// act on flip
} else if (o.flip) {
if (o.flip === 'x' || o.flip === 'y') {
o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset
} else {
if (o.offset == null) {
bbox = target.bbox()
o.flip = bbox.cx
o.offset = bbox.cy
} else {
o.flip = o.offset
}
}

matrix = new SVG.Matrix().flip(o.flip, o.offset)

// act on translate
} else if (o.x != null || o.y != null) {
matrix = new SVG.Translate(o.x, o.y)
}

if (!matrix) return this

matrix.relative = relative

this.last().transforms.push(matrix)

return this._callStart()
}
>>>>>>> 3.0.0
})

SVG.extend(SVG.Element, {
// Reset all transformations
untransform: function () {
return this.attr('transform', null)
},
// merge the whole transformation chain into one matrix and returns it
matrixify: function () {
var matrix = (this.attr('transform') || '')
// split transformations
.split(SVG.regex.transforms).slice(0, -1).map(function (str) {
// generate key => value pairs
var kv = str.trim().split('(')
return [kv[0], kv[1].split(SVG.regex.delimiter).map(function (str) { return parseFloat(str) })]
})
// merge every transformation into one matrix
.reduce(function (matrix, transform) {
if (transform[0] === 'matrix') return matrix.multiply(arrayToMatrix(transform[1]))
return matrix[transform[0]].apply(matrix, transform[1])
}, new SVG.Matrix())

return matrix
},
// add an element to another parent without changing the visual representation on the screen
toParent: function (parent) {
if (this === parent) return this
var ctm = this.screenCTM()
var pCtm = parent.screenCTM().inverse()

this.addTo(parent).untransform().transform(pCtm.multiply(ctm))

return this
},
// same as above with parent equals root-svg
toDoc: function () {
return this.toParent(this.doc())
// // ensure scale values on both axes
// o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1
// o.scaleY = o.scale != null ? o.scale : o.scaleY != null ? o.scaleY : 1
//
// matrix = new SVG.Scale(o.scaleX, o.scaleY, o.cx, o.cy)
//
// // act on skew
// } else if (o.skewX != null || o.skewY != null) {
// // ensure centre point
// ensureCentre(o, target)
//
// // ensure skew values on both axes
// o.skewX = o.skewX != null ? o.skewX : 0
// o.skewY = o.skewY != null ? o.skewY : 0
//
// matrix = new SVG.Skew(o.skewX, o.skewY, o.cx, o.cy)
//
// // act on flip
// } else if (o.flip) {
// if (o.flip === 'x' || o.flip === 'y') {
// o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset
// } else {
// if (o.offset == null) {
// bbox = target.bbox()
// o.flip = bbox.cx
// o.offset = bbox.cy
// } else {
// o.flip = o.offset
// }
// }
//
// matrix = new SVG.Matrix().flip(o.flip, o.offset)
//
// // act on translate
// } else if (o.x != null || o.y != null) {
// matrix = new SVG.Translate(o.x, o.y)
// }
//
// if (!matrix) return this
//
// matrix.relative = relative
//
// this.last().transforms.push(matrix)
//
// return this._callStart()
}
})

@@ -432,137 +368,3 @@ SVG.extend(SVG.Element, {
// }
//
// })
SVG.Transformation = SVG.invent({

create: function (source, inversed) {
if (arguments.length > 1 && typeof inversed !== 'boolean') {
return this.constructor.bind(this)([].slice.call(arguments))
}

var i, len
if (Array.isArray(source)) {
for (i = 0, len = this.arguments.length; i < len; ++i) {
this[this.arguments[i]] = source[i]
}
} else if (typeof source === 'object') {
for (i = 0, len = this.arguments.length; i < len; ++i) {
this[this.arguments[i]] = source[this.arguments[i]]
}
}

this.inversed = false

if (inversed === true) {
this.inversed = true
}
},

extend: {

arguments: [],
method: '',

at: function (pos) {
var params = []

for (var i = 0, len = this.arguments.length; i < len; ++i) {
params.push(this[this.arguments[i]])
}

var m = this._undo || new SVG.Matrix()

m = new SVG.Matrix().morph(SVG.Matrix.prototype[this.method].apply(m, params)).at(pos)

return this.inversed ? m.inverse() : m
},

undo: function (o) {
for (var i = 0, len = this.arguments.length; i < len; ++i) {
o[this.arguments[i]] = typeof this[this.arguments[i]] === 'undefined' ? 0 : o[this.arguments[i]]
}

// The method SVG.Matrix.extract which was used before calling this
// method to obtain a value for the parameter o doesn't return a cx and
// a cy so we use the ones that were provided to this object at its creation
o.cx = this.cx
o.cy = this.cy

this._undo = new SVG[capitalize(this.method)](o, true).at(1)
return this
}

}

})

SVG.Translate = SVG.invent({

parent: SVG.Matrix,
inherit: SVG.Transformation,

create: function (source, inversed) {
this.constructor.apply(this, [].slice.call(arguments))
},

extend: {
arguments: ['transformedX', 'transformedY'],
method: 'translate'
}

})

SVG.Rotate = SVG.invent({

parent: SVG.Matrix,
inherit: SVG.Transformation,

create: function (source, inversed) {
this.constructor.apply(this, [].slice.call(arguments))
},

extend: {
arguments: ['rotation', 'cx', 'cy'],
method: 'rotate',
at: function (pos) {
var m = new SVG.Matrix().rotate(new SVG.Number().morph(this.rotation - (this._undo ? this._undo.rotation : 0)).at(pos), this.cx, this.cy)
return this.inversed ? m.inverse() : m
},
undo: function (o) {
this._undo = o
return this
}
}

})

SVG.Scale = SVG.invent({

parent: SVG.Matrix,
inherit: SVG.Transformation,

create: function (source, inversed) {
this.constructor.apply(this, [].slice.call(arguments))
},

extend: {
arguments: ['scaleX', 'scaleY', 'cx', 'cy'],
method: 'scale'
}

})

SVG.Skew = SVG.invent({

parent: SVG.Matrix,
inherit: SVG.Transformation,

create: function (source, inversed) {
this.constructor.apply(this, [].slice.call(arguments))
},

extend: {
arguments: ['skewX', 'skewY', 'cx', 'cy'],
method: 'skew'
}
})
>>>>>>> 3.0.0

+ 1
- 0
src/utilities.js View File

@@ -1,3 +1,4 @@

SVG.utils = {
// Map function
map: function (array, block) {

Loading…
Cancel
Save