小編給大家分享一下canvas.toDataURL()報(bào)錯(cuò)怎么辦,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
創(chuàng)新互聯(lián)公司主要從事成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)沐川,十年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專(zhuān)業(yè),歡迎來(lái)電咨詢建站服務(wù):13518219792
報(bào)錯(cuò)詳盡信息
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
關(guān)鍵詞
canvas.toDataURL()
crossOrigin
Access-Control-Allow-Origin
前言
最近在做一個(gè)創(chuàng)意類(lèi)的圖片合成工具,大概齊就是通過(guò)拼接自定義的文字和圖片信息生成一張商品圖片類(lèi)似的功能,項(xiàng)目中用到了fabric.js這個(gè)畫(huà)板庫(kù),最后一步在保存圖片的時(shí)候報(bào)上面的一長(zhǎng)串錯(cuò)誤,墻內(nèi)墻外搜了一遍,給出的解決方案都不全面,為避免同學(xué)們?cè)俅尾瓤樱谑怯辛舜宋?/p>
正文
我們?cè)赾onvertDOM2Image時(shí),如果DOM內(nèi)存在圖片資源,該資源所在的web-server是不支持跨域的,保存圖片是不會(huì)成功的。
因此在排查問(wèn)題時(shí),首先要確定
web-server是否允許跨域,我們以nginx為例,response-header內(nèi)要存在Access-Control-Allow-Orgin:xxxx(可以是*,安全性要求比較高的可以根據(jù)主域名自定義)
如果是img標(biāo)簽, 是否添加了crossorigin="anonymous", 如果是Image對(duì)象,同樣是否添加了改屬性obj.crossOrigin='anonymous'
如果還不行,這里先不把答案放出來(lái),我們先看看栗子
在接下來(lái)的栗子中我們會(huì)用到將Image轉(zhuǎn)換為canvas對(duì)象的方法
function convertImageToCanvas(image) { // 創(chuàng)建canvas DOM元素,并設(shè)置其寬高和圖片一樣 let canvas = document.createElement("canvas"); canvas.width = image.width; canvas.height = image.height; canvas.getContext("2d").drawImage(image, 0, 0); // 我們?cè)趯?shí)際的開(kāi)發(fā)中,需要將抓換后的base64圖片編碼傳輸?shù)胶笈_(tái)圖片服務(wù)器,由server直接存儲(chǔ)或者生成一張圖片; // 所以會(huì)用到 toDataURL console.log(canvas.toDataURL('image/jpeg')) return canvas; }
栗子1
本地未設(shè)置跨域允許選項(xiàng)crossorigin=anonymous,web-server未設(shè)置跨域允許選項(xiàng)
本地未設(shè)置跨域允許選項(xiàng)crossorigin=anonymous,web-server未設(shè)置跨域允許選項(xiàng)
function setCanvas(DOMID) { let img = document.getElementById(DOMID).querySelector('img') document.body.appendChild(convertImageToCanvas(img)) }
很顯然,報(bào)錯(cuò)
栗子2
本地標(biāo)簽內(nèi)設(shè)置跨域允許選項(xiàng), web-server未設(shè)置跨域允許選項(xiàng)
這次連圖片都出不來(lái),直接報(bào)錯(cuò)
這個(gè)好理解,瀏覽器同源策略限制嘛
Access to image at 'xxxx' (redirected from 'xxxx') from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
栗子3
本地未設(shè)置跨域允許選項(xiàng)crossorigin=anonymous
, web-server
設(shè)置跨域允許選項(xiàng)
報(bào)錯(cuò),妥妥的。
栗子4
本地標(biāo)簽內(nèi)設(shè)置跨域允許選項(xiàng)crossorigin=anonymous
, web-server
設(shè)置跨域允許選項(xiàng)
本地設(shè)置跨域允許選項(xiàng)`crossorigin=anonymous`,`web-server`設(shè)置跨域允許選項(xiàng)
居然可以了,但是~如果在代碼內(nèi)設(shè)置跨域呢?
栗子5
function setCanvas(DOMID) { let img = document.getElementById(DOMID).querySelector('img') img.crossOrigin= 'anonymous' document.body.appendChild(convertImageToCanvas(img)) }
報(bào)錯(cuò)
我看官方文檔的意思是必須同步設(shè)置crossOrigin=anonymous,該圖片憑證才會(huì)被信任
This means that CORS is enabled and credentials are sent if the image is fetched from the same origin from which the document was loaded.
否則緩存的圖像數(shù)據(jù)仍然會(huì)被畫(huà)布視為有污染的跨源內(nèi)容.
怎么辦?重新取一遍圖片唄,加個(gè)隨機(jī)數(shù),圖片還是那個(gè)圖片,不過(guò)加了個(gè)馬甲,瀏覽器就不認(rèn)識(shí)了
栗子6
function setCanvas(DOMID) { let img = document.getElementById(DOMID).querySelector('img') img.src =img.src+'?v='+Math.random() img.crossOrigin= 'anonymous' img.onload=()=>{ document.body.appendChild(convertImageToCanvas(img)) } }
binggo, 完美解決
所以我們?cè)陂_(kāi)發(fā)過(guò)程中,新建圖片,更換圖片,還原圖片等功能代碼內(nèi),最好每一次都加個(gè)隨機(jī)數(shù),以保證源都是最新的,不走緩存
多說(shuō)一點(diǎn)吧,關(guān)于fabric.js的相關(guān)跨域配置見(jiàn)下方
let _fabricConfig = { // .... crossOrigin:'anonymous' }; /* fabric對(duì)象 */ let _fabricObj = new fabric.Canvas(id, _fabricConfig); // 新建圖片對(duì)象時(shí) let imgInstance = new fabric.Image.fromURL(url + '?v='+ Math.random(), img => {}, {crossOrigin: 'anonymous'}) // 動(dòng)態(tài)更新圖片時(shí) let currentActive = _fabricInstance.getActiveObj(); currentActive.setSrc(randomURL, img =>{}, {crossOrigin: 'anonymous'})
以上是“canvas.toDataURL()報(bào)錯(cuò)怎么辦”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!