Image placeholder

使用 JavaScript 适配 iphone X 刘海滚动条

Image placeholder
F2EX 2017-09-29

北京时间9月13日凌晨,苹果召开秋季新品发布会,正式推出旗下首款采用全面屏设计的 iPhone X ,这款手机为异形全面屏设计,也就是所谓的“刘海屏”。然而这个奇怪的“刘海”当然也就成了大家吐槽的点。现实总是要面对,全世界的开发者也尝试使用各种方法来解决这个问题,来看下如何使用 JavaScript 适配 iphone X 的刘海滚动条。

核心代码

HTML
<div class="outer">
<div class="inner">
<ul>
<li>Macoun</li>
<li>McIntosh</li>
<li>Autumn Glory</li>
<li>Opal</li>
<li>Rome</li>
<li>Red Delicious</li>
<li>Golden Delicious</li>
<li>Cameo</li>
<li>Granny Smith</li>
<li>Rainier Gala</li>
<li>SweeTango </li>
<li>Pacific Rose</li>
<li>SnapDragon</li>
<li>Envy</li>
<li>Cameo</li>
<li>Granny Smith</li>
<li>Rainier Gala</li>
<li>SweeTango </li>
<li>Pacific Rose</li>
<li>SnapDragon</li>
<li>Envy</li>
</ul>
<div class="notch"></div>
</div>
</div>
CSS
:root {
  --width: 494px;
  --height: 242px;
  --chrome: 22.5px;
  --outer-border-radius: 25px;
  --thumb-radius: 0px;
}

html {
  box-sizing: border-box;
}

* {
  box-sizing: inherit;
}

body {
  min-height: 100vh;
  display: flex;
  align-items: center;
  background: radial-gradient(turquoise, midnightblue);
  font-weight: lighter;
  font-size: 10px;
}

.outer {
  position: relative;
  margin: 0 auto;
  width: var(--width);
  height: var(--height);
  border-radius: var(--outer-border-radius);
  border: solid 2px buttonface;
  display: flex;
  align-items: center;
  
  background: black;
}

.inner {
  background: white;
/*   position: absolute; */
  margin: 0 auto;
  width: calc(100% - var(--chrome));
  height: calc(100% - var(--chrome));
  border-radius: calc(var(--chrome) - 10px);
  overflow-y: scroll;
  overflow-x: hidden;
}

.notch {
  position: absolute;
  background: black;
  width: 3%;
  height: 60%;
  top: 20%;
  left:calc(var(--chrome)/2);
  border-radius: 0 10px 10px 0;
}

ul {
  padding-left: calc(var(--chrome)/4);
  padding-right: 10px;
  margin: 5px 0;
  overflow: hidden;
}

li {
  list-style: none;
  padding: 5px 5px;
  border-bottom: 1px solid #dadada;
  transform-origin: center left;
}

*::-webkit-scrollbar { 
  width: 5px;
  padding: 100px;
  transform: scalex(10);
}

*::-webkit-scrollbar-thumb {
  border-radius: var(--thumb-radius);
  background-color: #5555;
  padding-right: 5px;
  transform: scalex(10);
}
JavaScript
console.clear();

const THRESH = 10;

const $ = selector => document.querySelector(selector);
const $$ = selector => document.querySelectorAll(selector);

const items = $$("li");
const style = getComputedStyle(document.body);
// const chromeWidth = style.getPropertyValue("--chrome");
const chromeWidth = 22.5;

const setCustomProperty = (property, value) => {
  style.setProperty("--${property}", value);
};

let notchRect = $(".notch").getBoundingClientRect();

window.addEventListener("resize", () => {
  notchRect = $(".notch").getBoundingClientRect();
});

bumpItems();

$(".inner").onscroll = onScroll;

function onScroll(e) {
  window.requestAnimationFrame(bumpItems);
}

function bumpItems() {
  for (let item of items) {
    const itemRect = item.getBoundingClientRect();
    const distFromBottom = itemRect.top - notchRect.bottom;
    const distFromTop = itemRect.bottom - notchRect.top;

    if (Math.abs(distFromTop) < THRESH) {
      item.style.transform = `translateX(${lerp(
        0,
        chromeWidth,
        (distFromTop + THRESH) / (THRESH * 2)
      )}px)`;
    } else if (
      distFromTop > 0 &&
      Math.abs(distFromBottom) > THRESH &&
      distFromBottom < 0
    ) {
      item.style.transform = `translateX(${chromeWidth}px)`;
    } else if (Math.abs(distFromBottom) < THRESH) {
      item.style.transform = `translateX(${lerp(
        chromeWidth,
        0,
        (distFromBottom + THRESH) / (THRESH * 2)
      )}px)`;
    } else {
      item.style.transform = `translateX(0)`;
    }
  }
}

function lerp(v0, v1, t) {
  return v0 * (1 - t) + v1 * t;
}

实际效果


2017-09-29