runemadsen / rune.js

A JavaScript library for programming graphic design systems with SVG
http://runemadsen.github.io/rune.js
MIT License
654 stars 35 forks source link

Transform translate(x y) support? #28

Closed vorg closed 7 years ago

vorg commented 7 years ago

Both scale and rotate modify elements transform property. There is no way to add transform though. Even that move(x, y) exists it's not always what I need:

Move + rotate: screen shot 2017-08-11 at 18 29 29 copy

Move + transform (simulated with parent group move + elem rotate) screen shot 2017-08-11 at 18 53 44 copy

runemadsen commented 7 years ago

Hi @vorg. Can you post the two code examples? That will help me understand your issue better. Thx

vorg commented 7 years ago

move + rotate

Completely wrong

screen shot 2017-08-12 at 21 15 59

var r = new Rune({
  container: 'body',
  width: 400,
  height: 400
})

r.rect(0, 0, r.width, r.height).fill(250, 250, 100).stroke(false)
for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 10; j++) {
    var x = i * 40 + 20
    var y = j * 40 + 20
    r.rect(-15, -5, 30, 10)
      .move(x, y)
      .fill(100, 100, 255)
      .stroke(false)
      .rotate(45)
  }
}

r.draw()

move + rotate with offset

Rects are off the center

screen shot 2017-08-12 at 21 16 04
// move + rotate + offset

var r2 = new Rune({
  container: 'body',
  width: 400,
  height: 400
})

r2.rect(0, 0, r.width, r.height).fill(250, 250, 100).stroke(false)

for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 10; j++) {
    var x = i * 40 + 20
    var y = j * 40 + 20
    r2.rect(-15, -5, 30, 10)
      .move(x, y)
      .fill(100, 100, 255)
      .stroke(false)
      .rotate(45, x, y)
  }
}

r2.draw()

translate + rotate

Perfect on spot

screen shot 2017-08-12 at 21 16 13
var r3 = new Rune({
  container: 'body',
  width: 400,
  height: 400
})

r3.rect(0, 0, r.width, r.height).fill(250, 250, 100).stroke(false)

for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 10; j++) {
    var x = i * 40 + 20
    var y = j * 40 + 20
    r3.rect(-15, -5, 30, 10)
      .fill(100, 100, 255)
      .stroke(false)
  }
}

r3.draw()

// manual fixup
var rects = r3.el.querySelectorAll('rect')
rects = Array.prototype.slice.call(rects)
rects.shift() // skip background rect
rects.forEach((rect, idx) => {
  var i = idx % 10
  var j = Math.floor(idx / 10)
  var x = i * 40 + 20
  var y = j * 40 + 20
  rect.setAttribute('transform', `translate(${x} ${y}) rotate(45)`)
})

parent group move + shape rotate

Same result as above

screen shot 2017-08-12 at 21 16 13
var r4 = new Rune({
  container: 'body',
  width: 400,
  height: 400
})

r4.rect(0, 0, r.width, r.height).fill(250, 250, 100).stroke(false)

for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 10; j++) {
    var x = i * 40 + 20
    var y = j * 40 + 20
    var g = r4.group(x, y)
    r4.rect(-15, -5, 30, 10, g)
      .fill(100, 100, 255)
      .rotate(45)
      .stroke(false)
  }
}

r4.draw()
runemadsen commented 7 years ago

Just getting back to this. This is all expected behavior in Rune.js. Like P5 and Processing, rotate() will always rotate around the 0,0 origin point, unless you specify a location to rotate around. It's simply a matter of tweaking your numbers to achieve the design that you want.

var r = new Rune({
  container: "body",
  width: 400,
  height: 400
});

r.rect(0, 0, r.width, r.height).fill(250, 250, 100).stroke(false)

for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 10; j++) {
    var x = i * 40 + 15
    var y = j * 40 + 5
    r.rect(0, 0, 30, 10)
      .move(x, y)
      .fill(100, 100, 255)
      .stroke(false)
      .rotate(45, x, y)
  }
}

r.draw();
pattern