From 24707ce087519302f4bfc1e6a9badaefd447a1ba Mon Sep 17 00:00:00 2001 From: anotherso1a <1181581742@qq.com> Date: Tue, 14 Nov 2023 19:55:04 +0800 Subject: [PATCH 1/2] feat: add preview image api --- packages/api-proxy/src/common/js/web.js | 16 ++++ .../api-proxy/src/common/stylus/Preview.styl | 29 +++++++ packages/api-proxy/src/web/api/index.js | 3 + .../src/web/api/preview-image/Preview.js | 77 +++++++++++++++++++ .../src/web/api/preview-image/index.js | 12 +++ packages/api-proxy/src/web/api/toast/Toast.js | 9 +-- 6 files changed, 138 insertions(+), 8 deletions(-) create mode 100644 packages/api-proxy/src/common/stylus/Preview.styl create mode 100644 packages/api-proxy/src/web/api/preview-image/Preview.js create mode 100644 packages/api-proxy/src/web/api/preview-image/index.js 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..0c5f8931c0 --- /dev/null +++ b/packages/api-proxy/src/web/api/preview-image/Preview.js @@ -0,0 +1,77 @@ +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..cc1357d144 --- /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 = { From 54d126e33bc5105576c4a8c26dd9c690771b8111 Mon Sep 17 00:00:00 2001 From: anotherso1a <1181581742@qq.com> Date: Tue, 14 Nov 2023 20:00:46 +0800 Subject: [PATCH 2/2] style: lint fix --- .../api-proxy/src/web/api/preview-image/Preview.js | 11 +++++++---- packages/api-proxy/src/web/api/preview-image/index.js | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/api-proxy/src/web/api/preview-image/Preview.js b/packages/api-proxy/src/web/api/preview-image/Preview.js index 0c5f8931c0..a60bd0ffc6 100644 --- a/packages/api-proxy/src/web/api/preview-image/Preview.js +++ b/packages/api-proxy/src/web/api/preview-image/Preview.js @@ -5,7 +5,7 @@ import '../../../common/stylus/Preview.styl' * todo: unit test */ export default class Preview { - constructor() { + constructor () { this.currentIndex = 0 this.maxIndex = 0 this.minDistance = 30 @@ -15,10 +15,11 @@ export default class Preview { document.body.appendChild(this.preview) this.initEvent() } + /** * Initializes the event listeners for the preview image feature. */ - initEvent() { + initEvent () { // swipe to change image let startX = 0 this.preview.addEventListener('touchstart', (e) => { @@ -45,12 +46,13 @@ export default class Preview { this.preview.querySelector('.__mpx_preview_images__').remove() }) } + /** * 显示预览图片 * @param {Object} options - 选项对象 * @param {string[]} options.urls - 图片地址数组 */ - show(options) { + 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 @@ -68,10 +70,11 @@ export default class Preview { webHandleFail({ errMsg: 'previewImage:fail', err: e }, fail, complete) } } + /** * 更新文本提示 */ - updateTextTip() { + 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 index cc1357d144..3c64a9eaf0 100644 --- a/packages/api-proxy/src/web/api/preview-image/index.js +++ b/packages/api-proxy/src/web/api/preview-image/index.js @@ -1,4 +1,4 @@ -import Preview from "./Preview" +import Preview from './Preview' let preview = null