需要帮助来了解CSS转换原点的工作方式

时间:2019-03-22 14:56:49

标签: html css

我浏览了CSS specMDN / Opera上有关转换原点的文章,但无法确切了解转换原点的工作原理。

我已经设置了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

     

”此属性是通过首先用   属性的取反值,然后应用元素的变换,   然后根据属性值进行翻译。)“

     

来自Opera

     

技术上,通过计算   否定转换原点值(X轴上为-3em,   在上例中元素的顶部),将元素转换为   该值,然后应用在   转换属性,然后按实际值转换元素   转换来源的。

如果我尝试执行上述步骤并追踪div在坐标系统中的确切位置,则会进一步混淆。

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

1 个答案:

答案 0 :(得分:0)

这是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>