摘要:前言昨天寫了新手引導動畫的種實現(xiàn)方式里面用到了于是就順便了解了一下實現(xiàn)思路大概就是利用的標簽嵌入最后再利用繪制從而實現(xiàn)最終目的先讓大家看看效果示例示例其實寫的很清楚不過也相對比較簡單一點是已經(jīng)構建好的字符串其實我覺得整個過程里面最麻煩
前言
昨天寫了新手引導動畫的4種實現(xiàn)方式,
里面用到了 html2canvas 于是就順便了解了一下實現(xiàn)思路.
大概就是 利用 svg 的 foreignObject 標簽, 嵌入 dom, 最后再利用 canvas 繪制 svg. 從而實現(xiàn)最終目的.
先讓大家看看效果
MDN示例
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var data = ""; var DOMURL = window.URL || window.webkitURL || window; var img = new Image(); var svg = new Blob([data], {type: "image/svg+xml;charset=utf-8"}); var url = DOMURL.createObjectURL(svg); img.onload = function () { ctx.drawImage(img, 0, 0); DOMURL.revokeObjectURL(url); } img.src = url;
MDN示例其實寫的很清楚,不過也相對比較簡單一點, dom 是已經(jīng)構建好的字符串, 其實我覺得整個過程里面最麻煩的就是構建 dom. 所以接下來,我們就來看看具體怎么實現(xiàn)吧
第一步 遍歷目標節(jié)點的所有子元素,并構建對應的字符串/** * 遞歸遍歷所有子節(jié)點 * @param element Document Element 要計算的元素 * @param isTop Boolean 是否是最外層元素 **/ function renderDom (element, isTop) { let tag = element.tagName.toLowerCase() let str = `<${tag} ` // 最外層的節(jié)點,需要加 xmlns 命名空間 isTop && (str += `xmlns="http://www.w3.org/1999/xhtml" `) str += ` style="${getElementStyles(element)}"> ` if (element.children.length) { // 遞歸子元素 for (let el of element.children) { str += renderDom(el) } } else { str += element.innerHTML } str += `${tag}> ` return str }
這里只做了一個最簡單的處理,由于是簡單實現(xiàn),很多特殊情況沒考慮進去(如:單標簽, img等),有興趣的童鞋可以自己嘗試實現(xiàn)看看.最外層的元素, 需要加命名空間,否則無法識別
這里用到的 getElementStyles 就是獲取元素的最終渲染樣式,下一步會實現(xiàn).
第二步, 獲取元素的最終渲染樣式,并拼接成行內(nèi)樣式正常的 dom 元素, 是無法直接放在 foreignObject 里面準確地渲染的, 因為還要涉及到父子元素直接的屬性繼承, 元素默認屬性, 非行內(nèi)樣式無法渲染等問題.
所以我們要獲取每個元素的最終渲染樣式, 然后拼接成行內(nèi)樣式.
如何獲取元素的最終渲染樣式呢? 剛好,瀏覽器有提供一個 window.getComputedStyle() 方法可以做到.
// 計算每個 dom 的樣式 // 這里本來應該直接用 Object.keys + forEach 遍歷取出的 // 但是不知道為什么,遍歷取出的,會渲染不出來,應該是某些屬性有問題 // 暫時沒空去排查那些有問題,所以目前先把常用的直接寫死. function getElementStyles (el) { let css = window.getComputedStyle(el) let style = "" // 尺寸相關 style += `width:${css.width};` style += `height: ${css.height};` style += `line-height: ${css.lineHeight};` style += `max-height: ${css.maxHeight};` style += `min-height: ${css.minHeight};` style += `max-width: ${css.maxWidth};` style += `min-width: ${css.minWidth};` style += `font-size: ${css.fontSize};` // 顏色相關 style += `color: ${css.color};` style += `background: ${css.background};` // 邊框相關 style += `border: ${css.border};` style += `box-sizing: ${css.boxSizing};` // 位置相關 style += `margin: ${css.margin};` style += `padding: ${css.padding};` style += `position: ${css.position};` style += `left: ${css.left};` style += `right: ${css.right};` style += `top: ${css.top};` style += `bottom: ${css.bottom};` // 布局相關 style += `display: ${css.display};` style += `flex: ${css.flex};` return style }第三步, 渲染 svg
把拼接好的 svg 字符串用 Blob 對象 new 出來(Blob真的是個很強大的對象啊), 然后用 DOMURL.createObjectURL() 轉換為 url,
有了url, 接下來就看大家自由發(fā)揮了. 可以直接下載,也可以在 canvas 里繪制. 或者當作圖片直接插入到文檔...
// 主入口函數(shù) function shotScreen () { let target = document.querySelector(".content") let data = getSvgDomString(target) let DOMURL = window.URL || window.webkitURL || window; let img = new Image(); let svg = new Blob([data], {type: "image/svg+xml;charset=utf-8"}); let url = DOMURL.createObjectURL(svg); img.src = url; document.body.appendChild(img) } // 計算 svg 的字符串 function getSvgDomString (element) { return ` ` }
這里順便給個繪制到 canvas 里的代碼
// 如果想畫到 canvas 里面 let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); let img = new Image(); img.onload = function () { ctx.drawImage(img, 0, 0); DOMURL.revokeObjectURL(url); }最后
參考文檔:
MDN: 將 DOM 對象繪制到 canvas 中
MDN: foreignObject
完整的代碼在這里,可以直接運行看效果.
本文地址在->個人技術帖合集, 歡迎給個 start 或 follow
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100062.html
摘要:最近碰到個需求,需要把當前頁面生成,并下載。但這并不是真的截圖,而是通過遍歷頁面結構,收集所有元素信息及相應樣式,渲染出。由于只能將它能處理的生成,因此渲染出來的結果并不是與原來一致。 最近碰到個需求,需要把當前頁面生成pdf,并下載。弄了幾天,自己整理整理,記錄下來,我覺得應該會有人需要 :) 項目源碼地址:https://github.com/linwalker/... html2...
摘要:最近碰到個需求,需要把當前頁面生成,并下載。但這并不是真的截圖,而是通過遍歷頁面結構,收集所有元素信息及相應樣式,渲染出。由于只能將它能處理的生成,因此渲染出來的結果并不是與原來一致。 最近碰到個需求,需要把當前頁面生成pdf,并下載。弄了幾天,自己整理整理,記錄下來,我覺得應該會有人需要 :) 項目源碼地址:https://github.com/linwalker/... html2...
摘要:谷歌是通過來實現(xiàn)這個組件的,比較復雜谷歌的工具加載文件和截圖文件有興趣的同學可以看一下。高亮區(qū)域核心部分截圖搞定了,接下來就是高亮區(qū)域了。 幾乎所有的APP應用包括Web應用都需要一個意見反饋,這樣才能了解用戶對產(chǎn)品的意見和建議,以便于不斷提升完善自己的產(chǎn)品。目前的反饋組件一般有兩種,一種是打開一個反饋頁面填寫表單,另一種則是通過彈窗來完成,相比較而言第二種更加方便,而且更加容易組件化...
摘要:本人建議第二種,更保險三轉換的位圖不能被以上版本所識別。客戶使用的時候發(fā)現(xiàn)了這個問題,沒法。五離成功只有一步之遙了,使用了之后安卓手機不能將圖片分享給朋友。識別不了問題分析安卓能識別但不能識別矢量圖片解決辦法自己手寫咯。判斷手機為安卓還是。 前言 首先做個自我介紹,我是成都某企業(yè)的一名剛剛入行約一年的前端,在之前的開發(fā)過程中,遇到了問題,也解決了問題,但是在下一次解決相同問題的時候,只...
摘要:本人建議第二種,更保險三轉換的位圖不能被以上版本所識別。客戶使用的時候發(fā)現(xiàn)了這個問題,沒法。五離成功只有一步之遙了,使用了之后安卓手機不能將圖片分享給朋友。識別不了問題分析安卓能識別但不能識別矢量圖片解決辦法自己手寫咯。判斷手機為安卓還是。 前言 首先做個自我介紹,我是成都某企業(yè)的一名剛剛入行約一年的前端,在之前的開發(fā)過程中,遇到了問題,也解決了問題,但是在下一次解決相同問題的時候,只...
閱讀 3655·2021-09-22 15:15
閱讀 3559·2021-08-12 13:24
閱讀 1312·2019-08-30 15:53
閱讀 1822·2019-08-30 15:43
閱讀 1184·2019-08-29 17:04
閱讀 2793·2019-08-29 15:08
閱讀 1582·2019-08-29 13:13
閱讀 3088·2019-08-29 11:06