ssbc / visual-docs

Diagrams and animations documenting Secure Scuttlebutt (scuttlebutt.nz) and Āhau (ahau.io)
https://scuttlebutt.nz
Other
16 stars 1 forks source link

transforms are not combined #4

Closed cameralibre closed 2 years ago

cameralibre commented 4 years ago

Context:

Problem

Currently when there are transform properties being animated, they are not correctly formatted or combined into a single transform property.

Current output:

@keyframes animation-name {
  0% { scale:0; } /* not valid css! */
  10% { translate-x:0px; scale:1; }  /* translateX should also not be converted to kebab-case */
  100% { translate-x:10px; scale:0; }
}

Correct output:

@keyframes animation-name {
  0% { transform: scale(0); } 
  10% { transform: translateX(0) scale(1); }
  100% { transform: translateX(10px) scale(0); }
}

in the anime.js anim object there are two entries which should help me here:

cameralibre commented 4 years ago

the value of anim.animations[i].type can be either css or transform (maybe more? But I haven't seen anything else)

It can be transform or css, or attribute - I guess that would be when animating an SVG viewBox, for example, which can't be changed via CSS. I should probably have a warning if (type === attribute) as I guess it won't be a valid CSS animation.

function getAnimationType(el, prop) {
  if (is.dom(el) && !is.inp(el) && (!is.nil(getAttribute(el, prop)) || (is.svg(el) && el[prop]))) return 'attribute';
  if (is.dom(el) && arrayContains(validTransforms, prop)) return 'transform';
  if (is.dom(el) && (prop !== 'transform' && getCSSValue(el, prop))) return 'css';
  if (el[prop] != null) return 'object';
}

https://github.com/juliangarnier/anime/blob/3ebfd913a04f7dc59cc3d52e38275272a5a12ae6/src/index.js#L433-L438

cameralibre commented 4 years ago

anim.animatables[i].transforms stores a list array and a last value.

Here's where those entries are created:

function getElementTransforms(el) {
  if (!is.dom(el)) return;
  const str = el.style.transform || '';
  const reg  = /(\w+)\(([^)]*)\)/g;
  const transforms = new Map();
  let m; while (m = reg.exec(str)) transforms.set(m[1], m[2]);
  return transforms;
}

function getTransformValue(el, propName, animatable, unit) {
  const defaultVal = stringContains(propName, 'scale') ? 1 : 0 + getTransformUnit(propName);
  const value = getElementTransforms(el).get(propName) || defaultVal;
  if (animatable) {
    animatable.transforms.list.set(propName, value);
    animatable.transforms['last'] = propName;
  }
  return unit ? convertPxToUnit(el, value, unit) : value;
}

https://github.com/juliangarnier/anime/blob/3ebfd913a04f7dc59cc3d52e38275272a5a12ae6/src/index.js#L440-L457

cameralibre commented 4 years ago

I've added a simple solution that doesn't use the list array or the last value, which will need further testing. My suspicion is that not taking the order of transforms into account will lead to inaccurate animations...