# uni.previewImage(options)

预览图片

# previewImage 兼容性 ?

Web 微信小程序 支付宝小程序 Android iOS HarmonyOS
4.0 4.41 5.31 3.9 4.11 4.61

# 参数

名称 类型 必填
options PreviewImageOptions 是
名称 类型 必备 兼容性 描述
current any 否 current 为当前显示图片的链接/索引值,不填或填写的值无效则为 urls 的第一张。APP平台仅支持索引值。
urls Array<string.ImageURIString> 是 需要预览的图片链接列表
showmenu boolean 否
是否显示长按菜单
indicator string 否
图片指示器样式
合法值 描述
default 底部圆点指示器
number 顶部数字指示器
none 不显示指示器
loop boolean 否
是否可循环预览
longPressActions LongPressActionsOptions 否
长按图片显示操作菜单。
名称 类型 必备 描述
itemList Array<string> 是 按钮的文字数组
itemColor string 否 按钮的文字颜色,字符串格式,默认为"#000000"
success (result: LongPressActionsSuccessResult) => void 否 接口调用成功的回调函数
fail (result: LongPressActionsFailResult) => void 否 接口调用失败的回调函数
complete (result: any) => void 否 接口调用结束的回调函数(调用成功、失败都会执行)
success (callback: PreviewImageSuccess) => void 否 接口调用成功的回调函数
fail (callback: PreviewImageFail) => void 否 接口调用失败的回调函数
complete (callback: any) => void 否 接口调用结束的回调函数(调用成功、失败都会执行)
referrerPolicy string 否
需要基础库: 2.13.0

origin: 发送完整的referrer; no-referrer: 不发送。格式固定为 https://servicewechat.com/{appid}/{version}/page-frame.html,其中 {appid} 为小程序的 appid,{version} 为小程序的版本号,版本号为 0 表示为开发版、体验版以及审核版本,版本号为 devtools 表示为开发者工具,其余为正式版本;
# LongPressActionsSuccessResult 的属性值
名称 类型 必备 描述
tapIndex number 是 接口调用成功的回调函数
index number 是 接口调用结束的回调函数(调用成功、失败都会执行)
# LongPressActionsFailResult 的属性值
名称 类型 必备 描述
errCode number 是 错误码
合法值 描述
1001 urls至少包含一张图片地址
1101001 用户取消
1101003 文件不存在
1101004 图片加载失败
1101005 未获取权限
1101010 其他错误
errSubject string 是 统一错误主题(模块)名称
data any 否 错误信息中包含的数据
cause Error 否 源错误信息,可以包含多个错误,详见SourceError
errMsg string 是

# PreviewImageSuccess 的属性值

名称 类型 必备 描述
errSubject string 是 调用API的名称
errMsg string 是 描述信息

# PreviewImageFail 的属性值

名称 类型 必备 描述
errCode number 是 错误码
合法值 描述
1001 urls至少包含一张图片地址
1101001 用户取消
1101003 文件不存在
1101004 图片加载失败
1101005 未获取权限
1101010 其他错误
errSubject string 是 统一错误主题(模块)名称
data any 否 错误信息中包含的数据
cause Error 否 源错误信息,可以包含多个错误,详见SourceError
errMsg string 是

# 示例

示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见

扫码体验(手机浏览器跳转到App直达页)

示例

<template>
  <!-- #ifdef APP && !VUE3-VAPOR -->
  <scroll-view class="uni-theme-root" style="flex: 1">
  <!-- #endif -->
    <view class="preview-page uni-theme-root">
      <!-- #ifndef MP-ALIPAY -->
      <view>
        <text class="text-desc">图片指示器样式</text>
        <radio-group class="cell-ct option-panel" @change="onIndicatorChanged">
          <view class="indicator-it" v-for="(item, index) in indicator" :key="item.value">
            <view class="option-item">
              <radio :disabled="isWeb" :checked="index == 0" :value="item.value" />
              <text>{{ item.name }}</text>
            </view>
          </view>
        </radio-group>
      </view>
      <view>
        <checkbox-group @change="onCheckboxChange" style="margin-top: 16px; margin-left: 8px">
          <view class="option-item" style="margin-right: 15px"><checkbox :disabled="isWeb" :checked="isLoop" /><text>循环播放</text></view>
        </checkbox-group>
      </view>
      <view>
        <text class="text-desc">长按行为</text>
        <radio-group class="cell-ct option-panel long-press-panel" @change="onLongPressCheckboxChange">
          <view class="indicator-it" v-for="(item, index) in longPressAction" :key="item.value">
            <view class="option-item">
              <radio :disabled="isWeb" :checked="index == 1" :value="item.value" />
              <text>{{ item.name }}</text>
            </view>
          </view>
        </radio-group>
      </view>
      <!-- #endif -->
      <view class="image-panel">
        <text class="text-desc">点击图片开始预览</text>
        <view class="cell-ct" style="margin: 8px;">
          <view class="cell cell-choose-image" v-for="(image, index) in imageList" :key="index">
            <text style="width: 100px; height: 100px;background-color: lightgray; color: red; text-align: center; line-height: 100px;font-size: 14px;" v-if="image.error"
              @click="previewImage(index)">图片路径非法</text>
            <image class="preview-image" mode="aspectFit" :src="image.src"
              v-if="!image.error" @click="previewImage(index)"
              @error="onImageLoadError(index,$event as ImageErrorEvent)">
            </image>
          </view>
          <image class="cell cell-choose-image" src="/static/plus.png" @click="chooseImage">
          </image>
        </view>
      </view>
      <view class="notice-panel">
        <text class="notice-title">注意事项:</text>
        <text class="notice-text">1、indicator属性仅App平台支持。</text>
        <text class="notice-text">2、Web平台不支持loop属性。</text>
      </view>
    </view>
  <!-- #ifdef APP && !VUE3-VAPOR -->
  </scroll-view>
  <!-- #endif -->
</template>

<script setup lang="uts">
  type Indicator = "number" | "default" | "none"
  type ItemType = {
    value : Indicator,
    name : string
  }

  type ImageType = {
    src : string,
    error : boolean
  }

  type LongPressType = {
    value : string,
    name : string
  }

  const imageList = ref([
    { src: "https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/uni@2x.png", error: false },
    // 只支持 http 图片链接
    // #ifndef MP-ALIPAY
    { src: "/static/test-image/logo.png", error: false },
    { src: "/static/test-image/logo.svg", error: false },
    // #endif
    // #ifdef APP
    { src: "/static/uni2.png", error: false },
    // #endif
  ] as ImageType[])

  const indicator = ref([{
    value: "default",
    name: "圆点"
  }, {
    value: "number",
    name: "数字"
  }, {
    value: "none",
    name: "不显示"
  }] as ItemType[])

  const longPressAction = ref([{
    value: "0",
    name: "默认长按行为"
  }, {
    value: "1",
    name: "自定义长按行为"
  }] as LongPressType[])

  const currentIndicator = ref("default"  as Indicator)

  // #ifdef WEB
  const isWeb = ref(true)
  // #endif
  // #ifndef WEB
  const isWeb = ref(false)
  // #endif

  // #ifdef APP-IOS
  const isIOS = ref(true)
  // #endif
  // #ifndef APP-IOS
  const isIOS = ref(false)
  // #endif

  const isLongPress = ref(true)
  const isLoop = ref(true)

  const previewImage = (index : number) => {
    let list = [] as Array<string>
    imageList.value.forEach((item : ImageType) => {
      list.push(item.src)
    })
    uni.previewImage({
      urls: list,
      current: index,
      // #ifdef MP-ALIPAY
      enableSavePhoto:true,
      // #endif
      // #ifndef MP-ALIPAY
      indicator: currentIndicator.value,
      loop: isLoop.value,
      longPressActions: (isLongPress.value ? ({
        itemList: ["按钮1", "按钮2", "按钮3"],
        itemColor: "#ccc",
        success: (e : LongPressActionsSuccessResult) => {
          uni.showToast({
            title: "用户选中了第" + (e.index + 1) + "张图片,并选中了第" + (e.tapIndex + 1) + "个选项",
            position: "bottom"
          })
        },
        fail: (e : LongPressActionsFailResult) => {
          uni.showToast({
            title: "用户关闭了action sheet",
            position: "bottom"
          })
        }
      } as LongPressActionsOptions) : null)
      // #endif
    })
  }

  const chooseImage = () => {
    uni.chooseImage({
      sourceType: ['album'],
      count: 1,
      success: (e) => {
        imageList.value = imageList.value.concat({ src: e.tempFilePaths[0], error: false } as ImageType)
        // imageList.value = imageList.value.concat(e.tempFilePaths)
      },
      fail(_) {
      }
    })
  }

  const onIndicatorChanged = (e : UniRadioGroupChangeEvent) => {
    currentIndicator.value = e.detail.value as Indicator
  }

  const onCheckboxChange = (_ : UniCheckboxGroupChangeEvent) => {
    isLoop.value = !isLoop.value
  }

  const onLongPressCheckboxChange = (e: UniRadioGroupChangeEvent) => {
    isLongPress.value = (e.detail.value == "1")
  }

  const onImageLoadError = (index : number, error : UniImageErrorEvent) => {
    imageList.value[index].error = true
  }

  const closePreviewImage = ()=>{
    uni.closePreviewImage({})
    uni.hideActionSheet()
  }

  const testSetCurrentIndicator = (value:string) =>{
    currentIndicator.value = value as Indicator
  }

  defineExpose({
  	testSetCurrentIndicator,
    previewImage,
    closePreviewImage
  })
</script>

<style>
  .preview-page {
    padding-left: 8px;
    padding-right: 8px;
  }

  .text-desc {
    margin-top: 16px;
    margin-left: 8px;
    margin-bottom: 16px;
    font-weight: bold;
    color: var(--text-color, #333333);
  }

  .cell-ct {
    display: flex;
    flex-wrap: wrap;
    flex-direction: row;
  }

  .option-panel,
  .image-panel,
  .preview-image {
    background-color: var(--list-background-color, #ffffff);
  }

  .long-press-panel {
    margin-bottom: 16px;
  }

  .preview-image {
    width: 100px;
    height: 100px;
  }

  .notice-panel {
    margin: 8px;
  }

  .notice-title {
    color: var(--text-color, #333333);
    font-size: 18px;
    margin-bottom: 4px;
  }

  .notice-text {
    font-size: 17px;
    margin-left: 4px;
    color: var(--active-color, #808080);
  }

  .cell {
    margin-left: 3px;
    margin-right: 3px;
    width: 100px;
    height: 100px;
  }

  .cell-choose-image {
    border-width: 1px;
    border-style: solid;
    border-color: var(--border-color, lightgray);
  }

  .indicator-it {
    margin: 8px;
  }

  .option-item {
    display: flex;
    flex-direction: row;
    align-items: center;
  }

  .cell-pd {
    padding: 11px 0px;
  }
</style>

# 参见

# 开源自定义

内置的previewImage弹出的界面,无法充分自定义。所以uni-app x提供了开源的previewImage页面,开发者可以自己定义UI。

开源插件地址:https://ext.dcloud.net.cn/plugin?id=21314

这个插件是ext api,下载到项目下会覆盖uni.previewImage的实现。

单独下载开源插件后,调用uni.previewImage,会在栈顶页面打开一个dialogPage,在父页面的getDialogPages中可以看到。使用内置的uni.previewImage看不到。

# uni.closePreviewImage(options)

关闭图片预览

# closePreviewImage 兼容性 ?

Web 微信小程序 支付宝小程序 Android iOS HarmonyOS
4.0 x x 3.9 4.11 4.61

# 参数

名称 类型 必填 兼容性
options ClosePreviewImageOptions 是
名称 类型 必备 兼容性 描述
success (callback: ClosePreviewImageSuccess) => void 否
接口调用成功的回调函数
fail (callback: ClosePreviewImageFail) => void 否
接口调用失败的回调函数
complete (callback: any) => void 否
接口调用结束的回调函数(调用成功、失败都会执行)

# ClosePreviewImageSuccess 的属性值

名称 类型 必备 兼容性 描述
errMsg string 是
错误信息

# ClosePreviewImageFail 的属性值

名称 类型 必备 兼容性 描述
errCode number 是
错误码
合法值 兼容性 描述
1001
urls至少包含一张图片地址
1101001
用户取消
1101003
文件不存在
1101004
图片加载失败
1101005
未获取权限
1101010
其他错误
errSubject string 是
统一错误主题(模块)名称
data any 否
错误信息中包含的数据
cause Error 否 源错误信息,可以包含多个错误,详见SourceError
errMsg string 是

# 参见

# 通用类型

# GeneralCallbackResult

名称 类型 必备 描述
errMsg string 是 错误信息