background-size: cover
覆盖一些文本。问题在于如何保持遮罩层div相对于背景图像的位置不变,而不管窗口大小如何?这里有一个fiddle可以玩耍:http://jsfiddle.net/resting/2yr0b6v7/。因此,我想将单词eye
定位在猫的眼睛上方,而不管窗口大小如何。欢迎使用CSS或JS解决方案。background-size: cover
覆盖一些文本。问题在于如何保持遮罩层div相对于背景图像的位置不变,而不管窗口大小如何?这里有一个fiddle可以玩耍:http://jsfiddle.net/resting/2yr0b6v7/。因此,我想将单词eye
定位在猫的眼睛上方,而不管窗口大小如何。欢迎使用CSS或JS解决方案。编辑: 加入了js备选方案
我曾经相信这可以通过CSS实现,几乎放弃了,但后来我记起了新生的css单位vh和vw......
CSS
html, body{
height: 100%;
width: 100%;
}
.cat {
height: 100%;
width: 100%;
position: relative;
background:url(http://placekitten.com/g/800/400) no-repeat center center / cover;
}
.place-on-eye {
position: absolute;
color: #fff;
margin:0;
}
@media (min-aspect-ratio: 2/1) {
.place-on-eye {
bottom: 50%;
left: 46.875%;
margin-bottom: 1.25vw;
}
}
@media (max-aspect-ratio: 2/1) {
.place-on-eye {
bottom: 52.5%;
left: 50%;
margin-left: -6.25vh;
}
}
说明
左眼的位置大约是375, 190,由于图像居中,我们还需要知道它距离中心有多远,即25, 10。由于图像会覆盖,图像的大小将根据视口的宽高比是否大于背景图像的宽高比而改变。了解这一点后,我们可以使用媒体查询来定位文本。
图像的宽高比为2:1,因此当视口宽高比> 2:1时,我们知道图像的宽度就是视口的宽度,因此<p>
的左侧位置应始终为46.867%(375/800)。底部位置将更加困难,因为图像超出了视口的顶部和底部。我们知道图像处于中心位置,因此首先将<p>
移至中心,然后将其向上推2.5%(10/400)的图像高度。我们不知道图像的高度,但我们知道图像的宽高比以及图像的宽度等于视口的宽度,因此高度的2.5%= 1.25%宽度。因此,我们必须将底部向上移动1.25%的宽度,我们可以通过设置margin-bottom:1.25vw
来实现。顺便说一句,在这种情况下,我们可以不使用vw
,因为填充始终是相对于宽度计算的,因此我们可以设置padding-bottom:1.25%
,但是在下一个情况中无法工作,即必须相对于高度定位左侧时。
当宽高比<2:1时,情况类似。图像的高度是视口的高度,因此底部位置应始终为52.5%(210/400),左侧的计算方式与上述类似。将其移动到中心,然后将其向后移3.125%(25/800)图像的宽度,该宽度等于图像高度的6.25%,该高度等于视口高度,因此margin-left:-6.25vh
。
希望这样做是正确的,并且能够帮助您!
JS替代方案
这里有一个使用js的替代方案。它使用了一些功能,例如forEach和bind,这可能会根据您需要让其在旧浏览器上运行的程度而导致问题,但它们很容易被替换。使用js,您可以直接计算背景图像的缩放尺寸,从而使定位更加容易。虽然这不是最优雅的代码,但是看下面:
//elem: element that has the bg image
//features: array of features to mark on the image
//bgWidth: intrinsic width of background image
//bgHeight: intrinsic height of background image
function FeatureImage(elem, features, bgWidth, bgHeight) {
this.ratio = bgWidth / bgHeight; //aspect ratio of bg image
this.element = elem;
this.features = features;
var feature, p;
for (var i = 0; i < features.length; i++) {
feature = features[i];
feature.left = feature.x / bgWidth; //percent from the left edge of bg image the feature resides
feature.bottom = (bgHeight - feature.y) / bgHeight; //percent from bottom edge of bg image that feature resides
feature.p = this.createMarker(feature.name);
}
window.addEventListener("resize", this.setFeaturePositions.bind(this));
this.setFeaturePositions(); //initialize the <p> positions
}
FeatureImage.prototype.createMarker = function(name) {
var p = document.createElement("p"); //the <p> that acts as the feature marker
p.className = "featureTag";
p.innerHTML = name;
this.element.appendChild(p);
return p
}
FeatureImage.prototype.setFeaturePositions = function () {
var eratio = this.element.clientWidth / this.element.clientHeight; //calc the current container aspect ratio
if (eratio > this.ratio) { // width of scaled bg image is equal to width of container
this.scaledHeight = this.element.clientWidth / this.ratio; // pre calc the scaled height of bg image
this.scaledDY = (this.scaledHeight - this.element.clientHeight) / 2; // pre calc the amount of the image that is outside the bottom of the container
this.features.forEach(this.setWide, this); // set the position of each feature marker
}
else { // height of scaled bg image is equal to height of container
this.scaledWidth = this.element.clientHeight * this.ratio; // pre calc the scaled width of bg image
this.scaledDX = (this.scaledWidth - this.element.clientWidth) / 2; // pre calc the amount of the image that is outside the left of the container
this.features.forEach(this.setTall, this); // set the position of each feature marker
}
}
FeatureImage.prototype.setWide = function (feature) {
feature.p.style.left = feature.left * this.element.clientWidth + "px";
feature.p.style.bottom = this.scaledHeight * feature.bottom - this.scaledDY + "px"; // calc the pixels above the bottom edge of the image - the amount below the container
}
FeatureImage.prototype.setTall = function (feature) {
feature.p.style.bottom = feature.bottom * this.element.clientHeight + "px";
feature.p.style.left = this.scaledWidth * feature.left - this.scaledDX + "px"; // calc the pixels to the right of the left edge of image - the amount left of the container
}
var features = [
{
x: 375,
y: 190,
name: "right eye"
},
{
x: 495,
y: 175,
name: "left eye"
},
{
x: 445,
y: 255,
name: "nose"
},
{
x: 260,
y: 45,
name: "right ear"
},
{
x: 540,
y: 20,
name: "left ear"
}
];
var x = new FeatureImage(document.getElementsByClassName("cat")[0], features, 800, 400);
vw
vh
的替代方案?我猜如果我们能弄清楚背景图像的调整方式,应用相同的算法应该可以使叠加层与背景图像正确缩放。 - resting$(function() {
function position_spot() {
w = $(window).width();
h = $(window).height();
wR = w/h;
// Point to place overlay based on 1397x1300 size
mT = 293;
mL = -195;
imgW = 1397;
imgH = 1300;
imgR = imgW/imgH;
tR = mT / imgH; // Top ratio
lR = mL / imgW; // Left ratio
wWr = w / imgW; // window width ratio to image
wHr = h / imgH; // window height ratio to image
if (wR > imgR) {
// backgroundimage size
h = imgH * wWr;
w = imgW * wWr;
} else {
h = imgH * wHr;
w = imgW * wHr;
}
$('.overlay-spot').css({
'margin-top': h * tR,
'margin-left': w * lR
});
}
$(window).resize(function() {
position_spot();
});
position_spot();
});
background-position:center center;
background-size:cover;
背景图像的中心仍应在屏幕中心 - 这是一种常数,因此只需尝试使用您的p.place-on-eye
进行相同的操作。
.place-on-eye {
...
top: 50%;
left: 50%;
}
现在段落的左上角位于屏幕中心,如果你还添加宽度和高度属性,你实际上可以将元素中心定位到屏幕中心。就像这样:
.place-on-eye {
...
width:50px;
height:50px;
text-align:center /* to make sure the text is center according to elements width */
top: 50%;
left: 50%;
margin:-25px 0 0 -25px;
}
现在,p.place-on-eye
的中心位于您屏幕的正中央,就像您背景图像的中心一样。要将其移到猫眼上,只需根据需要偏移左和上边距即可。
因此,类似于 margin:-27px 0 0 -60px;
的东西应该可以解决问题。