- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试想出一种方法,通过 CSS 以透视方式围绕 Y 轴旋转图像,以便最终可见宽度等于所需的像素数。
例如,我可能想旋转一张 300px
图像,以便在应用旋转和透视后,图像的宽度现在为 240px
(80%原来的)。通过反复试验,我知道我可以设置 transform: perspective(300) rotateY(-12.68)
并将左上角点放在 -240px
(这是使用右图像的一侧作为原点)
我不太清楚如何对其进行逆向工程,以便对于任何给定的图像宽度、透视和所需宽度,我都可以计算出必要的旋转。
例如。对于同一张 300px
图像,我现在希望它在旋转后宽度为 150px
- 获得必要 Angular 所需的计算是什么?
这里有一个 playground,可以让您了解我在寻找什么,我已经复制了透视和旋转变换所做的数学计算来计算最左边点的最终位置,但我还没有能够在给定矩阵数学和涉及的多个步骤的情况下找出如何求解 Angular 。
https://repl.it/@BenSlinger/PerspectiveWidthDemo
const calculateLeftTopPointAfterTransforms = (perspective, rotation, width) => {
// convert degrees to radians
const rRad = rotation * (Math.PI / 180);
// place the camera
const cameraMatrix = math.matrix([0, 0, -perspective]);
// get the upper left point of the image based on middle right transform origin
const leftMostPoint = math.matrix([-width, -width / 2, 0]);
const rotateYMatrix = math.matrix([
[Math.cos(-rRad), 0, -Math.sin(-rRad)],
[0, 1, 0],
[Math.sin(-rRad), 0, Math.cos(-rRad)],
]);
// apply rotation to point
const rotatedPoint = math.multiply(rotateYMatrix, leftMostPoint);
const cameraProjection = math.subtract(rotatedPoint, cameraMatrix);
const pointInHomogenizedCoords = math.multiply(math.matrix([
[1, 0, 0 / perspective, 0],
[0, 1, 0 / perspective, 0],
[0, 0, 1, 0],
[0, 0, 1 / perspective, 0],
]), cameraProjection.resize([4], 1));
const finalPoint = [
math.subset(pointInHomogenizedCoords, math.index(0))
/ math.subset(pointInHomogenizedCoords, math.index(3)),
math.subset(pointInHomogenizedCoords, math.index(1))
/ math.subset(pointInHomogenizedCoords, math.index(3)),
];
return finalPoint;
}
<div id="app"></div>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.js"></script>
<script type="text/babel" data-plugins="transform-class-properties" >
// GOAL: Given the percentage defined in desiredWidth, calculate the rotation required for the transformed image to fill that space (shown by red background)
// eg: With desiredWidth 80 at perspective 300 and image size 300, rotation needs to be 12.68, putting the left point at 300 * .8 = 240.
// How do I calculate that rotation for any desired width, perspective and image size?
// factor out some styles
const inputStyles = { width: 50 };
const PerspDemo = () => {
const [desiredWidth, setDesiredWidth] = React.useState(80);
const [rotation, setRotation] = React.useState(25);
const [perspective, setPerspective] = React.useState(300);
const [imageSize, setImageSize] = React.useState(300);
const [transformedPointPosition, setTPP] = React.useState([0, 0]);
const boxStyles = { outline: '1px solid red', width: imageSize + 'px', height: imageSize + 'px', margin: '10px', position: 'relative' };
React.useEffect(() => {
setTPP(calculateLeftTopPointAfterTransforms(perspective, rotation, imageSize))
}, [rotation, perspective]);
return <div>
<div>
<label>Image size</label>
<input
style={inputStyles}
type="number"
onChange={(e) => setImageSize(e.target.value)}
value={imageSize}
/>
</div>
<div>
<label>Desired width after transforms (% of size)</label>
<input
style={inputStyles}
type="number"
onChange={(e) => setDesiredWidth(e.target.value)}
value={desiredWidth}
/>
</div>
<div>
<label>Rotation (deg)</label>
<input
style={inputStyles}
type="number"
onChange={(e) => setRotation(e.target.value)}
value={rotation}
/>
</div>
<div>
<label>Perspective</label>
<input
style={inputStyles}
type="number"
onChange={(e) => setPerspective(e.target.value)}
value={perspective}
/>
</div>
<div>No transforms:</div>
<div style={boxStyles}>
<div>
<img src={`https://picsum.photos/${imageSize}/${imageSize}`} />
</div>
</div>
<div>With rotation and perspective:</div>
<div style={boxStyles}>
<div style={{ display: 'flex', position: 'absolute', height: '100%', width: '100%' }}>
<div style={{ backgroundColor: 'white', flexBasis: 100 - desiredWidth + '%' }} />
<div style={{ backgroundColor: 'red', flexGrow: 1 }} />
</div>
<div style={{
transform: `perspective(${perspective}px) rotateY(-${rotation}deg)`,
transformOrigin: '100% 50% 0'
}}>
<img src={`https://picsum.photos/${imageSize}/${imageSize}`} />
</div>
</div>
<div>{transformedPointPosition.toString()}</div>
</div>;
};
ReactDOM.render(<PerspDemo />, document.getElementById('app'));
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/6.0.4/math.min.js"></script>
非常感谢任何帮助!
最佳答案
我会考虑一种不同的方法来找到没有矩阵计算的公式1 以获得以下内容:
R = (p * cos(angle) * D)/(p - (sin(angle) * D))
其中p
是透视,angle
是 Angular 旋转,D
是元素宽度,R
是我们要搜索的新宽度。
如果我们有 -45deg
的 Angular 和等于 100px
的视角以及初始宽度 200px
那么新的宽度将为: 58.58px
.box {
width: 200px;
height: 200px;
border: 1px solid;
background:
linear-gradient(red,red) right/58.58px 100% no-repeat;
position:relative;
}
img {
transform-origin:right;
}
<div class="box">
<img src="https://picsum.photos/id/1/200/200" style="transform:perspective(100px) rotateY(-45deg)">
</div>
如果我们有 -30deg
的 Angular 和等于 200px
的视角和初始宽度 200px
那么新的宽度将是 115.46px
.box {
width: 200px;
height: 200px;
border: 1px solid;
background:
linear-gradient(red,red) right/115.46px 100% no-repeat;
position:relative;
}
img {
transform-origin:right;
}
<div class="box">
<img src="https://picsum.photos/id/1/200/200" style="transform:perspective(200px) rotateY(-30deg)">
</div>
1 为了更好地理解该公式,让我们考虑下图:
想象一下,我们正在从顶部查看所有内容。红线是我们旋转的元素。大黑点是我们的视角,与场景的距离等于 p
(这是我们的视角)。由于 transform-origin
是正确的,因此将此点放在正确的位置是合乎逻辑的。否则,它应该在中心。
现在,我们看到的是R
设计的宽度,W
是我们在没有透视的情况下看到的宽度。很明显,大视角下我们看到的几乎和没有大视角的一样
.box {
width: 200px;
height: 200px;
border: 1px solid;
}
img {
transform-origin:right;
}
<div class="box">
<img src="https://picsum.photos/id/1/200/200" style="transform: rotateY(-30deg)">
</div>
<div class="box">
<img src="https://picsum.photos/id/1/200/200" style="transform:perspective(9999px) rotateY(-30deg)">
</div>
从小 Angular 看,我们看到的宽度很小
.box {
width: 200px;
height: 200px;
border: 1px solid;
}
img {
transform-origin:right;
}
<div class="box">
<img src="https://picsum.photos/id/1/200/200" style="transform: rotateY(-30deg)">
</div>
<div class="box">
<img src="https://picsum.photos/id/1/200/200" style="transform:perspective(15px) rotateY(-30deg)">
</div>
如果考虑图中O
标注的 Angular ,我们可以写出如下公式:
tan(O) = R/p
和
tan(O) = W/(L + p)
所以我们将有 R = p*W/(L + p)
和 W = cos(-angle)*D = cos(angle)*D
和L = sin(-angle)*D = -sin(angle)*D
这将给我们:
R = (p * cos(angle) * D)/(p - (sin(angle) * D))
为了找到 Angular ,我们可以将公式转换为:
R*p - R*D*sin(angle) = p*D*cos(angle)
R*p = D*(p*cos(angle) + R*sin(angle))
然后像描述的那样here 1我们可以得到如下等式:
angle = sin-1((R*p)/(D*sqrt(p²+R²))) - tan-1(p/R)
如果你想要一个等于 190px
和 R 等于 150px
和 D
等于 200px
你需要等于 -15.635deg
.box {
width: 200px;
height: 200px;
border: 1px solid;
background:
linear-gradient(red,red) right/150px 100% no-repeat;
position:relative;
}
img {
transform-origin:right;
}
<div class="box">
<img src="https://picsum.photos/id/1/200/200" style="transform:perspective(190px) rotateY(-15.635deg)">
</div>
1 感谢 https://math.stackexchange.com帮助我确定正确公式的社区
关于javascript - 如何在透视模式下计算旋转 Angular 以使宽度适合所需尺寸?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57431060/
我正在制作一个简单的程序来更改我的计算机背景。我在网上发现了一个stackoverflow问题,或多或少涵盖了我想做的事情。我现在可以成功地将我的墙纸更改为平铺、居中和从在线图像 URL 拉伸(str
是的,这是另一个每组最大的问题之一!我已经尝试了几天,试图解决这个问题,但无济于事。我也一直在寻找,但我什至不知道我是否在正确的地方寻找。问题的最简化版本如下。 我有 2 个表,一个是多对多表,另一个
我想解析一些数据,我有一个 BNF 语法来解析它。谁能推荐任何能够生成可在移动设备上使用的代码的语法编译器? 由于这是针对 JavaME 的,因此生成的代码必须是: 希望很小 对外来 Java 库的依
我有一个动物园时间序列对象,vels : 2011-05-01 00:00:00 7.52 2011-05-01 00:10:00 7.69 2011-05-01 00:20:00 7.67 2011
我想创建一个供小型制造公司使用的生产管理系统。该系统将允许记录设备制造的不同阶段。要求如下: 1.非基于浏览器的界面。需要基于 Swing 或 AWT 的东西。虽然我了解实现基于浏览器的解决方案的便利
是否有任何 java 或 clojure 邮件库可以实现 lamson 的功能?特别是lamson的邮件路由功能非常酷http://verpa.wordpress.com/2010/11/13/mak
sklearn 中的 fit() 方法似乎在同一界面中服务于不同的目的。 应用于训练集时,像这样: model.fit(X_train, y_train) fit() 用于学习稍后将在测试集上使用 p
我使用 OSM 显示县的边界。它在大多数情况下工作得很好,但在某些情况下,县更大并且不适合 map 。 如何在开始渲染之前调整缩放级别? var map = L.map("mapCnty").setV
我正在致力于缩小和丑化我的 javascript 文件。我想知道合适的尺寸是多大。如果我将所有js文件合并成一个文件(经过缩小和丑化),它会大于1mb。我想,最好将它们分成 2-3 个文件(每个文件
我是 Java 新手。 我想在 GridPane 中放置一个 TextArea。我在过去几个小时内尝试了此操作,结果如下: 如您所见,TextArea 比我的 Gridpane 大得多。这是我的代码:
sklearn 中的 fit() 方法似乎在同一界面中服务于不同的目的。 应用于训练集时,像这样: model.fit(X_train, y_train) fit() 用于学习稍后将在测试集上使用 p
我认为这是一个基本问题,但也许我混淆了这些概念。 假设我使用 R forecast 包中的函数 auto.arima() 将 ARIMA 模型拟合到时间序列。该模型假设方差不变。我如何获得该方差?是残
我使用 OSM 显示县的边界。它在大多数情况下工作得很好,但在某些情况下,县更大并且不适合 map 。 如何在开始渲染之前调整缩放级别? var map = L.map("mapCnty").setV
我有一个很长的标签,这是我的第一个标签,我想把它放在我的单元格中。这就是我所拥有的,但它不起作用。 我有一个自定义的 UITabelviewCell ,里面有几个标签。 -(CGFloat)table
假设我有一个包含 WCS header 的 FITS 文件,这样我就可以执行以下操作: #import healpy as hp #import astropy.io.fits as pyfits #
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 已关闭10 年前。 Improve
我们正在构建一个与其他系统有多个集成接触点的应用程序。我们有效地使用 Unity 来满足我们所有的依赖注入(inject)需求。整个业务层是用接口(interface)驱动的方法构建的,实际实现在应用
我得到了 MKMapView 和一些注释。我使用下一个代码来显示所有注释: NSArray *coordinates = [self.mapView valueForKeyPath:@"annotat
我在一家托管公司工作,我们经常收到安装、新域、滞后修复等方面的请求。为了大致了解仍然开放的内容,我决定制作一个非常简单的票务系统。我有一点 php 知识和一点 MySQL 知识。目前,我们将根据客户的
我想向我的 UITableView 添加背景图像,它适合 UI,还具有导航 Controller 和工具栏。在那种情况下,我没有找到适合 iPhone 和 iPad 不同屏幕的 tableview 的
我是一名优秀的程序员,十分优秀!