diff --git a/packages/api-proxy/src/common/js/web.js b/packages/api-proxy/src/common/js/web.js index 52ffe1cefe..da0961d419 100644 --- a/packages/api-proxy/src/common/js/web.js +++ b/packages/api-proxy/src/common/js/web.js @@ -15,8 +15,24 @@ function isTabBarPage (url, router) { return !!tabBarPagesMap[path.slice(1)] } +/** + * Creates a new DOM element with the specified tag, attributes, and children. + * + * @param {string} tag - The tag name of the new element. + * @param {Object.} [attrs={}] - An object containing the attributes to set on the new element. + * @param {Array.} [children=[]] - An array of child elements to append to the new element. + * @returns {HTMLElement} The newly created DOM element. + */ +function createDom (tag, attrs = {}, children = []) { + const dom = document.createElement(tag) + Object.keys(attrs).forEach(k => dom.setAttribute(k, attrs[k])) + children.length && children.forEach(child => dom.appendChild(child)) + return dom +} + export { webHandleSuccess, webHandleFail, + createDom, isTabBarPage } diff --git a/packages/api-proxy/src/common/stylus/Preview.styl b/packages/api-proxy/src/common/stylus/Preview.styl new file mode 100644 index 0000000000..7bb29dcbda --- /dev/null +++ b/packages/api-proxy/src/common/stylus/Preview.styl @@ -0,0 +1,29 @@ +.__mpx_preview__ + display none + width 100% + height 100% + background black + position fixed + top 0 + left 0 + z-index 1000 + .__mpx_preview_tip__ + position absolute + top 0 + left 50% + transform translateX(-50%) + color white + font-size 48px + letter-spacing 0.3em + .__mpx_preview_images__ + display flex + width 100% + height 100% + transition transform 0.3s ease-in-out + &>div + flex-shrink 0 + width 100% + height 100% + background-position center + background-size contain + background-repeat no-repeat diff --git a/packages/api-proxy/src/web/api/index.js b/packages/api-proxy/src/web/api/index.js index 25a28ad347..bab5615142 100644 --- a/packages/api-proxy/src/web/api/index.js +++ b/packages/api-proxy/src/web/api/index.js @@ -10,6 +10,9 @@ export * from './action-sheet' // showToast, hideToast, showLoading, hideLoading export * from './toast' +// previewImage +export * from './preview-image' + // showModal export * from './modal' diff --git a/packages/api-proxy/src/web/api/preview-image/Preview.js b/packages/api-proxy/src/web/api/preview-image/Preview.js new file mode 100644 index 0000000000..a60bd0ffc6 --- /dev/null +++ b/packages/api-proxy/src/web/api/preview-image/Preview.js @@ -0,0 +1,80 @@ +import { webHandleSuccess, webHandleFail, createDom, warn } from '../../../common/js' +import '../../../common/stylus/Preview.styl' +/** + * Preview class for displaying images in a slideshow format. + * todo: unit test + */ +export default class Preview { + constructor () { + this.currentIndex = 0 + this.maxIndex = 0 + this.minDistance = 30 + this.preview = createDom('div', { class: '__mpx_preview__' }, [ + this.textTip = createDom('div', { class: '__mpx_preview_tip__' }) + ]) + document.body.appendChild(this.preview) + this.initEvent() + } + + /** + * Initializes the event listeners for the preview image feature. + */ + initEvent () { + // swipe to change image + let startX = 0 + this.preview.addEventListener('touchstart', (e) => { + startX = e.touches[0].pageX + }) + this.preview.addEventListener('touchend', (e) => { + const endX = e.changedTouches[0].pageX + const distance = endX - startX + if (Math.abs(distance) < this.minDistance) { + return + } + if (distance > 0) { + this.currentIndex = Math.max(0, this.currentIndex - 1) + } + if (distance < 0) { + this.currentIndex = Math.min(this.maxIndex - 1, this.currentIndex + 1) + } + this.preview.querySelector('.__mpx_preview_images__').style.transform = `translateX(-${this.currentIndex * 100}%)` + this.updateTextTip() + }) + // click to close + this.preview.addEventListener('click', () => { + this.preview.style.display = 'none' + this.preview.querySelector('.__mpx_preview_images__').remove() + }) + } + + /** + * 显示预览图片 + * @param {Object} options - 选项对象 + * @param {string[]} options.urls - 图片地址数组 + */ + show (options) { + const supported = ['urls', 'success', 'fail', 'complete'] + Object.keys(options).forEach(key => !supported.includes(key) && warn(`previewImage: 暂不支持选项 ${key} !`)) + const { urls, success, fail, complete } = options + try { + this.preview.style.display = 'block' + // create images with urls + // append to preview + this.preview.appendChild(createDom('div', { class: '__mpx_preview_images__' }, urls.map(url => createDom('div', { + style: `background-image: url(${url})` + })))) + this.maxIndex = urls.length + this.updateTextTip() + webHandleSuccess({ errMsg: 'previewImage:ok' }, success, complete) + } catch (e) { + webHandleFail({ errMsg: 'previewImage:fail', err: e }, fail, complete) + } + } + + /** + * 更新文本提示 + */ + updateTextTip () { + this.textTip.textContent = `${this.currentIndex + 1}/${this.maxIndex}` + } +} diff --git a/packages/api-proxy/src/web/api/preview-image/index.js b/packages/api-proxy/src/web/api/preview-image/index.js new file mode 100644 index 0000000000..3c64a9eaf0 --- /dev/null +++ b/packages/api-proxy/src/web/api/preview-image/index.js @@ -0,0 +1,12 @@ +import Preview from './Preview' + +let preview = null + +/** + * 预览图片 + * @param {Object} options - 预览图片的配置项 + */ +export const previewImage = (options) => { + if (!preview) preview = new Preview() + preview.show(options) +} diff --git a/packages/api-proxy/src/web/api/toast/Toast.js b/packages/api-proxy/src/web/api/toast/Toast.js index 988d5863dd..073dc2bb1b 100644 --- a/packages/api-proxy/src/web/api/toast/Toast.js +++ b/packages/api-proxy/src/web/api/toast/Toast.js @@ -1,14 +1,7 @@ -import { webHandleSuccess } from '../../../common/js' +import { webHandleSuccess, createDom } from '../../../common/js' import '../../../common/stylus/Toast.styl' import '../../../common/stylus/Loading.styl' -function createDom (tag, attrs = {}, children = []) { - const dom = document.createElement(tag) - Object.keys(attrs).forEach(k => dom.setAttribute(k, attrs[k])) - children.length && children.forEach(child => dom.appendChild(child)) - return dom -} - export default class Toast { constructor () { this.defaultOpts = {