<div id="position"><label>Position: <input type="range" min="0" max="5" step="0.01"></slider></label><span></span></div>
<!-- Making the svg -->
-<svg width=1000px height=1000px id="canvas" viewbox="-1000 -1000 3000 3000">
+<svg width=1000px height=1000px id="canvas" viewbox="-1000 -2000 5000 5000">
<rect x=50 y=100 width=200 height=100 stroke=none stroke-width=2 />
</svg>
// })
//
+canvas.ellipse(20, 20).center(100, 100)
let r = canvas.rect(200, 400).move(100, 100)
.attr('opacity', 0.3)
.transform({ tx: 300, ty: 500, origin: 'top-left' })
let rAnim = r.clone().attr('fill', '#f00').animate(wait).attr('fill', '#0f0')
let rDecl = r.clone().attr('fill', 'blue').animate(new SVG.Spring(wait, 15))
-// Move once
-setTimeout(() => {
- let trans = {tx: 500, ty: 300}
- r.transform(trans, true)
- rAnim.animate(wait, 0, 'start').transform(trans, true)
- //rDecl.transform(trans, true)
-}, wait)
-
-// Move again
+// // Move once
// setTimeout(() => {
-// let trans = {rotate: 300}
+// let trans = {tx: 500, ty: 300}
// r.transform(trans, true)
-// rAnim.animate(wait).transform(trans, true)
-// //rDecl.transform(trans, true)
-// }, 1.5 * wait )
-
-
-
-
+// // rAnim.animate(wait, 0, 'start').transform(trans, true)
+// rDecl.transform(trans, true)
+// }, wait)
+// Move again
+setTimeout(() => {
+ let transform = {
+ origin: 'top-left',
+ translate: [530, 250],
+ rotate: 300,
+ scale: 2,
+ shear: 1,
+ }
+ let relative = true
+ let affine = false
+ r.transform(transform, relative)
+ rAnim.animate(wait).transform(transform, relative, affine)
+ rDecl.transform(transform, relative, affine)
+}, 0.1 * wait )
+
+
+// declaritive relative (affine/nonaffine)
+// declaritive absolute non affine
+// normal non affine relative
+
+// D N
+// R
+// A
}
-function getOrigin (o, element) {
+function getOrigin (o, element, relative) {
// Allow origin or around as the names
let origin = o.around == null ? o.origin : o.around
+ let ox, oy
// Allow the user to pass a string to rotate around a given point
if (typeof origin === 'string' || origin == null) {
: y + height / 2
// Set the bounds eg : "bottom-left", "Top right", "middle" etc...
- const ox = o.ox != null ? o.ox : bx
- const oy = o.oy != null ? o.oy : by
+ ox = o.ox != null ? o.ox : bx
+ oy = o.oy != null ? o.oy : by
- // Set the origin based on the current matrix location
- return [ox, oy]
+ } else {
+ ox = origin[0]
+ oy = origin[1]
+ }
+
+ // Transform the origin into the current reference frame
+ if ( relative ) {
+ let matrix = new SVG.Matrix(element)
+ let originRelative = new SVG.Point( ox, oy ).transform(matrix)
+ ox = originRelative.x
+ oy = originRelative.y
}
// Return the origin as it is if it wasn't a string
- return origin
+ return [ ox, oy ]
}
//
// M v -----|-----(D M v = F v)------|-----> T v
//
- // 1. define the final state (T) and decompose it (once) t = [tx, ty, the, lam, sy, sx]
- // 2. on every frame: pull the current state of all previous transforms (M - m can change)
+ // 1. define the final state (T) and decompose it (once)
+ // t = [tx, ty, the, lam, sy, sx]
+ // 2. on every frame: pull the current state of all previous transforms
+ // (M - m can change)
// and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0]
// 3. Find the interpolated matrix F(pos) = m + pos * (t - m)
// - Note F(0) = M
// 4. Now you get the delta matrix as a result: D = F * inv(M)
transform: function (transforms, relative, affine) {
- if (this._isDeclarative && this._tryRetarget('transform', transforms)) {
+ // If we have a declarative function, we should retarget it if possible
+ relative = transforms.relative || relative
+ if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) {
return this
}
// Parse the parameters
var isMatrix = transforms.a != null
- relative = transforms.relative || relative
affine = transforms.affine != null
? transforms.affine
: (affine != null ? affine : !isMatrix)
-
- const morpher = new SVG.Morphable().type(
- affine ? SVG.Morphable.TransformBag2 : SVG.Matrix
- ).stepper(this._stepper)
+ // Create a morepher and set its type
+ const morpher = new SVG.Morphable()
+ .type( affine ? SVG.Morphable.TransformBag2 : SVG.Matrix )
+ .stepper(this._stepper)
let origin
let element
let current
let currentAngle
var u = 0
- this.queue(function () {
+
+ function setup () {
// make sure element and origin is defined
element = element || this.element()
- origin = origin || getOrigin(transforms, element)
+ origin = origin || getOrigin(transforms, element, relative)
+
+this.element().parent().ellipse(50, 50).center(...origin)
// add the runner to the element so it can merge transformations
element.addRunner(this)
// Deactivate all transforms that have run so far if we are absolute
- if (!relative) {
+ let absolute = !relative
+ if ( absolute ) {
element._clearTransformRunnersBefore(this)
}
morpher.from(start)
morpher.to(target)
- }, function (pos) {
+ }
+
+ function run (pos) {
// clear all other transforms before this in case something is saved
// on this runner. We are absolute. We dont need these!
current = new SVG.Matrix(affineParameters)
this.addTransform(current)
-
return morpher.done()
+ }
- }, function (newTransforms) {
+ function retarget (newTransforms) {
// only get a new origin if it changed since the last call
- if ((newTransforms.origin || 'center').toString() != (transforms.origin || 'center').toString()) {
+ if (
+ (newTransforms.origin || 'center').toString()
+ != (transforms.origin || 'center').toString()
+ ) {
origin = getOrigin (transforms, element)
}
// overwrite the old transformations with the new ones
transforms = {...newTransforms, origin}
- })
-
+ }
+ this.queue(setup, run, retarget)
this._isDeclarative && this._rememberMorpher('transform', morpher)
-
return this
},