Положение фигуры, чтобы оно плавно следовало за курсором, а не прыгал? - PullRequest
0 голосов
/ 07 декабря 2018

Как я могу сделать так, чтобы белый прямоугольник непрерывно и плавно следовал за положением курсора, используя функцию перемещения с анимацией движения?

То, что у меня есть, не работает должным образом - положение прямоугольника обновляется только спорадически!

https://jsfiddle.net/jamesgreig/gaxrteoc/73/

var width = 1200
var height = 800
var draw = SVG('drawing').size(width, height)

var building = draw.rect(1200, 800).fill('https://www.dropbox.com/s/pidx5gd1cmt3kyx/mcw_elevation_small.jpg?raw=1')

var rect1 = draw.rect(300,80).fill('#FFF')
rect1.center(width/2, height/2)

var mask2 = draw.mask().add(rect1)
building.maskWith(mask2)

///////

var xPos = 300;
var yPos = 600;

onmousemove = function(e){
	xPos = e.clientX
	yPos = e.clientY
  console.log(xPos+' , '+yPos)
}

/////

function update(dt) {
  // move the rectangle towards the cursor 
  rect1.animate(300).move(xPos - 300, yPos - 80)
}

///////

var lastTime, animFrame;

function callback(ms) {
  // we get passed a timestamp in milliseconds
  // we use it to determine how much time has passed since the last call

  if (lastTime) {
    update((ms-lastTime)/1000) // call update and pass delta time in seconds
  }

  lastTime = ms
  animFrame = requestAnimationFrame(callback)
}

callback()

1 Ответ

0 голосов
/ 08 декабря 2018

TL; DR

Не использовать анимацию вообще (решение 2) или использовать новые контроллеры svg.js v3 (решение 3)

Когда выВызовите animate() для элемента несколько раз, анимация станет цепочкой.Вы вызываете animate с каждым requestAnimationFrame, что означает, что вы создаете новую анимацию каждые 16 мс.Этот ofc выглядит очень странно, потому что все анимации воспроизводятся одна за другой.

Существует несколько решений вашей проблемы:

Возможно, самое простое, но, возможно, не то, что вы хотите (даже если выподумайте так)

svg.js v2

  • остановите анимацию перед вызовом animate.В вашем случае вам нужно stop(finishAnimation=false, clearQueue=true).Затем следующий вызов animate должен поставить в очередь новую анимацию и немедленно воспроизвести ее

svg.js v3

  • в svg.js v3 animate() возвращает бегуна, которыйзапланировано на временной шкале анимации элементов.Перед тем, как снова animate(), вы должны сначала удалить бегуна с временной шкалы по соображениям производительности:

var runner = el.animate()
// later
runner.unschedule()
  • Однако это не требуется.Затем вы можете запланировать новую анимацию, используя новый синтаксис animate(duration, delay, when).Вы хотите animate(300, 0, 'now').Это сразу запустит новую анимацию

Возможно, решение, которое вы искали, но не искали

Не анимироватьсовсем.Вы хотите выделить определенную область здания в вашем примере.Просто свяжите прямоугольник с позицией мыши напрямую:

SVG.on(document, 'mousemove', (e) => {
  // This function converts the mouse coordinates
  // into the space of the draw element. No other math required :)
  const {x, y} = draw.point(e.clientX, e.clientY)
  rect.center(x, y)
})

Самое крутое и новейшее решение - но, может быть, вы все равно захотите рассмотреть второе решение

svg.js v3 приходитс новым типом анимации, называемой декларативной анимацией.Контролер отвечает за то, чтобы всегда доставлять анимацию туда, куда вы хотите, в тот момент, когда мышь движется вслед за настоящим бризом.

// Spring() creates a new controller behaving like a physical spring
// You can pass 2 parameters: new SVG.Spring(settleTime, overshoot)
// So if you want jiggling increase the overwhoot (0-20% is useful)
const runner = rect1.animate(new SVG.Spring())

// This part is similar to the second solution
SVG.on(document, 'mousemove', (e) => {
  const {x, y} = draw.point(e.clientX, e.clientY)
  runner.center(x, y)
})

Для получения дополнительной информации о svg.js v3, твиттер - лучший источник атм, потому что кодпримеры публикуются каждый день до xmas: https://twitter.com/svg_js

...