实现一个手机控制中心

Published on
/
/趣玩前端
<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <title>实现一个手机控制中心</title>
    <style>
      * {
        box-sizing: border-box;
      }

      html {
        color-scheme: dark only;
      }

      body {
        display: grid;
        place-items: center;
        min-height: 100vh;
        background: hsl(0 0% 4%);
      }

      body::before {
        --size: 45px;
        --line: color-mix(in lch, canvasText, transparent 80%);
        content: '';
        height: 100vh;
        width: 100vw;
        position: fixed;
        background: linear-gradient(
              90deg,
              var(--line) 1px,
              transparent 1px var(--size)
            )
            50% 50% / var(--size) var(--size),
          linear-gradient(var(--line) 1px, transparent 1px var(--size)) 50% 50% /
            var(--size) var(--size);
        -webkit-mask: linear-gradient(-20deg, transparent 50%, white);
        mask: linear-gradient(-20deg, transparent 50%, white);
        top: 0;
        transform-style: flat;
        pointer-events: none;
        z-index: -1;
      }

      main {
        display: grid;
        grid-template-columns: repeat(3, calc(var(--slider-height) * 1px));
        gap: 2rem;
      }

      .bear-link {
        color: canvasText;
        position: fixed;
        top: 1rem;
        left: 1rem;
        width: 48px;
        aspect-ratio: 1;
        display: grid;
        place-items: center;
        opacity: 0.8;
      }

      :where(.x-link, .bear-link):is(:hover, :focus-visible) {
        opacity: 1;
      }

      .bear-link svg {
        width: 75%;
      }

      @layer slider {
        .slider {
          position: relative;
          display: grid;
          place-items: center;
          margin: 0 auto;
        }

        .slider label {
          position: absolute;
          width: 1px;
          height: 1px;
          padding: 0;
          margin: -1px;
          overflow: hidden;
          clip: rect(0, 0, 0, 0);
          white-space: nowrap;
          border-width: 0;
        }

        .slider:focus-within,
        .slider:hover {
          --active: 1;
        }

        .slider:has(:focus-visible) {
          outline: 2px solid canvasText;
          outline-offset: 4px;
        }

        .slider [type='range'] {
          width: calc(var(--slider-width) * 1px);
          opacity: 0;
          height: calc(var(--slider-height) * 1px);
        }

        .slider [type='range']:hover {
          cursor: -webkit-grab;
        }

        .slider [type='range']:active {
          cursor: -webkit-grabbing;
        }

        .slider [type='range']:focus-visible {
          outline-offset: 0.25rem;
          outline-color: transparent;
        }

        .slider [type='range']::-webkit-slider-thumb {
          /*     appearance: none; */
          /*     -webkit-appearance: none; */
          height: calc(var(--slider-height) * 1px);
          width: 48px;
          margin-top: 0px;
          opacity: 1;
        }

        .slider [type='range']::-webkit-slider-runnable-track {
          /*   	-webkit-appearance: none; */
          height: calc(var(--slider-height) * 1px);
          background: hsl(10 0% 50% / 0.5);
          /* You need to specify a margin in Chrome */
          /* In Firefox and IE it is automatic */
          /* 	  margin-top: calc(var(--slider-height) * -0.5px); */
        }

        .slider [type='range']::-moz-range-track {
          height: calc(var(--slider-height) * 1px);
          background: hsl(10 0% 50% / 0.5);
          /* 	  margin-top: calc(var(--slider-height) * -0.5px); */
          /* You need to specify a margin in Chrome */
          /* In Firefox and IE it is automatic */
        }

        @supports (animation-timeline: scroll()) {
          @property --slider-complete {
            initial-value: 0;
            syntax: '<number>';
            inherits: true;
          }

          @-webkit-keyframes sync {
            to {
              --slider-complete: 1;
            }
          }

          @keyframes sync {
            to {
              --slider-complete: 1;
            }
          }

          .slider-wrap {
            timeline-scope: --thumb;
            animation: sync both linear reverse;
            animation-timeline: --thumb;
            animation-range: contain;
          }

          .slider [type='range']::-webkit-slider-thumb {
            view-timeline-name: --thumb;
            view-timeline-axis: inline;
          }
        }
      }

      @layer sliders {
        :root {
          --slider-radius: 16;
          --slider-height: 96;
          --slider-width: 214;
          --transition: 0.4s;
          --spring: linear(
            0 0%,
            0.5258 3.83%,
            0.9015 8.01%,
            1.0369 10.27%,
            1.1399 12.68%,
            1.2124 15.28%,
            1.2563 18.13%,
            1.2683 19.76%,
            1.2731 21.51%,
            1.2706 23.41%,
            1.2609 25.51%,
            1.2318 29.22%,
            1.1328 39.11%,
            1.0859 44.55%,
            1.0464 50.71%,
            1.0195 57.21%,
            1.004 63.99%,
            0.9963 72.12%,
            0.9953 83.93%,
            1 100%
          );
          --timing: linear(
            0 0%,
            0.4322 6.7%,
            0.5876 9.63%,
            0.7165 12.53%,
            0.8238 15.53%,
            0.9087 18.63%,
            0.9731 21.89%,
            1.0188 25.4%,
            1.0377 27.67%,
            1.0507 30.11%,
            1.058 32.77%,
            1.0598 35.74%,
            1.0528 41.1%,
            1.0164 56.54%,
            1.004 65.49%,
            0.998 78.52%,
            1 100%
          );
        }

        .slider {
          translate: 0 0;
          width: calc(var(--slider-width) * 1px);
          height: calc(var(--slider-height) * 1px);
          overflow: hidden;
          border-radius: calc(var(--slider-radius) * 1px);
        }

        /* Handling the sun */
        .slider--brightness .slider__indicator {
          pointer-events: none;
          height: 50%;
          aspect-ratio: 1;
          position: absolute;
          left: 12%;
          top: 50%;
          translate: 0 -50%;
          color: hsl(
            45 calc((0 + (var(--slider-complete) * 150)) * 1%)
              clamp(40%, (80 - (var(--slider-complete) * 40)) * 1%, 80%)
          );
          transition: color var(--transition);
          transition-timing-function: var(--timing);
          z-index: 20;
        }

        .slider--brightness .slider__indicator svg {
          scale: clamp(1, (1.75 - (1 * (var(--slider-complete) * 4))), 1.75);
          transition: scale var(--transition);
          transition-timing-function: var(--timing);
        }

        .slider--brightness .slider__indicator svg > path:first-of-type {
          transform-box: fill-box;
          transform-origin: center;
          opacity: clamp(0, calc((var(--slider-complete) * 2) - 0.125), 1);
          scale: clamp(0, calc((var(--slider-complete) * 2) - 0.125), 1);
          transition: opacity var(--transition), scale var(--transition);
          transition-timing-function: var(--timing);
        }

        .slider--brightness .slider__indicator #cut-out path {
          transform-box: fill-box;
          transform-origin: center center;
          translate: calc((25 + (var(--slider-complete) * 200)) * 1%)
            calc((25 + (var(--slider-complete) * 200)) * 1%);
          transition: translate var(--transition);
          transition-timing-function: var(--timing);
        }

        /* Handling the volume */
        .slider--volume .slider__indicator {
          pointer-events: none;
          height: 35%;
          aspect-ratio: 1;
          position: absolute;
          left: 16%;
          top: 50%;
          translate: 0 -50%;
          rotate: 90deg;
          color: hsl(
            190 calc((0 + (var(--slider-complete) * 150)) * 1%)
              clamp(40%, (80 - (var(--slider-complete) * 40)) * 1%, 80%)
          );
          transition: color var(--transition);
          transition-timing-function: var(--timing);
          z-index: 20;
        }

        /* Muted */
        .slider--volume .slider__indicator path:nth-of-type(3) {
          transform-box: fill-box;
          transform-origin: center;
          translate: 25% 0;
          scale: clamp(0, 1.25 - (var(--slider-complete) * 100), 2);
          transition: scale var(--transition) var(--timing);
        }

        /* Should come in at 25% and 75% */
        .slider--volume .slider__indicator path:nth-of-type(2) {
          transform-box: fill-box;
          transform-origin: center;
          translate: 25% 0;
          opacity: clamp(0, ((var(--slider-complete) - 0.25) * 100), 2);
          transition: opacity var(--transition) var(--timing);
        }

        .slider--volume .slider__indicator path:nth-of-type(4) {
          transform-box: fill-box;
          transform-origin: center;
          translate: 25% 0;
          opacity: clamp(0, ((var(--slider-complete) - 0.75) * 100), 2);
          transition: opacity var(--transition) var(--timing);
        }

        /* Handling the Intensity */
        .slider--intensity .slider__indicator {
          pointer-events: none;
          height: 50%;
          aspect-ratio: 1;
          position: absolute;
          left: 14%;
          top: 50%;
          translate: 0 -50%;
          rotate: 90deg;
          transition-timing-function: var(--timing);
          z-index: 20;
        }

        .slider--intensity .slider__indicator svg {
          overflow: visible !important;
          position: absolute;
          left: 0;
          bottom: 0;
        }
        .slider--intensity .slider__indicator g {
          transform-box: fill-box;
          transform-origin: 50% 50%;
          transform: scale(calc(1.5 - (var(--slider-complete) * 0.5)));
        }

        .slider--intensity .slider__indicator path:nth-of-type(1) {
          color: hsl(
            0 0% clamp(50%, (var(--slider-complete) * 100) * 1%, 100%)
          );
        }

        .slider--intensity .slider__indicator path:nth-of-type(2) {
          transform-box: fill-box;
          transform-origin: 50% 100%;
          scale: var(--slider-complete);
          opacity: var(--slider-complete);
        }
      }

      div.tp-dfwv {
        width: 280px;
      }

      [data-disguise='false'] {
        .slider__track,
        .slider__indicator {
          display: none;
        }

        .slider {
          box-shadow: none;
          border-radius: 0;
          background: transparent;
          overflow: visible;
          display: flex;
          gap: 1rem;

          label {
            position: static;
            width: -webkit-fit-content;
            width: -moz-fit-content;
            width: fit-content;
            height: -webkit-fit-content;
            height: -moz-fit-content;
            height: fit-content;
            padding: 0;
            margin: 0;
            overflow: visible;
            clip: unset;
            white-space: nowrap;
            border-width: 0;
            font-family: sans-serif, system-ui, -apple-system,
              BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
              'Open Sans', 'Helvetica Neue', sans-serif;
          }

          input {
            opacity: 1;
            width: 100%;
          }

          [type='range']::-webkit-slider-thumb {
            height: auto;
            width: auto;
          }

          [type='range']::-webkit-slider-runnable-track {
            background: transparent;
            height: auto;
          }

          [type='range']::-moz-range-track {
            background: transparent;
            height: auto;
          }
        }
      }

      [data-spring='true'] .track {
        transition: scale var(--spring) 0.625s;
      }

      [data-spring='true'] .slider__indicator {
        transition: transform var(--spring) 0.625s;
      }

      [data-origin='bottom'] :is(.track) {
        transform-origin: 0 50%;
      }
      [data-origin='top'] :is(.track) {
        transform-origin: 100% 50%;
      }
      [data-enhance='true'] :is(.track) {
        scale: calc(
            1 + (clamp(0, var(--stretch), 1) * var(--stretch-ratio, 0.2))
          )
          calc(
            1 -
              (clamp(0, var(--stretch), 1) * (var(--stretch-ratio, 0.2) * 0.5))
          );
        /* transition: all 0.2s; */
      }

      .container {
        position: relative;
      }

      .slider-wrap {
        position: absolute;
        timeline-scope: --thumb;
        height: calc(var(--slider-height) * 1px);
        width: calc(var(--slider-width) * 1px);
        rotate: -90deg;
        top: 50%;
        left: 50%;
        translate: -50% -50%;
      }

      [data-enhance='true'] .slider__indicator {
        transform: scale(
          calc(1 + clamp(0, var(--stretch), 1) * var(--stretch-ratio, 0.2))
        );
      }

      .slider__track {
        background: color-mix(in lch, canvasText, canvas 80%);
        pointer-events: none;
        height: calc(var(--slider-height) * 1px);
        width: calc(var(--slider-width) * 1px);
        position: absolute;
        inset: 0;
        border-radius: calc(var(--slider-radius) * 1px);
        -webkit-clip-path: inset(
          0 0 0 0 round calc(var(--slider-radius) * 1px)
        );
        clip-path: inset(0 0 0 0 round calc(var(--slider-radius) * 1px));
        --perfect-shadow: 0px 0px 0px 1px hsl(0 0% 0%),
          -9px 9px 9px -0.5px hsl(0 0% 0% / 0.5),
          -18px 18px 18px -1.5px hsl(0 0% 0% / 0.5),
          -37px 37px 37px -3px hsl(0 0% 0% / 0.5),
          -75px 75px 75px -6px hsl(0 0% 0% / 0.5),
          -150px 150px 150px -12px hsl(0 0% 0% / 0.5);
        box-shadow: var(--perfect-shadow);
      }

      .track__progress {
        width: 100%;
        height: 100%;
        background: color-mix(
          in lch,
          canvasText,
          canvas clamp(50%, (70 - (var(--slider-complete) * 20)) * 1%, 70%)
        );
        transform-origin: 0 50%;
        scale: var(--slider-complete) 1;
        transition: scale var(--transition), background var(--transition);
        transition-timing-function: var(--timing);
        z-index: -1;
      }
    </style>
  </head>
  <body>
     <main>
      <div class="container">
        <div class="slider-wrap">
          <div class="slider__track track">
            <div class="track__progress"></div>
          </div>
          <div class="slider slider--brightness">
            <label for="brightness" class="sr-only">Brightness</label>
            <input id="brightness" type="range" min="0" max="100" value="86" />
            <div class="slider__indicator">
              <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <defs>
                  <mask id="cut-out">
                    <rect width="100%" height="100%" fill="white"/>
                    <path
                      d="M7.5 12C7.5 10.8065 7.97411 9.66193 8.81802 8.81802C9.66193 7.97411 10.8065 7.5 12 7.5C13.1935 7.5 14.3381 7.97411 15.182 8.81802C16.0259 9.66193 16.5 10.8065 16.5 12C16.5 13.1935 16.0259 14.3381 15.182 15.182C14.3381 16.0259 13.1935 16.5 12 16.5C10.8065 16.5 9.66193 16.0259 8.81802 15.182C7.97411 14.3381 7.5 13.1935 7.5 12Z"
                      fill="black"
                    />

                </defs>
                <path
                  d="M12 2.25C12.1989 2.25 12.3897 2.32902 12.5303 2.46967C12.671 2.61032 12.75 2.80109 12.75 3V5.25C12.75 5.44891 12.671 5.63968 12.5303 5.78033C12.3897 5.92098 12.1989 6 12 6C11.8011 6 11.6103 5.92098 11.4697 5.78033C11.329 5.63968 11.25 5.44891 11.25 5.25V3C11.25 2.80109 11.329 2.61032 11.4697 2.46967C11.6103 2.32902 11.8011 2.25 12 2.25ZM18.894 6.166C19.0265 6.02382 19.0986 5.83578 19.0952 5.64148C19.0917 5.44718 19.013 5.26179 18.8756 5.12438C18.7382 4.98697 18.5528 4.90825 18.3585 4.90483C18.1642 4.9014 17.9762 4.97352 17.834 5.106L16.243 6.696C16.1713 6.76515 16.1142 6.84788 16.0748 6.93937C16.0355 7.03085 16.0147 7.12926 16.0138 7.22884C16.0129 7.32842 16.0318 7.42719 16.0695 7.51938C16.1072 7.61157 16.1628 7.69534 16.2332 7.76579C16.3036 7.83624 16.3873 7.89197 16.4795 7.92972C16.5716 7.96748 16.6704 7.9865 16.7699 7.98568C16.8695 7.98486 16.968 7.96422 17.0595 7.92496C17.151 7.8857 17.2338 7.8286 17.303 7.757L18.894 6.166ZM21.75 12C21.75 12.1989 21.671 12.3897 21.5303 12.5303C21.3897 12.671 21.1989 12.75 21 12.75H18.75C18.5511 12.75 18.3603 12.671 18.2197 12.5303C18.079 12.3897 18 12.1989 18 12C18 11.8011 18.079 11.6103 18.2197 11.4697C18.3603 11.329 18.5511 11.25 18.75 11.25H21C21.1989 11.25 21.3897 11.329 21.5303 11.4697C21.671 11.6103 21.75 11.8011 21.75 12ZM17.834 18.894C17.9762 19.0265 18.1642 19.0986 18.3585 19.0952C18.5528 19.0917 18.7382 19.013 18.8756 18.8756C19.013 18.7382 19.0917 18.5528 19.0952 18.3585C19.0986 18.1642 19.0265 17.9762 18.894 17.834L17.304 16.243C17.2348 16.1713 17.1521 16.1142 17.0606 16.0748C16.9691 16.0355 16.8707 16.0147 16.7712 16.0138C16.6716 16.0129 16.5728 16.0318 16.4806 16.0695C16.3884 16.1072 16.3047 16.1628 16.2342 16.2332C16.1638 16.3036 16.108 16.3873 16.0703 16.4795C16.0325 16.5716 16.0135 16.6704 16.0143 16.7699C16.0151 16.8695 16.0358 16.968 16.075 17.0595C16.1143 17.151 16.1714 17.2338 16.243 17.303L17.834 18.894ZM12 18C12.1989 18 12.3897 18.079 12.5303 18.2197C12.671 18.3603 12.75 18.5511 12.75 18.75V21C12.75 21.1989 12.671 21.3897 12.5303 21.5303C12.3897 21.671 12.1989 21.75 12 21.75C11.8011 21.75 11.6103 21.671 11.4697 21.5303C11.329 21.3897 11.25 21.1989 11.25 21V18.75C11.25 18.5511 11.329 18.3603 11.4697 18.2197C11.6103 18.079 11.8011 18 12 18ZM7.758 17.303C7.89455 17.1615 7.97006 16.972 7.96826 16.7753C7.96646 16.5787 7.88749 16.3906 7.74837 16.2516C7.60925 16.1126 7.4211 16.0339 7.22445 16.0322C7.0278 16.0306 6.83839 16.1063 6.697 16.243L5.106 17.833C4.96931 17.9744 4.89363 18.1638 4.89524 18.3605C4.89686 18.5571 4.97565 18.7452 5.11464 18.8844C5.25363 19.0235 5.4417 19.1025 5.63835 19.1043C5.835 19.1061 6.02448 19.0306 6.166 18.894L7.757 17.304L7.758 17.303ZM6 12C6 12.1989 5.92098 12.3897 5.78033 12.5303C5.63968 12.671 5.44891 12.75 5.25 12.75H3C2.80109 12.75 2.61032 12.671 2.46967 12.5303C2.32902 12.3897 2.25 12.1989 2.25 12C2.25 11.8011 2.32902 11.6103 2.46967 11.4697C2.61032 11.329 2.80109 11.25 3 11.25H5.25C5.44891 11.25 5.63968 11.329 5.78033 11.4697C5.92098 11.6103 6 11.8011 6 12ZM6.697 7.757C6.83917 7.88948 7.02722 7.9616 7.22152 7.95818C7.41582 7.95475 7.60121 7.87603 7.73862 7.73862C7.87603 7.60121 7.95475 7.41582 7.95818 7.22152C7.9616 7.02722 7.88948 6.83917 7.757 6.697L6.167 5.106C6.02561 4.96931 5.8362 4.89363 5.63955 4.89524C5.4429 4.89686 5.25475 4.97565 5.11563 5.11464C4.97651 5.25363 4.89754 5.4417 4.89574 5.63835C4.89394 5.835 4.96945 6.02448 5.106 6.166L6.697 7.757Z"
                  fill="currentColor"
                />
                <path
                  mask="url(#cut-out)"
                  d="M7.5 12C7.5 10.8065 7.97411 9.66193 8.81802 8.81802C9.66193 7.97411 10.8065 7.5 12 7.5C13.1935 7.5 14.3381 7.97411 15.182 8.81802C16.0259 9.66193 16.5 10.8065 16.5 12C16.5 13.1935 16.0259 14.3381 15.182 15.182C14.3381 16.0259 13.1935 16.5 12 16.5C10.8065 16.5 9.66193 16.0259 8.81802 15.182C7.97411 14.3381 7.5 13.1935 7.5 12Z"
                  fill="currentColor"
                />
              </svg>
            </div>
          </div>
        </div>
      </div>
      <div class="container">
        <div class="slider-wrap">
          <div class="slider__track track">
            <div class="track__progress"></div>
          </div>
          <div class="slider slider--volume">
            <label for="volume" class="sr-only">Volume</label>
            <input id="volume" type="range" min="0" max="100" value="50" />
            <div class="slider__indicator">
              <svg  viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M13.5 4.05714C13.5 2.72114 11.884 2.05214 10.94 2.99714L6.44001 7.49714H4.50801C3.36701 7.49714 2.19001 8.16114 1.84801 9.40214C1.61598 10.2476 1.49893 11.1204 1.50001 11.9971C1.50001 12.8951 1.62101 13.7651 1.85001 14.5921C2.19101 15.8321 3.36801 16.4971 4.50901 16.4971H6.43901L10.939 20.9971C11.884 21.9421 13.5 21.2731 13.5 19.9371V4.05714Z" fill="currentColor"/>
                <path d="M15.9332 7.7589C16.0028 7.68921 16.0855 7.63392 16.1766 7.5962C16.2676 7.55848 16.3652 7.53906 16.4637 7.53906C16.5622 7.53906 16.6598 7.55848 16.7508 7.5962C16.8418 7.63392 16.9245 7.68921 16.9942 7.7589C17.5514 8.31607 17.9935 8.97755 18.2951 9.70557C18.5967 10.4336 18.7519 11.2139 18.7519 12.0019C18.7519 12.7899 18.5967 13.5702 18.2951 14.2982C17.9935 15.0263 17.5514 15.6877 16.9942 16.2449C16.8527 16.3815 16.6632 16.457 16.4665 16.4552C16.2699 16.4534 16.0818 16.3744 15.9428 16.2353C15.8038 16.0962 15.725 15.908 15.7234 15.7114C15.7218 15.5147 15.7975 15.3253 15.9342 15.1839C16.3521 14.766 16.6835 14.27 16.9097 13.724C17.1358 13.178 17.2522 12.5929 17.2522 12.0019C17.2522 11.4109 17.1358 10.8258 16.9097 10.2798C16.6835 9.73385 16.3521 9.23777 15.9342 8.8199C15.7937 8.67928 15.7148 8.48865 15.7148 8.2899C15.7148 8.09115 15.7937 7.90053 15.9342 7.7599L15.9332 7.7589Z" fill="currentColor"/>
                <path d="M17.2987 9.23871C17.23 9.16502 17.1472 9.10592 17.0552 9.06493C16.9632 9.02394 16.8639 9.00189 16.7632 9.00012C16.6625 8.99834 16.5625 9.01686 16.4691 9.05459C16.3757 9.09231 16.2909 9.14845 16.2197 9.21967C16.1485 9.29089 16.0923 9.37572 16.0546 9.46911C16.0169 9.5625 15.9983 9.66253 16.0001 9.76323C16.0019 9.86393 16.0239 9.96325 16.0649 10.0552C16.1059 10.1472 16.165 10.23 16.2387 10.2987L17.9587 12.0187L16.2387 13.7387C16.165 13.8074 16.1059 13.8902 16.0649 13.9822C16.0239 14.0742 16.0019 14.1735 16.0001 14.2742C15.9983 14.3749 16.0169 14.4749 16.0546 14.5683C16.0923 14.6617 16.1485 14.7465 16.2197 14.8177C16.2909 14.889 16.3757 14.9451 16.4691 14.9828C16.5625 15.0206 16.6625 15.0391 16.7632 15.0373C16.8639 15.0355 16.9632 15.0135 17.0552 14.9725C17.1472 14.9315 17.23 14.8724 17.2987 14.7987L19.0187 13.0787L20.7387 14.7987C20.8074 14.8724 20.8902 14.9315 20.9822 14.9725C21.0742 15.0135 21.1735 15.0355 21.2742 15.0373C21.3749 15.0391 21.4749 15.0206 21.5683 14.9828C21.6617 14.9451 21.7465 14.889 21.8177 14.8177C21.889 14.7465 21.9451 14.6617 21.9828 14.5683C22.0206 14.4749 22.0391 14.3749 22.0373 14.2742C22.0355 14.1735 22.0135 14.0742 21.9725 13.9822C21.9315 13.8902 21.8724 13.8074 21.7987 13.7387L20.0787 12.0187L21.7987 10.2987C21.8724 10.23 21.9315 10.1472 21.9725 10.0552C22.0135 9.96325 22.0355 9.86393 22.0373 9.76323C22.0391 9.66253 22.0206 9.5625 21.9828 9.46911C21.9451 9.37572 21.889 9.29089 21.8177 9.21967C21.7465 9.14845 21.6617 9.09231 21.5683 9.05459C21.4749 9.01686 21.3749 8.99834 21.2742 9.00012C21.1735 9.00189 21.0742 9.02394 20.9822 9.06493C20.8902 9.10592 20.8074 9.16502 20.7387 9.23871L19.0187 10.9587L17.2987 9.23871Z" fill="currentColor"/>
                <path d="M18.5826 5.04747C18.7232 4.90702 18.9139 4.82813 19.1126 4.82813C19.3114 4.82813 19.502 4.90702 19.6426 5.04747C23.4506 8.85447 23.4506 15.0275 19.6426 18.8355C19.5004 18.9679 19.3124 19.0401 19.1181 19.0366C18.9238 19.0332 18.7384 18.9545 18.601 18.8171C18.4636 18.6797 18.3849 18.4943 18.3814 18.3C18.378 18.1057 18.4501 17.9176 18.5826 17.7755C19.3488 17.0094 19.9566 16.0999 20.3713 15.0988C20.7859 14.0978 20.9994 13.025 20.9994 11.9415C20.9994 10.858 20.7859 9.78509 20.3713 8.78409C19.9566 7.78308 19.3488 6.87356 18.5826 6.10747C18.4422 5.96684 18.3633 5.77622 18.3633 5.57747C18.3633 5.37872 18.4422 5.18809 18.5826 5.04747Z" fill="currentColor"/>

              </svg>
            </div>
          </div>
        </div>
      </div>
      <div class="container">
        <div class="slider-wrap">
          <div class="slider__track track">
            <div class="track__progress"></div>
          </div>
          <div class="slider slider--intensity">
            <label for="intensity" class="sr-only">Intensity</label>
            <input id="intensity" type="range" min="0" max="100" value="0" />
            <div class="slider__indicator">
              <svg viewBox="0 0 32 57" fill="none" xmlns="http://www.w3.org/2000/svg">
                <g>
                  <path d="M18.8594 34.5H13.1406C12.3156 34.5 12.0156 35.175 12.0156 36H19.9844C19.9844 35.175 19.6844 34.5 18.8594 34.5ZM13.1922 39.9141C13.5484 40.3266 13.75 40.8516 13.75 41.4V53.8641C13.75 54.8906 14.5891 55.5 15.6203 55.5H16.3844C17.4109 55.5 18.2547 54.8953 18.2547 53.8641V41.4C18.2547 40.8516 18.4563 40.3312 18.8125 39.9141C19.5344 39.075 19.9844 38.2969 19.9844 36.75H12.0156C12.0156 38.3906 12.4656 39.075 13.1922 39.9141ZM14.6875 44.1703C14.6875 43.4391 15.2781 42.8438 16 42.8438C16.7219 42.8438 17.3125 43.4391 17.3125 44.1703V45.8297C17.3125 46.5609 16.7219 47.1562 16 47.1562C15.2781 47.1562 14.6875 46.5609 14.6875 45.8297V44.1703Z" fill="currentColor"/>
                  <path d="M0.928649 1.98112C0.496331 1.05884 1.1694 0 2.18797 0H29.812C30.8306 0 31.5037 1.05884 31.0714 1.98112L17.4244 31.0945C17.1654 31.6471 16.6102 32 16 32V32C15.3898 32 14.8346 31.6471 14.5756 31.0945L0.928649 1.98112Z" fill="currentColor"/>
                </g>
              </svg>
            </div>
          </div>
        </div>
      </div>
    </main>
    <script type="module">
      import gsap from 'https://cdn.skypack.dev/gsap@3.12.4';
      import Draggable from 'https://cdn.skypack.dev/gsap@3.12.4/Draggable';
      import { Pane } from 'https://cdn.skypack.dev/tweakpane';

      gsap.registerPlugin(Draggable);

      const config = {
        disguise: true,
        enhance: false,
        stretch: 25,
      };

      const ctrl = new Pane({
        title: 'Config',
        expanded: true,
      });

      const binding = ctrl.addBinding(config, 'disguise', {
        label: '装饰 🥸',
      });

      const enhancer = ctrl.addBinding(config, 'enhance', {
        label: '增强 ✨',
      });

      const stretch = ctrl.addBinding(config, 'stretch', {
        label: '拉伸 🤏',
        min: 0,
        max: 100,
        step: 1,
      });

      stretch.disabled = true;

      const sync = () => {
        document.documentElement.dataset.disguise = config.disguise;
        document.documentElement.dataset.enhance = config.enhance;
        binding.label = `装饰 ${config.disguise ? '🥸' : '🫣'}`;
        enhancer.label = `增强 ${config.enhance ? '🔥' : '✨'}`;
        stretch.disabled = !config.enhance;
      };

      ctrl.on('change', sync);
      sync();

      /**
       * Class for the Slider with Draggable bounce
       */
      const STRETCH_DISTANCE = 25;
      class Slider {
        constructor(element) {
          this.element = element;
          const input = element.querySelector('[type=range]');
          // This is the polyfill for not having scroll animation support
          if (!CSS.supports('animation-timeline: scroll()')) {
            const sync = () => {
              const val = (input.value - input.min) / (input.max - input.min);
              element.style.setProperty('--slider-complete', val);
            };
            console.info('polyfilling scroll-animation');
            input.addEventListener('input', sync);
            input.addEventListener('pointerdown', sync);
            sync();
          }
          this.setSpring();
        }
        setSpring() {
          const PROXY = document.createElement('div');

          const wrap = this.element;
          const slider = this.element.querySelector('.slider');

          Draggable.create(PROXY, {
            type: 'y',
            trigger: slider,
            allowContextMenu: true,
            onPress: function () {
              // This wouldn't live here ordinarily but for demo purposes.
              wrap.style.setProperty(
                '--stretch-ratio',
                config.stretch / slider.getBoundingClientRect().height
              );

              wrap.dataset.spring = false;
              const bounds = slider.getBoundingClientRect();
              const start = this.pointerY - bounds.top;
              const end = bounds.top + bounds.height - this.pointerY;
              PROXY.dataset.start = start;
              PROXY.dataset.end = end;
              gsap.set(PROXY, { y: start });
            },
            onDrag: function () {
              const start = Number.parseInt(PROXY.dataset.start, 10);
              const end = Number.parseInt(PROXY.dataset.end, 10);
              if (this.y < start * -1) {
                // stretching at the top
                wrap.dataset.origin = 'bottom';
                wrap.style.setProperty(
                  '--stretch',
                  gsap.utils.mapRange(
                    0,
                    config.stretch,
                    0,
                    1,
                    Math.abs(start * -1 - this.y)
                  )
                );
              } else if (this.y > end) {
                wrap.dataset.origin = 'top';
                wrap.style.setProperty(
                  '--stretch',
                  gsap.utils.mapRange(0, config.stretch, 0, 1, this.y - end)
                );
              } else {
                wrap.style.setProperty('--stretch', 0);
              }
            },
            onDragEnd: () => {
              gsap.set(PROXY, { y: 0 });
              wrap.style.setProperty('--stretch', 0);
              wrap.dataset.spring = true;
            },
          });
        }
      }

      const sliders = document.querySelectorAll('.slider-wrap');
      for (const slider of sliders) new Slider(slider);
    </script>
  </body>
</html>