From e065a4415b7d6991ac14de81646f109e43bef9e7 Mon Sep 17 00:00:00 2001 From: Saivan Date: Sat, 3 Mar 2018 22:08:26 +1100 Subject: Added matrix composition and decompositions This commit adds matrix composition and decompositions (untested), it also adds another playground to test that this is working as expected in every case. We also fixed a few linting errors. --- playgrounds/matrix/drag.js | 79 ++++++++++++++++++++++++++++++++++ playgrounds/matrix/matrix.html | 47 ++++++++++++++++++++ playgrounds/matrix/matrix.js | 41 ++++++++++++++++++ playgrounds/playground.css | 43 +++++++++++++++--- playgrounds/transforms/transforms.html | 15 ++----- playgrounds/transforms/transforms.js | 54 +++-------------------- 6 files changed, 213 insertions(+), 66 deletions(-) create mode 100644 playgrounds/matrix/drag.js create mode 100644 playgrounds/matrix/matrix.html create mode 100644 playgrounds/matrix/matrix.js (limited to 'playgrounds') diff --git a/playgrounds/matrix/drag.js b/playgrounds/matrix/drag.js new file mode 100644 index 0000000..636ae30 --- /dev/null +++ b/playgrounds/matrix/drag.js @@ -0,0 +1,79 @@ + +function reactToDrag (element, onDrag, beforeDrag) { + + let xStart, yStart + + let startDrag = event=> { + + // Avoid the default events + event.preventDefault() + + // Store the position where the drag started + xStart = event.pageX + yStart = event.pageY + + // Fire the start drag event + if (beforeDrag) { + var {x, y} = parent.point(event.pageX, event.pageY) + beforeDrag(event, x, y) + } + + // Register events to react to dragging + SVG.on(window, 'mousemove.drag', reactDrag) + SVG.on(window, 'touchmove.drag', reactDrag) + + // Register the events required to finish dragging + SVG.on(window, 'mouseup.drag', stopDrag) + SVG.on(window, 'touchend.drag', stopDrag) + } + + let reactDrag = event=> { + + // Convert screen coordinates to svg coordinates and use them + var {x, y} = parent.point(event.pageX, event.pageY) + if (onDrag) + onDrag(event, x, y) + } + + let stopDrag = event=> { + SVG.off(window, 'mousemove.drag') + SVG.off(window, 'touchmove.drag') + SVG.off(window, 'mouseup.drag') + SVG.off(window, 'touchend.drag') + } + + // Bind the drag tracker to this element directly + let parent = element.doc() + let point = new SVG.Point() + element.mousedown(startDrag).touchstart(startDrag) +} + +SVG.extend(SVG.Element, { + draggable: function (after) { + + let sx, sy + + reactToDrag(this, (e, x, y)=> { + + let matrix = this.transform + this.transform({ + origin: [sx, sy], + position: [x, y], + }) + + if (after) { + after(this, x, y) + } + + }, (e, x, y)=> { + + var toAbsolute = this.transform().inverse() + var p = new SVG.Point(x, y).transform(toAbsolute) + sx = p.x + sy = p.y + + }) + + return this + }, +}) diff --git a/playgrounds/matrix/matrix.html b/playgrounds/matrix/matrix.html new file mode 100644 index 0000000..cd34b7d --- /dev/null +++ b/playgrounds/matrix/matrix.html @@ -0,0 +1,47 @@ + + + + + + + SVG Playground + + + + + +

SVG Transformations

+ +

+ This playground tests the compose/decompose functionality in + svg matrix, as well as the draggable code and the transformations. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/playgrounds/matrix/matrix.js b/playgrounds/matrix/matrix.js new file mode 100644 index 0000000..33e21d1 --- /dev/null +++ b/playgrounds/matrix/matrix.js @@ -0,0 +1,41 @@ + +function print (mat) { + let {a, b, c, d} = mat + console.log(` + a: ${a.toFixed(2)} + b: ${b.toFixed(2)} + c: ${c.toFixed(2)} + d: ${d.toFixed(2)} + `) +} + +function moveit () { + + let {cx: x0, cy: y0} = or.rbox(svg) + let {cx: x1, cy: y1} = b1.rbox(svg) + let {cx: x2, cy: y2} = b2.rbox(svg) + + let m = new SVG.Matrix( + (x1 - x0) / 50, (y1 - y0) / 50, (x2 - x0) / 50, (y2 - y0) / 50, x0, y0) + let com = m.decompose() + let g = new SVG.Matrix().compose(com) + + // Transform both of the items + target.transform(m) + mover.transform(g) + + console.log(com); + print(m) + print(g) +} + +// Declare the two points +let svg = SVG('svg') +var or = SVG("#or").draggable(moveit) +var b1 = SVG("#b1").draggable(moveit) +var b2 = SVG("#b2").draggable(moveit) + +// Declare the squares +let target = SVG("#true") +let mover = SVG("#guess") +let tester = SVG("#tester") diff --git a/playgrounds/playground.css b/playgrounds/playground.css index 1808d6a..71fabed 100644 --- a/playgrounds/playground.css +++ b/playgrounds/playground.css @@ -1,24 +1,53 @@ +* { + box-sizing: border-box; +} + html { background-color : #f5f6f7; - text-align: center; + /* text-align: center; */ +} + +body { + margin: 0; + width: 100vw; + height: 99vh; + grid-gap: 30px; + display: inline-grid; + align-items: center; + grid-template-columns: 10vw 40vw auto 10vw; + grid-template-rows: 0 10vw auto 0; } h1 { + text-align: right; + border-right: solid 3px #f06; + padding-right: 12px; color: #f06; - font-size: 6vh; - margin: 4vh; + font-size: 52px; + font-family: Helvetica; + grid-row: 2; + grid-column: 2; + line-height: 1.8em; +} + +p { + padding-right: 50px; + color: #444; + font-size: 18px; font-family: Helvetica; + grid-row: 2; + grid-column: 3; } svg { - width: 70vw; - height: 80vh; + height: 100%; + width: 100%; + grid-row: 3; + grid-column: 2/4; background-color: white; - position: fixed; border-radius: 20px; border: #f065 1px solid; - left: 15vw; } .pink { diff --git a/playgrounds/transforms/transforms.html b/playgrounds/transforms/transforms.html index d206d06..ac60f14 100644 --- a/playgrounds/transforms/transforms.html +++ b/playgrounds/transforms/transforms.html @@ -12,19 +12,12 @@

SVG JS Playground

- + - - - + + diff --git a/playgrounds/transforms/transforms.js b/playgrounds/transforms/transforms.js index 76045a3..b27e1c3 100644 --- a/playgrounds/transforms/transforms.js +++ b/playgrounds/transforms/transforms.js @@ -1,51 +1,9 @@ -// let mover = SVG.select("#new")[0] -// mover.transform({ -// // position: [800, 500], -// // origin: [200, 400], -// // skew: [20, 0], -// // rotate: 30, -// }) - -// var draw = SVG.select('svg')[0] -// var rect = draw.rect(100, 100) -// .transform({ -// // rotate: -10, -// translate: [-50, -50], -// // scale: 2 -// }).opacity(0.3) -// -// -// var es = SVG.select('ellipse') - -draw = SVG("svg") - -offset = draw.screenCTM() -draw.viewbox(100,100, 1000, 1000) -nested = draw.nested().size(500, 500).move(100,100).viewbox(0, 0, 400, 400) -rect = nested.rect(50, 50).stroke({width:0}).move(25, 90).scale(2, 0, 0).translate(10, 10).fill("red") - - -var box = rect.rbox() - -console.log(box.x - offset.e, box.y - offset.f); - - -div = document.createElement('div') - -Object.assign(div.style, { - position : 'absolute', - left : box.x + 'px', - top : box.y + 'px', - width : box.width + 'px', - opacity : 0.4, - height : box.height + 'px', - background : 'blue', +let mover = SVG.select("#new")[0] +mover.transform({ + position: [800, 500], + origin: [200, 400], + skew: [20, 0], + rotate: 30, }) - - -document.body.appendChild(div) - -// rect1.toParent(nested).transform() -// rect2.toParent(g2).transform() -- cgit v1.2.3