-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15926 from xiaoyan428820/main
feat: [harmony-hybrid]新增previewImage桥接原生
- Loading branch information
Showing
5 changed files
with
34 additions
and
179 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
packages/taro-platform-harmony-hybrid/src/api/apis/media/image/NativeImage.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { asyncAndRelease } from '../../harmony-native/ApiDecorator' | ||
|
||
class NativeImage { | ||
@asyncAndRelease | ||
previewImage (_options: any):void {} | ||
} | ||
|
||
const nativeImage = new NativeImage() | ||
|
||
export default nativeImage |
187 changes: 14 additions & 173 deletions
187
packages/taro-platform-harmony-hybrid/src/api/apis/media/image/previewImage.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,196 +1,37 @@ | ||
import { SwiperProps } from '@tarojs/components' | ||
import { | ||
defineCustomElementTaroSwiperCore, | ||
defineCustomElementTaroSwiperItemCore, | ||
} from '@tarojs/components/dist/components' | ||
import { eventCenter } from '@tarojs/runtime' | ||
import { isFunction } from '@tarojs/shared' | ||
import Taro from '@tarojs/taro' | ||
import { showActionSheet, showToast } from '@tarojs/taro-h5' | ||
|
||
import native from '../../NativeApi' | ||
import { shouldBeObject } from '../../utils' | ||
import { MethodHandler } from '../../utils/handler' | ||
import { saveImageToPhotosAlbum } from './saveImageToPhotosAlbum' | ||
import nativeImage from './NativeImage' | ||
|
||
/** | ||
* 在新页面中全屏预览图片。预览的过程中用户可以进行保存图片、发送给朋友等操作。 | ||
* | ||
* @canUse previewImage | ||
* @__object [urls, current, showmenu] | ||
*/ | ||
export const previewImage: typeof Taro.previewImage = async (options) => { | ||
// TODO 改为通过 window.__taroAppConfig 获取配置的 Swiper 插件创建节点 | ||
defineCustomElementTaroSwiperCore() | ||
defineCustomElementTaroSwiperItemCore() | ||
const PRESS_TIME = 1000 | ||
const SHOW_TIME = 2000 | ||
const SAVE_IMAGE_BUTTON = 1 | ||
|
||
export const previewImage: typeof Taro.previewImage = (options) => { | ||
// options must be an Object | ||
const isObject = shouldBeObject(options) | ||
if (!isObject.flag) { | ||
const res = { errMsg: `previewImage:fail ${isObject.msg}` } | ||
console.error(res.errMsg) | ||
return Promise.reject(res) | ||
} | ||
|
||
const { urls = [], current, success, fail, complete, showmenu } = options | ||
const { urls = [], current, showmenu, success, fail, complete } = options | ||
const handle = new MethodHandler({ name: 'previewImage', success, fail, complete }) | ||
const container = document.createElement('div') | ||
const removeHandler = () => { | ||
eventCenter.off('__taroRouterChange', removeHandler) | ||
container.remove() | ||
eventCenter.trigger('__taroExitFullScreen', {}) | ||
} | ||
// 路由改变后应该关闭预览框 | ||
eventCenter.on('__taroRouterChange', removeHandler) | ||
|
||
container.classList.add('preview-image') | ||
container.style.cssText = | ||
'position:fixed;top:0;left:0;z-index:999;width:100%;height:100%;overflow:hidden;outline:0;background-color:#111;' | ||
container.addEventListener('click', removeHandler) | ||
|
||
const swiper: HTMLElement & Omit<SwiperProps, 'style' | 'children'> = document.createElement('taro-swiper-core') | ||
// @ts-ignore | ||
swiper.full = true | ||
// @ts-ignore | ||
swiper.zoom = true | ||
|
||
let children: Node[] = [] | ||
|
||
function loadImage (url: string, loadFail: typeof fail): Promise<Node> { | ||
return new Promise((resolve) => { | ||
const item = document.createElement('taro-swiper-item-core') | ||
item.style.cssText = 'display:flex;align-items:start;justify-content:center;overflow-y:scroll;' | ||
const image = new Image() | ||
|
||
image.style.maxWidth = '100%' | ||
image.src = url | ||
const div = document.createElement('div') | ||
div.classList.add('swiper-zoom-container') | ||
div.style.cssText = 'display:flex;align-items:center;justify-content:center;max-width:100%;min-height:100%;' | ||
div.appendChild(image) | ||
div.style.zIndex = '900' | ||
|
||
let pressTimer | ||
function startPress () { | ||
pressTimer = setTimeout(async function () { | ||
if (!showmenu) { | ||
return | ||
} | ||
try { | ||
const { tapIndex } = await showActionSheet({ | ||
itemList: ['转发给朋友', '保存图片', '收藏', '翻译图片中的文字', '提取文字'], | ||
}) | ||
if (tapIndex !== SAVE_IMAGE_BUTTON) { | ||
return | ||
} | ||
native.downloadFile({ | ||
url: url, // 仅为示例,并非真实的资源 | ||
success: function (res: any) { | ||
// 只要服务器有响应数据,就会把响应内容写入文件并进入 success 回调,业务需要自行判断是否下载到了想要的内容 | ||
saveImageToPhotosAlbum({ | ||
filePath: res.tempFilePath, | ||
success: function (res: any) { | ||
showToast({ | ||
title: '保存成功', | ||
icon: 'success', | ||
duration: SHOW_TIME, | ||
}) | ||
handle.success(res) | ||
}, | ||
fail: function (err: any) { | ||
handle.fail(err) | ||
}, | ||
}) | ||
}, | ||
fail: function (err: any) { | ||
handle.fail(err) | ||
}, | ||
}) | ||
} catch (e) { | ||
return handle.fail({ | ||
errMsg: e.errMsg?.replace('^.*:fail ', ''), | ||
}) | ||
} | ||
}, PRESS_TIME) // 这里的1000表示长按的时间,以毫秒为单位,您可以根据需要调整 | ||
} | ||
|
||
function cancelPress () { | ||
clearTimeout(pressTimer) | ||
} | ||
|
||
// 添加触摸事件监听器 | ||
div.addEventListener('touchstart', startPress) | ||
div.addEventListener('touchend', cancelPress) | ||
div.addEventListener('touchmove', cancelPress) | ||
|
||
item.appendChild(div) | ||
// Note: 等待图片加载完后返回,会导致轮播被卡住 | ||
resolve(item) | ||
if (isFunction(loadFail)) { | ||
image.addEventListener('error', (err) => { | ||
loadFail({ errMsg: err.message }) | ||
}) | ||
} | ||
return new Promise<TaroGeneral.CallbackResult>((resolve, reject) => { | ||
nativeImage.previewImage({ | ||
urls, | ||
current, | ||
showmenu, | ||
success: (res) => { | ||
handle.success(res, { resolve, reject }) | ||
}, | ||
fail: (res) => { | ||
handle.fail(res, { resolve, reject }) | ||
}, | ||
}) | ||
} | ||
|
||
try { | ||
children = await Promise.all(urls.map((e) => loadImage(e, fail))) | ||
} catch (error) { | ||
return handle.fail({ | ||
errMsg: error, | ||
}) | ||
} | ||
|
||
for (let i = 0; i < children.length; i++) { | ||
const child = children[i] | ||
swiper.appendChild(child) | ||
} | ||
|
||
// 根据微信小程序文档标准(https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.previewImage.html) | ||
// current是一个字符串 | ||
let currentIndex = 0 | ||
if (current && typeof current === 'string') { | ||
const index = urls.indexOf(current) | ||
currentIndex = index > -1 ? index : 0 | ||
} | ||
|
||
swiper.current = currentIndex | ||
|
||
// 创建一个固定定位的容器 | ||
const indexContainer = document.createElement('div') | ||
indexContainer.style.position = 'fixed' | ||
indexContainer.style.top = '35px' | ||
indexContainer.style.left = '50%' | ||
indexContainer.style.transform = 'translateX(-50%)' | ||
indexContainer.style.zIndex = '999' // 确保显示在最上层 | ||
container.appendChild(indexContainer) | ||
|
||
// 创建一个div用来显示索引 | ||
const indexDisplay = document.createElement('div') | ||
indexContainer.style.position = 'fixed' | ||
indexDisplay.id = 'index-display' | ||
indexDisplay.style.backgroundColor = '#111' // 设置背景颜色为黑色 | ||
indexDisplay.style.color = 'white' // 设置文字颜色为白色 | ||
indexContainer.style.transform = 'translateX(-50%)' | ||
indexContainer.style.zIndex = '999' // 确保显示在最上层 | ||
indexDisplay.style.border = '1px solid #111' | ||
indexContainer.appendChild(indexDisplay) | ||
indexDisplay.innerText = `${currentIndex + 1} / ${urls.length}` | ||
|
||
// 监听滑块index并渲染 | ||
swiper.addEventListener('change', (e) => { | ||
// @ts-ignore | ||
const index = e.detail.current | ||
indexDisplay.innerText = `${index + 1} / ${urls.length}` | ||
}) | ||
|
||
container.appendChild(swiper) | ||
document.body.appendChild(container) | ||
eventCenter.trigger('__taroEnterFullScreen', {}) | ||
|
||
return handle.success() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters