不難想,你會" />

国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運營 > 從微信H5點擊保存圖片說起

從微信H5點擊保存圖片說起

時間:2023-05-21 11:40:02 | 來源:網(wǎng)站運營

時間:2023-05-21 11:40:02 來源:網(wǎng)站運營

從微信H5點擊保存圖片說起:微信H5里保存圖片,大都是通過長按操作,彈起actionsheet保存照片。但我們的部分用戶是老年群體,不知道怎么進行“長按”操作??紤]到這個因素,產(chǎn)品要求實現(xiàn)點擊保存按鈕來保存圖片。

不難想,你會立馬蹦出這幾個方案:

方案一 使用HTML5的download屬性

瀏覽器里,如果有點擊下載圖片的需求,可以使用download屬性,如:

<a href="me.png" download="me"></a>但在使用前,需要考慮下兩個問題:跨域問題和兼容問題。

1.跨域問題

download只對同源資源有效。MDN上關(guān)于這一點有說明,詳見:

想解決這個問題,也比較簡單,搭個代理轉(zhuǎn)發(fā)一下即可。

2.兼容性問題

caniuse上顯示的download屬性兼容情況如下:

圖中顯示QQ瀏覽器是不支持的,而微信內(nèi)置的瀏覽器和QQ瀏覽器使用的是一樣的內(nèi)核,即X5內(nèi)核,那基本可推斷出微信也是不支持download屬性的。

但我又有一點不甘心,決定親自實踐看是否支持download屬性。

var hasDownloadAttribute = 'download' in document.createElement('a')將該腳本加在網(wǎng)頁里,并在微信環(huán)境打開,運行結(jié)果居然是"true"。

只有兩種推論:

1)當前設(shè)備的微信內(nèi)置瀏覽器不是X5內(nèi)核

2)當前設(shè)備微信內(nèi)置瀏覽器是X5內(nèi)核,微信已經(jīng)開始支持download屬性了。

那怎么驗證當前設(shè)備微信內(nèi)置瀏覽器是不是X5內(nèi)核呢?在微信里打開

,結(jié)果顯示當前設(shè)備的微信內(nèi)置瀏覽器不是X5內(nèi)核。嗯,能解釋得通了。

而我當前設(shè)備上的微信內(nèi)置瀏覽器是什么呢?通過navigator.userAgent查看,當前設(shè)備上的微信內(nèi)置的瀏覽器是Chrome 78.0,內(nèi)核是Blink。

但是不是應(yīng)用了download屬性就可以實現(xiàn)微信H5點擊圖片下載了?

太天真。拋開兼容性問題,實踐下來,還是無法實現(xiàn)點擊保存圖片。保存圖片需要系統(tǒng)相冊的權(quán)限,只能由app本身來做,不論你是Webview還是微信內(nèi)置瀏覽器的網(wǎng)頁,如果沒有跟微信通信,調(diào)用app本身保存圖片的能力,無法實現(xiàn)點擊保存圖片。

方案二 使用download.js

download兼容性不好是吧?那我用第三方庫download.js可以了吧?

示例代碼如下:

import axios from 'axios';import download from 'downloadjs'; axios.get(someUrl, { responseType: 'blob'}).then(res => { download(res.data, "awesome.png", "image/png");})先講結(jié)論,同方案1一樣,只是解決了兼容性問題,但無法調(diào)起微信app保存圖片的能力。

不work沒關(guān)系,可以順便來看看download.js怎么兼容的。

download.js的源碼,我濃縮了一下,用偽代碼表示是這樣。

const saver = (url, mimeType) => { // 如果支持download屬性 if ('download' in anchor) { anchor.href = url; anchor.style.display = 'none'; document.body.appendChild(anchor); setTimeout(() => { anchor.click(); document.body.removeChild(anchor); setTimeout(() => { // 釋放通過createObjectURL創(chuàng)建的URL window.URL.revokeObjectUrl(blob); }, 250) }, 100) return; } // 兼容不支持download屬性的部分Safari瀏覽器 if (/(Version)//(/d+)/.(/d+)(?:/.(/d+))?.*Safari///.test(navigator.userAgent)) { if (/^data:/.test(url) { url = 'data:' + url.replace(/^data:([/w///-/+]+)/, defaultMime) } if (!window.open(url)) { location.href = url; } return } // 利用iframe來實現(xiàn)下載。需要注意的是,如果瀏覽器支持預(yù)覽該文件格式,則不能實現(xiàn)下載。 const f = document.createElement('iframe'); document.body.appendChild(f); f.src = url; setTimeout(() => { document.body.removeChild(f); }, 300)}// Case 1: 如果支持Blob和URLif (window.URL) { // 創(chuàng)建指向blob對象的URL const url = window.URL.createObjectURL(blob); saver(url); return;}// Case 2: 如果支持Blob和msSaveBlob,但不支持URL。if (navigator.msSaveBlob) { navigator.msSaveBlob(dataUrlToBlob(payload), filename); return;} // Case 3: 如果支持Blob,但不支持URL和msSaveBlob// 將blob轉(zhuǎn)成base64編碼的數(shù)據(jù)const reader = new FileReader()reader.readAsDataURL(blob)reader.onloadend = function () { const base64data = reader.result saver(base64data);}// Case 4: 如果Blob和URL都不支持if (!window.Blob && !window.URL) { const base64Data = window.btoa(blob); const url = `data:${mimeType};base64,${base64Data}`; saver(url);}上面有個比較關(guān)鍵的函數(shù):dataUrlToBlob。它主要是將dataUrl轉(zhuǎn)成Blob對象,保證msSaveBlob接收的參數(shù)是Blob對象實例。

function dataUrlToBlob (strUrl) { const parts = strUrl.split(/[:;,]/) const type = parts[1] const indexDecoder = strUrl.indexOf('charset') > 0 ? 3 : 2 // 如果字符串是base64編碼,解碼方法使用atob;否則使用decodeURIComponent。 const decoder = parts[indexDecoder] == 'base64' ? atob : decodeURIComponent // 解碼 const binData = decoder(parts.pop()) const mx = binData.length let i = 0 // 創(chuàng)建數(shù)組長度為mx的數(shù)組,其中數(shù)組元素都是0 const uiArr = new Uint8Array(mx) // 將解碼后的數(shù)據(jù)進行unicode編碼 for (i; i < mx; ++i) { uiArr[i] = binData.charCodeAt(i) } return new Blob([uiArr], { type })}總結(jié)一下就是:先看是否支持Blob和URL,再看是否支持download屬性。

雖然方案二是不work的,但解決瀏覽器里H5相關(guān)資源的下載可以使用download.js。

方案三 使用微信js-sdk

方案一和方案二不能下載圖片的原因,都在于沒有與原生app進行通信,調(diào)用原生app下載圖片的能力。那引入微信的js-sdk總可以了吧?

先說結(jié)論,就該應(yīng)用場景來說,不支持。

需要下載的圖片資源來源于管理系統(tǒng)后臺,而不是用戶。

而微信js-sdk需要用戶先從本地系統(tǒng)相冊上傳圖片到微信圖片服務(wù)器,才能從圖片服務(wù)器下載圖片到本地。文檔如下:

文檔里也有說明,上傳圖片的有效期是3天,所以為了長期為用戶提供下載服務(wù),還需要下載圖片到自己的服務(wù)器上。下載圖片需要前后調(diào)用三個API:wx.chooseImage、wx.uploadImage和wx.downloadImage。

wx.chooseImage({ count: 1, // 默認9 sizeType: ['original'], sourceType: ['album', 'camera'], success (res) { const localId = res.localIds[0] // 選擇圖片成功,上傳到微信圖片服務(wù)器 wx.uploadImage({ localId, // 需要上傳的圖片的本地ID,由chooseImage接口獲得 isShowProgressTips: 1, // 默認為1,顯示進度提示 success (res) { const serverId = res.serverId // 返回圖片的服務(wù)器端ID wx.downloadImage({ serverId, // 需要下載的圖片的服務(wù)器端ID,由uploadImage接口獲得 isShowProgressTips: 1, // 默認為1,顯示進度提示 success (res) { this.localId = res.localId } }) } }) }})

方案四 js手動實現(xiàn)長按事件,喚起actionsheet

已知的是用戶長按圖片,能喚起actionsheet,那肯定app和微信H5之間是有通信的,對touchstart和touchend事件有監(jiān)聽。那既然點擊事件無法喚起微信保存圖片的actionsheet,我能不能用js模擬用戶,手動實現(xiàn)長按事件呢?

onClick的回調(diào)里綁定longPress函數(shù)。

function longPress () { const target = document.getElementById('share-img') const startEvent = createTouchEvent(target, 'touchstart') target.dispatchEvent(startEvent) // 5s后觸發(fā)touchend setTimeout(() => { const endEvent = createTouchEvent(target, 'touchend') target.dispatchEvent(endEvent) }, 5000)}function createTouchEvent (touchTarget, type) { const event = document.createEvent('UIEvent') event.initUIEvent(type, true, true, window, 1) const touches = [{ target: touchTarget }] Object.defineProperties(event, { changedTouches: { value: touches } }) return event}實踐下來,雖然能模擬長按事件,但無法喚起actionsheet。究其原因,應(yīng)該是原生微信app頂層layer對用戶的長按手勢有監(jiān)聽。所以無論js里怎么模擬長按事件,永遠不是用戶的手勢操作,也無法觸發(fā)長按手勢回調(diào),喚起actionsheet。

微信里應(yīng)該也對UIWebview加了longPress的gesture recognizer。就iOS而言,偽代碼如下:

NSString *imgURL = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", touchPoint.x, touchPoint.y];NSString *urlToSave = [self.webView stringByEvaluatingJavaScriptFromString:imgURL];UILongPressGestureRecognizer* longPressed = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];longPressed.delegate = self;[self.webView addGestureRecognizer:longPressed];但微信H5里長按保存圖片,不止是頂層layer長按gensture的監(jiān)聽,也涉及到app與webview的通信。比如,app里可能會inject這段腳本到webview里進行長按事件的監(jiān)聽。

可以比較肯定的是,微信注入的腳本里,addEventListener的第三個參數(shù)useCapture option一定是設(shè)置成了true。因為touchstart回調(diào)里如果調(diào)用了event.preventDefault(),長按圖片是無法喚起保存圖片的actionsheet。

let startTime = 0;document.addEventListner('touchstart', function() { startTime = Date.now();}, true)document.addEventListener('touchend', function() { const endTime = Date.now(); if (endTime - startTime > 3000) { // dispatchLongTimeEvent(); }}, true)終上,我無法解決如何在微信H5里點擊保存圖片。

如果H5僅僅是微信內(nèi)置瀏覽器打開的網(wǎng)頁,就需要微信提供相應(yīng)的API支持;

如果H5是微信小程序打開的webview,需要webview和微信小程序可以通信,并調(diào)用微信小程序下載圖片的API。



關(guān)鍵詞:圖片,保存

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點擊下載Chrome瀏覽器
關(guān)閉