我想将“固定”元素绝对定位在背景图像上方。无论宽高比如何,它们都必须位于图像内容的完全相同部分之上。该图像具有适合对象:封面和 16:9 的固有纵横比,因此对于较低的纵横比,例如4:3,图像的左右两侧将被裁剪掉。因此,位于左侧:30% 的图钉现在将位于图像的不同部分上方。
这是当前设置的简化版本:
我有一个包含图像的 div:
<body>
<div class="pin-container">
<img src="./test.jpg" class="main-image"/>
</div>
</body>
在我的 JS 中,引脚被添加到“引脚容器”div 中:
const pins = [
{
xPercent: 30,
yPercent: 50,
text: 'Pin A',
},
{
xPercent: 80,
yPercent: 20,
text: 'Pin B',
},
{
xPercent: 50,
yPercent: 50,
text: 'Pin C',
},
];
const pinContainer = document.querySelector('.pin-container');
pins.forEach((pinDetails) => {
const pin = document.createElement('div');
pin.className = 'pin';
const pinText = document.createElement('p');
pinText.className = 'pin-text';
pinText.innerText = pinDetails.text;
pin.appendChild(pinText);
pin.style.left =
pinDetails.xPercent *
(window.innerWidth / window.innerHeight / (16 / 9)) +
'%';
pin.style.top = pinDetails.yPercent + '%';
pinContainer.appendChild(pin);
});
CSS 规定 img 元素和 pin-container div 都应该占据整个屏幕,pin 元素绝对位于顶部:
.pin-container {
height: 100vh;
width: 100vw;
position: relative;
}
.main-image {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
object-position: 75%;
}
.pin {
position: absolute;
z-index: 1;
background-color: white;
padding: 10px;
border-radius: 50%;
}
问题在于我尝试在 JS 中使用的公式 - 仅获取纵横比的差异并将 xPercent 值乘以该差异是不够的。这样做会同等地影响所有引脚 - 如果屏幕纵横比为 4:3,则对于 xPercent 为 30:
的引脚,公式的工作原理如下pinDetails.xPercent * (window.innerWidth / window.innerHeight / (16 / 9)) 30 * (4/3 / (16/9)) 30 * (1.33.../1.77...) 30*0.75 = 22.5%
正如应该的那样,“left”属性的值会减小,将图钉进一步推向屏幕左侧,并正确考虑到被裁剪的图像的左侧。
但是,这同样适用于所有引脚,无论其位置如何。因此,xPercent 为 80 的图钉的左侧属性也会减少,从而将其进一步推向左侧。但在这种情况下,因为图像具有 object-position: center,所以图像的右侧也会被裁剪掉,事实上 left: 80% 的 pin 应该增加其 left 属性,将其进一步推向正确地解释了被剪掉的图像的右侧。
据我所知,这需要在一条曲线上 - 50% 的引脚应该保持其左侧值不变,因为图像的中心将始终位于同一位置,并且接近 50% 的引脚应该他们留下的财产变化很小。当引脚接近 0% 时,纵横比的差异应越来越降低其左值,而当引脚接近 100% 时,其左值应越来越高。
我无法弄清楚的是,究竟需要如何改变公式才能实现这一点,或者我是否只是错误地处理了整个问题,并且有一种更简单的方法来实现我想要的效果。
为了加分 - 图像的重要内容实际上聚集在右侧,所以我理想情况下希望设置 .main-image object-position: 75%。但这似乎给问题增加了一层额外的复杂性,因此最好先处理居中图像!
任何帮助将不胜感激!!
不确定这是否是您所需要的,但我想出了一个更简单的解决方案:我将缩放和居中应用于包含地图和标记的父元素。这样标记将始终保持在正确的位置。
在此示例中,图像中的字母 O 和字母 D 上应该有一个标记。如果您调整窗口大小,标记将保持在原位。
一个问题是标记也会随着图像缩放,我通过在放置标记时“反向缩放”标记来解决这个问题。
https://jsfiddle.net/xgLp48n0/8/
const container = document.querySelector("#container")
const map = document.querySelector("#map")
const img = document.querySelector("img")
let scale
function cover() {
let viewW = container.getBoundingClientRect().width
let viewH = container.getBoundingClientRect().height
let imgW = img.naturalWidth
let imgH = img.naturalHeight
scale = Math.max((viewW / imgW), (viewH / imgH))
let xdiff = (viewW / 2) - (imgW / 2)
let ydiff = (viewH / 2) - ( imgH / 2)
let offsetX = ((imgW - viewW) * scale) / 2
let offsetY = ((imgH * scale) - viewH) / 2
map.style.transform = `translate(-${offsetX}px, -${offsetY}px) scale(${scale})`
}
function placePin(x, y) {
const pin = document.createElement("div")
pin.classList.add("pin")
map.appendChild(pin)
pin.style.transform = `translate(${x}px, ${y}px) scale(${1/scale})`
}
cover()
placePin(840, 1020)
placePin(1430, 940)
window.addEventListener("resize", (event) => cover());
#container {
width: 80vw;
height: 60vh;
outline: 2px solid blue;
overflow: hidden;
}
.pin {
position: absolute;
border-radius: 50%;
background-color: red;
width: 16px;
height: 16px;
}
#img {
position: absolute;
opacity:0.8;
}
#map {
transform-origin: center;
position: relative;
}
<div id="container">
<div id="map">
<div id="img">
<img src="https://images.unsplash.com/photo-1455849318743-b2233052fcff?q=80&w=2669&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" >
</div>
</div>
</div>