Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产成人一区二区精品非洲,久久精品国产三级不卡,99国产精品久久

          整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢(xún)熱線(xiàn):

          html中如何設(shè)置默認(rèn)圖片?

          大家可能都知道img標(biāo)簽是怎么設(shè)置默認(rèn)圖片的,但是你知道background-img是如何設(shè)置默認(rèn)圖片的嘛?

          html中如何設(shè)置默認(rèn)圖片?

          JS監(jiān)聽(tīng)

          <img src="圖片的url地址" alt="圖片描述" onerror="this.src='默認(rèn)圖片的url地址'"/>
          

          這里是應(yīng)用了img標(biāo)簽的onerror事件,當(dāng)加載失敗就用默認(rèn)圖片地址。但是這里可能出現(xiàn)如果默認(rèn)圖片地址也加載不出來(lái),或者失敗,在IE內(nèi)核的瀏覽器下就會(huì)反復(fù)加載,出現(xiàn)死循環(huán),最后造成堆棧溢出錯(cuò)誤。因此, 需要用下面兩種方法解決:

          1. 更改 onerror 代碼為其它處理方式或者確保 onerror 中的默認(rèn)圖片足夠小,并且存在。
          2. 控制 onerror 事件只觸發(fā)一次,需要增加這句話(huà):this.onerror=null。
          <img src="圖片的url地址" alt="圖片描述" onerror="this.src='默認(rèn)圖片的url地址';this.onerror=null"/>
          

          html中如何設(shè)置默認(rèn)圖片?

          background-img

          background是可以設(shè)置多個(gè)背景圖片的,最前面的優(yōu)先級(jí)越高,所以如果javan1.jpg沒(méi)有就好顯示第二個(gè)javan2.jpg,如果還沒(méi)有就好顯示第三個(gè)javan3.jpg。

          第一種:

          background: url("javan1.jpg") 0 0 no-repeat,
           url("javan2.jpg") 200px 0 no-repeat,
           url("javan3.jpg") 400px 201px no-repeat;
          

          第二種:

          background-image: url("javan1.jpg"), url("javan2.jpg"), url("javan3.jpg");
          background-repeat: no-repeat, no-repeat, no-repeat; 
          background-position: 0 0, 200px 0, 400px 201px;
          

          需要注意的是:IE8及更早瀏覽器不支持CSS3 background-image,即不支持多背景和使用漸變作為背景圖像。

          拓展-CSS漸變

          background-image: linear-gradient( [ <angle> | <side-or-corner> ,]? <color-stop> [, <color-stop>]+ );
          

          上面這種CSS語(yǔ)法我們經(jīng)常見(jiàn)到,可能有人看不懂具體的意思,其實(shí)上面的些符號(hào)含義與正則表達(dá)式有很多一致之處:

          1. [] 在正則中表示一個(gè)字符類(lèi),這里,你可以理解為一個(gè)小單元。
          2. | 表示候選。也就是“或者”的意思,要么前面的,要么就后面的。
          3. ? 為量詞,表示0個(gè)或1個(gè),言外之意就是,你可以不指定方向,直接漸變色走起。
          4. + 也是量詞,表示1個(gè)或者更多個(gè)。因此,終止顏色是不可缺少的。例如:linear-gradient(red)是醬油命,白板。
          5. <> 中的是關(guān)鍵字,主要是讓開(kāi)發(fā)人員知道這里應(yīng)該放些什么內(nèi)容。

          水平漸變

          {
           background-image: linear-gradient(left, red 100px, yellow 200px);
          }
          

          CSS水平漸變

          左上角漸變

          {
           background-image:linear-gradient(left top, red 100px, yellow 200px);
          }
          

          CSS左上角漸變

          公告

          喜歡小編的點(diǎn)擊關(guān)注,了解更多資源!

          者開(kāi)源了一個(gè)Web思維導(dǎo)圖,在做導(dǎo)出為圖片的功能時(shí)走了挺多彎路,所以通過(guò)本文來(lái)記錄一下。

          思維導(dǎo)圖的節(jié)點(diǎn)和連線(xiàn)都是通過(guò) svg渲染的,作為一個(gè)純 js 庫(kù),我們不考慮通過(guò)后端來(lái)實(shí)現(xiàn),所以只能思考如何通過(guò)純前端的方式來(lái)實(shí)現(xiàn)將svg或html轉(zhuǎn)換為圖片。

          使用img標(biāo)簽結(jié)合canvas導(dǎo)出

          我們都知道 img 標(biāo)簽可以顯示 svg,然后 canvas 又可以渲染 img,那么是不是只要將svg渲染到img標(biāo)簽里,再通過(guò)canvas導(dǎo)出為圖片就可以呢,答案是肯定的。

          const svgToPng = async (svgStr) => {
              // 轉(zhuǎn)換成blob數(shù)據(jù)
              let blob = new Blob([svgStr], {
                type: 'image/svg+xml'
              })
              // 轉(zhuǎn)換成data:url數(shù)據(jù)
              let svgUrl = await blobToUrl(blob)
              // 繪制到canvas上
              let imgData = await drawToCanvas(svgUrl)
              // 下載
              downloadFile(imgData, '圖片.png')
          }

          svgStr是要導(dǎo)出的svg字符串,比如:

          然后通過(guò)Blob構(gòu)造函數(shù)創(chuàng)建一個(gè)類(lèi)型為image/svg+xml的blob數(shù)據(jù),接下來(lái)將blob數(shù)據(jù)轉(zhuǎn)換成data:URL:

          const blobToUrl = (blob) => {
              return new Promise((resolve, reject) => {
                  let reader = new FileReader()
                  reader.onload = evt => {
                      resolve(evt.target.result)
                  }
                  reader.onerror = err => {
                      reject(err)
                  }
                  reader.readAsDataURL(blob)
              })
          }

          其實(shí)就是base64格式的字符串。

          接下來(lái)就可以通過(guò)img來(lái)加載,并渲染到canvas里進(jìn)行導(dǎo)出:

          const drawToCanvas = (svgUrl) => {
              return new Promise((resolve, reject) => {
                const img = new Image()
                // 跨域圖片需要添加這個(gè)屬性,否則畫(huà)布被污染了無(wú)法導(dǎo)出圖片
                img.setAttribute('crossOrigin', 'anonymous')
                img.onload = async () => {
                  try {
                    let canvas = document.createElement('canvas')
                    canvas.width = img.width
                    canvas.height = img.height
                    let ctx = canvas.getContext('2d')
                    ctx.drawImage(img, 0, 0, img.width, img.height)
                    resolve(canvas.toDataURL())
                  } catch (error) {
                    reject(error)
                  }
                }
                img.onerror = e => {
                  reject(e)
                }
                img.src = svgUrl
              })
          }

          canvas.toDataURL()方法返回的也是一個(gè)base64格式的data:URL字符串:

          最后就可以通過(guò)a標(biāo)簽來(lái)下載:

          const downloadFile = (file, fileName) => {
            let a = document.createElement('a')
            a.href = file
            a.download = fileName
            a.click()
          }

          實(shí)現(xiàn)很簡(jiǎn)單,效果也不錯(cuò),不過(guò)這樣就沒(méi)問(wèn)題了嗎,接下來(lái)我們插入兩張圖片試試。

          處理存在圖片的情況

          第一張圖片是使用base64的data:URL方式插入的,第二張圖片是使用普通url插入的:

          導(dǎo)出結(jié)果如下:

          可以看到,第一張圖片沒(méi)有問(wèn)題,第二張圖片裂開(kāi)了,可能你覺(jué)得同源策略的問(wèn)題,但實(shí)際上換成同源的圖片,同樣也是裂開(kāi)的,解決方法很簡(jiǎn)單,遍歷svg節(jié)點(diǎn)樹(shù),將圖片都轉(zhuǎn)換成data:URL的形式即可:

          // 操作svg使用了@svgdotjs/svg.js庫(kù)
          const transfromImg = (svgNode) => {
              let imageList = svgNode.find('image')
              let task = imageList.map(async item => {
                // 獲取圖片url
                let imgUlr = item.attr('href') || item.attr('xlink:href')
                // 已經(jīng)是data:URL形式不用轉(zhuǎn)換
                if (/^data:/.test(imgUlr)) {
                  return
                }
                // 轉(zhuǎn)換并替換圖片url
                let imgData = await drawToCanvas(imgUlr)
                item.attr('href', imgData)
              })
              await Promise.all(task)
              return svgNode.svg()// 返回svg html字符串
          }

          這里使用了前面的drawToCanvas方法來(lái)將圖片轉(zhuǎn)換成data:URL,這樣導(dǎo)出就正常了:

          到這里,將純 svg 轉(zhuǎn)換為圖片就基本沒(méi)啥問(wèn)題了。

          處理存在foreignObject標(biāo)簽的情況

          svg提供了一個(gè)foreignObject標(biāo)簽,可以插入html節(jié)點(diǎn),實(shí)際上,筆者就是使用它來(lái)實(shí)現(xiàn)節(jié)點(diǎn)的富文本編輯效果的:

          接下來(lái)使用前面的方式來(lái)導(dǎo)出,結(jié)果如下:

          明明顯示沒(méi)有問(wèn)題,導(dǎo)出時(shí)foreignObject內(nèi)容卻發(fā)生了偏移,這是為啥呢,其實(shí)是因?yàn)槟J(rèn)樣式的問(wèn)題,頁(yè)面全局清除了margin和padding,以及將box-sizing設(shè)置成了border-box:

          那么當(dāng)svg存在于文檔樹(shù)中時(shí)是沒(méi)有問(wèn)題的,但是導(dǎo)出時(shí)使用的是svg字符串,是脫離于文檔的,所以沒(méi)有這個(gè)樣式覆蓋,那么顯示自然會(huì)出現(xiàn)問(wèn)題,知道了原因,解決方法有兩種,一是遍歷所有嵌入的html節(jié)點(diǎn),手動(dòng)添加內(nèi)聯(lián)樣式,注意一定要給所有的html節(jié)點(diǎn)都添加,只給svg、foreignObject或最外層的html節(jié)點(diǎn)添加都是不行的;第二種是直接在foreignObject標(biāo)簽里添加一個(gè)style標(biāo)簽,通過(guò)style標(biāo)簽來(lái)加上樣式,并且只要給其中一個(gè)foreignObject標(biāo)簽添加就可以了,兩種方式看你喜歡哪種,筆者使用的是第二種:

          const transformForeignObject = (svgNode) => {
              let foreignObjectList = svgNode.find('foreignObject')
              if (foreignObjectList.length > 0) {
                  foreignObjectList[0].add(SVG(`<style>
                  * {
                      margin: 0;
                      padding: 0;
                      box-sizing: border-box;
                  }
                  </style>`))
              }
              return svgNode.svg()
          }

          導(dǎo)出結(jié)果如下:

          可以看到,一切正常。

          關(guān)于兼容性的問(wèn)題,筆者測(cè)試了最新的chrome、firefox、opera、safari、360急速瀏覽器,運(yùn)行都是正常的。

          踩坑記錄

          前面介紹的是筆者目前采用的方案,看著實(shí)現(xiàn)其實(shí)非常簡(jiǎn)單,但是過(guò)程漫長(zhǎng)且坎坷,接下來(lái),開(kāi)始我的表演。

          foreignObject標(biāo)簽內(nèi)容在firefox瀏覽器上無(wú)法顯示

          對(duì)于svg的操作筆者使用的是svg.js庫(kù),創(chuàng)建富文本節(jié)點(diǎn)的核心代碼大致如下:

          import { SVG, ForeignObject } from '@svgdotjs/svg.js'
          
          let html = `<div>節(jié)點(diǎn)文本</div>`
          let foreignObject = new ForeignObject()
          foreignObject.add(SVG(html))
          g.add(foreignObject)

          SVG方法是用來(lái)將一段html字符串轉(zhuǎn)換為dom節(jié)點(diǎn)的。

          在chrome瀏覽器和opera瀏覽器上渲染非常正常,但是在firefox瀏覽器上foreignObject標(biāo)簽的內(nèi)容完全渲染不出來(lái):

          檢查元素也看不出有任何問(wèn)題,并且神奇的是只要在控制臺(tái)元素里編輯一下嵌入的html內(nèi)容,它就可以顯示了,百度搜索了一圈,也沒(méi)找到解決方法,然后因?yàn)閒irefox瀏覽器占有率并不高,于是這個(gè)問(wèn)題就擱淺了。

          使用img結(jié)合canvas導(dǎo)出圖片里foreignObject標(biāo)簽內(nèi)容為空

          chrome瀏覽器雖然渲染是正常的:

          但是使用前面的方式導(dǎo)出時(shí)foreignObject標(biāo)簽內(nèi)容卻是跟在firefox瀏覽器里顯示一樣是空的:

          firefox能忍這個(gè)不能忍,于是嘗試使用一些將html轉(zhuǎn)換為圖片的庫(kù)。

          使用html2canvas、dom-to-image等庫(kù)

          使用html2canvas:

          import html2canvas from 'html2canvas'
          
          const useHtml2canvas = async (svgNode) => {
              let el = document.createElement('div')
              el.style.position = 'absolute'
              el.style.left = '-9999999px'
              el.appendChild(svgNode)
              document.body.appendChild(el)// html2canvas轉(zhuǎn)換需要被轉(zhuǎn)換的節(jié)點(diǎn)在文檔中
              let canvas = await html2canvas(el, {
                  backgroundColor: null
              })
              mdocument.body.removeChild(el)
              return canvas.toDataURL()
          }

          html2canvas可以成功導(dǎo)出,但是存在一個(gè)問(wèn)題,就是foreignObject標(biāo)簽里的文本樣式會(huì)丟失:

          這應(yīng)該是html2canvas的一個(gè)bug,不過(guò)看它這issues數(shù)量和提交記錄:

          指望html2canvas改是不現(xiàn)實(shí)的,于是又嘗試使用dom-to-image:

          import domtoimage from 'dom-to-image'
          
          const dataUrl = domtoimage.toPng(el)

          發(fā)現(xiàn)dom-to-image更不行,導(dǎo)出完全是空白的:

          并且它上一次更新時(shí)間已經(jīng)是五六年前,所以沒(méi)辦法,只能回頭使用html2canvas。

          后來(lái)有人建議使用dom-to-image-more,粗略看了一下,它是在dom-to-image庫(kù)的基礎(chǔ)上修改的,嘗試了一下,發(fā)現(xiàn)確實(shí)可以,于是就改為使用這個(gè)庫(kù),然后又有人反饋在一些瀏覽器上導(dǎo)出節(jié)點(diǎn)內(nèi)容是空的,包括firefox、360,甚至chrome之前的版本都不行,筆者只能感嘆,太難了,然后又有人建議使用上一個(gè)大版本,可以解決在firefox上的導(dǎo)出問(wèn)題,但是筆者試了一下,在其他一些瀏覽器上依舊存在問(wèn)題,于是又在考慮要不要換回html2canvas,雖然它存在一定問(wèn)題,但至少不是完全空的。

          解決foreignObject標(biāo)簽內(nèi)容在firefox瀏覽器上無(wú)法顯示的問(wèn)題

          用的人多了,這個(gè)問(wèn)題又有人提了出來(lái),于是筆者又嘗試看看能不能解決,之前一直認(rèn)為是firefox瀏覽器的問(wèn)題,畢竟在chrome和opera上都是正常的,這一次就想會(huì)不會(huì)是svgjs庫(kù)的問(wèn)題,于是就去搜它的issue,沒(méi)想到,還真的搜出來(lái)了issue,大意就是因?yàn)橥ㄟ^(guò)SVG方法轉(zhuǎn)換的dom節(jié)點(diǎn)是在svg的命名空間下,也就是使用document.createElementNS方法創(chuàng)建的,導(dǎo)致部分瀏覽器渲染不出來(lái),歸根結(jié)底,這還是不同瀏覽器對(duì)于規(guī)范的不同實(shí)現(xiàn)導(dǎo)致的:

          你說(shuō)chrome很強(qiáng)吧,確實(shí),但是無(wú)形中它阻止了問(wèn)題的暴露。

          知道了原因,那么修改也很簡(jiǎn)單了,只要將SVG方法第二個(gè)參數(shù)設(shè)為true即可,或者自己來(lái)創(chuàng)建節(jié)點(diǎn)也可以:

          foreignObject.add(document.createElemnt('div'))

          果然,在firefox瀏覽器上正常渲染了。

          解決img結(jié)合canvas導(dǎo)出圖片為空的問(wèn)題

          解決了在firefox瀏覽器上foreignObject標(biāo)簽為空的問(wèn)題后,自然會(huì)懷疑之前使用img結(jié)合canvas導(dǎo)出圖片時(shí)foreignObject標(biāo)簽為空會(huì)不會(huì)也是因?yàn)檫@個(gè)問(wèn)題,同時(shí)了解了一下dom-to-image庫(kù)的實(shí)現(xiàn)原理,發(fā)現(xiàn)它也是通過(guò)將dom節(jié)點(diǎn)添加到svg的foreignObject標(biāo)簽中實(shí)現(xiàn)將html轉(zhuǎn)換成圖片的,那么就很搞笑了,我本身要轉(zhuǎn)換的內(nèi)容就是一個(gè)嵌入了foreignObject標(biāo)簽的svg,使用dom-to-image轉(zhuǎn)換,它會(huì)再次把傳給它的svg添加到一個(gè)foreignObject標(biāo)簽中,這不是套娃嗎,既然dom-to-image-more能通過(guò)foreignObject標(biāo)簽成功導(dǎo)出,那么不用它必然也可以,到這里基本確信之前不行就是因?yàn)槊臻g的問(wèn)題。

          果然,在去掉了dom-to-image-more庫(kù)后,重新使用之前的方式成功導(dǎo)出了,并且在firefox、chrome、opera、360等瀏覽器中都不存在問(wèn)題,兼容性反而比dom-to-image-more庫(kù)好。

          總結(jié)

          雖然筆者的實(shí)現(xiàn)很簡(jiǎn)單,但是dom-to-image-more這個(gè)庫(kù)實(shí)際上有一千多行代碼,那么它到底多做了些什么呢,點(diǎn)個(gè)關(guān)注,我們下一篇文章再見(jiàn)。

          題的引出是這樣的,在一個(gè)項(xiàng)目中有大量的頁(yè)面主體是table做數(shù)據(jù)展示,所以就封裝了一個(gè)table的組件,提供動(dòng)態(tài)渲染的方案。有個(gè)問(wèn)題是數(shù)據(jù)類(lèi)型中有圖片,對(duì)于圖片的加載失敗我們需要做容錯(cuò)。一般我們的思路都是對(duì)img綁定error事件,替換該圖片為一個(gè)默認(rèn)的圖片。但是error事件是不會(huì)冒泡的,我們渲染是動(dòng)態(tài)的,我們不能delegate事件到body上。如果將處理寫(xiě)在js里,那么每次渲染的時(shí)候都要去給圖片綁定error事件,寫(xiě)在模板里拼接(內(nèi)聯(lián)事件)又會(huì)很麻煩(我采取的方案是用戶(hù)編寫(xiě)基本th,td模板,所以需要使用者拼接,思考過(guò)走配置的方法初始化table這個(gè)問(wèn)題可以忽略。。。)

          博主也是個(gè)糾結(jié)的人,有沒(méi)有更好的解決方案呢?下面介紹一個(gè)css黑魔法,用偽元素對(duì)圖片加載失敗做處理。

          什么是偽元素?科普鏈接:http://www.w3school.com.cn/css/css_pseudo_elements.asp

          css知識(shí)扎實(shí)的人肯定會(huì)有個(gè)疑問(wèn),img是可替換元素(科普:http://www.cnblogs.com/wkylin/archive/2011/05/12/2044328.html),是不能應(yīng)用偽元素的啊?!

          對(duì),沒(méi)錯(cuò),是不能用,至于黑魔法嘛~img不能用,但是加載失敗了能不能用呢?

          哈哈哈,我們?cè)赾hrome下測(cè)試看下:

          有的!!!那我們后面可做的事情就思路了啊,哈哈哈

          后面引入我寫(xiě)的一個(gè)demo

          正常的圖片:

          容錯(cuò)后的:

          至于為什么圖片加載失敗后,會(huì)可以使用偽元素,我的理解大概是這樣的。當(dāng)加載成功的時(shí)候img是沒(méi)有任何子節(jié)點(diǎn)的,befor和after是在元素的內(nèi)容前后插入內(nèi)容。但當(dāng)圖片加載失敗之后,是不是把替代文本作為字內(nèi)容了呢?后面我會(huì)用一個(gè)偽元素標(biāo)簽是試驗(yàn)?你們猜到是哪個(gè)了么?

          兼容性:

          在ios的Safari和uc上不能實(shí)現(xiàn),so 這個(gè)方案還是要考慮下的

          ╮(╯▽╰)╭,博主也是糾結(jié)啊,如果有更好的方案可以和我聯(lián)系

          額,不對(duì),跑題了,我們今天是介紹這個(gè)偽元素的黑魔法的,哈哈哈~


          主站蜘蛛池模板: 国产a∨精品一区二区三区不卡| 精品无码AV一区二区三区不卡| 亚洲人成网站18禁止一区| 日本一道一区二区免费看| 无码毛片一区二区三区中文字幕| 一区二区三区视频在线播放| 亚洲一区精品无码| 无码精品尤物一区二区三区| 韩国精品一区视频在线播放| 一区二区三区精品高清视频免费在线播放| 国产一区二区精品久久岳√| 在线视频一区二区三区三区不卡 | 国产高清一区二区三区视频| 日韩精品一区二区三区在线观看| 嫩B人妻精品一区二区三区| 亚洲第一区视频在线观看| 日韩精品一区二区三区中文版 | 2022年亚洲午夜一区二区福利 | 末成年女A∨片一区二区| 无码一区二区三区在线| 亚洲第一区在线观看| 国产精品日本一区二区在线播放| 国产成人午夜精品一区二区三区| 国产福利电影一区二区三区| 亚洲天堂一区二区三区| 日韩精品无码Av一区二区| 制服丝袜一区在线| 一区二区三区免费视频网站| 精品女同一区二区三区免费站| 免费无码一区二区| 日韩一区二区在线视频| 国产一区二区三区在线视頻| 日韩高清一区二区| 精品无码日韩一区二区三区不卡 | 91精品一区国产高清在线| 国产精品无码一区二区在线观| 日本高清成本人视频一区| 在线视频精品一区| 亚洲一区二区三区高清在线观看| 国精产品一区二区三区糖心| 国产产一区二区三区久久毛片国语|