我浏览了CSS spec,MDN / 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在坐标系统中的确切位置,则会进一步混淆。
任何帮助将不胜感激,谢谢
答案 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 Change</span>