【问题标题】:Need help in understanding how transform-origin works in CSS [duplicate]在理解 CSS 中的 transform-origin 如何工作时需要帮助 [重复]
【发布时间】:2019-08-13 14:28:45
【问题描述】:

我浏览了 CSS specMDN/Opera 关于 transform-origin 的文章,但无法准确理解 transform-origin 的工作原理。

我已经设置了jsfiddle。类为“test”的 div 是一个“50px”宽的正方形。有一个按钮可以旋转 div 30 度。示例 HTML 如下

<div class='container'>
    <div class='test'></div>
</div>
<button class='button'>
    Rotate
</button>

示例 CSS 如下

.rotate {
  transform: rotate(30deg);
  transform-origin: 70px 80px;
}

如果我将变换原点设置为正方形的边缘,例如 (0,0)/(50px,0)/(0,50px)/(50px, 50px) 或正方形内圆周/区域上的任何点可以稍微想象一下变换原点是如何工作的。 但是,如果我将属性设置为正方形边界之外的一个点,我将无法想象或理解 div 的确切位置。

在 MDN/Opera 文章中,有如下一句话,

来自 MDN

"这个属性是通过首先翻译元素来应用的 取反属性值,然后应用元素的变换, 然后按属性值进行翻译。)”

来自歌剧

从技术上讲,变换原点是通过计算 转换原点值的否定(X 轴上的 -3em 和 上例中元素的顶部),将元素转换为 这个值,然后应用在 transform 属性,然后将元素转换为实际值 变换原点。

如果我尝试按照上述步骤跟踪 div 将在坐标系中的确切位置,则会增加更多的混乱。

任何帮助将不胜感激,谢谢

【问题讨论】:

标签: html css


【解决方案1】:

这是Dan Wilson 的一支非常棒的笔,它可以直观地解释Transform Origin 的工作原理:

https://codepen.io/danwilson/full/EXqEZM

var display = document.getElementById('transform-origin');
var origin = document.querySelector('.origin');
var style = document.documentElement.style;

var autopilot;
autopilot = setTimeout(() => {
  change();
  autopilot = setInterval(change, 3000)
}, 1500);

function change(ex, ey) {
  var x = ex || (Math.random());
  var y = ey || (Math.random());
  style.setProperty('--x', x);
  style.setProperty('--y', y);
  display.textContent = Math.round(x * 100) + '% ' + Math.round(y * 100) + '%';
}

document.documentElement.addEventListener('mouseup', onPress);
document.documentElement.addEventListener('touchend', onPress);
var width = window.innerWidth;
var height = window.innerHeight;
var box = origin.getBoundingClientRect();
var side = box.right - box.left;

function onPress(e) {
  clearTimeout(autopilot);
  clearInterval(autopilot);
  
  var x = e.clientX || e.changedTouches[0].clientX;
  var y = e.clientY || e.changedTouches[0].clientY;
  
  if (window.innerWidth !== width || window.innerHeight !== height) {
    box = origin.getBoundingClientRect();
    width = window.innerWidth;
    height = window.innerHeight;
    side = box.right - box.left;
  }
  
  var ex = (x - box.left) / side;
  var ey = (y - box.top) / side;
  
  change(ex,ey);
}
:root {
  --x: .5;
  --y: .5;
  --side: 30vmin;
  --duration: 1500ms;
  --easing: ease-in-out;
}

.shape {
  animation: rotate 1000ms infinite linear;
  transition: transform-origin var(--duration) var(--easing);
  transform-origin: calc(var(--x) * 100%) calc(var(--y) * 100%);
  
  
  width: var(--side);
  height: var(--side);
  background: 
    linear-gradient(315deg, hsl(248, 40%,50%) 10%, transparent 10%, transparent), 
    linear-gradient(225deg, hsl(348, 40%,50%) 10%, transparent 10%, transparent), 
    linear-gradient(135deg, hsl(48, 40%,50%) 10%, transparent 10%, transparent), 
    linear-gradient(45deg, hsl(168, 40%,50%) 10%, hsl(168, 70%,50%) 10%, hsl(168, 70%,50%));
  position: relative;
  will-change: transform, transform-origin;
}
.point {
  --point: 1vmin;
  background: black;
  width: var(--point);
  height: var(--point);
  border-radius: 50%;
  position: absolute;
  top: calc(var(--point) * -.5);
  left: calc(var(--point) * -.5);
  transform: translate(calc(var(--x) * var(--side)), calc(var(--y) * var(--side)));
  transition: transform var(--duration) var(--easing);
  will-change: transform;
  opacity: .6;
}
.origin {
  width: var(--side);
  height: var(--side);
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 1px dashed hsl(233, 70%, 50%);
  background: linear-gradient(315deg, hsla(248, 40%,50%, .2) 10%, transparent 10%, transparent), 
    linear-gradient(225deg, hsla(348, 40%,50%, .2) 10%, transparent 10%, transparent), 
    linear-gradient(135deg, hsla(48, 40%,50%, .2) 10%, transparent 10%, transparent), 
    linear-gradient(45deg, hsla(168, 40%,50%, .2) 10%, transparent 10%, transparent);
}

@keyframes rotate {
  100% {
    transform: rotate(360deg)
  }
}





p {
  position: absolute;
  top:50%;
  left:50%;
  transform: translate(-50%,var(--side));
  text-align: center;
  z-index:10;
}
span {
  display: block;
}
#instruction {
  position: absolute;
  top: 2vmin;
  left: 50%;
  transform: translateX(-50%);
  opacity: .78;
  text-align: center;
}

body {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  background: radial-gradient(circle, hsl(198, 70%, 96%), hsl(198, 70%, 90%));
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
}
*, *::before, *::after {
  box-sizing: border-box;
}
<!--
Scale: qXPdbw
Skew: PKJqJW
-->
<div class="shape"></div>
<div class="origin">
  <div class="point"></div>
</div>
<p>transform-origin:<span id="transform-origin">50% 50%</span></p>

<span id="instruction">Press Anywhere to&nbsp;Change</span>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-04
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多