Appearance
BizImageCompare 图片对比
分割线拖动的前后对比组件:两图同框叠放,after 经 clip-path 裁切,拖动分割线查看差异;支持左右(默认)/ 上下分割、角标签、键盘微调(聚焦后 ←→/↑↓,Shift 加速)。质检前后对比、AI 处理效果、证照变更比对等场景。
基础用法
左右拖动分割线对比(示例为同图去色 / 原色)。
<script setup lang="ts">
/** 基础用法:左右拖动分割线对比前后两图(同图去色 / 原色演示) */
import { BizImageCompare } from 'vue3-ep-biz-lib'
const before =
'https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=640&h=360&fit=crop&q=70&sat=-100'
const after =
'https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=640&h=360&fit=crop&q=70'
</script>
<template>
<BizImageCompare :before="before" :after="after" :height="300" />
</template>
显示代码
上下分割与键盘微调
当前位置 50% —— 点击图片区域后可用 ↑↓ 键盘微调(Shift + 大步)
direction="horizontal" 上下拖动;slide 事件实时回传百分比;聚焦后方向键微调。<script setup lang="ts">
/** 上下分割 + 键盘微调:direction=horizontal,聚焦后 ↑↓ 移动、Shift 加速 */
import { ref } from 'vue'
import { BizImageCompare } from 'vue3-ep-biz-lib'
const before =
'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=640&h=360&fit=crop&q=70&sat=-100'
const after =
'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=640&h=360&fit=crop&q=70'
const percent = ref(50)
const onSlide = (value: number): void => {
percent.value = value
}
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 8px; max-width: 640px">
<BizImageCompare
:before="before"
:after="after"
direction="horizontal"
:height="300"
before-label="处理前"
after-label="处理后"
@slide="onSlide"
/>
<div style="font-size: 12px; color: var(--el-text-color-secondary)">
当前位置 {{ percent }}% —— 点击图片区域后可用 ↑↓ 键盘微调(Shift + 大步)
</div>
</div>
</template>
显示代码
角标签
展示角标签
自定义前后文案;
show-labels=false 纯净对比(截图 / 归档场景)。<script setup lang="ts">
/** 角标签:自定义前后文案、show-labels=false 纯净对比(截图 / 归档场景) */
import { ref } from 'vue'
import { ElSwitch } from 'element-plus'
import { BizImageCompare } from 'vue3-ep-biz-lib'
const before =
'https://images.unsplash.com/photo-1516035069371-29a1b244cc32?w=640&h=360&fit=crop&q=70&sat=-100'
const after =
'https://images.unsplash.com/photo-1516035069371-29a1b244cc32?w=640&h=360&fit=crop&q=70'
const showLabels = ref(true)
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 8px; max-width: 640px">
<div style="display: flex; gap: 8px; align-items: center">
<ElSwitch v-model="showLabels" />
<span style="font-size: 13px">展示角标签</span>
</div>
<BizImageCompare
:before="before"
:after="after"
:height="300"
:show-labels="showLabels"
before-label="原图(灰度)"
after-label="修复后"
/>
</div>
</template>
显示代码
初始位置与编程式
position 设初始分割;setPosition 与 slide 事件和外部滑杆双向联动。<script setup lang="ts">
/** 初始位置与编程式定位:position 设初始分割;ElSlider 与 setPosition / slide 事件双向联动 */
import { ref } from 'vue'
import { ElSlider } from 'element-plus'
import { BizImageCompare } from 'vue3-ep-biz-lib'
const before =
'https://images.unsplash.com/photo-1470770841072-f978cf4d019e?w=640&h=360&fit=crop&q=70&sat=-100'
const after =
'https://images.unsplash.com/photo-1470770841072-f978cf4d019e?w=640&h=360&fit=crop&q=70'
const percent = ref(70)
const compareRef = ref<{ setPosition: (value: number) => void }>()
/** 滑杆 → 组件 */
const onInput = (value: number | number[]): void => {
if (typeof value === 'number') compareRef.value?.setPosition(value)
}
/** 组件拖动 → 滑杆 */
const onSlide = (value: number): void => {
percent.value = value
}
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 8px; max-width: 640px">
<BizImageCompare
ref="compareRef"
:before="before"
:after="after"
:height="300"
:position="70"
@slide="onSlide"
/>
<div style="display: flex; gap: 12px; align-items: center">
<ElSlider :model-value="percent" style="flex: 1" @input="onInput" />
<span style="width: 48px; text-align: right; font-size: 13px">{{ percent }}%</span>
</div>
</div>
</template>
显示代码
多组对比切换
同一页面在多对前后图间切换(批量质检浏览 / 案例归档)。
<script setup lang="ts">
/** 多组对比切换:同一页面在多对前后图间切换(案例归档 / 批量质检浏览) */
import { computed, ref } from 'vue'
import { ElRadioGroup, ElRadioButton } from 'element-plus'
import { BizImageCompare } from 'vue3-ep-biz-lib'
interface Pair {
key: string
label: string
before: string
after: string
beforeLabel: string
afterLabel: string
}
const id = 'photo-1441974231531-c6227db76b6e'
const watch = 'photo-1523275335684-37898b6baf30'
const camera = 'photo-1505740420928-5e560c06d30e'
const pairs: Pair[] = [
{
key: 'nature',
label: '风景调色',
before: `https://images.unsplash.com/${id}?w=640&h=360&fit=crop&q=70&sat=-100`,
after: `https://images.unsplash.com/${id}?w=640&h=360&fit=crop&q=70`,
beforeLabel: '原图',
afterLabel: '调色后',
},
{
key: 'product',
label: '商品修图',
before: `https://images.unsplash.com/${watch}?w=640&h=360&fit=crop&q=70&sat=-100`,
after: `https://images.unsplash.com/${watch}?w=640&h=360&fit=crop&q=70`,
beforeLabel: '初修',
afterLabel: '终稿',
},
{
key: 'device',
label: '样品比对',
before: `https://images.unsplash.com/${camera}?w=640&h=360&fit=crop&q=70&sat=-100`,
after: `https://images.unsplash.com/${camera}?w=640&h=360&fit=crop&q=70`,
beforeLabel: '打样 1',
afterLabel: '打样 2',
},
]
const activeKey = ref('nature')
const active = computed<Pair>(() => pairs.find((p) => p.key === activeKey.value) ?? pairs[0])
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 8px; max-width: 640px">
<ElRadioGroup v-model="activeKey">
<ElRadioButton v-for="p in pairs" :key="p.key" :value="p.key">{{ p.label }}</ElRadioButton>
</ElRadioGroup>
<BizImageCompare
:key="active.key"
:before="active.before"
:after="active.after"
:before-label="active.beforeLabel"
:after-label="active.afterLabel"
:height="300"
/>
</div>
</template>
显示代码
质检阈值联动
差异轻微 · 可自动放行分割位置 50%(拖动到 60% 以上试试)
slide 实时位置按阈值给出人工复核建议。<script setup lang="ts">
/** 质检判定联动:slide 事件实时回传位置,按阈值给出人工复核建议 */
import { computed, ref } from 'vue'
import { ElTag } from 'element-plus'
import { BizImageCompare } from 'vue3-ep-biz-lib'
const before =
'https://images.unsplash.com/photo-1583394838336-acd977736f90?w=640&h=360&fit=crop&q=70&sat=-100'
const after =
'https://images.unsplash.com/photo-1583394838336-acd977736f90?w=640&h=360&fit=crop&q=70'
const percent = ref(50)
/** 差异覆盖超过 60% 建议人工复核(演示规则) */
const verdict = computed<{ text: string; type: 'success' | 'danger' }>(() =>
percent.value >= 60
? { text: '差异显著 · 建议人工复核', type: 'danger' }
: { text: '差异轻微 · 可自动放行', type: 'success' },
)
const onSlide = (value: number): void => {
percent.value = value
}
</script>
<template>
<div style="display: flex; flex-direction: column; gap: 8px; max-width: 640px">
<BizImageCompare
:before="before"
:after="after"
:height="300"
before-label="送检样品"
after-label="标准样件"
@slide="onSlide"
/>
<div style="display: flex; gap: 8px; align-items: center; font-size: 13px">
<ElTag :type="verdict.type" effect="dark">{{ verdict.text }}</ElTag>
<span style="color: var(--el-text-color-secondary)">分割位置 {{ percent }}%(拖动到 60% 以上试试)</span>
</div>
</div>
</template>
显示代码
Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| before | string | —(必填) | 对比前图片 |
| after | string | —(必填) | 对比后图片 |
| before-label / after-label | string | 对比前 / 对比后 | 角标签文案 |
| direction | 'vertical' | 'horizontal' | vertical | 分割方向 |
| height | number | 360 | 容器高度 px |
| position | number | 50 | 初始分割位置百分比 |
| show-labels | boolean | true | 展示角标签 |
Events
| 事件名 | 参数 | 说明 |
|---|---|---|
| slide | (percent) | 分割位置变化(0-100) |
Expose
| 属性/方法 | 说明 |
|---|---|
| setPosition(percent) | 编程式设置分割位置 |