乐趣区

关于javascript:如何突破浏览器12px限制

目前 Chrome 浏览器仍然没有放开 12px 的限度,但 Chrome 依然是应用人数最多的浏览器。

在笔者开发某个我的项目时突发奇想:如果理论须要 11px 的字体大小怎么办?这在 Chrome 中是实现不了的。对于字体,一开始想到的就是 rem 等非 px 单位。然而 rem 只是为了响应式适配,并不能冲破这一限度。

em、rem 等单位只是为了不同分辨率下展现成果提出的换算单位,常见的库 px2rem 也只是利用了 js 将 px 转为 rem。包含微信小程序提出的rpx 单位也是一样!

这条路走不通,就只剩下一个办法:扭转视觉大小而非理论大小

实践根底

css 中有一个属性:transform: scale();

  • 值的绝对值 >1,就是放大,比方 2,就是放大 2 倍
  • 值的绝对值 0< 值 <1,就是放大,比方 0.5,就是原来的 0.5 倍;
  • 值的正负,负值示意图形翻转。

默认状况下,scale(x, y):以 x / y 轴进行缩放;如果 y 没有值,默认 y==x
也能够离开写:scaleX() scaleY() scaleZ(),离开写的时候,能够对 Z 轴进行缩放

第二种写法:transform: scale3d(x, y, z)该写法是下面的办法的复合写法,后果和下面的一样。

但应用这个属性要留神一点:scale 缩放的时候是以“缩放元素所在空间的中心点”为基准的。
所以如果用在扭转元素视觉大小的场景下,个别还须要利用另一个元素来“复原地位”:

transform-origin: top left;

语法上说,transform-origin 领有三个属性值:

transform-origin: x-axis y-axis z-axis;

默认为:

transform-origin:50% 50% 0;

属性值能够是百分比、em、px 等具体的值,也能够是 top、right、bottom、left 和 center 这样的关键词。作用就是更改一个元素变形的原点。

理论利用

<div class="mmcce__info-r">
  <!-- 一些 html 构造 -->
  <div v-show="xxx" class="mmcce-valid-mj-period" :class="{'mmcce-mh': showStr}" @click="handleShowStr"> <!-- click 中事件管制展现与否 -->
    <div class="mmcce-valid-period-child">{{couponInfo.startTimeFormat}}-{{couponInfo.endTimeFormat}}</div><!-- 父级构造,点击显示上面内容 -->
    <div class="mmcce-valid-pro" ref="mmcceW" :style="{opacity: showStr ? 1 : 0}">
      <!-- 上面内容在前面有解说 -->
      <div class="mmcce-text" 
        v-for="(item, index) in couponInfo.thresholdStr" 
        :key="index" 
        :index="index"
        :style="{height: mTextH[index] +'px'}"
      >{{item}}</div>
    </div>
  </div>
</div>
.mmcce-valid-mj-period {
  max-height: 15px;
  transition: all .2s ease;

  &.mmcce-mh {max-height: 200px;}

  .mmcce-valid-pro {
    display: flex;
    flex-direction: column;
    padding-bottom: 12px;

    .mmcce-text {
      width: 200%;
      font-size: 22px;
      height: 15px;
      line-height: 30px;
      color: #737373;
      letter-spacing: 0;
      transform       : scale(.5);
      transform-origin: top left;
    }
  }
}

.mmcce-valid-period-child {
  position: relative;
  width      : 200%;
  white-space: nowrap;
  font-size  : 22px;
  color      : #979797;
  line-height: 30px;

  transform       : scale(.5);
  transform-origin: top left;

  //xxx
}

能够明确阐明的是,这样的 hack 须要明确规定缩放元素的 height 值!

下面代码中为什么 .mmcce-valid-mj-period 类中要用 max-height?为什么对开展元素中的文字类.mmcce-text 中应用 height
我将类 .mmcce-text 中的 height 去掉后,看下成果:

OK,能够看到,占高没有按咱们想的“被缩放”。影响到了上面的元素地位。

实质上是“视觉大小扭转了但理论大小无变动”。

这一点须要留神,一般来说,给被缩放元素显式设置一个大于等于其 font-size 的高度值即可。

缩放带来的其它问题

可能在很多人应用的场景中是不会思考到这个问题的:被缩放元素限度高度当前如果元素换行那么会呈现文字重叠的景象。

为此,我采纳了在 mounted 生命周期中获取父元素宽度,而后动静计算是否须要换行以及换行的行数,最初用动静 style 从新渲染每一条数据的 height 值。
这里有三点须要留神:

  1. 这里用的是一种取巧的办法:用 每个文字的视觉 font-size 值 * 字符串长度。因为笔者遇到的场景不会呈现问题所以能够这么用。在不确定场景中更举荐用 canvas 或 dom 理论计算每个字符的宽度再做判断(须要晓得文字、字母和数字的宽度是不一样的);
  2. 须要留神一些非凡机型的展现,比方三星的 galaxy fold,这玩意是个折叠屏,它的计算会和个别的屏幕计算的不统一;
  3. 在 vue 生命周期中,mounted 能够操作 dom,但不能获取理论 dom 元素;你能够通过 this.$el 获取元素。但要留神:在这个期间被获取的元素不能用 v-if(即:必须存在于虚构 tree 中)。这也是下面代码中笔者应用v-showopacity的起因。

对于第三点,这里有个机会问题。比方刚进入页面时要展现弹窗,弹窗是一个组件。那你在 index.vue 中是获取不到这个组件的。(这个和 v-if 还是 v-show 没有关系)然而你能够将比方 header 也拆分进去,而后在 header 组件的 mounted 中去调用弹窗组件暴露出的办法。

mounted(){
  let thresholdStr = this.info.dropDownTextList;
  let minW = false;
  if(this.$el.querySelector('.mmcce-valid-pro').clientWidth < 140) { // 以 iPhone5 位准,再小于其中元素宽度的的机型就要做非凡解决了
    minW = true
  }
  let mmcw = this.$el.querySelector('.mmcce-valid-pro').getBoundingClientRect().width;

  let mmch = [];

  for(let i=0;i<thresholdStr.length;i++) {
    // 11 是指缩放后文字的 font-size 值,这是一种取巧的形式
    if(11*(thresholdStr[i].length) > mmcw) {if(minW) {mmch[i] = Math.floor((11*thresholdStr[i].length) / mmcw) * 15;
      }else {mmch[i] = Math.floor((11*(thresholdStr[i].length) + 40) / mmcw) * 15;
      }
    }else {mmch[i] = 15;
    }
  }

  this.mTextH = mmch;
},
退出移动版