计算旋转后长方体阴影的位置

Calculate position of box-shadow after rotation

本文关键字:位置 阴影 长方体 旋转 计算      更新时间:2023-09-26

使用CSS在旋转的元素上放置阴影时,阴影取决于元素的旋转。这里有一个例子:

.box {
  width: 200px;
  height: 100px;
  position: absolute;
  left: 20px;
  background-color: #BBF;
  -moz-box-shadow: 10px 10px 5px #888;
  -webkit-box-shadow: 10px 10px 5px #888;
  box-shadow: 10px 10px 5px #888;
}
#box1 {
  top: 20px;
}
#box2 {
  top: 170px;
  -webkit-transform: rotate(20deg);
  -moz-transform: rotate(20deg);
  -o-transform: rotate(20deg);
  -ms-transform: rotate(20deg);
}
#box3 {
  top: 80px;
  left: 250px;
  -webkit-transform: rotate(120deg);
  -moz-transform: rotate(120deg);
  -o-transform: rotate(120deg);
  -ms-transform: rotate(120deg);
}
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="box3" class="box"></div>

是否可以计算旋转后阴影应该落在哪里,以便阴影看起来来自所有元素上的同一光源?我假设我必须使用javascript或服务器端,这很好。

为了在所有元素上复制相同的阴影,无论是否旋转,我最终使用了以下内容:

var shadowOffset = 13;
var shadowX = Math.round(Math.sin(angle * (Math.PI / 180)) * shadowOffset, 2);
var shadowY = Math.round(Math.cos(angle * (Math.PI / 180)) * shadowOffset, 2);

适合这样的框阴影参数:

$("#box2").css({ "box-shadow": shadowX + "px " + shadowY + "px 5px #888" });

下面是一个例子:http://jsfiddle.net/3Ybr7/1/

它并不完美,尤其是在阴影位于两个像素之间的小元素上,但它有点奏效。

基于这里的答案:在旋转时保持长方体阴影方向一致,您可以在CSS中使用变换和伪元素来实现这一点
关键是变换原点在链式变换中随元素移动。以下是所有元素阴影方向相同的示例:

.box {
  width: 200px; height: 100px;
  position: absolute;
  left: 20px;
}
.box:before {
  content: '';
  position: absolute;
  top: 5px; left: 5px;
  width: 190px; height: 90px;
  background-color: #888;
  box-shadow: 0px 0px 5px 5px #888;
}
.box:after {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background-color: #BBF;
}
#box1 { top: 20px; }
#box1:before { transform: translate(10px, 10px); }
#box2 { top: 170px; transform: rotate(20deg); }
#box2:before { transform: rotate(-20deg) translate(10px, 10px) rotate(20deg); }
#box3 { top: 80px; left: 250px; transform: rotate(120deg); }
#box3:before { transform: rotate(-120deg) translate(10px, 10px) rotate(120deg); }
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="box3" class="box"></div>

我编写了一个convertOffset函数,它获取x和y阴影坐标和度数,并返回新的x/y坐标以匹配旋转。这不仅适用于任何阴影位置,而且还支持插入阴影。请尝试编辑以下代码段并尝试使用不同的值。

var xOffset = -4;
var yOffset = 5;
var blurSpreadColor = '4px 0 #222';
var inset = false;
for (var i = 1; i < 6; i++) {
  var el = document.getElementById('div' + i);
  var degrees = (i - 1) * 26;
  var offset = convertOffset(xOffset, yOffset, degrees);
  el.style.transform = 'rotate(' + degrees + 'deg)';
  el.style.boxShadow = (inset ? 'inset ' : '') + offset[0] + 'px ' + offset[1] + 'px ' + blurSpreadColor;
}
function convertOffset(x, y, deg) {
  var radians = deg * Math.PI / 180;
  var sin = Math.sin(radians);
  var cos = Math.cos(radians);
  return [
    Math.round((x * cos + y * sin) * 100) / 100,
    Math.round((-x * sin + y * cos) * 100) / 100
  ];
}
.box {
  width: 100px;
  height: 50px;
  background: lightblue;
  margin: 35px 8px;
  display: inline-block;
}
<div class="box" id="div1"></div>
<div class="box" id="div2"></div>
<div class="box" id="div3"></div>
<div class="box" id="div4"></div>
<div class="box" id="div5"></div>