同时更改宽度、高度和变换会导致奇怪的过渡

Changing both width, height and transform simultaneously cause the weird transition

如果我同时更改 widthheighttransform 属性,它会产生非常奇怪的过渡。示例如下。查看矩形及其相对于红线的位置。

The demo.

我知道用 lefttop 属性替换 transform 属性 可以修复它,但这不是我的解决方案,因为它会产生性能和其他问题。

更新: scale 变换不是解决方案,因为在实际情况下比例可以改变,内部内容不应受到比例变换的影响。 –

const states = [{
    height: '250px',
    width: '500px',
    transform: 'translate(50px, 50px)'
  },
  {
    height: '150px',
    width: '250px',
    transform: 'translate(175px, 100px)'
  },
]

let currentState = 0;

function updateState() {
  const box = document.querySelector(".box");

  const state = states[currentState];

  currentState = (currentState + 1) % states.length

  box.style.height = state.height
  box.style.width = state.width
  box.style.transform = state.transform
}
.button {
  position: absolute;
  top: 0;
  left: 0;
}

.box {
  transition: 0.4s ease-in-out;
  position: absolute;
  background: #AAA;
  left: 0;
  top: 0;
}

.line {
  position: absolute;
  left: 300px;
  height: 100%;
  background: red;
  width: 1px;
}

.small-box {
  width: 10px;
  height: 10px;
  border: solid 1px black;
  position: absolute;
  transform: translateX(-50%);
}
<div class="box">
  <div class="small-box" style="left: 50%; top:0"></div>
</div>
<div class="line"></div>
<button class="button" onclick="updateState()">Update State</button>

试试这个例子,我确实使用 transform: scale 而不是 transform: translate。向上移动 small-box,因为如果缩放 box 本身,small-box 也会缩放。并包装成 flex.

const states = [
  {
    height: '250px',
    width: '500px',
    // transform: 'translate(50px, 50px)',
  },
  {
    height: '150px',
    width: '250px',
    // transform: 'translate(175px, 100px)',
  },
];

let currentState = 0;

function updateState() {
  const box = document.querySelector('.box');

  const state = states[currentState];

  currentState = (currentState + 1) % states.length;

  box.style.height = state.height;
  box.style.width = state.width;
  box.style.transform = state.transform;
}
.wrapper { /* Added */
  width: 600px;
  height: 300px;
  position: relative;
  border: 1px solid red;
  display: flex;
  justify-content: center;
  align-items: flex-start;
}
.button {
  position: absolute;
  top: 0;
  left: 0;
}

.box {
  transition: 0.4s ease-in-out;
  /* position: absolute; */
  background: #aaa;
  /* left: 0; */
  /* top: 0; */
  transform-origin: top center;
}
.line {
  position: absolute;
  left: 50%; /* Changed */
  height: 100%;
  background: red;
  width: 1px;
}
.small-box {
  width: 10px;
  height: 10px;
  border: solid 1px black;
  position: absolute;
  transform: translateX(-50%); /* Added */
}
<div class="wrapper">
  <div class="box">
    <div class="small-box" style="left: 50%; top: 0"></div>
  </div>
  <div class="line"></div>
  <button class="button" onclick="updateState()">Update State</button>
</div>

我在 js 上更改了 transform 属性 : 50px 并且 100px 变成了 calc(300px - 50%)

calc(300px - 50%) 是行位置减去 .box 的一半 div

const states = [{
    height: '250px',
    width: '500px',
    transform: 'translate(calc(300px - 50%), 50px)'
  },
  {
    height: '150px',
    width: '250px',
    transform: 'translate(calc(300px - 50%), 100px)'
  },
]

let currentState = 0;

function updateState() {
  const box = document.querySelector(".box");

  const state = states[currentState];

  currentState = (currentState + 1) % states.length

  box.style.height = state.height
  box.style.width = state.width
  box.style.transform = state.transform
}
.button {
  position: absolute;
  top: 0;
  left: 0;
}

.box {
  transition: 0.4s ease-in-out;
  position: absolute;
  background: #AAA;
  left: 0;
  top: 0;
}

.line {
  position: absolute;
  left: 300px;
  height: 100%;
  background: red;
  width: 1px;
}

.small-box {
  width: 10px;
  height: 10px;
  border: solid 1px black;
  position: absolute;
  transform: translateX(-50%);
}
<div class="box">
  <div class="small-box" style="left: 50%; top:0"></div>
</div>
<div class="line"></div>
<button class="button" onclick="updateState()">Update State</button>