Browse Source

fix playgrounds, delete unneeded files

tags/3.0.0
Ulrich-Matthias Schäfer 5 years ago
parent
commit
51dafe62e0

+ 2
- 1
CHANGELOG.md View File

@@ -29,6 +29,8 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http:
- added possibility to pass in additional attribues to element creators e.g. `canvas.rect({x:100})` or `canvas.rect(100, 100, {x:100})` (#796)
- added `SVG.List` (#645)
- added `words()` and `element()` to `Dom` because of (#935)
- added lab, lch, hsl and cmyk color spaces (#790)
- added `random()` method on `SVG.Color` to create random colors of different kinds (#939)

### Removed
- removed `SVG.Array.split()` function
@@ -41,7 +43,6 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http:
- removed `SVG.Nested` (#809)
- removed `show()` from `SVG.A` to avoid name clash (#802)
- removed `size()` from `SVG.Text` to avoid name clash (#799)
- removed `move(), dmove()` etc for groups to avoid inconsistencies, we will expect users to use transforms to move around groups as they should (especially since they are much simpler now).
- removed `native()` function
- removed `Bare` in favour of `Dom` (#935)


+ 1
- 1
LICENSE.txt View File

@@ -1,4 +1,4 @@
Copyright (c) 2012-2017 Wout Fierens
Copyright (c) 2012-2018 Wout Fierens
https://svgdotjs.github.io/

Permission is hereby granted, free of charge, to any person obtaining

+ 0
- 520
dirty.html View File

@@ -1,520 +0,0 @@

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="dist/polyfills.js"></script>
<script type="text/javascript" src="dist/polyfillsIE.js"></script>
<script type="text/javascript" src="dist/svg.min.js"></script>






</head>
<body style="background-color: #c7c7ff">

<!-- <div id="absolute"><label>Absolute: <input type="range" min="0" max="1" step="0.01"></slider></label><span></span></div>
<div id="position"><label>Position: <input type="range" min="0" max="5" step="0.01"></slider></label><span></span></div> -->

<button name="back1000">Back 1000</button>
<button name="back100">Back 100</button>
<button name="forth100">Forth 100</button>
<button name="forth1000">Forth 1000</button>
<button name="speed2">Speed x2</button>
<button name="speed05">Speed x0.5</button>
<button name="stop">Stop</button>
<button name="finish">Finish</button>
<button name="pause">Pause</button>
<button name="play">Play</button>
<button name="reverse">Reverse</button>
<span id="displayText"></span>
<br>

<!-- Making the svg -->
<svg width=1000px height=500px id="canvas">
<rect x=50 y=100 width=200 height=100 stroke=none stroke-width=2 />
</svg>

<!-- Modifying the svg -->
<script type="text/javascript">

// import SVG from './src/svg.js'
//
// window.SVG = SVG

var rect = SVG('rect').hide()
var sin = Math.sin
var pi = Math.PI
var round = Math.round

function getColor(t) {
var a = round(80 * sin(2 * pi * t / 0.5 + 0.01) + 150)
var b = round(50 * sin(2 * pi * t / 0.5 + 4.6) + 200)
var c = round(100 * sin(2 * pi * t / 0.5 + 2.3) + 150)
var color = 'rgb('+ a +','+ b +','+ c +')'
return color
}

// var rect1 = SVG('<rect>').addTo('svg').size(50, 50).move(100, 100)
// var rect2 = SVG('<rect>').addTo('svg').size(50, 50).move(100, 200)
//
// var anim1 = new SVG.Runner(1000).element(rect1).loop(5, true, 1000).move(200, 100)
// var anim2 = new SVG.Runner(1000).element(rect2).loop(5, true, 1000).move(200, 200)
//
// SVG('#absolute').on('input slide', function (e) {
// var val = e.target.value
// document.querySelector('#absolute span').textContent = val
// anim1.absolute(val)
// })
//
// SVG('#position').on('input slide', function (e) {
// var val = e.target.value
// document.querySelector('#position span').textContent = val
// anim2.position(val)
// })


// rect.animate(4000)
// .during(t => rect.transform({scale: sqrt(1 + t), rotate: 720 * t}))
// .after(500, ()=> {rect.attr('stroke', 'white')})
// .queue(() => rect.attr('fill', getColor(0)))
// .animate(1500, 500, true)
// .queue(()=> {}, t => rect.attr('fill', getColor(t)))
// .animate(1000, true)
// .move(200, 200)
// .size(300, 300)

// SVG.Animator.timeout(()=> { rect.animate().pause() }, 1000 - 10)
// SVG.Animator.timeout(()=> { rect.animate().play() }, 2000 - 10)



// SVG('rect')
// .clone().show()
// .animate()
// .move(300, 200)

//
// for (let i = 0 ; i < 15; i++) {
// for (let j = 0 ; j < 10; j++) {
//
// // Make the rect
// let o = i + j
// let rect = SVG('rect').clone().show()
// .width(40).height(40)
// .x(50 * i).y(50 * j)
// .attr('fill', getColor(o * 0.1))
//
// // Move the rect
// let {cx, cy} = rect.bbox()
//
// // Animate the rect
// rect.animate(3000, Math.random() * 2000)
// // .during(t => rect.transform({rotate: 700 * t, origin: [cx, cy]}))
// .transform({rotate: 720}, true)
// // .during(t => rect.attr('transform', `rotate(${700 * t})`))
// .during(t => rect.attr('fill', getColor(o * 0.1 + t)))
// }
// }

var canvas = SVG('#canvas')

canvas.attr('viewBox', null)

SVG.defaults.timeline.ease = '-'

var r = new SVG.Runner(1000)
var t = new SVG.Timeline().persist(true)

r.schedule(t, 200)
.animate(500).loop(5, true, 100)
.animate(600, 200, 'absolute')
.animate(600, 300)
.animate(600, 300, 'now')
.animate(1000, 0, 'absolute').loop(6, true)

var schedule = t.schedule()

schedule.forEach(function (s, i) {
var rect = canvas.rect(s.duration / 10, 25)
.move(100 + s.start/10, 100 + i*30)
.attr('fill', '#000')

s.runner.element(rect)
.attr('fill', getColor(i*0.1))

// if (i===0)
// s.runner.during(console.log)
})

// t.play()

var mover = canvas.line(100, 100, 100, 300).attr('stroke', 'black')
mover.clone().insertAfter(mover)
canvas.line(100, 300, 800, 300).attr('stroke', 'black')

var text = SVG('#displayText')

t.on('time', function (e) {
mover.x(100 + e.detail/10)
text.node.textContent = e.detail
})

t.on('finished', function (e) {
console.log('finished')
})

SVG('button[name="back100"]').on('click', function (e) {
t.seek(-100)
})
SVG('button[name="back1000"]').on('click', function (e) {
t.seek(-1000)
})
SVG('button[name="forth100"]').on('click', function (e) {
t.seek(100)
})
SVG('button[name="forth1000"]').on('click', function (e) {
t.seek(1000)
})

SVG('button[name="speed2"]').on('click', function (e) {
t.speed(2)
})

SVG('button[name="speed05"]').on('click', function (e) {
t.speed(0.5)
})

SVG('button[name="pause"]').on('click', function (e) {
t.pause()
})

SVG('button[name="play"]').on('click', function (e) {
t.play()
})

SVG('button[name="stop"]').on('click', function (e) {
t.stop()
})

SVG('button[name="finish"]').on('click', function (e) {
t.finish()
})

SVG('button[name="reverse"]').on('click', function (e) {
t.reverse()
})


canvas.rect(100, 100).on('click', function (e) {
e.target.instance.animate()
.move(Math.random()*1000, Math.random()*750)
.timeline().on('finished', function (e) {
console.log('rect finished')
})
})

console.log(schedule)
















// var bla = SVG('<rect>').size(0, 0).move(200, 200).addTo('svg')
// bla.animate().size(220, 200).queue(null, console.log)

// var randPoint = (x = 50, y = 50) => [
// Math.random() * 100 - 50 + x,
// Math.random() * 100 - 50 + y
// ]
//
// var poly = SVG('<polygon>').plot([
// randPoint(),
// randPoint(),
// randPoint(),
// randPoint(),
// randPoint()
// ]).attr({fill: 'none', stroke: 'black'}).addTo('svg')
// var polyAni = poly.animate(new SVG.Spring(3000, 0))
//
// SVG.on(document, 'click', function (e) {
// polyAni.plot([
// randPoint(e.pageX-50, e.pageY-50),
// randPoint(e.pageX+50, e.pageY-50),
// randPoint(e.pageX+50, e.pageY),
// randPoint(e.pageX+50, e.pageY+50),
// randPoint(e.pageX-50, e.pageY+50)
// ])
// })

// var mover = SVG('<ellipse>').size(50, 50).center(100, 100).addTo('svg')
// var anim = mover.animate(new SVG.Spring(500, 10))
//
// let date = +new Date
// SVG.on(document, 'mousemove', function (e) {
// // if (+new Date - date > 50) {
// // date = +new Date
// // } else {
// // return
// // }
//
// //var p = mover.point(e.pageX, e.pageY)
// var p = mover.doc().point(e.clientX, e.clientY)
// //var p = {x: e.pageX, y: e.pageY}
// //console.log(p)
// anim.transform({px: p.x - 100, py: p.y - 100})
// //anim.center(p.x, p.y)
// })
/*
let canvas = SVG('#canvas')

let rectangle = canvas.rect(100, 200).move(100, 0)

let bbox = rectangle.bbox()

var timer = 0
rectangle.timeline().source(() => {
timer += 2
document.querySelector('#absolute span').textContent = timer
return timer
})
rectangle.animate().transform({
rotate: 90,
origin: [bbox.cx, bbox.cy]
})*/

//


// SVG('#absolute').on('input slide', function (e) {
// var val = e.target.value
//
// canvas.clear()
// canvas.ellipse(20, 20)
// let re = canvas.rect(300, 150).move(100, 150).attr('opacity', 0.5)
// re.clone()
// .transform({rotate: 45, skew: 30}, true)
//
// re.clone()
// .transform({
// rotate: 45, skew: 30, /*translate: [150, 140], */
// }, true)
// .transform({rotate: val, origin: 'bottom-right'}, true)
//
// re.clone()
// .transform({rotate: 45, skew: 30}, true)
// .transform({rotate: val, origin: 'bottom-right'}, true)
// .transform({skew}, true)
// let a = canvas.rect(200, 400).move(500, 400)
// .attr('opacity', 0.3)
// .addClass('pink')
// //.transform({ px: 100, py: 500, origin: 'top-left' })
//
//
// var timer = 0
// a.timeline().source(() => {
// timer += 1
// document.querySelector('#absolute span').textContent = timer
// return timer
// })
//
// let obj = { rotate: val * 180, origin: 'top-left' }
// let obj2 = { rotate: val * 280, origin: 'center' }
//
// a.clone() // startPosition
// a.clone().transform(obj, true).transform(obj2, true) // endPosition
// })


// let a = canvas.rect(200, 400).move(500, 400)
//
// a.animate(1000, 500).move(100, 100).animate(1000, 500).move(500, 400)




/* FUZZYMS PLANETS!! */
// let canvas = SVG('#canvas')
// let gradient = canvas.gradient('radial', function(gradient) {
// gradient.stop(0, '#f00')
// gradient.stop(1, '#ff0')
// })
//
// let gradientEarth = canvas.gradient('linear', function(gradient) {
// gradient.stop(0, '#00f')
// gradient.stop(1, '#0f0')
// })
//
// let sun = canvas.circle(200).center(500, 300).attr({ fill: gradient })
//
// let earth = canvas.circle(100).center(1000, 300).attr({fill: gradientEarth})
//
// let moon = canvas.circle(50).center(1200, 300).attr({fill: '#ffa'})
//
// earth.animate(10000).loop().ease('-')
// .transform({rotate: 360, origin: [500, 300]}, true)
// .transform({rotate: 720, origin: 'center'}, true)
// .on('step', (e) => {
// // console.log(e)
// })
//
// moon.animate(10000).loop().ease('-')
// .transform({rotate: 360, origin: [500, 300]}, true)
// .transform({rotate: 3600, origin: [1000, 300]}, true)














/**
* FUZZYS EXAMPLE
*/
// let a = canvas.rect(200, 400).move(500, 400)
// .attr('opacity', 0.3)
// .addClass('pink')
// .transform({ tx: 300, ty: 500, origin: 'top-left' })
//
// let obj = { rotate: 100, origin: 'top-left'}
// let obj2 = { rotate: 280, origin: 'center' }
// let obj3 = { rotate: 1000, origin: 'center', translate: [300, 200]}
//
//
// var c = a.clone()
//
// c.animate(3000)
// .transform(obj)
// .transform(obj2, true) // animation
//
// a.clone().attr('fill', 'blue')
// .transform(obj)
// .transform(obj2, true) // endPosition


// SAIVANS EXAMPLE


// 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' })
//
// // Normal usage
// let wait = 3000
// 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))
// //let rDecl = r.clone().attr('fill', 'blue').animate(new SVG.PID(0.01, 0.001, 1, 10))
//
// // var timer = 0
// // rDecl.timeline().source(() => {
// // timer += 100
// // return timer
// // })
//
// let runTransformation = (transform) => {
// return () => {
// //transform = new SVG.Matrix(transform)
// let relative = true
// let affine = true
// r.transform(transform, relative)
// rAnim.animate(wait).transform(transform, relative, affine)
// rDecl.transform(transform, relative, affine)
// }
// }
//
// setTimeout(runTransformation({
// origin: 'top-left',
// translate: [530, 250],
// rotate: 300,
// scale: 2,
// shear: 1,
// }), 0.1 * wait )
//
//
//
// setTimeout(runTransformation({
// origin: 'top-left',
// translate: [530, 250],
// rotate: 100,
// scale: 2,
// shear: 1,
// }), 0.4 * wait)
//
// setTimeout(runTransformation({
// origin: 'top-left',
// translate: [530, 250],
// rotate: 100,
// scale: 2,
// shear: 1,
// }), 0.6 * wait)


// canvas.circle(50).center(100, 0).attr('fill', 'gray')
//
// setTimeout(runTransformation({
// rotate: 360,
// origin: [100, 0]
// }), 0.1 * wait )
//
//
// setTimeout(runTransformation({
// rotate: 360,
// }), 0.4 * wait)

// const getConsole = (time) => {
// return () => {
// console.group(time)
// console.log(0, rAnim.element()._transformationRunners[0] && rAnim.element()._transformationRunners[0].transforms.decompose().rotate)
// console.log(1, rAnim.element()._transformationRunners[1] && rAnim.element()._transformationRunners[1].transforms.decompose().rotate)
// console.log(2, rAnim.element()._transformationRunners[2] && rAnim.element()._transformationRunners[2].transforms.decompose().rotate)
// console.log(3, rAnim.element()._transformationRunners[3] && rAnim.element()._transformationRunners[3].transforms.decompose().rotate)
// console.log(4, rAnim.element()._transformationRunners[4] && rAnim.element()._transformationRunners[4].transforms.decompose().rotate)
// console.groupEnd(time)
// }
// }
//
// logCall = (time) => {
// setTimeout(getConsole(time), time)
// }
//
// logCall(0.2 * wait)
// logCall(0.3 * wait)
// logCall(0.4 * wait)
// logCall(0.5 * wait)
// logCall(0.6 * wait)
// logCall(0.7 * wait)
// logCall(0.8 * wait)
// logCall(0.9 * wait)
// logCall(1 * wait)
// logCall(1.1 * wait)
// logCall(1.2 * wait)
// logCall(1.3 * wait)
// logCall(1.4 * wait)
// logCall(1.5 * wait)

</script>

</body>
</html>

+ 1
- 1
playgrounds/colors/index.html View File

@@ -21,6 +21,6 @@
</body>

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

</html>

+ 1
- 1
playgrounds/colors/main.js View File

@@ -12,7 +12,7 @@ function rectangles ( method='Vibrant') {

// Add the squares
for ( let i = 0; i < 20; i++ ) {
let color = SVG.Color.random( method.toLowerCase() ).hex()
let color = SVG.Color.random( method.toLowerCase() ).toHex()
let rect = group.rect(100, 100)
.x( 20 + 100 * i )
.fill( color )

+ 1
- 1
playgrounds/matrix/drag.js View File

@@ -35,7 +35,7 @@ function reactToDrag(element, onDrag, beforeDrag) {
}

// Bind the drag tracker to this element directly
let parent = element.doc()
let parent = element.root()
let point = new SVG.Point()
element.mousedown(startDrag).touchstart(startDrag)
}

+ 1
- 1
playgrounds/matrix/index.html View File

@@ -5,7 +5,7 @@
<head>
<meta charset="utf-8">
<title>SVG Playground</title>
<link rel="stylesheet" href="../playground.css">
<link rel="stylesheet" href="style.css">
</head>

<body>

+ 1
- 1
playgrounds/transforms/index.html View File

@@ -5,7 +5,7 @@
<head>
<meta charset="utf-8">
<title>SVG Playground</title>
<link rel="stylesheet" href="../playground.css">
<link rel="stylesheet" href="style.css">
</head>

<body>

+ 5
- 5
spec/SpecRunner.html View File

@@ -17,7 +17,7 @@
<!-- include source files here... -->
<script src="../dist/polyfills.js" charset="utf-8"></script>
<script src="../dist/polyfillsIE.js" charset="utf-8"></script>
<script src="../dist/svg.min.js" charset="utf-8"></script>
<script src="../dist/svg.js" charset="utf-8"></script>

</head>

@@ -58,15 +58,15 @@

<!--<script src="es5TestBundle.js"></script>-->

<!-- <script src="spec/adopter.js"></script>
<script src="spec/adopter.js"></script>
<script src="spec/arrange.js"></script>
<script src="spec/array.js"></script>
<script src="spec/bare.js"></script>
<script src="spec/boxes.js"></script>
<script src="spec/circle.js"></script>
<script src="spec/clip.js"></script> -->
<script src="spec/clip.js"></script>
<script src="spec/color.js"></script>
<!-- <script src="spec/container.js"></script>
<script src="spec/container.js"></script>
<script src="spec/defs.js"></script>
<script src="spec/doc.js"></script>
<script src="spec/easing.js"></script>
@@ -104,6 +104,6 @@
<script src="spec/morphing.js"></script>
<script src="spec/animator.js"></script>
<script src="spec/runner.js"></script>
<script src="spec/queue.js"></script> -->
<script src="spec/queue.js"></script>
</body>
</html>

+ 17
- 11
src/modules/core/event.js View File

@@ -3,27 +3,32 @@ import { makeInstance } from '../../utils/adopter.js'
import { globals } from '../../utils/window.js'

let listenerId = 0
let windowEvents = {}

function getEvents (node) {
const n = makeInstance(node).getEventHolder()
function getEvents (instance) {
let n = instance.getEventHolder()

// We dont want to save events in global space
if (n === globals.window) n = windowEvents
if (!n.events) n.events = {}
return n.events
}

function getEventTarget (node) {
return makeInstance(node).getEventTarget()
function getEventTarget (instance) {
return instance.getEventTarget()
}

function clearEvents (node) {
const n = makeInstance(node).getEventHolder()
function clearEvents (instance) {
const n = instance.getEventHolder()
if (n.events) n.events = {}
}

// Add event binder in the SVG namespace
export function on (node, events, listener, binding, options) {
var l = listener.bind(binding || node)
var bag = getEvents(node)
var n = getEventTarget(node)
var instance = makeInstance(node)
var bag = getEvents(instance)
var n = getEventTarget(instance)

// events can be an array of events or a string of events
events = Array.isArray(events) ? events : events.split(delimiter)
@@ -51,8 +56,9 @@ export function on (node, events, listener, binding, options) {

// Add event unbinder in the SVG namespace
export function off (node, events, listener, options) {
var bag = getEvents(node)
var n = getEventTarget(node)
var instance = makeInstance(node)
var bag = getEvents(instance)
var n = getEventTarget(instance)

// listener can be a function or a number
if (typeof listener === 'function') {
@@ -109,7 +115,7 @@ export function off (node, events, listener, options) {
off(n, event)
}

clearEvents(node)
clearEvents(instance)
}
})
}

+ 1
- 1
src/utils/adopter.js View File

@@ -51,7 +51,7 @@ export function adopt (node) {
if (node.instance instanceof Base) return node.instance

// initialize variables
var className = capitalize(node.nodeName)
var className = capitalize(node.nodeName || 'Dom')

// Make sure that gradients are adopted correctly
if (className === 'LinearGradient' || className === 'RadialGradient') {

+ 0
- 107
todo.md View File

@@ -1,107 +0,0 @@
# tests to write
- sugar.js
- insertBefore
- insertAfter
- after
- before
- ax, ay, amove
- Path.js
- targets
- Element.js
- svg
- attr.js
- Style.js


# Where We Left Off

Saivan
======


Ulima
=====
- Use runners[runnerid] = {startTime, runner, persist}
timeline.persist('monkey-in', Infinity)
- folding transformations
- testing direct non affine morph
- why cant i use current?
- handle null values

Both
====
- We discussed that matrices should always be applied from the left for animation, so we have:
- If we have C R x where C is the current Matrix and R is the relative matrix that we want to apply
- It could be animated by instead left multiplying (C R inv(C)) so that we have (C R inv(C)) C R
- This allows us to always left multiply (which greatly simplifies things)
=> Conclusion: We dont do this. We apply transformations left or right whatever is necessary

Latest
======
- Runners would call an element.mergeMatrix() function that requests a native animation frame. Each runner would cancel the call made by the last runner, so that the function only runs once per frame.
-https://en.wikipedia.org/wiki/Change_of_basis#Change_of_coordinates_of_a_vector



# Timeline Description

- [T] Timeline constructors
- [T] timeline () - Returns the timeline context to the user

- [T] Time Management
- [T] play () - Lets the timeline keep playing from here
- [T] pause () - Pauses the timeline where it currently is
- [T] stop () - Pauses the timeline and sets time = 0
- [T] finish () - Moves the time to the final time for the final animation, forces declaratives to snap to their final positions
- [T] speed (newSpeed) - Sets the playback speed
- [T] seek (dt) - Scrubs the timeline time forward or backward by dt
- [T] time (t) - Sets the absolute time to t
- [T] backwards (back) - Sets the speed to (back ? speed : -speed)
- [T] position (p) - sets the position in range [0, 1]
- [T] loop (times, swing, waits)

- [T] Runner Management
- [T] remove(tagOrRunner, end) - Removes all runners with tag from the timeline
- [T] reset () - Deletes all of the runners and resets the timeline
- [T] persist (tag, lifetime) - how long to keep a reference to an animation after it is completed
- [T] schedule (tag, time, when) - move the start time of the runner to time otherwise, returns all of the scheduled runners start and end times.

- [T] Hidden Methods
- [x] `_step (dt)`
- [x] `_continue ()`


# Runner

- [x] Constructors
- [x] animate (duration, delay, when) - Makes a new runner and returns the timeline context to the user with the new runner active.
- [x] loop (duration, times, swing) - Makes a new runner with the looping set as described by the parameters, returns timeline
- [x] delay (by, when) - Makes a new runner to start <by> ms after the last active runner is complete

- [x] Runner Methods
- [x] element (svgElement) - Given an element, you can bind it directly
- [x] animate (args) - Calls animate if we have an element set
- [x] loop (args) - Calls loop with arguments if we have an element
- [x] delay (args) - calls delay if we have an element

- [x] Runner Events
- [x] on (eventName, fn) - Binds a function to an event
- [x] off (eventName) - Unbinds all function from that event
- [x] fire () - Fires an event

- [x] Basic Functionality
- [x] queue (initFn, runFn, alwaysInitialise) - Given two functions, the runner will run initFn once, and run runFn on every step. If alwaysInitialise is true, it will always run the initialisation as well.
- [x] during (runFn) - The function to run on each frame

- [x] Runner Animation Methods
- [x] time (time) - Sets the time to the given time and runs the runner
- [x] step (dt) - Runs the runner method if
- [x] finish () - runs step with dT = Infinity
- [x] reverse () - Makes non-declarative runners play backwards
- [x] ease (fn) - Sets the easing function, can not be used to convert a non-declarative to a declarative animation.
- [x] active (activated) - Activates or deactivates a runner
- [x] loop (o) - Activates a loop sequence

- [x] Runner Management
- [x] tag (name) - Name a runner or act as a getter
- [x] untag ()

+ 0
- 330
useCases.md View File

@@ -1,330 +0,0 @@


# Tagged Animations

The user can tag and control the runner for any animation

```js

var animation = element
.loop(300, true)
.tag('first')
.rotate(360)
.translate(50)
.animate(300, 200)
.tag('second')
.scale(3)

element.timeline.finish()
element.timeline.pause()
element.timeline.stop()
element.timeline.play()

```


# Absolute Timeline Times

The user can specify their time which is relative to the timelines time.


```js

var animation = element.animate(2000).move(200, 200)

// after 1000 ms
animation.animate(1000, 500, 'absolute').scale(2)


var runner = elemenet.move(0, 0).animate(1000)

// after 500ms
runner.move(200, 200)

```

This block of code would:
- Spend the first 1000ms moving the element
- At this time, it will snap the scale to 1.5 (halfway to 2)
- After this time, the scale and the move should go together


# Rotating While Scaling

The user may want to run multiple animations concurrently and have
control over each animation that they define.

```js

let animationA = element.loop(300, ">").rotate(360)
let animationB = element.loop(200, "><").scale(2)

// Maybe they want to disable a runner - which acts like pausing
animationB.active(false)

// Maybe they want to remove an animation matching a tag
animationB.tag('B')
element.timeline().remove('B')

// They can move around a runner as well
element.timeline()
.schedule('B', 300, 'absolute') // Moves a runner to start at 300
// time(currentAbsolute - newAbsolute)
.shift('B', 300) // Shifts the runner start time by 300
// which is sugar to
.schedule('B', 300, 'relative')
// seek(shiftTime)

```

Lets demonstrate the difference between the schedule and shift

```
Given this:

--------
--------------
----------------

Schedule:
--------
--------------
----------------

Shift:
--------
--------------
----------------
```



# A Sequenced Animation

The user might want to be able to run a long sequenced animation that they have
predesigned as they please.

```js

let timeline = element.loop(300, "><").scale(2)
.animate(300).rotate(30)
.animate(300, 200).fill(blue)

// They might want to move forwards or backwards
timeline.seek(-300)

// They might want to set a specific time
timeline.time(200)

// Or a specific position
timeline.position(0.3)

// Maybe they want to clear the timeline
timeline.reset()

```


# User wants to Loop Something

If the user wants to loop something, they should be able to call the loop
method at any time, and it will just change the behaviour of the current
runner. If we are running declaratively, we will throw an error.

## Correct Usages

They can invoke this from the timeline

```js
element.loop(duration, times, swing)
```

If they want to work with absolute times, they should animate first

```js
element.animate(300, 200, true)
.loop(Infinity, true)
```

Or alternatively, they could equivalently do this:

```js
element.loop({
now: true,
times: Infinity,
delay: 200,
duration: 300,
swing: true,
wait: [200, 300]
})
```

## Error Case



# Declarative Animations

The user might want to have something chase their mouse around. This would
require a declarative animation.

```js

el.animate((curr, target, dt, ctx) => {

// Find the error and the value
let error = target - current
ctx.speed = (ctx.error - error) / dt
ctx.error = error
return newPos

})

SVG.on(document, 'mousemove', (ev) => {

el.timeline(controller)
.move(ev.pageX, ev.pageY)

})

```


## Springy Mouse Chaser

Pretend we gave the user a springy controller that basically springs to a
target in 300ms for example. They might be constantly changing the target with:

```js

el.animate(Spring(500), 200)
.tag('declarative')
.persist()
.move(10, 10)

el.animate('declarative')
.move(300, 200)



SVG.on(document, 'mousemove', function (ev) {

el.animate(springy, 200)
.tag('declarative')
.move(ev.pageX, ev.pageY)

})

```


# Repeated Animations

The user might want to duplicate an animation and have it rerun a few times

```js

// User makes two copies of an animation
let animA = el.animate(300, 300, 'now')...(animation)...
let animB = animA.clone() // Deep copy

// Now let the user attach and reschedule their animations
el.timeline()
.schedule(animA, 500, 'absolute')
.schedule(animB, 2000, 'absolute')

```

Then the user can loop the timeline, by changing its play mode

```js
el.timeline()
.loop(times, swing, waits)
```


# Advanced Animations

The user can create their own runners and then attach it to the timeline
themselves if they like.

```js

// They declare their animation
let rotation = () => new SVG.Runner().rotate(500)

// They attach an element, and schedule the runner
let leftAnimation = rotation().element(leftSquare).reverse()

// They might want to animate another
let rightAnimation = rotation().element(rightSquare)

// They can schedule these two runners to a master element
timelineElement.timeline()
.schedule(leftAnimation, 300, 'absolute')
.schedule(rightAnimation, 500, 'now')
.schedule(rightAnimation, 300, 'end')

// Or they can schedule it to a timeline as well
let timeline = new SVG.Timeline()
.schedule(leftAnimation, 300, 'absolute')
.schedule(rightAnimation, 500, 'now')

```


# Modifying Controller Parameters

Some user might want to change the speed of a controller, or how the controller
works in the middle of an animation. For example, they might do:

```js

var pid = PID(30, 20, 40)
let animation = el.animate(pid).move(.., ..)


// Some time later, the user slides a slider, and they can do:
slider1.onSlide( v => pid.p(v) )

```


# Bidirectional Scheduling **(TODO)**

We would like to schedule a runner to a timeline, or to do the opposite

```js

// If we have a runner and a timeline
let timeline = new Timeline()...
let runner = new Runner()...

// Since the user can schedule a runner onto a timeline
timeline.schedule(runner, ...rest)

// It should be possible to do the opposite
runner.schedule(timeline, ...rest)

// It could be Implemented like this
runner.schedule = (t, duration, delay, now) {
this._timeline.remove(this) // Should work even if its not scheduled
t.schedule(this, duration, delay, now)
return this
}

// The benefit would be that they could call animate afterwards: eg:
runner.schedule(timeline, ...rest)
.animate()...

```

# Binding Events

The user might want to react to some events that the runner might emit. We will
emit the following events from the runner:
- start - when a runner first initialises
- finish - when a runner finishes
- step - on every step

Maybe they also want to react to timeline events as well

Loading…
Cancel
Save