如何重新缩放连续旋转的元素以完全适合其(固定大小)容器?
How to rescale a continuously rotating element to fit exactly in its (fixed size) container?
我让一个(矩形)图像无限旋转。旋转时,我想调整它的大小(这样图像就不会被截断)。
换句话说:我尽量显示整个图像。
因此,“0 度”示例是正确的,但“80 度”示例更像是:
您可能已经注意到,这是作为 StreamElements 小部件执行的。这可能就是 overflow:visible
不起作用的原因。
HTML:
<div class="main-container">
<img src="some_url">
</div>
CSS:
.main-container {
width:100%;
height:100%;
overflow:visible;
display: grid;
place-items: center;
}
img {
max-width: 100%;
object-fit: contain;
animation: spin 5s infinite linear;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
我认为 transform: ... scale(x)
可能有效,但如果不使用固定关键帧值(这似乎是一个不可靠的解决方案)我无法做到这一点。
我认为如果没有 Javascript 并且还转换 Javascript 中的元素而不是 CSS 中的元素,您将无法解决这个问题。
这是我的做法,我没有重现您的确切示例,我使用了 2 个简单的 divs:一个容器和第一个容器中的另一个容器(而不是图像);
const cont= document.querySelector('.main-container');
const rot= document.querySelector('.rotater');
const H= rot.offsetHeight, h= cont.offsetHeight;
const W= rot.offsetWidth;
var t=0;
var anim= setInterval(rotate, 20);
function rotate(){
rot.style.transform= "rotate(-" + t + "deg)";
update(t);
t++;
}
function update(T){
let alpha= Math.atan(H/W);
let diagLength= Math.sqrt(
Math.pow(H, 2) + Math.pow(W, 2));
let theta= degToRad(T);
theta= radTrunc(theta);
theta= (theta> Math.PI/2 && theta< Math.PI) || (theta> 3*Math.PI/2 && theta< 2*Math.PI) ? Math.PI - theta : theta;
let beta= (Math.PI/2) - (alpha + theta);
let nonScaledHeight= Math.cos(beta) * diagLength;
let ratio= Math.abs(h/nonScaledHeight);
ratio= ratio> 1 ? 1 : ratio;
rot.style.transform += " scale(" + ratio + ")";
}
function degToRad(angle){
return angle * Math.PI / 180;
}
function radTrunc(angle){
while(angle> (Math.PI * 2)){
angle -= Math.PI*2;
}
return angle;
}
.main-container{
width: 600px;
height: 200px;
background: blue;
}
.rotater{
width: 250px;
height: 200px;
background: green;
margin: auto;
}
<div class="main-container">
<div class="rotater"></div>
</div>
您在函数 update
中看到的所有计算都是基本三角函数,我们计算旋转时内部 div 的高度:nonScaledHeight
以及该值的比率外层的高度 div 就是内层的缩放比例 div。
degToRad
将角度 t
从度数转换为弧度,radTrunc
确保角度保持在 [0, 2*PI[
.
范围内
我让一个(矩形)图像无限旋转。旋转时,我想调整它的大小(这样图像就不会被截断)。
换句话说:我尽量显示整个图像。
因此,“0 度”示例是正确的,但“80 度”示例更像是:
您可能已经注意到,这是作为 StreamElements 小部件执行的。这可能就是 overflow:visible
不起作用的原因。
HTML:
<div class="main-container">
<img src="some_url">
</div>
CSS:
.main-container {
width:100%;
height:100%;
overflow:visible;
display: grid;
place-items: center;
}
img {
max-width: 100%;
object-fit: contain;
animation: spin 5s infinite linear;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
我认为 transform: ... scale(x)
可能有效,但如果不使用固定关键帧值(这似乎是一个不可靠的解决方案)我无法做到这一点。
我认为如果没有 Javascript 并且还转换 Javascript 中的元素而不是 CSS 中的元素,您将无法解决这个问题。 这是我的做法,我没有重现您的确切示例,我使用了 2 个简单的 divs:一个容器和第一个容器中的另一个容器(而不是图像);
const cont= document.querySelector('.main-container');
const rot= document.querySelector('.rotater');
const H= rot.offsetHeight, h= cont.offsetHeight;
const W= rot.offsetWidth;
var t=0;
var anim= setInterval(rotate, 20);
function rotate(){
rot.style.transform= "rotate(-" + t + "deg)";
update(t);
t++;
}
function update(T){
let alpha= Math.atan(H/W);
let diagLength= Math.sqrt(
Math.pow(H, 2) + Math.pow(W, 2));
let theta= degToRad(T);
theta= radTrunc(theta);
theta= (theta> Math.PI/2 && theta< Math.PI) || (theta> 3*Math.PI/2 && theta< 2*Math.PI) ? Math.PI - theta : theta;
let beta= (Math.PI/2) - (alpha + theta);
let nonScaledHeight= Math.cos(beta) * diagLength;
let ratio= Math.abs(h/nonScaledHeight);
ratio= ratio> 1 ? 1 : ratio;
rot.style.transform += " scale(" + ratio + ")";
}
function degToRad(angle){
return angle * Math.PI / 180;
}
function radTrunc(angle){
while(angle> (Math.PI * 2)){
angle -= Math.PI*2;
}
return angle;
}
.main-container{
width: 600px;
height: 200px;
background: blue;
}
.rotater{
width: 250px;
height: 200px;
background: green;
margin: auto;
}
<div class="main-container">
<div class="rotater"></div>
</div>
您在函数 update
中看到的所有计算都是基本三角函数,我们计算旋转时内部 div 的高度:nonScaledHeight
以及该值的比率外层的高度 div 就是内层的缩放比例 div。
degToRad
将角度 t
从度数转换为弧度,radTrunc
确保角度保持在 [0, 2*PI[
.