Skip to content

Commit

Permalink
feat: [harmony-hybrid]新增previewImage桥接原生
Browse files Browse the repository at this point in the history
  • Loading branch information
qcjxs committed Jun 18, 2024
1 parent 46e62d3 commit c2b0673
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 179 deletions.
10 changes: 5 additions & 5 deletions packages/taro-platform-harmony-hybrid/src/api/apis/NativeApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,11 +378,11 @@ export class NativeApi {
return option
}

// @ts-ignore
@(asyncAndNotRelease)
getFileInfo (option: any): any {
return option
}
@(asyncAndRelease)
getFileInformation (_option: any): void {}

@(asyncAndRelease)
getFileInfo (_option: any): void {}

// @ts-ignore
@(asyncAndNotRelease)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class NativeFileSystemManager implements Taro.FileSystemManager {
}

getFileInfo (option: any): any {
native.getFileInfo(option)
native.getFileInformation(option)
}

readFile (option: any): any {
Expand Down
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
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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ class HosMap extends React.Component<IProps> {
constructor (props: IProps) {
super(props)
this.componentId = `HosMap_${Math.floor(Math.random() * 100000)}_${Date.now()}`
}

componentDidMount (): void {
const {
latitude,
longitude,
Expand All @@ -77,6 +80,7 @@ class HosMap extends React.Component<IProps> {
onError,
onAnchorPointTap,
} = this.props

this.nativeRenderArgs = {
componentId: this.componentId,
latitude,
Expand Down

0 comments on commit c2b0673

Please sign in to comment.