8pt

Image Compare

前后对比滑块•媒体
介绍

拖动分割线对比前后两张画面,支持键盘左右键。裁切用两层反向 translate 实现,不改尺寸、不触发重排。

纯 HTML、CSS 与少量原生 JS,没有框架依赖。复制提示词交给 Claude Code、Cursor、Trae 或 Codex,模型会把 Image Compare 加进你的项目并换成你的配色。

适用场景

图片对比、视频展示、画廊、轮播和媒体卡片。

安装

订阅 Builder 后,用 8pt CLI 装进项目,或在已接入 8pt MCP 的编辑器里直接调用。

$ npm i -g @8pt-dev/cli && 8pt add image-compare
mcp › 使用 8pt MCP 调用 get_component("image-compare")

代码

Image Compare 的源码,动效只用 transform 与 opacity,并尊重减少动态效果设置。

<div class="x-cmp" tabindex="0" role="slider" aria-label="对比位置" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50">
  <div class="x-cmp__img x-cmp__after" aria-hidden="true">
    <div class="x-cmp__ui"><i class="h"></i><i class="t"></i><i class="t s"></i><span class="b"></span><div class="cards"><i></i><i></i><i></i></div></div>
  </div>
  <div class="x-cmp__clip"><div class="x-cmp__clipin">
    <div class="x-cmp__img x-cmp__before" aria-hidden="true">
      <div class="x-cmp__ui"><i class="h"></i><i class="t"></i><i class="t s"></i><span class="b"></span><div class="cards"><i></i><i></i><i></i></div></div>
    </div>
  </div></div>
  <span class="x-cmp__tag l">线框</span><span class="x-cmp__tag r">成品</span>
  <span class="x-cmp__handle" aria-hidden="true"><b>‹ ›</b></span>
</div>
.x-cmp{--p:.5;position:relative;overflow:hidden;width:100%;height:100%;min-height:200px;border-radius:0;cursor:ew-resize;touch-action:none;outline:0;user-select:none}
.x-cmp__img{position:absolute;inset:0;display:grid;place-items:center}
.x-cmp__after{background:radial-gradient(80% 90% at 70% 10%,color-mix(in srgb,var(--d-accent,#4D74FF) 55%,#000),#0c0b1d 70%)}
.x-cmp__before{background:var(--d-bg,#f6f6f8);background-image:linear-gradient(var(--d-line,rgba(127,127,140,.18)) 1px,transparent 1px),linear-gradient(90deg,var(--d-line,rgba(127,127,140,.18)) 1px,transparent 1px);background-size:16px 16px}
.x-cmp__clip{position:absolute;inset:0;overflow:hidden;transform:translateX(calc((var(--p) - 1) * 100%))}
.x-cmp__clipin{position:absolute;inset:0;transform:translateX(calc((1 - var(--p)) * 100%))}
.x-cmp__ui{display:grid;justify-items:center;gap:8px;width:76%}
.x-cmp__ui i,.x-cmp__ui span{display:block;border-radius:6px}
.x-cmp__ui .h{width:40%;height:8px}
.x-cmp__ui .t{width:86%;height:16px}
.x-cmp__ui .t.s{width:60%}
.x-cmp__ui .b{width:30%;height:22px;border-radius:999px;margin-top:4px}
…
const init = (root) => {
  const box = root.querySelector('.x-cmp');
  let p = 0.5, drag = false, raf = 0, auto = 0, t = 0;
  const set = (v) => { p = Math.max(0, Math.min(1, v)); box.style.setProperty('--p', p); box.setAttribute('aria-valuenow', Math.round(p * 100)); };
  const size = () => box.style.setProperty('--w', box.clientWidth + 'px');
  const ro = new ResizeObserver(size); ro.observe(box); size();
  const at = (e) => { const r = box.getBoundingClientRect(); set((e.clientX - r.left) / r.width); };
  box.addEventListener('pointerdown', e => { drag = true; stop(); box.setPointerCapture(e.pointerId); at(e); });
  box.addEventListener('pointermove', e => { if (drag) { cancelAnimationFrame(raf); raf = requestAnimationFrame(() => at(e)); } });
  box.addEventListener('pointerup', () => drag = false);
  box.addEventListener('keydown', e => { if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') { e.preventDefault(); stop(); set(p + (e.key === 'ArrowRight' ? 0.05 : -0.05)); } });
  // idle sweep so the card preview shows both sides
…
订阅 Builder 查看完整源码。查看价格

更多媒体组件

查看全部

Film Strip Carousel

Auto Tab Showcase

更多组件

查看全部

AI Prompt Composer

Media Bento Grid

Agent Chat Window

Model Pill Marquee

Director Art Cards

Mac File Window

Disk Cleanup Panel

Glass Folder

继续探索