]> source.dussan.org Git - svg.js.git/commitdiff
Release 3.0.5 3.0.5
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>
Wed, 12 Dec 2018 22:21:10 +0000 (23:21 +0100)
committerUlrich-Matthias Schäfer <ulima.ums@googlemail.com>
Wed, 12 Dec 2018 22:21:10 +0000 (23:21 +0100)
16 files changed:
.config/karma.es6.js
.config/rollup.tests.js
CHANGELOG.md
package.json
spec/SpecRunner.html
spec/SpecRunnerEs6.html
spec/runSVGDomTest.js
spec/spec/elements/G.js [new file with mode: 0644]
src/animation/Animator.js
src/animation/Runner.js
src/animation/Timeline.js
src/elements/Element.js
src/elements/G.js
src/modules/core/parser.js
src/modules/optional/sugar.js
src/utils/utils.js

index 7a7a8750b073d40aed5569403247bd32741dede9..81605cfd8c60786adf05a77e29933d60275b861c 100644 (file)
@@ -33,7 +33,7 @@ module.exports = function (config) {
           type: 'module'
         },
         {
-          pattern: 'spec/spec/types/*.js',
+          pattern: 'spec/spec/*/*.js',
           included: true,
           type: 'module'
         }
index 518be9408e61a37ab75ffb7b664be5dcea8ee428..e524a79a285fe7dd36514ebf42330700b98358b6 100644 (file)
@@ -2,7 +2,10 @@ import babel from 'rollup-plugin-babel'
 import multiEntry from 'rollup-plugin-multi-entry'
 
 export default {
-  input: ['spec/setupBrowser.js', 'spec/spec/types/*.js', 'spec/spec/utils/*.js'],
+  input: [
+    'spec/setupBrowser.js',
+    'spec/spec/*/*.js'
+  ],
   output: {
     file: 'spec/es5TestBundle.js',
     name: 'SVGTests',
index b53f1795a085a7be985b4c5a49f8739e0fd50fd1..ad3da1b4f6a3460c0eb03b749c506dd520e795f9 100644 (file)
@@ -7,6 +7,13 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http:
 
 ====
 
+## [3.0.5] - 2018-12-12
+ - fixed `parser` which didnt have all reqired css rules and not focusable=false
+ - group `x(), y(), width(), height(), dx(), dy()` now correctly change the bbox of the group by moving/resizing all children
+ - fixed timeline which fired `finished` to early
+ - fixed `Animator.frame()`. The passed callback gets the current time now (same as RAF)
+ - allow `loop(true)` which is the same as `loop()`
+
 ## [3.0.4] - 2018-12-07
 
 ### Fixed
@@ -754,6 +761,7 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http:
 
 
 <!-- Headings above link to the releases listed here -->
+[3.0.5]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.5
 [3.0.4]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.4
 [3.0.3]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.3
 [3.0.2]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.2
index 6485a38cec3eac336ff9d6983ffe64b8631e438c..1068ae9f2f21db77ece7e4fbbee7b2c86d9c6d38 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "@svgdotjs/svg.js",
-  "version": "3.0.4",
+  "version": "3.0.5",
   "description": "A lightweight library for manipulating and animating SVG.",
   "url": "https://svgdotjs.github.io/",
   "homepage": "https://svgdotjs.github.io/",
@@ -64,7 +64,7 @@
     "test:svgdom": "node -r esm ./spec/runSVGDomTest.js || true",
     "test:es6": "npx karma start .config/karma.es6.js --single-run",
     "zip": "zip -j dist/svg.js.zip -- LICENSE.txt README.md CHANGELOG.md dist/svg.js dist/svg.js.map dist/svg.min.js dist/svg.min.js.map dist/polyfills.js dist/polyfillsIE.js",
-    "prepublishOnly": "rm -r ./dist && npm run build && npm run build:polyfills && npm test",
+    "prepublishOnly": "rm -rf ./dist && npm run build && npm run build:polyfills && npm test",
     "postpublish": "npm run zip"
   },
   "devDependencies": {
index da55e8282dc139ce66e0492f4064d38a749bdd03..a1c62497cd78242bad4c143fee6b0e568a7c0aab 100644 (file)
@@ -56,7 +56,7 @@
 
   <!-- include spec files here... -->
 
-  <!--<script src="es5TestBundle.js"></script>-->
+  <script src="es5TestBundle.js"></script>
 
   <script src="spec/adopter.js"></script>
   <script src="spec/arrange.js"></script>
index cca33c0792a11d88fef72efc8c1b37031d792b1d..3f8f90abad4f1128e744c98374f148ec85cb61c2 100644 (file)
@@ -25,6 +25,7 @@
   <script type="module" src="spec/types/Base.js"></script>
   <script type="module" src="spec/types/Box.js"></script>
   <script type="module" src="spec/utils/adopter.js"></script>
+  <script type="module" src="spec/elements/G.js"></script>
 
 </body>
 </html>
index 0db744de58bab4bc19631edd68b4de8de55cbbd4..57055f475fb9e96ed51a02ebccd26b6c25254bd0 100644 (file)
@@ -12,7 +12,8 @@ jasmine.loadConfig({
   "spec_dir": "spec/",
   "spec_files": [
     "spec/types/*.js",
-    "spec/utils/*.js"
+    "spec/utils/*.js",
+    "spec/elements/*.js"
   ],
   "helpers": [
     "setupSVGDom.js"
diff --git a/spec/spec/elements/G.js b/spec/spec/elements/G.js
new file mode 100644 (file)
index 0000000..2c2efc8
--- /dev/null
@@ -0,0 +1,139 @@
+import { G, Rect, makeInstance } from '../../../src/main';
+
+const { any, createSpy, objectContaining } = jasmine
+
+
+describe('G.js', () => {
+
+  describe('()', () => {
+    it('creates a new object of type G', () => {
+      expect(new G()).toEqual(any(G))
+    })
+
+    it('sets passed attributes on the element', () => {
+      expect(new G({id:'foo'}).id()).toBe('foo')
+    })
+  })
+
+  describe('x()', () => {
+    it('gets the x value of the bbox', () => {
+      const canvas = makeInstance().addTo('#canvas')
+
+      const g = new G()
+      g.add(new Rect({width:100, height:120, x:10, y:20}))
+      g.add(new Rect({width:70, height:100, x:50, y:60}))
+
+      g.addTo(canvas)
+
+      expect(g.x()).toBe(g.bbox().x)
+      expect(g.x()).toBe(10)
+    })
+    it('sets the x value of the bbox by moving all children', () => {
+      const canvas = makeInstance().addTo('#canvas')
+
+      const g = new G()
+      g.add(new Rect({width:100, height:120, x:10, y:20}))
+      g.add(new Rect({width:70, height:100, x:50, y:60}))
+
+      g.addTo(canvas)
+
+      expect(g.x(0)).toBe(g)
+      expect(g.bbox().x).toBe(0)
+      expect(g.children()[0].x()).toBe(0)
+      expect(g.children()[1].x()).toBe(40)
+    })
+  })
+
+  describe('y()', () => {
+    it('gets the y value of the bbox', () => {
+      const canvas = makeInstance().addTo('#canvas')
+
+      const g = new G()
+      g.add(new Rect({width:100, height:120, x:10, y:20}))
+      g.add(new Rect({width:70, height:100, x:50, y:60}))
+
+      g.addTo(canvas)
+
+      expect(g.y()).toBe(g.bbox().y)
+      expect(g.y()).toBe(20)
+    })
+    it('sets the y value of the bbox by moving all children', () => {
+      const canvas = makeInstance().addTo('#canvas')
+
+      const g = new G()
+      g.add(new Rect({width:100, height:120, x:10, y:20}))
+      g.add(new Rect({width:70, height:100, x:50, y:60}))
+
+      g.addTo(canvas)
+
+      expect(g.y(0)).toBe(g)
+      expect(g.bbox().y).toBe(0)
+      expect(g.children()[0].y()).toBe(0)
+      expect(g.children()[1].y()).toBe(40)
+    })
+  })
+
+  describe('width()', () => {
+    it('gets the width value of the bbox', () => {
+      const canvas = makeInstance().addTo('#canvas')
+
+      const g = new G()
+      g.add(new Rect({width:100, height:120, x:10, y:20}))
+      g.add(new Rect({width:70, height:100, x:50, y:60}))
+
+      g.addTo(canvas)
+
+      expect(g.width()).toBe(g.bbox().width)
+      expect(g.width()).toBe(110)
+    })
+    it('sets the width value of the bbox by moving all children', () => {
+      const canvas = makeInstance().addTo('#canvas')
+
+      const g = new G()
+      g.add(new Rect({width:100, height:120, x:10, y:20}))
+      g.add(new Rect({width:70, height:100, x:50, y:60}))
+
+      g.addTo(canvas)
+
+      expect(g.width(100)).toBe(g)
+      expect(g.bbox().width).toBe(100)
+      expect(g.children()[0].width()).toBeCloseTo(90.909, 3)
+      expect(g.children()[1].width()).toBeCloseTo(63.636, 3)
+
+      expect(g.children()[0].x()).toBeCloseTo(10, 3)
+      expect(g.children()[1].x()).toBeCloseTo(46.364, 3)
+    })
+  })
+
+  describe('height()', () => {
+    it('gets the height value of the bbox', () => {
+      const canvas = makeInstance().addTo('#canvas')
+
+      const g = new G()
+      g.add(new Rect({width:100, height:120, x:10, y:20}))
+      g.add(new Rect({width:70, height:100, x:50, y:60}))
+
+      g.addTo(canvas)
+
+      expect(g.height()).toBe(g.bbox().height)
+      expect(g.height()).toBe(140)
+    })
+    it('sets the height value of the bbox by moving all children', () => {
+      const canvas = makeInstance().addTo('#canvas')
+
+      const g = new G()
+      g.add(new Rect({width:100, height:120, x:10, y:20}))
+      g.add(new Rect({width:70, height:100, x:50, y:60}))
+
+      g.addTo(canvas)
+
+      expect(g.height(100)).toBe(g)
+      expect(g.bbox().height).toBe(100)
+      expect(g.children()[0].height()).toBeCloseTo(85.714, 3)
+      expect(g.children()[1].height()).toBeCloseTo(71.429, 3)
+
+      expect(g.children()[0].y()).toBeCloseTo(20, 3)
+      expect(g.children()[1].y()).toBeCloseTo(48.571, 3)
+    })
+  })
+})
index 390b20083fbafcad65cd4347da9bb79f1e747dcf..21c735c5d832c9bf6783e5780644c6b6ade11842 100644 (file)
@@ -83,7 +83,7 @@ const Animator = {
     var nextFrame = null
     var lastFrame = Animator.frames.last()
     while ((nextFrame !== lastFrame) && (nextFrame = Animator.frames.shift())) {
-      nextFrame.run()
+      nextFrame.run(now)
     }
 
     var nextImmediate = null
index 8c265787974cd469dd23542e3b6e508a7363cd69..eebfb752a8c8a5dd443d8560063a0f4421e2f4d9 100644 (file)
@@ -136,6 +136,10 @@ export default class Runner extends EventTarget {
     this._times = times || Infinity
     this._swing = swing || false
     this._wait = wait || 0
+
+    // Allow true to be passed
+    if (this._times === true) { this._times = Infinity }
+
     return this
   }
 
index f5460b35115f1783fb21af6d45ff7599a47f1e2c..66ba61fdf19f33288806cd5ffb7636ff7a2fab8b 100644 (file)
@@ -40,7 +40,8 @@ export default class Timeline extends EventTarget {
     this._lastStepTime = 0
 
     // Make sure that step is always called in class context
-    this._step = this._step.bind(this)
+    this._step = this._stepFn.bind(this, false)
+    this._stepImmediate = this._stepFn.bind(this, true)
   }
 
   // schedules a runner on the timeline
@@ -184,7 +185,7 @@ export default class Timeline extends EventTarget {
     return this
   }
 
-  _step (immediateStep = false) {
+  _stepFn (immediateStep = false) {
     // Get the time delta from the last time and update the time
     var time = this._timeSource()
     var dtSource = time - this._lastSourceTime
@@ -278,8 +279,8 @@ export default class Timeline extends EventTarget {
     if ((runnersLeft && !(this._speed < 0 && this._time === 0)) || (this._runnerIds.length && this._speed < 0 && this._time > 0)) {
       this._continue()
     } else {
-      this.fire('finished')
       this.pause()
+      this.fire('finished')
     }
 
     return this
@@ -290,7 +291,7 @@ export default class Timeline extends EventTarget {
     Animator.cancelFrame(this._nextFrame)
     this._nextFrame = null
 
-    if (immediateStep) return this._step(true)
+    if (immediateStep) return this._stepImmediate()
     if (this._paused) return this
 
     this._nextFrame = Animator.frame(this._step)
index 594daa1cb17f802c605e7c044733d45bb75b013c..ba15f526e0b9844f455307bed1310b5189c41e2a 100644 (file)
@@ -55,6 +55,16 @@ export default class Element extends Dom {
     return this.root().defs()
   }
 
+  // Relative move over x axis
+  dx (x) {
+    return this.x(new SVGNumber(x).plus(this.x()))
+  }
+
+  // Relative move over y axis
+  dy (y) {
+    return this.y(new SVGNumber(y).plus(this.y()))
+  }
+
   // Get parent document
   root () {
     let p = this.parent(Svg)
index 0a11c1ef2697255a34abce63cd62a67c6da558f8..8171fed62a64786c5d0e00999323ebaf0ee7444e 100644 (file)
@@ -1,44 +1,80 @@
 import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'
+import { proportionalSize } from '../utils/utils.js'
 import { registerMethods } from '../utils/methods.js'
 import Container from './Container.js'
+import SVGNumber from '../types/SVGNumber.js'
 
 export default class G extends Container {
   constructor (node) {
     super(nodeOrNew('g', node), node)
   }
 
-  x (x) {
-    if (x == null) return this.transform()['x']
-    return this.move(x, 0)
+  x (x, box = this.bbox()) {
+    if (x == null) return box.x
+
+    this.children().dx(x - box.x)
+    return this
   }
 
-  y (y) {
-    if (y == null) return this.transform()['y']
-    return this.move(0, y)
+  y (y, box = this.bbox()) {
+    if (y == null) return box.y
+
+    this.children().dy(y - box.y)
+    return this
   }
 
   move (x, y) {
-    return this.translate(x, y)
+    const box = this.bbox()
+    return this.x(x, box).y(y, box)
   }
 
   dx (dx) {
-    return this.transform({ dx }, true)
+    return this.children().dx(dx)
   }
 
   dy (dy) {
-    return this.transform({ dy }, true)
+    return this.children().dy(dy)
   }
 
-  dmove (dx, dy) {
-    return this.transform({ dx, dy }, true)
+  width (width, box = this.bbox()) {
+    if (width == null) return box.width
+
+    const scale = width / box.width
+
+    this.each(function () {
+      const _width = this.width()
+      const _x = this.x()
+
+      this.width(_width * scale)
+      this.x((_x - box.x) * scale + box.x)
+    })
+
+    return this
   }
 
-  width () {
-    return this.bbox().width
+  height (height, box = this.bbox()) {
+    if (height == null) return box.height
+
+    const scale = height / box.height
+
+    this.each(function () {
+      const _height = this.height()
+      const _y = this.y()
+
+      this.height(_height * scale)
+      this.y((_y - box.y) * scale + box.y)
+    })
+
+    return this
   }
 
-  height () {
-    return this.bbox().height
+  size (width, height) {
+    const box = this.bbox()
+    const p = proportionalSize(this, width, height, box)
+
+    return this
+      .width(new SVGNumber(p.width), box)
+      .height(new SVGNumber(p.height), box)
   }
 }
 
index 1ff2380e05624870c0f1f7954ca2b46bf483ec56..dfa7b7bd0984ef0a1f6a652d7febc592c2829569 100644 (file)
@@ -5,7 +5,7 @@ export default function parser () {
   // Reuse cached element if possible
   if (!parser.nodes) {
     let svg = makeInstance().size(2, 0)
-    svg.node.cssText = [
+    svg.node.style.cssText = [
       'opacity: 0',
       'position: absolute',
       'left: -100%',
@@ -13,6 +13,8 @@ export default function parser () {
       'overflow: hidden'
     ].join(';')
 
+    svg.attr('focusable', 'false')
+
     let path = svg.path().node
 
     parser.nodes = { svg, path }
index d4255c37b363079bc40dc50548721b880a534379..c05512d0aa7b8b196e7985318d163921ca548535 100644 (file)
@@ -38,7 +38,7 @@ var sugar = {
     return this
   }
 
-  registerMethods([ 'Shape', 'Runner' ], extension)
+  registerMethods([ 'Element', 'Runner' ], extension)
 })
 
 registerMethods([ 'Element', 'Runner' ], {
@@ -110,18 +110,6 @@ registerMethods([ 'Element', 'Runner' ], {
   }
 })
 
-registerMethods('Element', {
-  // Relative move over x axis
-  dx: function (x) {
-    return this.x(new SVGNumber(x).plus(this.x()))
-  },
-
-  // Relative move over y axis
-  dy: function (y) {
-    return this.y(new SVGNumber(y).plus(this.y()))
-  }
-})
-
 registerMethods('radius', {
   // Add x and y radius
   radius: function (x, y) {
index 3bac0de38159e7bb69e6bdf02aac00716fd02746..c2046a9bc8932d728db6faeb5e0ee05820c69576 100644 (file)
@@ -56,9 +56,9 @@ export function capitalize (s) {
 }
 
 // Calculate proportional width and height values when necessary
-export function proportionalSize (element, width, height) {
+export function proportionalSize (element, width, height, box) {
   if (width == null || height == null) {
-    var box = element.bbox()
+    box = box || element.bbox()
 
     if (width == null) {
       width = box.width / box.height * height