From aab592ba613d4665244e6690cc80c4f999dc58dd Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 5 Dec 2017 15:04:19 -0500 Subject: [PATCH 01/20] Try to manage svg coordinates --- Procfile | 2 +- demo/demo.coffee | 40 +++++++++++++++++++++++++++------------ demo/demo.sass | 13 +++++++++++++ demo/index.pug | 5 +++-- karma.conf.coffee | 5 +++-- package.json | 8 ++++++-- src/referentiel.coffee | 14 +++++++++----- test/position-basique.pug | 11 +++++++++++ test/position.coffee | 7 ------- test/pug_loader.coffee | 28 +++++++++++++++++++++++++++ 10 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 test/position-basique.pug create mode 100644 test/pug_loader.coffee diff --git a/Procfile b/Procfile index 18cad01..6d49bab 100644 --- a/Procfile +++ b/Procfile @@ -1,5 +1,5 @@ web: ./node_modules/.bin/http-server -c-1 . sass: ./node_modules/.bin/node-sass --recursive --output demo demo && ./node_modules/.bin/node-sass --watch --recursive --output demo demo webpack: webpack -w -pug: ./node_modules/.bin/pug -w index.pug demo +pug: ./node_modules/.bin/pug -w index.pug demo test tests: ./node_modules/.bin/karma start diff --git a/demo/demo.coffee b/demo/demo.coffee index 477ff1f..4326601 100644 --- a/demo/demo.coffee +++ b/demo/demo.coffee @@ -1,23 +1,39 @@ $ -> + parse_assert = (input)-> + $.map input.split(':'), (i)-> + [ + $.map i.split(','), (s)-> + parseFloat(s) + ] + add_marker = (point)-> + $marker = $('
') + $marker.css('top', point[1]-5) + $marker.css('left', point[0]-5) + $('body').append($marker) + $('.referentiel').each -> - console.log this ref = new Referentiel(this) - $(this).on 'click', (e)-> - input = [e.pageX, e.pageY] - p = ref.global_to_local(input) - console.log input, '->', p - $pointer = $('.pointer', this) - $pointer.css('left', p[0]-3) - $pointer.css('top', p[1]-3) + $('[data-assert]', this).each (assert)-> + [global, local] = parse_assert $(this).data('assert') + result = ref.global_to_local(global) + console.log this, global, result, local + add_marker(global) + $assert = $(this) + $assert.css('left', result[0]-3) + $assert.css('top', result[1]-3) + $assert.attr('cx', result[0]) + $assert.attr('cy', result[1]) - $('body').on 'mousemove', (e)-> - return + $('body').on 'click', (e)-> $('.referentiel').each -> - console.log this ref = new Referentiel(this) input = [e.pageX, e.pageY] p = ref.global_to_local(input) + $('.pointer', this).remove() + $pointer = $('
') console.log input, '->', p - $pointer = $('.pointer', this) $pointer.css('left', p[0]-3) $pointer.css('top', p[1]-3) + $pointer.attr('cx', p[0]) + $pointer.attr('cy', p[1]) + $(this).append($pointer) diff --git a/demo/demo.sass b/demo/demo.sass index d19d86c..0b2f1d8 100644 --- a/demo/demo.sass +++ b/demo/demo.sass @@ -10,3 +10,16 @@ background: pink overflow: hidden position: relative +.marker + width: 10px + height: 10px + background: rgba(255, 0, 0, 0.5) + position: fixed + border-radius: 50% +.assert + position: absolute + width: 6px + height: 6px + background: black + position: absolute + border-radius: 50% diff --git a/demo/index.pug b/demo/index.pug index a9b8958..0d8b39a 100644 --- a/demo/index.pug +++ b/demo/index.pug @@ -8,11 +8,12 @@ html(lang='en') script(type='text/javascript', src='../dist/referentiel.js') script(type='text/javascript', src='../node_modules/jquery/dist/jquery.js') script(type='text/javascript', src='http://coffeescript.org/v1/browser-compiler/coffee-script.js') - script(type='text/javascript', src='coffee-script.js') + //script(type='text/javascript', src='coffee-script.js') script(type='text/coffeescript', src='demo.coffee') link(rel="stylesheet" media="all" href="../node_modules/reset-css/reset.css") link(rel="stylesheet" media="all" href="demo.css") body + include ../test/position-basique.pug //.super(style="height: 200px; width: 200px;") //div(style="margin-top: 40px; margin-left: 40px") //div(style="margin-top: 40px") @@ -24,7 +25,7 @@ html(lang='en') .referentiel .pointer //div(style="margin-top: 14px") - div(style="position: absolute; top: 40px; left: 50px;") + //div(style="position: absolute; top: 40px; left: 50px;") .referentiel .pointer //div diff --git a/karma.conf.coffee b/karma.conf.coffee index 597554d..bb91ad3 100644 --- a/karma.conf.coffee +++ b/karma.conf.coffee @@ -110,6 +110,7 @@ module.exports = (config) -> 'node_modules/reset-css/reset.css', 'node_modules/jquery/dist/jquery.js', { pattern: 'test/**/*.coffee', included: true } + { pattern: 'test/**/*.html', served: true, included: false} ] preprocessors: { @@ -127,14 +128,14 @@ module.exports = (config) -> # - config.LOG_DEBUG logLevel: config.LOG_INFO - autoWatch: false + autoWatch: true # browsers: [ 'Chrome', 'Firefox' ] browsers: Object.keys(customLaunchers) # Continuous Integration mode # if true, Karma captures browsers, runs the tests and exits - singleRun: true + singleRun: false port: 9876 colors: true diff --git a/package.json b/package.json index ff7ee29..8b3c77b 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "src" ], "scripts": { - "test": "npm run build && ./node_modules/.bin/karma start", + "test": "npm run build && ./node_modules/.bin/karma start --single-run", + "test-watch": "npm run build && ./node_modules/.bin/karma start", "start": "npm run build && ./node_modules/.bin/nf start", "build": "./node_modules/.bin/webpack" }, @@ -33,12 +34,15 @@ "jasmine": "2.8.0", "jasmine-core": "2.8.0", "jquery": "3.2.1", - "karma": "1.7.0", + "jsdom": "^11.5.1", + "karma": "^1.7.0", "karma-browserstack-launcher": "1.3.0", "karma-chrome-launcher": "2.2.0", "karma-coffee-preprocessor": "1.0.1", "karma-firefox-launcher": "1.0.1", "karma-jasmine": "1.1.0", + "karma-jsdom-launcher": "^6.1.2", + "karma-phantomjs-launcher": "^1.0.4", "karma-sauce-launcher": "1.2.0", "mocha": "3.5.0", "node-sass": "4.5.3", diff --git a/src/referentiel.coffee b/src/referentiel.coffee index 23a60f4..57d33c2 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -104,8 +104,7 @@ module.exports = class Referentiel @_matrix_offset = @matrix_offset_compute() @_matrix_offset matrix_offset_compute: -> - left = @reference.offsetLeft - top = @reference.offsetTop + [left, top] = @offset() switch @getPropertyValue('position') when 'absolute' return [[1,0,left],[0,1,top],[0,0,1]] @@ -117,11 +116,16 @@ module.exports = class Referentiel parent = @reference.parentElement parent_position = @getPropertyValue('position',parent) if parent_position == 'static' - left -= parent.offsetLeft - top -= parent.offsetTop - + [parent_left, parent_top] = @offset(parent) + left -= parent_left + top -= parent_top [[1,0,left],[0,1,top],[0,0,1]] + offset: (element = null)-> + element ||= @reference + return [element.offsetLeft, element.offsetTop] if element.offsetLeft? + domRect = element.getBoundingClientRect() + [domRect.x, domRect.y] getPropertyValue: (property, element = null)-> return Referentiel.jquery(element || @reference).css(property) if Referentiel.jquery window.getComputedStyle(element || @reference).getPropertyValue(property) diff --git a/test/position-basique.pug b/test/position-basique.pug new file mode 100644 index 0000000..3521dce --- /dev/null +++ b/test/position-basique.pug @@ -0,0 +1,11 @@ +//.referentiel(style="position: fixed; top: 50px; left: 20px;") + .assert(data-assert="20,50:0,0") + .assert(data-assert="30,60:10,10") + + +div(style="position: fixed; top: 12px; left: 13px;") + div(style="position: fixed; top: 50px; left: 20px;") + div(style="position: fixed; top: 50px; left: 20px;") + .referentiel + .assert(data-assert="20,50:0,0") + .assert(data-assert="30,60:10,10") diff --git a/test/position.coffee b/test/position.coffee index 7e7ac8a..422a443 100644 --- a/test/position.coffee +++ b/test/position.coffee @@ -1,12 +1,5 @@ describe "Positions", -> describe 'Fixed', -> - it 'basic', -> - ref = from_template(' -
- ') - expect(ref.global_to_local([20, 50])).toEqual([0, 0]) - expect(ref.global_to_local([30, 60])).toEqual([10, 10]) - it 'scoped', -> ref = from_template('
diff --git a/test/pug_loader.coffee b/test/pug_loader.coffee new file mode 100644 index 0000000..3b9a92a --- /dev/null +++ b/test/pug_loader.coffee @@ -0,0 +1,28 @@ +load_template = (template_name, callback)-> + $.get + url: '/base/test/'+template_name+'.html', + dataType: 'text' + success: callback +parse_assert = (input)-> + $.map input.split(':'), (i)-> + [ + $.map i.split(','), (s)-> + parseFloat(s) + ] +describe "Pug", -> + run_test_from_template = (template_name, callback)-> + load_template template_name, (template)-> + $context = $('
'+template+'
') + $('body').append($context) + $('.referentiel', $context).each -> + referentiel = new Referentiel(this) + $('[data-assert]', this).each (assert)-> + [global, local] = parse_assert $(this).data('assert') + result = referentiel.global_to_local(global) + expect(result).toEqual(local) + callback() + add_test = (template_name)-> + it template_name, (done)-> + run_test_from_template template_name, done + for template_name in ['svg-1', 'position-basique'] + add_test(template_name) From deaa723e47c3387496121777f56c081fea5335a0 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 5 Dec 2017 15:58:16 -0500 Subject: [PATCH 02/20] Add some test on svg elements --- demo/demo.coffee | 11 ++++++++--- demo/index.pug | 2 +- src/referentiel.coffee | 12 ++++++++++++ test/position-basique.pug | 10 +--------- test/position-scoped.pug | 6 ++++++ test/pug_loader.coffee | 8 +++++++- test/svg-1.pug | 4 ++++ test/svg-2.pug | 4 ++++ test/svg-3.pug | 4 ++++ 9 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 test/position-scoped.pug create mode 100644 test/svg-1.pug create mode 100644 test/svg-2.pug create mode 100644 test/svg-3.pug diff --git a/demo/demo.coffee b/demo/demo.coffee index 4326601..541540d 100644 --- a/demo/demo.coffee +++ b/demo/demo.coffee @@ -9,6 +9,8 @@ $ -> $marker = $('
') $marker.css('top', point[1]-5) $marker.css('left', point[0]-5) + $marker.attr('data-x', point[0]) + $marker.attr('data-y', point[1]) $('body').append($marker) $('.referentiel').each -> @@ -23,17 +25,20 @@ $ -> $assert.css('top', result[1]-3) $assert.attr('cx', result[0]) $assert.attr('cy', result[1]) + $assert.data('x', result[0]) + $assert.data('y', result[1]) $('body').on 'click', (e)-> $('.referentiel').each -> ref = new Referentiel(this) input = [e.pageX, e.pageY] p = ref.global_to_local(input) - $('.pointer', this).remove() - $pointer = $('
') + if $('.pointer', this).length == 0 + $pointer = $('
') + $(this).append($pointer) + $pointer = $('.pointer', this) console.log input, '->', p $pointer.css('left', p[0]-3) $pointer.css('top', p[1]-3) $pointer.attr('cx', p[0]) $pointer.attr('cy', p[1]) - $(this).append($pointer) diff --git a/demo/index.pug b/demo/index.pug index 0d8b39a..c762256 100644 --- a/demo/index.pug +++ b/demo/index.pug @@ -13,7 +13,7 @@ html(lang='en') link(rel="stylesheet" media="all" href="../node_modules/reset-css/reset.css") link(rel="stylesheet" media="all" href="demo.css") body - include ../test/position-basique.pug + include ../test/svg-3.pug //.super(style="height: 200px; width: 200px;") //div(style="margin-top: 40px; margin-left: 40px") //div(style="margin-top: 40px") diff --git a/src/referentiel.coffee b/src/referentiel.coffee index 57d33c2..d935108 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -21,6 +21,7 @@ module.exports = class Referentiel delete @_matrix delete @_matrix_transformation delete @_matrix_transform_origin + delete @_matrix_svg matrix_inv: -> return @_matrix_inv if @_matrix_inv @@ -104,6 +105,7 @@ module.exports = class Referentiel @_matrix_offset = @matrix_offset_compute() @_matrix_offset matrix_offset_compute: -> + return @matrix_svg() if @reference instanceof SVGElement [left, top] = @offset() switch @getPropertyValue('position') when 'absolute' @@ -121,6 +123,16 @@ module.exports = class Referentiel top -= parent_top [[1,0,left],[0,1,top],[0,0,1]] + matrix_svg: -> + return @_matrix_svg if @_matrix_svg + @_matrix_svg = @matrix_svg_compute() + @_matrix_svg + matrix_svg_compute: -> + return [[1,0,0], [0,1,0], [0,0,1]] unless @reference instanceof SVGElement + mat = @reference.getScreenCTM() + return [[1,0,0], [0,1,0], [0,0,1]] unless mat + [[mat.a, mat.b, mat.e], [mat.c, mat.d, mat.f], [0,0,1]] + offset: (element = null)-> element ||= @reference return [element.offsetLeft, element.offsetTop] if element.offsetLeft? diff --git a/test/position-basique.pug b/test/position-basique.pug index 3521dce..9b541eb 100644 --- a/test/position-basique.pug +++ b/test/position-basique.pug @@ -1,11 +1,3 @@ -//.referentiel(style="position: fixed; top: 50px; left: 20px;") +.referentiel(style="position: fixed; top: 50px; left: 20px;") .assert(data-assert="20,50:0,0") .assert(data-assert="30,60:10,10") - - -div(style="position: fixed; top: 12px; left: 13px;") - div(style="position: fixed; top: 50px; left: 20px;") - div(style="position: fixed; top: 50px; left: 20px;") - .referentiel - .assert(data-assert="20,50:0,0") - .assert(data-assert="30,60:10,10") diff --git a/test/position-scoped.pug b/test/position-scoped.pug new file mode 100644 index 0000000..8e8ce76 --- /dev/null +++ b/test/position-scoped.pug @@ -0,0 +1,6 @@ +div(style="position: fixed; top: 12px; left: 13px;") + div(style="position: fixed; top: 50px; left: 20px;") + div(style="position: fixed; top: 50px; left: 20px;") + .referentiel + .assert(data-assert="20,50:0,0") + .assert(data-assert="30,60:10,10") diff --git a/test/pug_loader.coffee b/test/pug_loader.coffee index 3b9a92a..148b6c0 100644 --- a/test/pug_loader.coffee +++ b/test/pug_loader.coffee @@ -24,5 +24,11 @@ describe "Pug", -> add_test = (template_name)-> it template_name, (done)-> run_test_from_template template_name, done - for template_name in ['svg-1', 'position-basique'] + for template_name in [ + 'svg-1', + 'svg-2', + 'svg-3', + 'position-basique', + 'position-scoped', + ] add_test(template_name) diff --git a/test/svg-1.pug b/test/svg-1.pug new file mode 100644 index 0000000..cda6173 --- /dev/null +++ b/test/svg-1.pug @@ -0,0 +1,4 @@ +svg.referentiel(style="margin: 40px;" width=200 height=200 viewbox="0 0 200 200") + circle.pointer(cx=10 cy=10 r=10) + circle(data-assert="40,40:0,0" r=1) + circle(data-assert="61,62:21,22" r=1) diff --git a/test/svg-2.pug b/test/svg-2.pug new file mode 100644 index 0000000..7531e0e --- /dev/null +++ b/test/svg-2.pug @@ -0,0 +1,4 @@ +svg.referentiel(style="margin: 10px" width=100 height=100 viewbox="0 0 50 50") + circle.pointer(cx=10 cy=10 r=10) + circle(data-assert="98,98:44,44" r=1) + circle(data-assert="150,138:70,64" r=1) diff --git a/test/svg-3.pug b/test/svg-3.pug new file mode 100644 index 0000000..269dc62 --- /dev/null +++ b/test/svg-3.pug @@ -0,0 +1,4 @@ +svg.referentiel(style="margin: 10px" width=100 height=100 viewbox="11 12 50 100") + circle.pointer(cx=10 cy=10 r=10) + circle(data-assert="30,30:6,32" r=1) + circle(data-assert="100,100:76,102" r=1) From d5c2dff5ead06b2fddc360b16285dea7c55e5fd3 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Wed, 6 Dec 2017 17:01:56 -0500 Subject: [PATCH 03/20] Fix tests (still having firefox issues...) --- demo/demo.sass | 4 ++-- test/helper.coffee | 4 ---- test/pug_loader.coffee | 1 + test/svg-3.pug | 9 +++++---- test/svg-4.pug | 5 +++++ 5 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 test/svg-4.pug diff --git a/demo/demo.sass b/demo/demo.sass index 0b2f1d8..6773b87 100644 --- a/demo/demo.sass +++ b/demo/demo.sass @@ -5,8 +5,8 @@ position: absolute border-radius: 50% .referentiel - width: 200px - height: 200px + width: 100px + height: 100px background: pink overflow: hidden position: relative diff --git a/test/helper.coffee b/test/helper.coffee index 0725683..ee0bc31 100644 --- a/test/helper.coffee +++ b/test/helper.coffee @@ -9,7 +9,3 @@ from_template = (template)-> $('.reference', $context)[0], $('.context', $context)[0] ) - -# afterEach -> -# console.log 'CLEAR' -# $('body').html('') diff --git a/test/pug_loader.coffee b/test/pug_loader.coffee index 148b6c0..11a4abb 100644 --- a/test/pug_loader.coffee +++ b/test/pug_loader.coffee @@ -28,6 +28,7 @@ describe "Pug", -> 'svg-1', 'svg-2', 'svg-3', + 'svg-4', 'position-basique', 'position-scoped', ] diff --git a/test/svg-3.pug b/test/svg-3.pug index 269dc62..1bafe13 100644 --- a/test/svg-3.pug +++ b/test/svg-3.pug @@ -1,4 +1,5 @@ -svg.referentiel(style="margin: 10px" width=100 height=100 viewbox="11 12 50 100") - circle.pointer(cx=10 cy=10 r=10) - circle(data-assert="30,30:6,32" r=1) - circle(data-assert="100,100:76,102" r=1) +svg.referentiel(style="margin: 10px" width=100 height=100 viewbox="10 11 100 100") + circle.pointer(r=10) + circle(data-assert="30,30:30,31" r=1) + circle(data-assert="100,100:100,101" r=1) + circle(cx=20 cy=21 r=10) diff --git a/test/svg-4.pug b/test/svg-4.pug new file mode 100644 index 0000000..e714079 --- /dev/null +++ b/test/svg-4.pug @@ -0,0 +1,5 @@ +svg(width=200 height=200 viewbox="0 0 100 100") + g.referentiel(style="transform: scale(0.5);") + circle.pointer(cx=10 cy=10 r=10) + circle(data-assert="0,0:0,0" r=1) + circle(data-assert="10,10:10,10" r=1) From 062e9548eae9124b5064d97842cadc29189cac0c Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Fri, 15 Dec 2017 17:22:16 -0400 Subject: [PATCH 04/20] WIP Changes with greg. --- README.md | 3 +++ demo/index.pug | 9 ++++++--- src/referentiel.coffee | 8 ++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f9a8aa5..b0b9616 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,9 @@ the changes. (You will only get scroll issues with fixed elements) getComputedElement... - [ ] Add more tests and edge cases... - [ ] Manage scroll (globally and on elements) +- [ ] Round in the tests +- [ ] Greg's test +- [ ] CamelCase + check webkit naming convention ### Big Thanks diff --git a/demo/index.pug b/demo/index.pug index a9b8958..a009c4b 100644 --- a/demo/index.pug +++ b/demo/index.pug @@ -24,9 +24,12 @@ html(lang='en') .referentiel .pointer //div(style="margin-top: 14px") - div(style="position: absolute; top: 40px; left: 50px;") - .referentiel - .pointer + div(style="position: relative; top: 40px; left: 40px") + p Hello World + div + div(style="position: absolute; top: 40px; left: 50px;") + .referentiel + .pointer //div div(style="position: absolute; top: 40px; left: 50px;") div(style="transform: scale(1.2) rotate(30deg)") diff --git a/src/referentiel.coffee b/src/referentiel.coffee index 23a60f4..472bb2c 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -31,14 +31,18 @@ module.exports = class Referentiel matrix: -> return @_matrix if @_matrix @_matrix = @matrix_compute() + console.log @reference, @_matrix @_matrix matrix_compute: -> matrix_locale = @matrix_locale() if @getPropertyValue('position') == 'fixed' return matrix_locale - if @reference.parentElement? - parent_referentiel = new Referentiel(@reference.parentElement) + if @reference.offsetParent? + parent_referentiel = new Referentiel(@reference.offsetParent) return @_multiply(parent_referentiel.matrix(), matrix_locale) + # if @reference.parentElement? + # parent_referentiel = new Referentiel(@reference.parentElement) + # return @_multiply(parent_referentiel.matrix(), matrix_locale) matrix_locale matrix_locale: -> From f171bc404b96dbf6e24812cc0986b0781a156e67 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Mon, 12 Mar 2018 17:03:53 -0400 Subject: [PATCH 05/20] Small fix for IE + svg transform --- src/referentiel.coffee | 14 ++++++++------ test/svg-4.pug | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/referentiel.coffee b/src/referentiel.coffee index d935108..d5b9fce 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -37,8 +37,8 @@ module.exports = class Referentiel matrix_locale = @matrix_locale() if @getPropertyValue('position') == 'fixed' return matrix_locale - if @reference.parentElement? - parent_referentiel = new Referentiel(@reference.parentElement) + if @reference.parentNode? && @reference.parentNode != document.documentElement + parent_referentiel = new Referentiel(@reference.parentNode) return @_multiply(parent_referentiel.matrix(), matrix_locale) matrix_locale @@ -73,9 +73,11 @@ module.exports = class Referentiel @_matrix_transformation = @matrix_transformation_compute() @_matrix_transformation matrix_transformation_compute: -> - transform = @getPropertyValue('transform') + transform = @reference.getAttribute('transform') || 'none' + transform = @reference.style.transform unless transform.match(/^matrix\((.*)\)$/) + transform = @getPropertyValue('transform') unless transform.match(/^matrix\((.*)\)$/) if res = transform.match(/^matrix\((.*)\)$/) - floats = res[1].split(',').map((e)-> + floats = res[1].replace(',', ' ').replace(' ', ' ').split(' ').map((e)-> parseFloat(e) ) return [[floats[0], floats[2], floats[4]],[floats[1], floats[3], floats[5]], [0, 0, 1]] @@ -114,8 +116,8 @@ module.exports = class Referentiel left += window.pageXOffset top += window.pageYOffset return [[1,0,left],[0,1,top],[0,0,1]] - if @reference.parentElement? - parent = @reference.parentElement + if @reference.parentNode? + parent = @reference.parentNode parent_position = @getPropertyValue('position',parent) if parent_position == 'static' [parent_left, parent_top] = @offset(parent) diff --git a/test/svg-4.pug b/test/svg-4.pug index e714079..318cc9f 100644 --- a/test/svg-4.pug +++ b/test/svg-4.pug @@ -1,4 +1,4 @@ -svg(width=200 height=200 viewbox="0 0 100 100") +//svg(width=200 height=200 viewbox="0 0 100 100") g.referentiel(style="transform: scale(0.5);") circle.pointer(cx=10 cy=10 r=10) circle(data-assert="0,0:0,0" r=1) From eff413a9da5ff2e04af17f6d13f555751274181a Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 13 Mar 2018 10:42:33 -0400 Subject: [PATCH 06/20] Manage svg viewbox + improve matrix multiply --- src/referentiel.coffee | 49 +++++++++++++++++++++++++++--------------- test/svg-2.pug | 7 +++--- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/referentiel.coffee b/src/referentiel.coffee index d5b9fce..cf3410e 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -48,11 +48,10 @@ module.exports = class Referentiel @_matrix_locale matrix_locale_compute: -> @_multiply( + @matrix_svg(), @matrix_offset(), - @_multiply( - @matrix_transformation_with_origin(), - @matrix_border() - ), + @matrix_transformation_with_origin(), + @matrix_border() ) matrix_transformation_with_origin: -> @@ -61,10 +60,8 @@ module.exports = class Referentiel @_matrix_transformation_with_origin matrix_transformation_with_origin_compute: -> @_multiply( - @_multiply( - @matrix_transform_origin(), - @matrix_transformation() - ), + @matrix_transform_origin(), + @matrix_transformation(), @_inv(@matrix_transform_origin()) ) @@ -107,7 +104,6 @@ module.exports = class Referentiel @_matrix_offset = @matrix_offset_compute() @_matrix_offset matrix_offset_compute: -> - return @matrix_svg() if @reference instanceof SVGElement [left, top] = @offset() switch @getPropertyValue('position') when 'absolute' @@ -118,23 +114,38 @@ module.exports = class Referentiel return [[1,0,left],[0,1,top],[0,0,1]] if @reference.parentNode? parent = @reference.parentNode - parent_position = @getPropertyValue('position',parent) + parent_position = @getPropertyValue('position', parent) if parent_position == 'static' [parent_left, parent_top] = @offset(parent) left -= parent_left top -= parent_top [[1,0,left],[0,1,top],[0,0,1]] - matrix_svg: -> return @_matrix_svg if @_matrix_svg @_matrix_svg = @matrix_svg_compute() @_matrix_svg matrix_svg_compute: -> return [[1,0,0], [0,1,0], [0,0,1]] unless @reference instanceof SVGElement - mat = @reference.getScreenCTM() - return [[1,0,0], [0,1,0], [0,0,1]] unless mat - [[mat.a, mat.b, mat.e], [mat.c, mat.d, mat.f], [0,0,1]] - + attr = @reference.getAttribute('viewBox') + viewBox = attr.replace(',', ' ').replace(' ', ' ').split(' ').map (e)-> + parseFloat(e) + size = [ + parseFloat(@getPropertyValue('width').replace(/px/g, '')) + parseFloat(@getPropertyValue('height').replace(/px/g, '')) + ] + scale = [size[0] / viewBox[2], size[1] / viewBox[3] ] + @_multiply( + [ + [scale[0], 0, 0] + [0, scale[1], 0] + [0, 0, 1] + ], + [ + [1, 0, -viewBox[0]], + [0, 1, -viewBox[1]], + [0, 0, 1] + ] + ) offset: (element = null)-> element ||= @reference return [element.offsetLeft, element.offsetTop] if element.offsetLeft? @@ -150,7 +161,8 @@ module.exports = class Referentiel for k in [0...3] res[i] += m[i][k]*v[k] res - _multiply: (a, b)-> + _multiply: -> + [a, b, others...] = arguments res = [] for i in [0...3] res[i] = [] @@ -158,7 +170,10 @@ module.exports = class Referentiel res[i][j] = 0.0 for k in [0...3] res[i][j] += a[i][k]*b[k][j] - res + if others.length > 0 + @_multiply(res, others...) + else + res _det: (m)-> return ( m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - diff --git a/test/svg-2.pug b/test/svg-2.pug index 7531e0e..928c4d0 100644 --- a/test/svg-2.pug +++ b/test/svg-2.pug @@ -1,4 +1,5 @@ -svg.referentiel(style="margin: 10px" width=100 height=100 viewbox="0 0 50 50") +svg.referentiel(width=100 height=100 viewbox="10 10 50 50") circle.pointer(cx=10 cy=10 r=10) - circle(data-assert="98,98:44,44" r=1) - circle(data-assert="150,138:70,64" r=1) + circle(data-assert="0,0:10,10" r=1) + circle(data-assert="100,100:60,60" r=1) + circle(data-assert="90,90:55,55" r=1) From 87cc7d0fa56f1749ccb5c6a2dbba3abca867f7e1 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 13 Mar 2018 10:48:11 -0400 Subject: [PATCH 07/20] Fix no viewbox --- src/referentiel.coffee | 7 ++++--- test/pug_loader.coffee | 1 + test/svg-5.pug | 4 ++++ 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 test/svg-5.pug diff --git a/src/referentiel.coffee b/src/referentiel.coffee index cf3410e..545240a 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -126,13 +126,14 @@ module.exports = class Referentiel @_matrix_svg matrix_svg_compute: -> return [[1,0,0], [0,1,0], [0,0,1]] unless @reference instanceof SVGElement - attr = @reference.getAttribute('viewBox') - viewBox = attr.replace(',', ' ').replace(' ', ' ').split(' ').map (e)-> - parseFloat(e) size = [ parseFloat(@getPropertyValue('width').replace(/px/g, '')) parseFloat(@getPropertyValue('height').replace(/px/g, '')) ] + attr = @reference.getAttribute('viewBox') + return [[1,0,0], [0,1,0], [0,0,1]] unless attr? + viewBox = attr.replace(',', ' ').replace(' ', ' ').split(' ').map (e)-> + parseFloat(e) scale = [size[0] / viewBox[2], size[1] / viewBox[3] ] @_multiply( [ diff --git a/test/pug_loader.coffee b/test/pug_loader.coffee index 11a4abb..bcef930 100644 --- a/test/pug_loader.coffee +++ b/test/pug_loader.coffee @@ -29,6 +29,7 @@ describe "Pug", -> 'svg-2', 'svg-3', 'svg-4', + 'svg-5', 'position-basique', 'position-scoped', ] diff --git a/test/svg-5.pug b/test/svg-5.pug new file mode 100644 index 0000000..9477bd4 --- /dev/null +++ b/test/svg-5.pug @@ -0,0 +1,4 @@ +svg.referentiel(style="margin: 40px;" width=200 height=200) + circle.pointer(cx=10 cy=10 r=10) + circle(data-assert="40,40:0,0" r=1) + circle(data-assert="61,62:21,22" r=1) From f91c1b40d53f27a87147d8bd5e4e7538f8eda1d3 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 13 Mar 2018 16:14:27 -0400 Subject: [PATCH 08/20] Manage svg viewbox with more tests --- demo/demo.coffee | 3 +- demo/index.pug | 2 +- src/referentiel.coffee | 52 ++++++++++++++------------ test/pug_loader.coffee | 13 ++++--- test/svg-1.pug | 4 -- test/svg-basic.pug | 4 ++ test/svg-border.pug | 4 ++ test/svg-composition.pug | 5 +++ test/{svg-4.pug => svg-group.pug} | 2 +- test/{svg-3.pug => svg-margin.pug} | 0 test/{svg-5.pug => svg-no-viewbox.pug} | 0 test/{svg-2.pug => svg-viewport.pug} | 0 12 files changed, 53 insertions(+), 36 deletions(-) delete mode 100644 test/svg-1.pug create mode 100644 test/svg-basic.pug create mode 100644 test/svg-border.pug create mode 100644 test/svg-composition.pug rename test/{svg-4.pug => svg-group.pug} (76%) rename test/{svg-3.pug => svg-margin.pug} (100%) rename test/{svg-5.pug => svg-no-viewbox.pug} (100%) rename test/{svg-2.pug => svg-viewport.pug} (100%) diff --git a/demo/demo.coffee b/demo/demo.coffee index 541540d..12dd6e2 100644 --- a/demo/demo.coffee +++ b/demo/demo.coffee @@ -37,7 +37,8 @@ $ -> $pointer = $('
') $(this).append($pointer) $pointer = $('.pointer', this) - console.log input, '->', p + console.log '======' + console.log input, '->', p, new Referentiel(this).matrix(), this $pointer.css('left', p[0]-3) $pointer.css('top', p[1]-3) $pointer.attr('cx', p[0]) diff --git a/demo/index.pug b/demo/index.pug index c762256..daf0af4 100644 --- a/demo/index.pug +++ b/demo/index.pug @@ -13,7 +13,7 @@ html(lang='en') link(rel="stylesheet" media="all" href="../node_modules/reset-css/reset.css") link(rel="stylesheet" media="all" href="demo.css") body - include ../test/svg-3.pug + include ../test/svg-composition.pug //.super(style="height: 200px; width: 200px;") //div(style="margin-top: 40px; margin-left: 40px") //div(style="margin-top: 40px") diff --git a/src/referentiel.coffee b/src/referentiel.coffee index 545240a..02a4b14 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -37,8 +37,9 @@ module.exports = class Referentiel matrix_locale = @matrix_locale() if @getPropertyValue('position') == 'fixed' return matrix_locale - if @reference.parentNode? && @reference.parentNode != document.documentElement - parent_referentiel = new Referentiel(@reference.parentNode) + parent = @parent() + if parent + parent_referentiel = new Referentiel(parent) return @_multiply(parent_referentiel.matrix(), matrix_locale) matrix_locale @@ -48,21 +49,12 @@ module.exports = class Referentiel @_matrix_locale matrix_locale_compute: -> @_multiply( - @matrix_svg(), + @matrix_svg_viewbox(), @matrix_offset(), - @matrix_transformation_with_origin(), - @matrix_border() - ) - - matrix_transformation_with_origin: -> - return @_matrix_transformation_with_origin if @_matrix_transformation_with_origin - @_matrix_transformation_with_origin = @matrix_transformation_with_origin_compute() - @_matrix_transformation_with_origin - matrix_transformation_with_origin_compute: -> - @_multiply( @matrix_transform_origin(), @matrix_transformation(), - @_inv(@matrix_transform_origin()) + @_inv(@matrix_transform_origin()), + @matrix_border() ) matrix_transformation: -> @@ -103,6 +95,12 @@ module.exports = class Referentiel return @_matrix_offset if @_matrix_offset @_matrix_offset = @matrix_offset_compute() @_matrix_offset + parent: (element)-> + element ||= @reference + if element.parentNode? && element.parentNode != document.documentElement + element.parentNode + else + null matrix_offset_compute: -> [left, top] = @offset() switch @getPropertyValue('position') @@ -112,19 +110,19 @@ module.exports = class Referentiel left += window.pageXOffset top += window.pageYOffset return [[1,0,left],[0,1,top],[0,0,1]] - if @reference.parentNode? - parent = @reference.parentNode + parent = @parent() + if parent parent_position = @getPropertyValue('position', parent) if parent_position == 'static' [parent_left, parent_top] = @offset(parent) left -= parent_left top -= parent_top [[1,0,left],[0,1,top],[0,0,1]] - matrix_svg: -> - return @_matrix_svg if @_matrix_svg - @_matrix_svg = @matrix_svg_compute() - @_matrix_svg - matrix_svg_compute: -> + matrix_svg_viewbox: -> + return @_matrix_viewbox_svg if @_matrix_svg_viewbox + @_matrix_svg_viewbox = @matrix_svg_viewbox_compute() + @_matrix_svg_viewbox + matrix_svg_viewbox_compute: -> return [[1,0,0], [0,1,0], [0,0,1]] unless @reference instanceof SVGElement size = [ parseFloat(@getPropertyValue('width').replace(/px/g, '')) @@ -145,13 +143,19 @@ module.exports = class Referentiel [1, 0, -viewBox[0]], [0, 1, -viewBox[1]], [0, 0, 1] - ] + ], ) offset: (element = null)-> element ||= @reference return [element.offsetLeft, element.offsetTop] if element.offsetLeft? - domRect = element.getBoundingClientRect() - [domRect.x, domRect.y] + pos = @reference.getBoundingClientRect() + offset = [pos.left, pos.top] + parent = @parent(element) + if parent? + ppos = parent.getBoundingClientRect() + offset[0] -= ppos.left + offset[1] -= ppos.top + offset getPropertyValue: (property, element = null)-> return Referentiel.jquery(element || @reference).css(property) if Referentiel.jquery window.getComputedStyle(element || @reference).getPropertyValue(property) diff --git a/test/pug_loader.coffee b/test/pug_loader.coffee index bcef930..0c6f098 100644 --- a/test/pug_loader.coffee +++ b/test/pug_loader.coffee @@ -19,17 +19,20 @@ describe "Pug", -> $('[data-assert]', this).each (assert)-> [global, local] = parse_assert $(this).data('assert') result = referentiel.global_to_local(global) + console.log 'assert', global, local, result expect(result).toEqual(local) callback() add_test = (template_name)-> it template_name, (done)-> run_test_from_template template_name, done for template_name in [ - 'svg-1', - 'svg-2', - 'svg-3', - 'svg-4', - 'svg-5', + 'svg-basic', + 'svg-viewport', + 'svg-margin', + 'svg-border', + 'svg-group', + 'svg-no-viewbox', + 'svg-composition', 'position-basique', 'position-scoped', ] diff --git a/test/svg-1.pug b/test/svg-1.pug deleted file mode 100644 index cda6173..0000000 --- a/test/svg-1.pug +++ /dev/null @@ -1,4 +0,0 @@ -svg.referentiel(style="margin: 40px;" width=200 height=200 viewbox="0 0 200 200") - circle.pointer(cx=10 cy=10 r=10) - circle(data-assert="40,40:0,0" r=1) - circle(data-assert="61,62:21,22" r=1) diff --git a/test/svg-basic.pug b/test/svg-basic.pug new file mode 100644 index 0000000..56dffc5 --- /dev/null +++ b/test/svg-basic.pug @@ -0,0 +1,4 @@ +svg.referentiel(width=100 height=100 viewbox="0 0 100 100") + circle.pointer(cx=10 cy=10 r=10) + circle(data-assert="0,0:0,0" r=1) + circle(data-assert="21,22:21,22" r=1) diff --git a/test/svg-border.pug b/test/svg-border.pug new file mode 100644 index 0000000..0dce15d --- /dev/null +++ b/test/svg-border.pug @@ -0,0 +1,4 @@ +svg.referentiel(style="border: 10px solid black;" width=100 height=100 viewbox="10 20 100 100") + circle.pointer(cx=10 cy=10 r=10) + circle(data-assert="10,10:10,20" r=1) + circle(data-assert="110,110:110,120" r=1) diff --git a/test/svg-composition.pug b/test/svg-composition.pug new file mode 100644 index 0000000..765b01a --- /dev/null +++ b/test/svg-composition.pug @@ -0,0 +1,5 @@ +div(style="position: absolute; left: 10px; top: 20px;") + svg.referentiel(width=100 height=100 viewBox="20 30 100 100") + circle.pointer(cx=10 cy=10 r=10) + circle(data-assert="10,20:20,30" r=1) + circle(data-assert="100,100:110,110" r=1) diff --git a/test/svg-4.pug b/test/svg-group.pug similarity index 76% rename from test/svg-4.pug rename to test/svg-group.pug index 318cc9f..e714079 100644 --- a/test/svg-4.pug +++ b/test/svg-group.pug @@ -1,4 +1,4 @@ -//svg(width=200 height=200 viewbox="0 0 100 100") +svg(width=200 height=200 viewbox="0 0 100 100") g.referentiel(style="transform: scale(0.5);") circle.pointer(cx=10 cy=10 r=10) circle(data-assert="0,0:0,0" r=1) diff --git a/test/svg-3.pug b/test/svg-margin.pug similarity index 100% rename from test/svg-3.pug rename to test/svg-margin.pug diff --git a/test/svg-5.pug b/test/svg-no-viewbox.pug similarity index 100% rename from test/svg-5.pug rename to test/svg-no-viewbox.pug diff --git a/test/svg-2.pug b/test/svg-viewport.pug similarity index 100% rename from test/svg-2.pug rename to test/svg-viewport.pug From f3a6b7e600c0573d32d9a00b8bc446c81e2a2633 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 13 Mar 2018 19:25:00 -0400 Subject: [PATCH 09/20] Fix rubocop --- src/referentiel.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/referentiel.coffee b/src/referentiel.coffee index 02a4b14..becbe71 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -107,9 +107,9 @@ module.exports = class Referentiel when 'absolute' return [[1,0,left],[0,1,top],[0,0,1]] when 'fixed' - left += window.pageXOffset - top += window.pageYOffset - return [[1,0,left],[0,1,top],[0,0,1]] + left += window.pageXOffset + top += window.pageYOffset + return [[1,0,left],[0,1,top],[0,0,1]] parent = @parent() if parent parent_position = @getPropertyValue('position', parent) From 60d7c119235971b498a504ee422dd7f39faa0e43 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Sun, 25 Mar 2018 17:43:50 -0400 Subject: [PATCH 10/20] Fix indentation --- src/referentiel.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/referentiel.coffee b/src/referentiel.coffee index becbe71..1cc4642 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -106,10 +106,10 @@ module.exports = class Referentiel switch @getPropertyValue('position') when 'absolute' return [[1,0,left],[0,1,top],[0,0,1]] - when 'fixed' - left += window.pageXOffset - top += window.pageYOffset - return [[1,0,left],[0,1,top],[0,0,1]] + when 'fixed' + left += window.pageXOffset + top += window.pageYOffset + return [[1,0,left],[0,1,top],[0,0,1]] parent = @parent() if parent parent_position = @getPropertyValue('position', parent) From f950dc17af71fec6cfa179abf78f9f1a3613792f Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Mon, 26 Mar 2018 19:42:15 -0400 Subject: [PATCH 11/20] Fix greg issue + refactor referentiel --- src/referentiel.coffee | 21 ++--- test/borders.coffee | 14 ---- test/borders.pug | 3 + test/margins.pug | 3 + test/position-in-flow.pug | 5 ++ test/position-offset.pug | 8 ++ test/pug_loader.coffee | 15 +++- test/rotation-scale.pug | 4 + test/rotation-transform-origin.pug | 4 + test/rotation.pug | 4 + test/transform.coffee | 130 ----------------------------- 11 files changed, 49 insertions(+), 162 deletions(-) delete mode 100644 test/borders.coffee create mode 100644 test/borders.pug create mode 100644 test/margins.pug create mode 100644 test/position-in-flow.pug create mode 100644 test/position-offset.pug create mode 100644 test/rotation-scale.pug create mode 100644 test/rotation-transform-origin.pug create mode 100644 test/rotation.pug delete mode 100644 test/transform.coffee diff --git a/src/referentiel.coffee b/src/referentiel.coffee index 61e98f1..40b16f0 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -1,5 +1,5 @@ module.exports = class Referentiel - constructor: (@reference)-> + constructor: (@reference, @options = {})-> global_to_local: (point)-> @_multiply_point(@matrix_inv(), point) local_to_global: (point)-> @@ -32,23 +32,16 @@ module.exports = class Referentiel matrix: -> return @_matrix if @_matrix @_matrix = @matrix_compute() - console.log @reference, @_matrix @_matrix matrix_compute: -> matrix_locale = @matrix_locale() if @getPropertyValue('position') == 'fixed' return matrix_locale - # if @reference.offsetParent? - # parent_referentiel = new Referentiel(@reference.offsetParent) parent = @parent() if parent - parent_referentiel = new Referentiel(parent) + parent_referentiel = new Referentiel(parent, offsetParent: @reference.offsetParent) return @_multiply(parent_referentiel.matrix(), matrix_locale) - # if @reference.parentElement? - # parent_referentiel = new Referentiel(@reference.parentElement) - # return @_multiply(parent_referentiel.matrix(), matrix_locale) matrix_locale - matrix_locale: -> return @_matrix_locale if @_matrix_locale @_matrix_locale = @matrix_locale_compute() @@ -116,13 +109,9 @@ module.exports = class Referentiel left += window.pageXOffset top += window.pageYOffset return [[1,0,left],[0,1,top],[0,0,1]] - parent = @parent() - if parent - parent_position = @getPropertyValue('position', parent) - if parent_position == 'static' - [parent_left, parent_top] = @offset(parent) - left -= parent_left - top -= parent_top + if @options.offsetParent? + if @options.offsetParent != @reference + [left, top] = [0, 0] [[1,0,left],[0,1,top],[0,0,1]] matrix_svg_viewbox: -> return @_matrix_viewbox_svg if @_matrix_svg_viewbox diff --git a/test/borders.coffee b/test/borders.coffee deleted file mode 100644 index 82aa7bd..0000000 --- a/test/borders.coffee +++ /dev/null @@ -1,14 +0,0 @@ -describe 'borders', -> - it 'handle borders', -> - ref = from_template( - '
' - ) - expect(ref.global_to_local([20, 10])).toEqual([10, 5]) - expect(ref.global_to_local([10, 5])).toEqual([0, 0]) - - it 'handle margin', -> - ref = from_template( - '
' - ) - expect(ref.global_to_local([0, 0])).toEqual([-8, -6]) - expect(ref.global_to_local([8, 6])).toEqual([0, 0]) diff --git a/test/borders.pug b/test/borders.pug new file mode 100644 index 0000000..c357de4 --- /dev/null +++ b/test/borders.pug @@ -0,0 +1,3 @@ +.referentiel(style="border-top: 5px blue solid; border-left: 10px black solid;") + .assert(data-assert="10,5:0,0") + .assert(data-assert="110,105:100,100") diff --git a/test/margins.pug b/test/margins.pug new file mode 100644 index 0000000..59c8aa2 --- /dev/null +++ b/test/margins.pug @@ -0,0 +1,3 @@ +.referentiel(style="margin-top: 5px; margin-left: 10px;") + .assert(data-assert="10,5:0,0") + .assert(data-assert="110,105:100,100") diff --git a/test/position-in-flow.pug b/test/position-in-flow.pug new file mode 100644 index 0000000..3a91f4b --- /dev/null +++ b/test/position-in-flow.pug @@ -0,0 +1,5 @@ +div + div(style="width: 100%; height: 50px") + .referentiel + .assert(data-assert="0,50:0,0") + .assert(data-assert="50,50:50,0") diff --git a/test/position-offset.pug b/test/position-offset.pug new file mode 100644 index 0000000..07705d0 --- /dev/null +++ b/test/position-offset.pug @@ -0,0 +1,8 @@ +div(style="position: relative; top: 40px; left: 40px") + p Hello World + div + div(style="position: absolute; top: 40px; left: 50px;") + .referentiel + .assert(data-assert="90,80:0,0") + .assert(data-assert="140,130:50,50") + .assert(data-assert="190,180:100,100") diff --git a/test/pug_loader.coffee b/test/pug_loader.coffee index 0c6f098..83473fd 100644 --- a/test/pug_loader.coffee +++ b/test/pug_loader.coffee @@ -18,22 +18,33 @@ describe "Pug", -> referentiel = new Referentiel(this) $('[data-assert]', this).each (assert)-> [global, local] = parse_assert $(this).data('assert') + round = (value)-> + Math.round(value*1000)/1000 result = referentiel.global_to_local(global) - console.log 'assert', global, local, result + result = [round(result[0]), round(result[1])] + # console.log 'assert', global, local, result, referentiel.local_to_global(local) expect(result).toEqual(local) callback() add_test = (template_name)-> it template_name, (done)-> run_test_from_template template_name, done for template_name in [ + 'borders' + 'margins' + 'rotation-transform-origin', + 'rotation-transform-origin', + 'position-offset', + 'position-in-flow', + 'rotation', + 'rotation-scale', 'svg-basic', 'svg-viewport', 'svg-margin', 'svg-border', - 'svg-group', 'svg-no-viewbox', 'svg-composition', 'position-basique', 'position-scoped', + # 'svg-group', ] add_test(template_name) diff --git a/test/rotation-scale.pug b/test/rotation-scale.pug new file mode 100644 index 0000000..54c8c8c --- /dev/null +++ b/test/rotation-scale.pug @@ -0,0 +1,4 @@ +.referentiel(style="transform-origin: 0 0;transform: scale(2) rotate(30deg);") + .assert(data-assert="0,0:0,0") + .assert(data-assert="173.205,100:100,0") + .assert(data-assert="73.205,273.205:100,100") diff --git a/test/rotation-transform-origin.pug b/test/rotation-transform-origin.pug new file mode 100644 index 0000000..e728f69 --- /dev/null +++ b/test/rotation-transform-origin.pug @@ -0,0 +1,4 @@ +.referentiel(style="transform-origin: 5px 5px;transform: rotate(25deg);") + .assert(data-assert="5,5:5,5") + .assert(data-assert="0,0:-1.645,2.582") + .assert(data-assert="50.95055,131.24797:100,100") diff --git a/test/rotation.pug b/test/rotation.pug new file mode 100644 index 0000000..9f8164d --- /dev/null +++ b/test/rotation.pug @@ -0,0 +1,4 @@ +.referentiel(style="transform-origin: 0 0;transform: rotate(20deg);") + .assert(data-assert="0,0:0,0") + .assert(data-assert="59.7673,128.1713:100,100") + .assert(data-assert="29.88365,64.0856:50,50") diff --git a/test/transform.coffee b/test/transform.coffee deleted file mode 100644 index c4cc894..0000000 --- a/test/transform.coffee +++ /dev/null @@ -1,130 +0,0 @@ -describe "Rotations", -> - it 'handle rotations', -> - ref = new Referentiel( - dom('
') - ) - expect(ref.global_to_local([0, 0])).toEqual([0, 0]) - expect(ref.global_to_local([0, 10])).toEqual([10, 0]) - expect(ref.global_to_local([1, 0])).toEqual([0, -1]) - - it 'handle multiple transformations', -> - ref = new Referentiel( - dom('
') - ) - expect(ref.global_to_local([0, 0])).toEqual([0, 0]) - expect(ref.global_to_local([0, 10])).toEqual([0, -5]) - expect(ref.global_to_local([1, 0])).toEqual([-0.5, 0]) - - it 'handle transform-origin', -> - ref = from_template('
') - expect(ref.global_to_local([5, 5])).toEqual([5, 5]) - expect(ref.global_to_local([0, 0])).toEqual([0, 10]) - expect(ref.global_to_local([10, 0])).toEqual([0, 0]) - - - it 'handle borders', -> - ref = from_template( - '
' - ) - expect(ref.global_to_local([0, 0])).toEqual([-10, -5]) - expect(ref.global_to_local([10, 5])).toEqual([0, 0]) - - it 'handle margin', -> - ref = from_template('
') - expect(ref.global_to_local([0, 0])).toEqual([-8, -26]) - expect(ref.global_to_local([8, 26])).toEqual([0, 0]) - - it 'manage context', -> - ref = from_template(' -
-
-
-
-
-
-
-
- ') - expect(ref.global_to_local([0, 20])).toEqual([0, 0]) - - it 'manage context and rotation', -> - ref = from_template(' -
-
-
-
-
-
-
-
- ') - expect(ref.global_to_local([0, 20])).toEqual([0, 0]) - expect(ref.global_to_local([0, 20])).toEqual([0, 0]) - - it 'manage a absolute position with context', -> - ref = from_template(' -
-
-
-
-
-
-
-
-
-
- ') - expect(ref.global_to_local([50, 50])).toEqual([0, 0]) - expect(ref.global_to_local([100, 50])).toEqual([50, 0]) - - it 'manage a fixed position with context', -> - ref = from_template(' -
-
-
-
-
-
-
-
-
-
- ') - expect(ref.global_to_local([50, 50])).toEqual([0, 0]) - # expect(ref.global_to_local([50, 100])).toEqual([50, 80]) - - # fit 'manage a fixed position with scroll', -> - # ref = from_template(' - #
- #
- #
- #
- #
- #
- #
- #
- #
- #
- # ') - # window.scrollTo({top: '500px'}) - # console.log 'Before computing', window.scrollY, window.scrollX - # expect(ref.global_to_local([500, 0])).toEqual([50, 0]) - # expect(ref.global_to_local([0, 20])).toEqual([0, 0]) - # expect(ref.global_to_local([0, 40])).toEqual([0, 20]) - # - # it 'test issue repeated', -> - # ref = new Referentiel( - # dom('
') - # ) - # expect(ref.global_to_local([20, 20])).toEqual([0, 0]) - # expect(ref.global_to_local([20, 20])).toEqual([0, 0]) -# -# it 'handle a hierachy of transformation', -> -# elem = slim(!--PUG -# div syle="transform: rotate(90deg)" -# div syle="transform: scale(2)" -# PUG) -# referentiel = new referentiel(elem) -# expect(referentiel.local([5, 5])).to.equal([5, -5]) -# expect(referentiel.local([0, 0])).to.equal([10, 0]) -# expect(referentiel.local([10, 0])).to.equal([10, 10]) From d0229186ff3d99a43122a7846f64e0ebc8006649 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Mon, 26 Mar 2018 20:41:28 -0400 Subject: [PATCH 12/20] Refactoring + extract MatrixUtils to another file --- src/matrix_utils.coffee | 48 +++++++++++++++++++++++ src/referentiel.coffee | 84 ++++++++++------------------------------- 2 files changed, 68 insertions(+), 64 deletions(-) create mode 100644 src/matrix_utils.coffee diff --git a/src/matrix_utils.coffee b/src/matrix_utils.coffee new file mode 100644 index 0000000..f1a0109 --- /dev/null +++ b/src/matrix_utils.coffee @@ -0,0 +1,48 @@ +MatrixUtils = { + det: (m)-> + return ( + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - + m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]) + ) + inv: (m)-> + invdet = 1.0/MatrixUtils.det(m) + return [ + [ + (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * invdet, + (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * invdet, + (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * invdet, + ], + [ + (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * invdet, + (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * invdet, + (m[1][0] * m[0][2] - m[0][0] * m[1][2]) * invdet, + ], + [ + (m[1][0] * m[2][1] - m[2][0] * m[1][1]) * invdet, + (m[2][0] * m[0][1] - m[0][0] * m[2][1]) * invdet, + (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * invdet, + ] + ] + mult: -> + [a, b, others...] = arguments + res = [] + for i in [0...3] + res[i] = [] + for j in [0...3] + res[i][j] = 0.0 + for k in [0...3] + res[i][j] += a[i][k]*b[k][j] + if others.length > 0 + MatrixUtils.mult(res, others...) + else + res + mult_vector: (m, v)-> + res = [] + for i in [0...3] + res[i] = 0.0 + for k in [0...3] + res[i] += m[i][k]*v[k] + res +} +module.exports = MatrixUtils diff --git a/src/referentiel.coffee b/src/referentiel.coffee index 40b16f0..dd6e9c8 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -1,13 +1,13 @@ +MatrixUtils = require('./matrix_utils.coffee') module.exports = class Referentiel constructor: (@reference, @options = {})-> global_to_local: (point)-> @_multiply_point(@matrix_inv(), point) local_to_global: (point)-> @_multiply_point(@matrix(), point) - _multiply_point: (matrix, point)-> v = [point[0], point[1], 1] - res = @_multiply_vector(matrix, v) + res = MatrixUtils.mult_vector(matrix, v) [ @_export(res[0]), @_export(res[1]) ] _export: (value)-> res = @_round(value) @@ -22,37 +22,37 @@ module.exports = class Referentiel delete @_matrix_transformation delete @_matrix_transform_origin delete @_matrix_svg - matrix_inv: -> return @_matrix_inv if @_matrix_inv @_matrix_inv = @matrix_inv_compute() @_matrix_inv matrix_inv_compute: -> - @_inv(@matrix()) + MatrixUtils.inv(@matrix()) matrix: -> return @_matrix if @_matrix @_matrix = @matrix_compute() @_matrix matrix_compute: -> matrix_locale = @matrix_locale() - if @getPropertyValue('position') == 'fixed' + if @css('position') == 'fixed' return matrix_locale parent = @parent() if parent parent_referentiel = new Referentiel(parent, offsetParent: @reference.offsetParent) - return @_multiply(parent_referentiel.matrix(), matrix_locale) + return MatrixUtils.mult(parent_referentiel.matrix(), matrix_locale) matrix_locale + matrix_locale: -> return @_matrix_locale if @_matrix_locale @_matrix_locale = @matrix_locale_compute() @_matrix_locale matrix_locale_compute: -> - @_multiply( + MatrixUtils.mult( @matrix_svg_viewbox(), @matrix_offset(), @matrix_transform_origin(), @matrix_transformation(), - @_inv(@matrix_transform_origin()), + MatrixUtils.inv(@matrix_transform_origin()), @matrix_border() ) @@ -63,7 +63,7 @@ module.exports = class Referentiel matrix_transformation_compute: -> transform = @reference.getAttribute('transform') || 'none' transform = @reference.style.transform unless transform.match(/^matrix\((.*)\)$/) - transform = @getPropertyValue('transform') unless transform.match(/^matrix\((.*)\)$/) + transform = @css('transform') unless transform.match(/^matrix\((.*)\)$/) if res = transform.match(/^matrix\((.*)\)$/) floats = res[1].replace(',', ' ').replace(' ', ' ').split(' ').map((e)-> parseFloat(e) @@ -77,7 +77,7 @@ module.exports = class Referentiel @_matrix_transform_origin matrix_transform_origin_compute: -> - transform_origin = @getPropertyValue('transform-origin').replace(/px/g, '').split(' ').map (v)-> + transform_origin = @css('transform-origin').replace(/px/g, '').split(' ').map (v)-> parseFloat(v) [[1,0, transform_origin[0]], [0, 1, transform_origin[1]],[0,0,1]] @@ -86,8 +86,8 @@ module.exports = class Referentiel @_matrix_border = @matrix_border_compute() @_matrix_border matrix_border_compute: -> - left = parseFloat(@getPropertyValue('border-left-width').replace(/px/g, '') || 0) - top = parseFloat(@getPropertyValue('border-top-width').replace(/px/g, '') || 0) + left = parseFloat(@css('border-left-width').replace(/px/g, '') || 0) + top = parseFloat(@css('border-top-width').replace(/px/g, '') || 0) [[1,0,left],[0,1,top],[0,0,1]] matrix_offset: -> @@ -102,7 +102,7 @@ module.exports = class Referentiel null matrix_offset_compute: -> [left, top] = @offset() - switch @getPropertyValue('position') + switch @css('position') when 'absolute' return [[1,0,left],[0,1,top],[0,0,1]] when 'fixed' @@ -120,15 +120,15 @@ module.exports = class Referentiel matrix_svg_viewbox_compute: -> return [[1,0,0], [0,1,0], [0,0,1]] unless @reference instanceof SVGElement size = [ - parseFloat(@getPropertyValue('width').replace(/px/g, '')) - parseFloat(@getPropertyValue('height').replace(/px/g, '')) + parseFloat(@css('width').replace(/px/g, '')) + parseFloat(@css('height').replace(/px/g, '')) ] attr = @reference.getAttribute('viewBox') return [[1,0,0], [0,1,0], [0,0,1]] unless attr? viewBox = attr.replace(',', ' ').replace(' ', ' ').split(' ').map (e)-> parseFloat(e) scale = [size[0] / viewBox[2], size[1] / viewBox[3] ] - @_multiply( + MatrixUtils.mult( [ [scale[0], 0, 0] [0, scale[1], 0] @@ -151,51 +151,7 @@ module.exports = class Referentiel offset[0] -= ppos.left offset[1] -= ppos.top offset - getPropertyValue: (property, element = null)-> - return Referentiel.jquery(element || @reference).css(property) if Referentiel.jquery - window.getComputedStyle(element || @reference).getPropertyValue(property) - _multiply_vector: (m, v)-> - res = [] - for i in [0...3] - res[i] = 0.0 - for k in [0...3] - res[i] += m[i][k]*v[k] - res - _multiply: -> - [a, b, others...] = arguments - res = [] - for i in [0...3] - res[i] = [] - for j in [0...3] - res[i][j] = 0.0 - for k in [0...3] - res[i][j] += a[i][k]*b[k][j] - if others.length > 0 - @_multiply(res, others...) - else - res - _det: (m)-> - return ( - m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + - m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]) - ) - _inv: (m)-> - invdet = 1.0/@_det(m) - return [ - [ - (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * invdet, - (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * invdet, - (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * invdet, - ], - [ - (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * invdet, - (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * invdet, - (m[1][0] * m[0][2] - m[0][0] * m[1][2]) * invdet, - ], - [ - (m[1][0] * m[2][1] - m[2][0] * m[1][1]) * invdet, - (m[2][0] * m[0][1] - m[0][0] * m[2][1]) * invdet, - (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * invdet, - ] - ] + css: (property, element = null)-> + element ||= @reference + return Referentiel.jquery(element).css(property) if Referentiel.jquery + window.getComputedStyle(element).getPropertyValue(property) From 3add91be95b4f49a169ee0c92f2da9a3f0564b84 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 27 Mar 2018 08:03:28 -0400 Subject: [PATCH 13/20] Some refactoring. --- src/matrix_utils.coffee | 2 +- src/referentiel.coffee | 125 ++++++++++++++++++++++------------------ 2 files changed, 69 insertions(+), 58 deletions(-) diff --git a/src/matrix_utils.coffee b/src/matrix_utils.coffee index f1a0109..01f4afb 100644 --- a/src/matrix_utils.coffee +++ b/src/matrix_utils.coffee @@ -37,7 +37,7 @@ MatrixUtils = { MatrixUtils.mult(res, others...) else res - mult_vector: (m, v)-> + multVector: (m, v)-> res = [] for i in [0...3] res[i] = 0.0 diff --git a/src/referentiel.coffee b/src/referentiel.coffee index dd6e9c8..02aa7e6 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -2,12 +2,12 @@ MatrixUtils = require('./matrix_utils.coffee') module.exports = class Referentiel constructor: (@reference, @options = {})-> global_to_local: (point)-> - @_multiply_point(@matrix_inv(), point) + @_multiplyPoint(@matrixInv(), point) local_to_global: (point)-> - @_multiply_point(@matrix(), point) - _multiply_point: (matrix, point)-> + @_multiplyPoint(@matrix(), point) + _multiplyPoint: (matrix, point)-> v = [point[0], point[1], 1] - res = MatrixUtils.mult_vector(matrix, v) + res = MatrixUtils.multVector(matrix, v) [ @_export(res[0]), @_export(res[1]) ] _export: (value)-> res = @_round(value) @@ -17,50 +17,54 @@ module.exports = class Referentiel precision = 1000000.0 Math.round(precision*value)/precision clear_cache: -> - delete @_matrix_inv + delete @_matrixInv delete @_matrix - delete @_matrix_transformation - delete @_matrix_transform_origin - delete @_matrix_svg - matrix_inv: -> - return @_matrix_inv if @_matrix_inv - @_matrix_inv = @matrix_inv_compute() - @_matrix_inv - matrix_inv_compute: -> + delete @_matrixTransform + delete @_matrixTransformOrigin + delete @_matrixSVG + matrixInv: -> + return @_matrixInv if @_matrixInv + @_matrixInv = @matrixInv_compute() + @_matrixInv + matrixInv_compute: -> MatrixUtils.inv(@matrix()) matrix: -> return @_matrix if @_matrix - @_matrix = @matrix_compute() + @_matrix = @matrixCompute() @_matrix - matrix_compute: -> - matrix_locale = @matrix_locale() + matrixCompute: -> + matrixLocale = @matrixLocale() if @css('position') == 'fixed' - return matrix_locale + return matrixLocale parent = @parent() if parent - parent_referentiel = new Referentiel(parent, offsetParent: @reference.offsetParent) - return MatrixUtils.mult(parent_referentiel.matrix(), matrix_locale) - matrix_locale - - matrix_locale: -> - return @_matrix_locale if @_matrix_locale - @_matrix_locale = @matrix_locale_compute() - @_matrix_locale - matrix_locale_compute: -> + return MatrixUtils.mult( + (new Referentiel( + parent, + offsetParent: @reference.offsetParent + )).matrix(), + matrixLocale + ) + matrixLocale + matrixLocale: -> + return @_matrixLocale if @_matrixLocale + @_matrixLocale = @matrixLocaleCompute() + @_matrixLocale + matrixLocaleCompute: -> MatrixUtils.mult( - @matrix_svg_viewbox(), - @matrix_offset(), - @matrix_transform_origin(), - @matrix_transformation(), - MatrixUtils.inv(@matrix_transform_origin()), - @matrix_border() + @matrixSVGViewbox(), + @matrixOffset(), + @matrixTransformOrigin(), + @matrixTransform(), + MatrixUtils.inv(@matrixTransformOrigin()), + @matrixBorder() ) - matrix_transformation: -> - return @_matrix_transformation if @_matrix_transformation - @_matrix_transformation = @matrix_transformation_compute() - @_matrix_transformation - matrix_transformation_compute: -> + matrixTransform: -> + return @_matrixTransform if @_matrixTransform + @_matrixTransform = @matrixTransformCompute() + @_matrixTransform + matrixTransformCompute: -> transform = @reference.getAttribute('transform') || 'none' transform = @reference.style.transform unless transform.match(/^matrix\((.*)\)$/) transform = @css('transform') unless transform.match(/^matrix\((.*)\)$/) @@ -71,36 +75,36 @@ module.exports = class Referentiel return [[floats[0], floats[2], floats[4]],[floats[1], floats[3], floats[5]], [0, 0, 1]] [[1,0,0], [0,1,0], [0,0,1]] - matrix_transform_origin: -> - return @_matrix_transform_origin if @_matrix_transform_origin - @_matrix_transform_origin = @matrix_transform_origin_compute() - @_matrix_transform_origin + matrixTransformOrigin: -> + return @_matrixTransformOrigin if @_matrixTransformOrigin + @_matrixTransformOrigin = @matrixTransformOriginCompute() + @_matrixTransformOrigin - matrix_transform_origin_compute: -> + matrixTransformOriginCompute: -> transform_origin = @css('transform-origin').replace(/px/g, '').split(' ').map (v)-> parseFloat(v) [[1,0, transform_origin[0]], [0, 1, transform_origin[1]],[0,0,1]] - matrix_border: -> - return @_matrix_border if @_matrix_border - @_matrix_border = @matrix_border_compute() - @_matrix_border - matrix_border_compute: -> + matrixBorder: -> + return @_matrixBorder if @_matrixBorder + @_matrixBorder = @matrixBorderCompute() + @_matrixBorder + matrixBorderCompute: -> left = parseFloat(@css('border-left-width').replace(/px/g, '') || 0) top = parseFloat(@css('border-top-width').replace(/px/g, '') || 0) [[1,0,left],[0,1,top],[0,0,1]] - matrix_offset: -> - return @_matrix_offset if @_matrix_offset - @_matrix_offset = @matrix_offset_compute() - @_matrix_offset + matrixOffset: -> + return @_matrixOffset if @_matrixOffset + @_matrixOffset = @matrixOffsetCompute() + @_matrixOffset parent: (element)-> element ||= @reference if element.parentNode? && element.parentNode != document.documentElement element.parentNode else null - matrix_offset_compute: -> + matrixOffsetCompute: -> [left, top] = @offset() switch @css('position') when 'absolute' @@ -113,11 +117,11 @@ module.exports = class Referentiel if @options.offsetParent != @reference [left, top] = [0, 0] [[1,0,left],[0,1,top],[0,0,1]] - matrix_svg_viewbox: -> - return @_matrix_viewbox_svg if @_matrix_svg_viewbox - @_matrix_svg_viewbox = @matrix_svg_viewbox_compute() - @_matrix_svg_viewbox - matrix_svg_viewbox_compute: -> + matrixSVGViewbox: -> + return @_matrix_viewbox_svg if @_matrixSVGViewbox + @_matrixSVGViewbox = @matrixSVGViewboxCompute() + @_matrixSVGViewbox + matrixSVGViewboxCompute: -> return [[1,0,0], [0,1,0], [0,0,1]] unless @reference instanceof SVGElement size = [ parseFloat(@css('width').replace(/px/g, '')) @@ -155,3 +159,10 @@ module.exports = class Referentiel element ||= @reference return Referentiel.jquery(element).css(property) if Referentiel.jquery window.getComputedStyle(element).getPropertyValue(property) +cache = (klass, functionName)-> + compute = klass[functionName] + console.log klass + klass.prototype[functionName] = -> + console.log functionName, arguments... +cache Referentiel, 'matrix' +cache Referentiel, 'matrix_inv' From 54693485385f55bdc6ae5410c93d14475ec70fc7 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 27 Mar 2018 10:33:27 -0400 Subject: [PATCH 14/20] Refactoring meta-programming for cache --- src/referentiel.coffee | 52 ++++++------------------------------------ 1 file changed, 7 insertions(+), 45 deletions(-) diff --git a/src/referentiel.coffee b/src/referentiel.coffee index 02aa7e6..a010ab0 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -16,23 +16,9 @@ module.exports = class Referentiel _round: (value)-> precision = 1000000.0 Math.round(precision*value)/precision - clear_cache: -> - delete @_matrixInv - delete @_matrix - delete @_matrixTransform - delete @_matrixTransformOrigin - delete @_matrixSVG matrixInv: -> - return @_matrixInv if @_matrixInv - @_matrixInv = @matrixInv_compute() - @_matrixInv - matrixInv_compute: -> MatrixUtils.inv(@matrix()) matrix: -> - return @_matrix if @_matrix - @_matrix = @matrixCompute() - @_matrix - matrixCompute: -> matrixLocale = @matrixLocale() if @css('position') == 'fixed' return matrixLocale @@ -47,10 +33,6 @@ module.exports = class Referentiel ) matrixLocale matrixLocale: -> - return @_matrixLocale if @_matrixLocale - @_matrixLocale = @matrixLocaleCompute() - @_matrixLocale - matrixLocaleCompute: -> MatrixUtils.mult( @matrixSVGViewbox(), @matrixOffset(), @@ -59,12 +41,7 @@ module.exports = class Referentiel MatrixUtils.inv(@matrixTransformOrigin()), @matrixBorder() ) - matrixTransform: -> - return @_matrixTransform if @_matrixTransform - @_matrixTransform = @matrixTransformCompute() - @_matrixTransform - matrixTransformCompute: -> transform = @reference.getAttribute('transform') || 'none' transform = @reference.style.transform unless transform.match(/^matrix\((.*)\)$/) transform = @css('transform') unless transform.match(/^matrix\((.*)\)$/) @@ -76,35 +53,22 @@ module.exports = class Referentiel [[1,0,0], [0,1,0], [0,0,1]] matrixTransformOrigin: -> - return @_matrixTransformOrigin if @_matrixTransformOrigin - @_matrixTransformOrigin = @matrixTransformOriginCompute() - @_matrixTransformOrigin - - matrixTransformOriginCompute: -> transform_origin = @css('transform-origin').replace(/px/g, '').split(' ').map (v)-> parseFloat(v) [[1,0, transform_origin[0]], [0, 1, transform_origin[1]],[0,0,1]] matrixBorder: -> - return @_matrixBorder if @_matrixBorder - @_matrixBorder = @matrixBorderCompute() - @_matrixBorder - matrixBorderCompute: -> left = parseFloat(@css('border-left-width').replace(/px/g, '') || 0) top = parseFloat(@css('border-top-width').replace(/px/g, '') || 0) [[1,0,left],[0,1,top],[0,0,1]] - matrixOffset: -> - return @_matrixOffset if @_matrixOffset - @_matrixOffset = @matrixOffsetCompute() - @_matrixOffset parent: (element)-> element ||= @reference if element.parentNode? && element.parentNode != document.documentElement element.parentNode else null - matrixOffsetCompute: -> + matrixOffset: -> [left, top] = @offset() switch @css('position') when 'absolute' @@ -118,10 +82,6 @@ module.exports = class Referentiel [left, top] = [0, 0] [[1,0,left],[0,1,top],[0,0,1]] matrixSVGViewbox: -> - return @_matrix_viewbox_svg if @_matrixSVGViewbox - @_matrixSVGViewbox = @matrixSVGViewboxCompute() - @_matrixSVGViewbox - matrixSVGViewboxCompute: -> return [[1,0,0], [0,1,0], [0,0,1]] unless @reference instanceof SVGElement size = [ parseFloat(@css('width').replace(/px/g, '')) @@ -160,9 +120,11 @@ module.exports = class Referentiel return Referentiel.jquery(element).css(property) if Referentiel.jquery window.getComputedStyle(element).getPropertyValue(property) cache = (klass, functionName)-> - compute = klass[functionName] - console.log klass + func = klass.prototype[functionName] klass.prototype[functionName] = -> - console.log functionName, arguments... + @_cache ||= {} + unless @_cache[functionName] + @_cache[functionName] = func.apply(this, arguments) + @_cache[functionName] cache Referentiel, 'matrix' -cache Referentiel, 'matrix_inv' +cache Referentiel, 'matrixInv' From 13f461aae219761a1b9bbd8a46750f2bf30d946e Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 27 Mar 2018 10:41:18 -0400 Subject: [PATCH 15/20] MatrixUtils identity --- src/matrix_utils.coffee | 2 ++ src/referentiel.coffee | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/matrix_utils.coffee b/src/matrix_utils.coffee index 01f4afb..cbabe9f 100644 --- a/src/matrix_utils.coffee +++ b/src/matrix_utils.coffee @@ -1,4 +1,6 @@ MatrixUtils = { + identity: -> + [[1,0,0], [0,1,0], [0,0,1]] det: (m)-> return ( m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - diff --git a/src/referentiel.coffee b/src/referentiel.coffee index a010ab0..07d38de 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -50,7 +50,7 @@ module.exports = class Referentiel parseFloat(e) ) return [[floats[0], floats[2], floats[4]],[floats[1], floats[3], floats[5]], [0, 0, 1]] - [[1,0,0], [0,1,0], [0,0,1]] + MatrixUtils.identity() matrixTransformOrigin: -> transform_origin = @css('transform-origin').replace(/px/g, '').split(' ').map (v)-> @@ -82,13 +82,13 @@ module.exports = class Referentiel [left, top] = [0, 0] [[1,0,left],[0,1,top],[0,0,1]] matrixSVGViewbox: -> - return [[1,0,0], [0,1,0], [0,0,1]] unless @reference instanceof SVGElement + return MatrixUtils.identity() unless @reference instanceof SVGElement size = [ parseFloat(@css('width').replace(/px/g, '')) parseFloat(@css('height').replace(/px/g, '')) ] attr = @reference.getAttribute('viewBox') - return [[1,0,0], [0,1,0], [0,0,1]] unless attr? + return MatrixUtils.identity() unless attr? viewBox = attr.replace(',', ' ').replace(' ', ' ').split(' ').map (e)-> parseFloat(e) scale = [size[0] / viewBox[2], size[1] / viewBox[3] ] From d8f1027d0851685cb939d3dd110a07550bfa2e9c Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 27 Mar 2018 11:55:45 -0400 Subject: [PATCH 16/20] First draft of transformParser --- src/referentiel.coffee | 3 ++ src/transform_parser.coffee | 56 ++++++++++++++++++++++++++++++++++++ test/pug_loader.coffee | 2 +- test/transform_parser.coffee | 33 +++++++++++++++++++++ test/transform_parser.pug | 7 +++++ 5 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 src/transform_parser.coffee create mode 100644 test/transform_parser.coffee create mode 100644 test/transform_parser.pug diff --git a/src/referentiel.coffee b/src/referentiel.coffee index 07d38de..17a7829 100644 --- a/src/referentiel.coffee +++ b/src/referentiel.coffee @@ -1,3 +1,4 @@ +TransformParser = require('./transform_parser.coffee') MatrixUtils = require('./matrix_utils.coffee') module.exports = class Referentiel constructor: (@reference, @options = {})-> @@ -128,3 +129,5 @@ cache = (klass, functionName)-> @_cache[functionName] cache Referentiel, 'matrix' cache Referentiel, 'matrixInv' +Referentiel.MatrixUtils = MatrixUtils +Referentiel.TransformParser = TransformParser diff --git a/src/transform_parser.coffee b/src/transform_parser.coffee new file mode 100644 index 0000000..9932b5d --- /dev/null +++ b/src/transform_parser.coffee @@ -0,0 +1,56 @@ +MatrixUtils = require('./matrix_utils.coffee') +module.exports = TransformParser = { + parse: (input)-> + return 'none' if input == 'none' || input == '' + @to_css( + @export_matrix( + @parse_matrix(input) + ) + ) + export_matrix: (m)-> + res = [] + for i in [0...3] + res[i] = [] + for j in [0...3] + res[i][j] = @export_value(m[i][j]) + export_value: (value)-> + precison = 100000 + Math.round(value*precison)/precison + parse_matrix: (input)-> + matrix = [[1,0,0], [0,1,0], [0,0,1]] + if match = input.match(/^(rotate|translate|scale)\((.*)\)$/) + console.log 'MATCH !', match + matrix = @[match[1]](match[2]) + matrix + scale: (input)-> + scale = parseFloat(input) + [ + [scale,0,0] + [0,scale,0] + [0,0,1] + ] + translate: (input)-> + left = 0 + right = 0 + if match = input.match(/^(.*)px$/) + left = parseFloat(match[1]) + if match = input.match(/^(.*)px, (.*)px$/) + left = parseFloat(match[1]) + right = parseFloat(match[2]) + [ + [1,0,left] + [0,1,right] + [0,0,1] + ] + rotate: (input)-> + angle = 0 + if match = input.match(/^(.*)deg$/) + angle = parseFloat(match[1]) * Math.PI / 180 + [ + [Math.cos(angle),-Math.sin(angle), 0], + [Math.sin(angle),Math.cos(angle), 0], + [0,0,1] + ] + to_css: (m)-> + "matrix(#{[m[0][0], m[1][0], m[0][1], m[1][1], m[0][2], m[1][2]].join(', ')})" +} diff --git a/test/pug_loader.coffee b/test/pug_loader.coffee index 83473fd..b1adf10 100644 --- a/test/pug_loader.coffee +++ b/test/pug_loader.coffee @@ -9,7 +9,7 @@ parse_assert = (input)-> $.map i.split(','), (s)-> parseFloat(s) ] -describe "Pug", -> +describe "Referentiel", -> run_test_from_template = (template_name, callback)-> load_template template_name, (template)-> $context = $('
'+template+'
') diff --git a/test/transform_parser.coffee b/test/transform_parser.coffee new file mode 100644 index 0000000..c00a606 --- /dev/null +++ b/test/transform_parser.coffee @@ -0,0 +1,33 @@ +load_template = (template_name, callback)-> + $.get + url: '/base/test/'+template_name+'.html', + dataType: 'text' + success: callback +parse_assert = (input)-> + $.map input.split(':'), (i)-> + [ + $.map i.split(','), (s)-> + parseFloat(s) + ] +describe "Transform parser", -> + run_test_from_template = (template_name, callback)-> + load_template template_name, (template)-> + $context = $('
'+template+'
') + $('body').append($context) + $('.transform-parser', $context).each -> + console.log this + # input = $(this).css('transform') + input = this.style.transform + browserComputed = window.getComputedStyle(this).getPropertyValue('transform') + output = $(this).data('expected') || browserComputed + result = Referentiel.TransformParser.parse(input) + console.log 'ICI', input, result, output + expect(result).toEqual(output) + callback() + add_test = (template_name)-> + fit template_name, (done)-> + run_test_from_template template_name, done + for template_name in [ + 'transform_parser' + ] + add_test(template_name) diff --git a/test/transform_parser.pug b/test/transform_parser.pug new file mode 100644 index 0000000..076c4f6 --- /dev/null +++ b/test/transform_parser.pug @@ -0,0 +1,7 @@ +div.transform-parser +div.transform-parser(style="transform: none") +//div.transform-parser(style="transform: rotate(180deg)"") +div.transform-parser(style="transform: translate(10px, 12px)") +div.transform-parser(style="transform: translate(10px)") +div.transform-parser(style="transform: scale(2)") +//div.transform-parser(style="transform: rotate(180deg) rotate(-180deg)" data-expected="matrix(") From 696194bfbcd696b293f6921b4028c8000bd4c480 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 27 Mar 2018 12:36:40 -0400 Subject: [PATCH 17/20] TransformParser :-D --- src/transform_parser.coffee | 34 ++++++++++++++++++++++++++++------ test/transform_parser.coffee | 12 +++++++++++- test/transform_parser.pug | 15 +++++++++++++-- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/transform_parser.coffee b/src/transform_parser.coffee index 9932b5d..714306f 100644 --- a/src/transform_parser.coffee +++ b/src/transform_parser.coffee @@ -18,17 +18,37 @@ module.exports = TransformParser = { Math.round(value*precison)/precison parse_matrix: (input)-> matrix = [[1,0,0], [0,1,0], [0,0,1]] - if match = input.match(/^(rotate|translate|scale)\((.*)\)$/) - console.log 'MATCH !', match - matrix = @[match[1]](match[2]) + inputs = input.split(')') + for i in inputs + matrix = MatrixUtils.mult( + matrix, + @parseOperation("#{i})") + ) matrix + parseOperation: (input)-> + if match = input.match(/^[ ]*(rotate|translate|translateX|translateY|scale|scaleX|scaleY)\((.*)\)$/) + return @[match[1]](match[2]) + [[1,0,0], [0,1,0], [0,0,1]] scale: (input)-> - scale = parseFloat(input) + scale = input.split(',') + scale[1] = scale[0] if scale.length == 1 + scale = [ + parseFloat(scale[0]) + parseFloat(scale[1]) + ] [ - [scale,0,0] - [0,scale,0] + [scale[0],0,0] + [0,scale[1],0] [0,0,1] ] + scaleX: (input)-> + @scale("#{input},1") + scaleY: (input)-> + @scale("1, #{input}") + translateX: (input)-> + @translate(input) + translateY: (input)-> + @translate("0px, #{input}") translate: (input)-> left = 0 right = 0 @@ -46,6 +66,8 @@ module.exports = TransformParser = { angle = 0 if match = input.match(/^(.*)deg$/) angle = parseFloat(match[1]) * Math.PI / 180 + if match = input.match(/^(.*)turn$/) + angle = parseFloat(match[1]) * Math.PI * 2 [ [Math.cos(angle),-Math.sin(angle), 0], [Math.sin(angle),Math.cos(angle), 0], diff --git a/test/transform_parser.coffee b/test/transform_parser.coffee index c00a606..f67feab 100644 --- a/test/transform_parser.coffee +++ b/test/transform_parser.coffee @@ -9,6 +9,15 @@ parse_assert = (input)-> $.map i.split(','), (s)-> parseFloat(s) ] + +roundCSSMatrix = (input)-> + if res = input.match(/^matrix\((.*)\)$/) + values = res[1].replace(',', ' ').replace(' ', ' ').split(' ').map((e)-> + precision = 100000 + Math.round(parseFloat(e)*precision)/precision + ) + return "matrix(#{values.join(', ')})" + input describe "Transform parser", -> run_test_from_template = (template_name, callback)-> load_template template_name, (template)-> @@ -21,8 +30,9 @@ describe "Transform parser", -> browserComputed = window.getComputedStyle(this).getPropertyValue('transform') output = $(this).data('expected') || browserComputed result = Referentiel.TransformParser.parse(input) + console.log roundCSSMatrix(output) console.log 'ICI', input, result, output - expect(result).toEqual(output) + expect(result).toEqual(roundCSSMatrix(output)) callback() add_test = (template_name)-> fit template_name, (done)-> diff --git a/test/transform_parser.pug b/test/transform_parser.pug index 076c4f6..3026931 100644 --- a/test/transform_parser.pug +++ b/test/transform_parser.pug @@ -1,7 +1,18 @@ div.transform-parser div.transform-parser(style="transform: none") -//div.transform-parser(style="transform: rotate(180deg)"") div.transform-parser(style="transform: translate(10px, 12px)") div.transform-parser(style="transform: translate(10px)") +div.transform-parser(style="transform: translateX(10px)") +div.transform-parser(style="transform: translateY(10px)") div.transform-parser(style="transform: scale(2)") -//div.transform-parser(style="transform: rotate(180deg) rotate(-180deg)" data-expected="matrix(") +div.transform-parser(style="transform: scale(2, 3)") +div.transform-parser(style="transform: scaleX(2)") +div.transform-parser(style="transform: scaleY(2)") +div.transform-parser(style="transform: translate(40px, 12px) scale(2)") +div.transform-parser(style="transform: rotate(1turn)") +div.transform-parser(style="transform: rotate(180deg) rotate(-180deg)") +div.transform-parser(style="transform: rotate(180deg)") +div.transform-parser(style="transform: rotate(35deg)") +//div.transform-parser(style="transform: translateX(2em)") +//div.transform-parser(style="transform: translateX(2in)") +//div.transform-parser(style="transform: skew(30deg)") From a690c9e4fbdb477f794d3ecdf2658c782de90660 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Mon, 11 Jun 2018 08:07:26 +0400 Subject: [PATCH 18/20] Try to fix tests --- test/transform_parser.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/transform_parser.coffee b/test/transform_parser.coffee index f67feab..3ee6be7 100644 --- a/test/transform_parser.coffee +++ b/test/transform_parser.coffee @@ -35,7 +35,7 @@ describe "Transform parser", -> expect(result).toEqual(roundCSSMatrix(output)) callback() add_test = (template_name)-> - fit template_name, (done)-> + it template_name, (done)-> run_test_from_template template_name, done for template_name in [ 'transform_parser' From 2b692a5482c960262977d6efb0f58b0432ad3e18 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Mon, 11 Jun 2018 08:07:45 +0400 Subject: [PATCH 19/20] Remove console logs --- test/transform_parser.coffee | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/transform_parser.coffee b/test/transform_parser.coffee index 3ee6be7..257eca1 100644 --- a/test/transform_parser.coffee +++ b/test/transform_parser.coffee @@ -24,14 +24,11 @@ describe "Transform parser", -> $context = $('
'+template+'
') $('body').append($context) $('.transform-parser', $context).each -> - console.log this # input = $(this).css('transform') input = this.style.transform browserComputed = window.getComputedStyle(this).getPropertyValue('transform') output = $(this).data('expected') || browserComputed result = Referentiel.TransformParser.parse(input) - console.log roundCSSMatrix(output) - console.log 'ICI', input, result, output expect(result).toEqual(roundCSSMatrix(output)) callback() add_test = (template_name)-> From fc6fc6cc1dfd37da1286a1223b473883f66866f4 Mon Sep 17 00:00:00 2001 From: Luc Boissaye Date: Tue, 12 Jun 2018 11:14:53 -0400 Subject: [PATCH 20/20] Add Kevan test (do not work...) --- demo/index.pug | 2 +- test/pug_loader.coffee | 1 + test/svg-viewport-kevan.pug | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 test/svg-viewport-kevan.pug diff --git a/demo/index.pug b/demo/index.pug index 1397c1b..4a81478 100644 --- a/demo/index.pug +++ b/demo/index.pug @@ -13,7 +13,7 @@ html(lang='en') link(rel="stylesheet" media="all" href="../node_modules/reset-css/reset.css") link(rel="stylesheet" media="all" href="demo.css") body - include ../test/svg-composition.pug + include ../test/svg-viewport-kevan.pug //.super(style="height: 200px; width: 200px;") //div(style="margin-top: 40px; margin-left: 40px") //div(style="margin-top: 40px") diff --git a/test/pug_loader.coffee b/test/pug_loader.coffee index b1adf10..ce5028c 100644 --- a/test/pug_loader.coffee +++ b/test/pug_loader.coffee @@ -39,6 +39,7 @@ describe "Referentiel", -> 'rotation-scale', 'svg-basic', 'svg-viewport', + 'svg-viewport-kevan', 'svg-margin', 'svg-border', 'svg-no-viewbox', diff --git a/test/svg-viewport-kevan.pug b/test/svg-viewport-kevan.pug new file mode 100644 index 0000000..f4b3f64 --- /dev/null +++ b/test/svg-viewport-kevan.pug @@ -0,0 +1,5 @@ +svg.referentiel(width=300 height=250 viewbox="10 10 50 50" style="width: 300px; height: 250px;") + circle.pointer(cx=10 cy=10 r=10) + circle(data-assert="0,0:10,10" r=1) + circle(data-assert="100,100:60,60" r=1) + circle(data-assert="90,90:55,55" r=1)