javascript - 使用变换在窗口上居中元素
问题描述
我试图在单击卡片元素时将其居中,以突出显示它并使用 CSS 转换将其与其他卡片分开。我知道 CSS 变换是相对于元素的位置的,但我必须使用变换而不是顶部/左侧以避免重新定位其他卡片。我尝试使用 JavaScript 计算正确的偏移量,如下所示:
const cardRect = cardElement.getBoundingClientRect();
const offsetX = window.innerWidth / 2 - cardRect.x - cardRect.width / 2;
const offsetY = window.innerHeight / 2- cardRect.y - cardRect.height / 2;
然而这并没有奏效,因为边界客户端矩形一直在变化,因为我在卡片悬停时有一个比例(1.1)。
那么如何将点击的卡片移动到中心,而不抵消所有其他卡片呢?
这些卡片在 HTML 中是这样创建的:
<div class='container'>
<div class='movie'>
<img :src='/images/1.png'>
<h3>Harry Potter and the Sorcerer's Stone</h3>
</div>
<div class='movie'>
<img :src='/images/2.png'>
<h3>Harry Potter and the Chamber of Secrets</h3>
</div>
<div class='movie'>
<img :src='/images/3.png'>
<h3>Harry Potter and the Prisoner of Azkaban</h3>
</div>
etc...
</div>
一切的风格都是这样的:
.container {
display: flex;
flex-flow: row wrap;
}
.movie {
width: min-content;
flex: 1;
}
.movie:not(.selected-movie):hover { /* .selected-movie is a class applied to the clicked card */
transform: scale(1.1);
box-shadow: 10px 10px 32px 0px rgba(0,0,0,0.4),
-10px -10px 32px 0px rgba(0,0,0,0.4);
}
.selected-movie {
transform: translate(offsetX, offsetY); /* Here are the offsets needed */
flex: 0;
display: grid;
grid-template-areas:
'poster title'
'poster description';
}
这是一个显示问题的 JSFiddle:https ://jsfiddle.net/u6tpbjna/5/
解决方案
当点击的电影被选中时,你的一些其他 CSS 样式.selected-movie
会丢弃未选择的卡片样式,所以我暂时注释掉了这些样式。无论如何,我相信这应该回答您询问的关于在 CSS 中使用这些偏移量的问题。
这是使用 CSS 变量的绝佳机会,您可以使用 JavaScript 在页面加载和窗口调整大小时设置这些变量。从那里开始,其他一切都可以在 CSS 中完成。
见下文:
const cards = Array.from(document.querySelectorAll('.movie'));
const setCardOffsets = () => {
for (card of cards) {
const cardRect = card.getBoundingClientRect();
const cardOffsetX = window.innerWidth / 2 - cardRect.x - cardRect.width / 2;
const cardOffsetY = window.innerHeight / 2- cardRect.y - cardRect.height / 2;
card.style.setProperty('--offset-x', cardOffsetX + "px");
card.style.setProperty('--offset-y', cardOffsetY + "px");
}
}
setCardOffsets();
window.onresize = setCardOffsets;
document.addEventListener('click', e => {
if (e.target && e.target?.matches('.movie, .movie *')) {
const clickedCard = e.target.matches('.movie') ? e.target : e.target.closest('.movie');
if (clickedCard.classList.contains('selected-movie')) {
clickedCard.classList.remove('selected-movie');
return;
}
cards.forEach(card => card.classList.remove('selected-movie'));
clickedCard.classList.add('selected-movie');
}
});
.container {
display: flex;
flex-flow: row wrap;
}
.movie {
transform: scale(1) translate(0px, 0px);
width: min-content;
flex: 1;
position: relative;
transition: all 0.2s ease-out;
}
.movie:not(.selected-movie):hover {
transform: scale(1.1) translate(0px, 0px);
box-shadow: 10px 10px 32px 0px rgba(0,0,0,0.4),
-10px -10px 32px 0px rgba(0,0,0,0.4);
z-index: 2;
}
.selected-movie {
transform: scale(1.1) translate(var(--offset-x), var(--offset-y));
/*flex: 0;
display: grid;
grid-template-areas:
'poster title'
'poster description';*/
z-index: 1;
}
<div class='container'>
<div class='movie'>
<img src='/images/1.png'>
<h3>Harry Potter and the Sorcerer's Stone</h3>
</div>
<div class='movie'>
<img src='/images/2.png'>
<h3>Harry Potter and the Chamber of Secrets</h3>
</div>
<div class='movie'>
<img src='/images/3.png'>
<h3>Harry Potter and the Prisoner of Azkaban</h3>
</div>
</div>
我希望这有帮助!如果您对我的实施有任何疑问,请告诉我。
推荐阅读
- flutter - 在 Gitlab 上为 Flutter 设置 CI
- python - 如何从网站列表中抓取电子邮件和电话号码?
- java - 安排短信
- python - 请检查有关“sort_values”的错误消息
- c++ - 模板基类函数成员的别名
- python - 我的 TCP 服务器只发送 b' ' 而不是腌制数据
- process - 进程数
- machine-learning - 如何将数据集识别为时间序列数据?
- javascript - 虽然 this.state 是一个 Javascript 对象,但为什么即使在将具有数据的状态传递给它之后状态为 null?
- yii2 - Yii2 : 在 appasset 中切换生产和开发版本脚本