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.
This commit is contained in:
Saivan 2018-02-27 17:23:59 +11:00
parent 4b078f8732
commit 1cb509f863
13 changed files with 851 additions and 868 deletions

View File

@ -1,56 +1,55 @@
;( function() { /* global Snap */
;(function () {
SVG.bench = { SVG.bench = {
// Initalize test store // Initalize test store
_chain: [] _chain: [],
, _before: function() {} _before: function () {},
, _after: function() {} _after: function () {},
, draw: SVG().addTo('#draw') draw: SVG().addTo('#draw'),
, snap: Snap(100, 100) snap: Snap(100, 100),
, raw: document.getElementById('native') raw: document.getElementById('native'),
// Add descriptor // Add descriptor
, describe: function(name, closure) { describe: function (name, closure) {
this._chain.push({ this._chain.push({
name: name name: name,
, run: closure run: closure
}) })
return this return this
} },
// Add test // Add test
, test: function(name, run) { test: function (name, run) {
// run test // run test
var start = ( new Date ).getTime() var start = (new Date()).getTime()
run() run()
this.write( name, ( new Date ).getTime() - start ) this.write(name, (new Date()).getTime() - start)
// clear everything // clear everything
this.clear() this.clear()
} },
// Skip test // Skip test
, skip: function(name, run) { skip: function (name, run) {
this.write( name, false ) this.write(name, false)
} },
// Run tests // Run tests
, run: function() { run: function () {
this.pad() this.pad()
for (var h, i = 0, il = this._chain.length; i < il; i++) { 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 h.innerHTML = this._chain[i].name
this.pad().appendChild(h) this.pad().appendChild(h)
this._chain[i].run(this) this._chain[i].run(this)
} }
} },
// Write result // Write result
, write: function(name, ms) { write: function (name, ms) {
var test = document.createElement('div') var test = document.createElement('div')
if (typeof ms === 'number') { if (typeof ms === 'number') {
@ -60,14 +59,14 @@
test.className = 'test skipped' test.className = 'test skipped'
test.innerHTML = name + ' (skipped)' test.innerHTML = name + ' (skipped)'
} }
this.pad().appendChild(test) this.pad().appendChild(test)
return this return this
} },
// Reference writable element // Reference writable element
, pad: function() { pad: function () {
var pad = document.getElementById('pad') var pad = document.getElementById('pad')
if (!pad) { if (!pad) {
@ -76,15 +75,15 @@
} }
return pad return pad
} },
// Clear canvasses // Clear canvasses
, clear: function() { clear: function () {
while(this.raw.hasChildNodes()) while (this.raw.hasChildNodes()) {
this.raw.removeChild(this.raw.lastChild) this.raw.removeChild(this.raw.lastChild)
}
this.draw.clear() this.draw.clear()
this.snap.clear() this.snap.clear()
} }
} }
})()
})();

889
dist/svg.js vendored

File diff suppressed because it is too large Load Diff

4
dist/svg.min.js vendored

File diff suppressed because one or more lines are too long

View File

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

View File

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

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;
}

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>

View File

@ -0,0 +1,7 @@
let mover = SVG.select("#new")[0]
console.log(mover.transform());
mover.transform({
position: [30, 50]
})

View File

@ -19,11 +19,11 @@ describe('Transformations:', function() {
describe('SVG.Translate', function() { describe('SVG.Translate', function() {
var trans var trans
beforeEach(function(){ beforeEach(function(){
trans = new SVG.Translate(translated.transform()) trans = new SVG.Translate(translated.transform())
}) })
it('creates an object of type SVG.Transformation', function() { it('creates an object of type SVG.Transformation', function() {
expect(trans instanceof SVG.Transformation).toBeTruthy() 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() var extracted = (new SVG.Matrix(10,0,0,10,20,20)).extract()
trans.undo(extracted) trans.undo(extracted)
expect(trans._undo.toString()).toEqual('matrix(1,0,0,1,-2,-2)') expect(trans._undo.toString()).toEqual('matrix(1,0,0,1,-2,-2)')
var extracted = (new SVG.Matrix(10,50,50,30,20,20)).extract() var extracted = (new SVG.Matrix(10,50,50,30,20,20)).extract()
trans.undo(extracted) trans.undo(extracted)
expect(trans._undo.e).toBeCloseTo(-extracted.transformedX) expect(trans._undo.e).toBeCloseTo(-extracted.transformedX)
@ -78,14 +78,14 @@ describe('Transformations:', function() {
}) })
}) })
}) })
describe('SVG.Rotate', function() { describe('SVG.Rotate', function() {
var trans var trans
beforeEach(function(){ beforeEach(function(){
trans = new SVG.Rotate(45, 50, 50) trans = new SVG.Rotate(45, 50, 50)
}) })
it('creates an object of type SVG.Transformation', function() { it('creates an object of type SVG.Transformation', function() {
expect(trans instanceof SVG.Transformation).toBeTruthy() expect(trans instanceof SVG.Transformation).toBeTruthy()
@ -129,15 +129,15 @@ describe('Transformations:', function() {
}) })
}) })
}) })
describe('SVG.Scale', function() { describe('SVG.Scale', function() {
var trans var trans
beforeEach(function(){ beforeEach(function(){
trans = new SVG.Scale(2,2,50,50) trans = new SVG.Scale(2,2,50,50)
}) })
it('creates an object of type SVG.Transformation', function() { it('creates an object of type SVG.Transformation', function() {
expect(trans instanceof SVG.Transformation).toBeTruthy() expect(trans instanceof SVG.Transformation).toBeTruthy()
@ -170,7 +170,7 @@ describe('Transformations:', function() {
expect(trans._undo.d).toBeCloseTo(1/extracted.scaleY) expect(trans._undo.d).toBeCloseTo(1/extracted.scaleY)
expect(trans._undo.e).toBeCloseTo(45) expect(trans._undo.e).toBeCloseTo(45)
expect(trans._undo.f).toBeCloseTo(45) expect(trans._undo.f).toBeCloseTo(45)
var extracted = (new SVG.Matrix(10,50,50,30,20,20)).extract() var extracted = (new SVG.Matrix(10,50,50,30,20,20)).extract()
trans.undo(extracted) trans.undo(extracted)
expect(trans._undo.a).toBeCloseTo(1/extracted.scaleX) 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() { 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) var morphed = (new SVG.Scale(scaled.transform(2,2,50,50), true)).at(0.25)
expect(morphed.a).toBeCloseTo(0.8) expect(morphed.a).toBeCloseTo(0.8)
expect(morphed.d).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() { 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) var morphed = trans.undo((new SVG.Matrix(10,0,0,10,0,0)).extract()).at(0.5)
expect(morphed.a).toBeCloseTo(0.6) expect(morphed.a).toBeCloseTo(0.6)
@ -200,15 +200,15 @@ describe('Transformations:', function() {
expect(morphed.f).toBeCloseTo(20) expect(morphed.f).toBeCloseTo(20)
}) })
}) })
}) })
describe('SVG.Skew', function() { describe('SVG.Skew', function() {
var trans var trans
beforeEach(function(){ beforeEach(function(){
trans = new SVG.Skew(30,-30,50,50) trans = new SVG.Skew(30,-30,50,50)
}) })
it('creates an object of type SVG.Transformation', function() { it('creates an object of type SVG.Transformation', function() {
expect(trans instanceof SVG.Transformation).toBeTruthy() 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() { 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) var morphed = (new SVG.Scale(skewed.transform(20,-20,50,50), true)).at(0.25)
expect(morphed.a).toBeCloseTo(0.963) expect(morphed.a).toBeCloseTo(0.963)
expect(morphed.b).toBeCloseTo(0) expect(morphed.b).toBeCloseTo(0)
expect(morphed.c).toBeCloseTo(0) expect(morphed.c).toBeCloseTo(0)
@ -266,7 +266,7 @@ describe('Transformations:', function() {
expect(morphed.f).toBeCloseTo(0) expect(morphed.f).toBeCloseTo(0)
}) })
it('returns the resulting transformation which has to be made to set an absolute translation', function() { 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) 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) expect(morphed.a).toBeCloseTo(1.266)
@ -278,5 +278,4 @@ describe('Transformations:', function() {
}) })
}) })
}) })
}) })

View File

@ -1,4 +1,4 @@
/* global abcdef, arrayToMatrix, deltaTransformPoint, parseMatrix */ /* global abcdef, arrayToMatrix, parseMatrix, unitCircle, mag */
SVG.Matrix = SVG.invent({ SVG.Matrix = SVG.invent({
// Initialize // Initialize
@ -23,159 +23,130 @@ SVG.Matrix = SVG.invent({
}, },
// Add methods // Add methods
, extend: { extend: {
// Convert an object of affine parameters into a matrix // Convert an object of affine parameters into a matrix
compose: function (o, cx, cy) { compose: function (o, cx, cy) {
// Set the defaults // Set the defaults
var tx = o.translateX || 0 var tx = o.translateX || 0
, ty = o.translateY || 0 var ty = o.translateY || 0
, theta = o.theta || 0 var theta = o.theta || 0
, sx = o.scaleX || 1 var sx = o.scaleX || 1
, sy = o.scaleY || 1 var sy = o.scaleY || 1
, lam = o.shear || 0 var lam = o.shear || 0
, cx = cx || 0 cx = cx || 0
, cy = cy || 0 cy = cy || 0
// Calculate the trigonometric values // Calculate the trigonometric values
var ct = Math.cos(theta * Math.PI / 180) 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 // Calculate the matrix components directly
var a = sx * ct var a = sx * ct
, b = sx * st var b = sx * st
, c = lam * sx * ct - sy * st var c = lam * sx * ct - sy * st
, d = lam * sx * st + sy * ct var d = lam * sx * st + sy * ct
, e = - sx * ct * (cx + cy * lam) + sy * st * cy + tx + cx var e = -sx * ct * (cx + cy * lam) + sy * st * cy + tx + cx
, f = - sx * st * (cx + cy * lam) - sy * ct * cy + ty + cy var f = -sx * st * (cx + cy * lam) - sy * ct * cy + ty + cy
// Construct a new matrix and return it // Construct a new matrix and return it
var matrix = new SVG.Matrix([a, b, c, d, e, f]) var matrix = new SVG.Matrix([a, b, c, d, e, f])
return matrix return matrix
} },
// Decompose a matrix into the affine parameters needed to form it // 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 // Get the paramaters of the current matrix
var a = matrix.a var a = matrix.a
, b = matrix.b var b = matrix.b
, c = matrix.c var c = matrix.c
, d = matrix.d var d = matrix.d
, e = matrix.e var e = matrix.e
, f = matrix.f var f = matrix.f
// Project the first basis vector onto the unit circle // Project the first basis vector onto the unit circle
var circle = unitCircle (a, b) var circle = unitCircle(a, b)
, theta = circle.theta var theta = circle.theta
, ct = circle.cos var ct = circle.cos
, st = circle.sin var st = circle.sin
// Work out the transformation parameters // Work out the transformation parameters
var signX = Math.sign(a * ct + b * st) var signX = Math.sign(a * ct + b * st)
, sx = signX * mag (a, b) var sx = signX * mag(a, b)
, lam = (st * d + ct * c) / (ct * a + st * b) var lam = (st * d + ct * c) / (ct * a + st * b)
, signY = Math.sign(- c * st + d * ct) var sy = mag(lam * a - c, d - lam * b)
, sy = mag (lam * a - c, d - lam * b) var tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy)
, 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)
, ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy)
// Package and return the parameters // Package and return the parameters
return { return {
// Bundle the affine parameters // Bundle the affine parameters
translateX: tx translateX: tx,
, translateY: ty translateY: ty,
, theta: theta theta: theta,
, scaleX: sx scaleX: sx,
, scaleY: sy scaleY: sy,
, shear: lam shear: lam,
// Bundle the matrix parameters // 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, a: this.a,
b: this.b, b: this.b,
c: this.c, c: this.c,
d: this.d, d: this.d,
e: this.e, e: this.e,
f: this.f, f: this.f,
// Return the new origin point
x: this.e,
y: this.f,
matrix: new SVG.Matrix(this) matrix: new SVG.Matrix(this)
>>>>>>> 3.0.0
} }
}, },
// Clone matrix // Clone matrix
, form: function (o) { form: function (o) {
// Get all of the parameters required to form the matrix
// Get all of the parameters required to form the matrix var flipX = o.flip && (o.flip === 'x' || o.flip === 'both') ? -1 : 1
var flipX = o.flip && (o.flip == "x" || o.flip == "both") ? -1 : 1 var flipY = o.flip && (o.flip === 'y' || o.flip === 'both') ? -1 : 1
, flipY = o.flip && (o.flip == "y" || o.flip == "both") ? -1 : 1 var skewX = o.skew.length ? o.skew[0]
, kX = o.skew.length ? o.skew[0]
: isFinite(o.skew) ? o.skew : isFinite(o.skew) ? o.skew
: isFinite(o.skewX) ? o.skewX : isFinite(o.skewX) ? o.skewX
: 0 : 0
, kY = o.skew.length ? o.skew[1] var skewY = o.skew.length ? o.skew[1]
: isFinite(o.skew) ? o.skew : isFinite(o.skew) ? o.skew
: isFinite(o.skewY) ? o.skewY : isFinite(o.skewY) ? o.skewY
: 0 : 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.scale) ? o.scale * flipX
: isFinite(o.scaleX) ? o.scaleX * flipX : isFinite(o.scaleX) ? o.scaleX * flipX
: 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.scale) ? o.scale * flipY
: isFinite(o.scaleY) ? o.scaleY * flipY : isFinite(o.scaleY) ? o.scaleY * flipY
: flipY : flipY
, kx = Math.tan(SVG.utils.radians(skewX)) var kx = Math.tan(SVG.utils.radians(skewX))
, ky = Math.tan(SVG.utils.radians(skewY)) var ky = Math.tan(SVG.utils.radians(skewY))
, lam = o.shear || 0 var lam = o.shear || 0
, theta = SVG.utils.radians(o.rotate || 0) var theta = SVG.utils.radians(o.rotate || 0)
, st = Math.sin(theta) var st = Math.sin(theta)
, ct = Math.cos(theta) var ct = Math.cos(theta)
, ox = o.origin.length ? o.origin[0] : o.ox || 0 var ox = o.origin.length ? o.origin[0] : o.ox || 0
, oy = o.origin.length ? o.origin[1] : o.oy || 0 var oy = o.origin.length ? o.origin[1] : o.oy || 0
, px = o.position.length ? o.position[0] : o.px || ox var px = o.position.length ? o.position[0] : o.px || ox
, py = o.position.length ? o.position[1] : o.py || oy var py = o.position.length ? o.position[1] : o.py || oy
, tx = o.translate.length ? o.translate[0] : o.tx || 0 var tx = o.translate.length ? o.translate[0] : o.tx || 0
, ty = o.translate.length ? o.translate[1] : o.ty || 0 var ty = o.translate.length ? o.translate[1] : o.ty || 0
// Form the matrix parameters... aka. welcome to wonderland! (used wolfram) // Form the matrix parameters... aka. welcome to wonderland! (used wolfram)
var a = ct*sx + ky*st*sy var a = ct * sx + ky * st * sy
, b = ct*ky*sy - st*sx var b = ct * ky * sy - st * sx
, c = ct*kx*sx + st*sy + lam*(ct*sx+ky*st*sy) var c = ct * kx * sx + st * sy + lam * (ct * sx + ky * st * sy)
, d = -kx*st*sx + ct*sy + lam*(-st*sx + ct*ky*sy) var 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)) var e = px + tx + ox * (ct * sx + ky * st * sy) + oy * (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)) var f = py + ty + ox * (-st * sx + ct * ky * sy) + oy * (-kx * st * sx + ct * sy + lam * (-st * sx + ct * ky * sy))
, result = new Matrix(a, b, c, d, e, f) var result = new SVG.Matrix(a, b, c, d, e, f)
return result return result
} },
, clone: function() {
clone: function () { clone: function () {
>>>>>>> 3.0.0
return new SVG.Matrix(this) return new SVG.Matrix(this)
}, },
// Morph one matrix into another // Morph one matrix into another
@ -211,15 +182,15 @@ SVG.Matrix = SVG.invent({
return new SVG.Matrix(this.native().inverse()) return new SVG.Matrix(this.native().inverse())
}, },
// Translate matrix // Translate matrix
, translate: function(x, y) { translate: function (x, y) {
var translation = new SVG.Matrix(this.native().translate(x || 0, y || 0)) var translation = new SVG.Matrix(this.native().translate(x || 0, y || 0))
, matrix = this.multiply(translation) var matrix = this.multiply(translation)
return matrix return matrix
} },
// Scale matrix // Scale matrix
, scale: function(x, y, cx, cy) { scale: function (x, y, cx, cy) {
// Support uniform scaling // Support uniform scaling
if (arguments.length == 1) { if (arguments.length === 1) {
y = x y = x
} else if (arguments.length === 3) { } else if (arguments.length === 3) {
cy = cx cy = cx
@ -229,22 +200,21 @@ SVG.Matrix = SVG.invent({
// Rotate the current matrix // Rotate the current matrix
var scale = new SVG.Matrix(x, 0, 0, y, 0, 0) var scale = new SVG.Matrix(x, 0, 0, y, 0, 0)
, centered = this.around(cx, cy, rotation) var centered = this.around(cx, cy, scale)
, matrix = this.multiply(centered) var matrix = this.multiply(centered)
return scale return matrix
} },
// Rotate matrix // Rotate matrix
, rotate: function(r, cx, cy) { rotate: function (r, cx, cy) {
// Convert degrees to radians // Convert degrees to radians
r = SVG.utils.radians(r) r = SVG.utils.radians(r)
// Construct the rotation matrix // Construct the rotation matrix
var rotation = new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0) 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) var centered = this.around(cx, cy, rotation)
, matrix = this.multiply(centered) var matrix = this.multiply(centered)
return matrix return matrix
} },
// Flip matrix on x or y, at a given offset // Flip matrix on x or y, at a given offset
flip: function (a, o) { flip: function (a, o) {
return a === 'x' ? this.scale(-1, 1, o, 0) 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) : this.scale(-1, -1, a, o != null ? o : a)
}, },
// Skew // Skew
, shear: function(a, cx, cy) { shear: function (a, cx, cy) {
var shear = new SVG.Matrix(1, a, 0, 1, 0, 0) var shear = new SVG.Matrix(1, a, 0, 1, 0, 0)
, centered = this.around(cx, cy, shear) var centered = this.around(cx, cy, shear)
, matrix = this.multiply(centered) var matrix = this.multiply(centered)
return matrix return matrix
} },
, skew: function(x, y, cx, cy) { skew: function (x, y, cx, cy) {
// support uniformal skew // support uniformal skew
if (arguments.length === 1) { if (arguments.length === 1) {
y = x y = x
@ -274,10 +244,10 @@ SVG.Matrix = SVG.invent({
// Construct the matrix // Construct the matrix
var skew = new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0) var skew = new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0)
, centered = this.around(cx, cy, skew) var centered = this.around(cx, cy, skew)
, matrix = this.multiply(centered) var matrix = this.multiply(centered)
return matrix return matrix
} },
// SkewX // SkewX
skewX: function (x, cx, cy) { skewX: function (x, cx, cy) {
return this.skew(x, 0, cx, cy) return this.skew(x, 0, cx, cy)

View File

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

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)
},
// 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())
}
})
SVG.extend(SVG.Element, { SVG.extend(SVG.Element, {
// Add transformations // Add transformations
transform: function (o) { transform: function (o) {
/**
* EXTRACTING PARAMETERS
*/
// Act as a getter if no object was passed // Act as a getter if no object was passed
if (typeof o !== 'object') { if (typeof o !== 'object') {
matrix = new SVG.Matrix(this).extract() var matrix = new SVG.Matrix(this).decompose()
return typeof o === 'string' ? matrix[o] : matrix return typeof o === 'string' ? matrix[o] : matrix
} }
// Allow the user to define the origin with a string // 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 // Get the bounding box and string to use in our calculations
var string = o.origin.toLowerCase().trim() var string = o.origin.toLowerCase().trim()
, bbox = this.bbox() var bbox = this.bbox()
, x = bbox.x var x = bbox.x
, y = bbox.y var y = bbox.y
, width = bbox.width var width = bbox.width
, height = bbox.height var height = bbox.height
// Set the bounds eg : "bottom-left", "Top right", "middle" etc... // Set the bounds eg : "bottom-left", "Top right", "middle" etc...
o.ox = string.includes("left") ? x o.ox = string.includes('left') ? x
: string.includes("right") ? x + width : string.includes('right') ? x + width
: x + width / 2 : x + width / 2
o.oy = string.includes("top") ? y o.oy = string.includes('top') ? y
: string.includes("bottom") ? y + height : string.includes('bottom') ? y + height
: y + height / 2 : y + height / 2
// Make sure we only pass ox and oy // 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 // Get the resulting matrix and apply it to the element
var result = new SVG.Matrix().form(o) var result = new SVG.Matrix().form(o)
, matrixString = result.toString() var 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
// Apply the result // Apply the result
return this.attr('transform', matrix) return this.attr('transform', matrixString)
} },
}
// Map matrix to transform // Map matrix to transform
, matrix: function(m, relative) { matrix: function (m, relative) {
// Construct a matrix from the first parameter // Construct a matrix from the first parameter
var matrix = new SVG.Matrix(m) var matrix = new SVG.Matrix(m)
@ -120,10 +98,7 @@ SVG.extend(SVG.Element, {
}) })
SVG.extend(SVG.FX, { SVG.extend(SVG.FX, {
transform: function(o, relative) { transform: function (o, relative) {
// // get target in case of the fx module, otherwise reference this // // get target in case of the fx module, otherwise reference this
// var target = this.target() // var target = this.target()
@ -203,90 +178,51 @@ SVG.extend(SVG.FX, {
// //
// return this._callStart() // return this._callStart()
// } // }
// ensure scale values on both axes // // ensure scale values on both axes
o.scaleX = o.scale != null ? o.scale : o.scaleX != null ? o.scaleX : 1 // 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 // 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) // matrix = new SVG.Scale(o.scaleX, o.scaleY, o.cx, o.cy)
//
// act on skew // // act on skew
} else if (o.skewX != null || o.skewY != null) { // } else if (o.skewX != null || o.skewY != null) {
// ensure centre point // // ensure centre point
ensureCentre(o, target) // ensureCentre(o, target)
//
// ensure skew values on both axes // // ensure skew values on both axes
o.skewX = o.skewX != null ? o.skewX : 0 // o.skewX = o.skewX != null ? o.skewX : 0
o.skewY = o.skewY != null ? o.skewY : 0 // o.skewY = o.skewY != null ? o.skewY : 0
//
matrix = new SVG.Skew(o.skewX, o.skewY, o.cx, o.cy) // matrix = new SVG.Skew(o.skewX, o.skewY, o.cx, o.cy)
//
// act on flip // // act on flip
} else if (o.flip) { // } else if (o.flip) {
if (o.flip === 'x' || o.flip === 'y') { // if (o.flip === 'x' || o.flip === 'y') {
o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset // o.offset = o.offset == null ? target.bbox()['c' + o.flip] : o.offset
} else { // } else {
if (o.offset == null) { // if (o.offset == null) {
bbox = target.bbox() // bbox = target.bbox()
o.flip = bbox.cx // o.flip = bbox.cx
o.offset = bbox.cy // o.offset = bbox.cy
} else { // } else {
o.flip = o.offset // o.flip = o.offset
} // }
} // }
//
matrix = new SVG.Matrix().flip(o.flip, o.offset) // matrix = new SVG.Matrix().flip(o.flip, o.offset)
//
// act on translate // // act on translate
} else if (o.x != null || o.y != null) { // } else if (o.x != null || o.y != null) {
matrix = new SVG.Translate(o.x, o.y) // matrix = new SVG.Translate(o.x, o.y)
} // }
//
if (!matrix) return this // if (!matrix) return this
//
matrix.relative = relative // matrix.relative = relative
//
this.last().transforms.push(matrix) // this.last().transforms.push(matrix)
//
return this._callStart() // 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())
} }
}) })
@ -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

View File

@ -1,3 +1,4 @@
SVG.utils = { SVG.utils = {
// Map function // Map function
map: function (array, block) { map: function (array, block) {