我想拥有CSS图像封面的功能,它可以填充容器元素,但不改变图像的比例;容器元素的视口中无法容纳的所有内容都将超出容器并被隐藏。
但是,这在CSS中的工作方式(根据我到目前为止的使用方式)是将其定位在图像的中心。
我想说“将覆盖锚点设置为图像的x = 150和y = 375”。想知道如何做到这一点。这样,我可以在图像上选择一个点,并将其作为封面的中心点。
答案 0 :(得分:2)
您需要将background-position
用于背景图像,或将object-position
用于具有objec-fit
的图像
您需要通过将坐标除以图像尺寸并乘以100%来计算正确的值
background-position: calc(131 / 200 * 100%) calc(66 / 200 * 100%);
/* ^^^ ^^^ ^^ ^^^
||| ||| || |||
||| ||| || image height
||| ||| y coordinate
||| image width
x coordinate
*/
单击按钮,您将触发动画,这些动画表明焦点位于这些图像中的鸟上
document.addEventListener('click', e => {
if (e.target.nodeName.toLowerCase() == 'button') {
document.getElementById(e.target.dataset.id).classList.toggle('animate')
}
})
.container {
display: inline-block;
background-image: url(https://picsum.photos/id/990/200/200);
background-size: cover;
background-position: calc(131 / 200 * 100%) calc(66 / 200 * 100%);
transition: all 1s ease-in-out;
}
img {
-o-object-fit: cover;
object-fit: cover;
-o-object-position: calc(131 / 200 * 100%) calc(66 / 200 * 100%);
object-position: calc(131 / 200 * 100%) calc(66 / 200 * 100%);
transition: all 1s ease-in-out;
}
.animate[data-property=width] {
width: 5px !important;
}
.animate[data-property=height] {
height: 5px !important;
}
<span id="container-1" data-property="width" class="container" style="width:200px; height:100px"></span>
<span id="container-2" data-property="height" class="container" style="width:100px; height:200px"></span>
<img id="image-1" data-property="width" src="https://picsum.photos/id/990/200/200" alt="" style="width:200px; height:100px">
<img id="image-2" data-property="height" src="https://picsum.photos/id/990/200/200" alt="" style="width:100px; height:200px">
<br>
<button data-id="container-1">Animate</button>
<button data-id="container-2">Animate</button>
<button data-id="image-1">Animate</button>
<button data-id="image-2">Animate</button>
答案 1 :(得分:0)
由于background-size: cover
本身的工作方式,使用cover
极大地限制了可以居中的坐标数量。
background-size: cover
放大(或缩小)图像,以便始终显示尽可能多的图像,同时仍能覆盖整个容器。
让我们直观地看一些示例:
在案例1中,需要放大图像,以使图像的width
与容器的width
相匹配。
在第2种情况下,需要放大图像,以使图像的height
与容器的height
相匹配。
在情况3中,需要缩小图像,以使图像的height
与容器的height
相匹配。
您可能已经注意到,图像将始终始终在一个轴上居中。这意味着您只能使图像在其余轴上居中。此外,只能将落在两个红点之间或红色线(实际上只有1px
宽)上的坐标居中,否则图像将无法覆盖整个容器。
background: cover
是不够的。您需要使用JS。
要设计解决方案,您需要了解...
在花了数小时试图弄清楚这一点之后,我才真正意识到做您想做的事是完全不切实际的,因为所需的中心坐标离原始图像的边缘越近,输出图像将变得无限大。 。找出公式以产生适当比例的输出图像真的很棘手,因为比例也是一个变量。唯一可行的解决方法是通过例如在图像的外部边缘(如边框)周围应用禁区来限制坐标的中心,即该区域中的任何内容都不能或不应该居中。 。所谓边框的宽度将完全取决于图像的分辨率。
这就是我正在从事的工作。我们不欢迎您继续我离开的地方,尽管我必须警告您代码现在很乱。我正在全神贯注于如何在保持封面状态的同时正确缩放和定位图像。数学背景会帮助您节省大量时间。祝你好运。
const
srcImg = document.querySelector('#source-image'),
output = document.querySelector('#output')
let
srcImgWidth, srcImgHeight
const
test = document.querySelector('#test')
window.onload = ()=>{
srcImgWidth = srcImg.width
srcImgHeight = srcImg.height
}
srcImg.onclick = function(e){
const
ctrWidth = output.offsetWidth,
ctrHeight = output.offsetHeight,
compAxisX = ctrWidth / srcImgWidth,
compAxisY = ctrHeight / srcImgHeight,
rect = srcImg.getBoundingClientRect(),
x = e.clientX - rect.left,
y = e.clientY - rect.top
// create cover
if (compAxisX > compAxisY){
//console.log('width grow/shrink to match width')
output.style.backgroundSize = `${ctrWidth}px ${ctrWidth / srcImgWidth * srcImgHeight}px`
} else if (compAxisY > compAxisX) {
//console.log('height grow/shrink to match height')
output.style.backgroundSize = `${ctrHeight / srcImgHeight * srcImgWidth}px ${ctrHeight}px`
} else {
// square in square ???
output.style.backgroundSize = `${ctrWidth}px ${ctrHeight}px`
}
// determine scale of image
const
compAxisX1 = ctrWidth / 2 / x,
compAxisY1 = ctrHeight / 2 / y
let
qtrImplicitViewportX,
qtrImplicitViewportY,
scale
// cover container with implicit viewport
if (compAxisX1 > compAxisY1){
//console.log('width grow/shrink to match width')
qtrImplicitViewportX = ctrWidth / 2
qtrImplicitViewportY = ctrWidth / 2 / x * y
//srcImgWidth / x * scale * srcImgWidth + 'px'
//srcImgHeight / y * scale * srcImgHeight + 'px'
// x / srcImgWidth === qtrImplicitViewportY
newWidth = qtrImplicitViewportX / (x / srcImgWidth)
newHeight = qtrImplicitViewportY / (y / srcImgHeight)
console.log(newWidth, newHeight)
output.style.backgroundSize = `${newWidth}px ${newHeight}px`
output.style.backgroundPosition = '0% 100%'
} else if (compAxisY1 > compAxisX1){
//console.log('height grow/shrink to match height')
//qtrImplicitViewportX = ctrHeight / 2 / y * x
qtrImplicitViewportY = ctrHeight / 2
//srcImgWidth / x * scale * srcImgWidth + 'px'
//srcImgHeight / y * scale * srcImgHeight + 'px'
// x / srcImgWidth === qtrImplicitViewportY
newWidth = qtrImplicitViewportX / (x / srcImgWidth)
newHeight = qtrImplicitViewportY / (y / srcImgHeight)
console.log(newWidth, newHeight)
output.style.backgroundSize = `${newWidth}px ${newHeight}px`
output.style.backgroundPosition = '0% 100%'
} else {
}
test.style.width = newWidth + 'px'
test.style.height = newHeight + 'px'
test.style.bottom = output.getBoundingClientRect().bottom
test.style.left = output.getBoundingClientRect().left
}
#input-container {
padding: 10px;
display: inline-block;
background: grey;
}
#output {
width: 256px;
height: 377px;
resize: both;
position: relative;
overflow: auto;
box-sizing: border-box;
border: solid red 3px;
background-image: url('https://i.postimg.cc/s2PnSDmR/test0.png');
background-size: cover;
background-repeat: no-repeat;
}
#test {
z-index: -1;
width: 256px;
height: 377px;
position: absolute;
transform: translateY(-100%);
background: orange;
background-image: url('https://i.postimg.cc/s2PnSDmR/test0.png');
background-size: cover;
background-repeat: no-repeat;
}
<div id='input-container'>
<div>Click the Image to Center on Click Point</div>
<img id='source-image' src='https://i.postimg.cc/s2PnSDmR/test0.png' />
</div>
<div id='output'></div>
<div id='test'></div>