如何实现目标区域根据容器自适应展示?

336 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

前言

当我实现可视化系统的预览功能时,我想要用户配置的舞台不管是1920*1080,还是1440*900等不同的尺寸,都能自适应当前用户预览的设备尺寸显示。如何优雅的实现呢?

换句话说就是保持用户设定的舞台长宽比例不变的情况下, 在预览时自适应当前设备来展示。

需要满足两个基本需求:

  1. 最大限度利用当前设备的显示(缩放到目标尺寸)
  2. 保证展示区域在屏幕中心

具体实现的目标效果就是下面这样:

1、舞台尺寸:820 * 900

image.png

2、舞台尺寸: 1920 * 900 image.png

实现思路

想要最大限度利用当前屏幕,并且能够完全显示舞台上的内容,那么就需要找到一个合适的比例,对主舞台进行缩放。

获取放缩比例

父容器宽高: parentWidth, parentHeight 舞台实际宽高: width, height

width / parentWidth, height / parentHeight, 二者取较大值,我们就能得到合适的缩放比例。

this.scale = Math.max(width / parentWidth, height / parentHeight)

因为取较大值,才能保证舞台的长宽中较大的那个正好撑满屏幕。 (把容器想象成正方形就很好理解了)

实现平移到屏幕中央

对舞台放缩之后,正常来讲舞台仍然处于外层容器的正中心,但是这样其实并不是我们想要的效果。直接看图:

image.png

因为原来的舞台尺寸假如是 2000 * 1000, 现在缩放到 0.5 倍, 现在的舞台确实缩放到了原舞台的中心, 但是并没有在我们屏幕显示的中心, 我们需要使它向上向左偏移黄色箭头的距离。

这个距离如何计算呢?

  • 相比原来,缩小到了 scale 倍, 就是缩小了 (1 - scale) 倍, 那么左右上下各个方向空出来的大小就是 (1 - scale) / 2 倍, 注意这里的倍数是相对舞台原尺寸的。 所以偏移量应为: (1 - scale) / 2 * width , 转换成百分比(这里的百分比需要根据目前的尺寸来计算哦~), ((1 - scale) / 2 * width) / (width * scale) * 100 => (1 / scale - 1) / 2 * 100。 因为向左移动应该是负值, 所以再取一下负。 最后得到:
transform: `scale(${this.scale}) translate(${((1 - 1 / this.scale) / 2) * 100}%, ${
          ((1 - 1 / this.scale) / 2) * 100
        }%)`,

image.png

niceeee~, 我们已经成功将舞台移到父容器的左上位置了。 下面一步,就可以转换成 div在父容器居中显示 的问题了。

那这问题还不是手拿把掐啊!

方案一: flex大法!

父容器设置:

.screen-content__wrap {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;

image.png

想必黄色区域这块你应该猜到是什么了吧,就是我们原舞台区域被缩放空出来的那部分,所以我们居中的是原舞台的区域大小。

这个方案不太合适。

方案二: position 50% + 偏移 -50%

.main-screen {
    position: absolute;
    top: 50%;
    left: 50%;
  }

然后我们给之前计算的偏移量 - 50%

transform: `scale(${this.scale}) translate(${((1 - 1 / this.scale) / 2) * 100 - 50}%, ${
          ((1 - 1 / this.scale) / 2) * 100 - 50
        }%)`,

image.png

这样就实现了 缩放并居中 的需求了!

另一个思路

基于flex居中,其实还有一个思路, 不调整主舞台的偏移,直接flex居中,这时候肯定会以原始舞台区域居中显示, 这时候如何消除左上的偏移量呢? 我觉得可以通过父容器的 -margin 来试试。

但是发现其实flex布局会以当前舞台区域居中,直接打到了我们的理想效果!

image.png

意外收获,这样代码逻辑又简洁了不少~

总结

通过 父子容器的比值 确定合适的缩放比例, 然后通过translate偏移实现舞台居中。

通过 Flex 实现舞台居中算是写文章复盘的意外之喜了~ 感谢掘金哈哈哈

更文不易,觉得对你有帮助可以点个赞支持一下作者!感恩~