How to add CSS translation to an existing translation?

I place a div element on the screen using CSS translate. This works great, except that when the same element is shifted later, the original offset is discarded.

Set CSS starting position using javascript

div.style.transform ="translate(800px, 400px)";

After setting randomization using javascript, the CSS animation just dumps it back.

CSS animation

@keyframes testanimation {
  0% {
    transform: translateY(20px);
  }

  100% {
    transform: translateY(80px);
  }
}

How can I combine CSS translations to account for previous offsets? In this case, the goal is to start the animation in randomized places. 20px - 80px should be relative.

+4
source share
4 answers

, , , - , .

- position, left top. , :

div.style.position = "absolute";
div.style.left = "800px";
div.style.top = "400px";

, , .

+1

, reset , .

:

div {/* translate value reduced to fit in snippet window */
  border:solid;
  height:40px;
  width:40px;
  transform:translatex(180px) translatey(140px);
  animation:2s testanimation forwards;
}
@keyframes testanimation {
  0% {
    transform:translatex(180px) translatey(150px)
  }

  100% {
    transform:translatex(180px) translatey(180px)
  }
}
<div></div>
Hide result

:

div.style.transform ="translatex(800px) translatey(400px)";

:

@keyframes testanimation {
  0% {
    transform:translatex(800px) translatey(420px)
  }

  100% {
    transform:translatex(800px) translatey(480px)
  }
}


: + /.

div {/* value reduced to fit window demo */
  border:solid;
  height:40px;
  width:40px;
  position:relative;
  transform:translate(80px,40px);
  animation:2s testanimation forwards;
}
@keyframes testanimation {
  0% {
    top : 20px
  }

  100% {
    top:40px
  }
}
<div></div>
Hide result

:

div {
  /* value reduced to fit window demo */
  border: solid;
  height: 40px;
  width: 40px;
  position: relative;
  left: 80px;
  top: 40px;
  animation: 2s testanimation forwards;
}

@keyframes testanimation {
  0% {
    transform: translatey(20px)
  }
  100% {
    transform: translatey(40px)
  }
}
<div></div>
Hide result
0

:

#wrapperDiv {
  width: 100px;
  height: 100px;
  background: green;

  transform: translate(400px, 200px) rotate(50deg);
}

#yourDiv {
  width: 100px;
  height: 100px;
  background: red;
  
  animation: testanimation 2s infinite;
}

@keyframes testanimation {
  0% {
    transform: translateY(20px) rotate(0deg);
  }

  100% {
    transform: translateY(80px) rotate(40deg);
  }
}
<div id="wrapperDiv">
  <div id="yourDiv">
  <div>
<div>
Hide result

div#yourDiv div#wrapperDiv.

0

I think a more general solution would be to analyze the css transform property, as this allows you to animate an element without worrying about its state.

This is the solution I use for this case:

parseTransformMatrix = function(str){
  const match_float = "[+\\-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?"
  const match_sep = "\\s*,?\\s*"
  m = str.match(RegExp(`matrix\\((${match_float}(?:${match_sep}${match_float})*)\\)`))
  if(!m || !m.length || m.length < 2) return null
  return m[1].match(RegExp(match_float, 'g')).map(x => parseFloat(x))
}
// Test parseTransformMatrix method
console.log(parseTransformMatrix("matrix(1, 0, 0, 1, 96.2351, 309.123)"));

getElementTranslate = function(e){
  let t = e.css("transform")
  let r = { left: 0, top: 0 }
  if(!t) return r
  mat = parseTransformMatrix(t)
  if(!mat || !mat.length || mat.length != 6) return r
  r.left = mat[4]
  r.top = mat[5]
  return r
}

This eis a jQuery element, but you can easily use it getPropertyValueinstead if you don't want to have this dependency.

Using these functions, you can do something like:

let t = getElementTranslate(e)
e.css({transform:`translate(${t.left+20}px,${t.top+80}px)`})
0
source

Source: https://habr.com/ru/post/1674968/


All Articles