摘要:谷歌是通過來實現這個組件的,比較復雜谷歌的工具加載文件和截圖文件有興趣的同學可以看一下。高亮區域核心部分截圖搞定了,接下來就是高亮區域了。
幾乎所有的APP應用包括Web應用都需要一個意見反饋,這樣才能了解用戶對產品的意見和建議,以便于不斷提升完善自己的產品。目前的反饋組件一般有兩種,一種是打開一個反饋頁面填寫表單,另一種則是通過彈窗來完成,相比較而言第二種更加方便,而且更加容易組件化。
國內比較典型的有像知乎,百度這樣類型的反饋組件
國外則有谷歌的
由于本人比較喜歡谷歌的material design,而且谷歌的反饋組件功能也比較齊全,仿照谷歌的組件寫一個自己的通用組件。
下面是PC和手機上的效果圖:
demo演示
項目github地址
首先根據谷歌的反饋插件分析需要實現哪些功能,這個組件在很多谷歌頁面中都會出現,谷歌搜索頁出現的位置是底部。
根據實際操作能知道這個組件至少要包含這些功能:
截取當前屏幕;
能編輯頁面的高亮或者遮擋區域;
可以適應pc于手機;
知道功能后就能一步步開始實現它了。谷歌是通過iframe來實現這個組件的,比較復雜
谷歌的feedback工具加載文件:load.js和截圖文件screenshot.min.js有興趣的同學可以看一下。
這里使用自己的思路,使用現成模塊來簡單實現這個功能。
需要獲取當前屏幕內容,第一時間反應是使用canvas了,先把dom元素畫到canvas如何再生成圖片,幸好有一個牛掰的模塊叫做html2canvas,它可以將指定的DOM元素繪制到canvas上。
安裝html2canvas
npm i html2canvas
html2canvas 1.0.0版本中可以使用作者提供的html2canvas-proxy模塊來實現跨越資源代理。具體配置可以參考文檔。順便提一下,之前0.5.0版本中,html2canvas提供的代理方便不太好使,解決的方法是自己啟動一個處理服務,在頁面中遇到跨域圖片資源,使用服務將圖片轉成base64格式然后回填到圖片src屬性上,這樣來實現跨越圖片截圖。
如果頁面上不僅僅有圖片還有視頻該怎么辦呢,怎么截取視頻圖片呢?html2canvas是不支持截取video標簽內容的,但是html2canvas截圖時可以渲染元素的背景圖片。那么如果可以獲取視頻當前播放的幀,把這一幀作為video標簽的background,html2canvas就能讀取到了。
如何讀取video的幀,這個canvas的drawImage()方法就能做到(注意不能獲取跨域的視頻資源)。
let video = videoItem[0]; if(!video.style.backgroundImage) { let w = $(video).width(); let h = $(video).height(); $(video).after(""); let canvas = $(video).next("canvas").css({display: "none"}); let ctx = canvas.get(0).getContext("2d"); ctx.drawImage(video, 0, 0, w, h); try { video.style.backgroundImage = "url("+ canvas.get(0).toDataURL("image/png") +")"; }catch (e) { console.log(e) }finally { canvas.remove(); } }
做完這些準備就可以開始時截圖了
html2canvas(document.body, { proxy: this.props.proxy || "", width: window.innerWidth, height: window.innerHeight, x: document.documentElement.scrollLeft || document.body.scrollLeft, y: document.documentElement.scrollTop || document.body.scrollTop, }).then((canvas) => { let src = canvas.toDataURL("image/png"); ... }).catch((e) => { });
注意:html2canvas v1.0.0使用promise,v0.5.0采用的是回調函數。
2.高亮區域核心部分截圖搞定了,接下來就是高亮區域了。高亮分為兩部分:
鼠標放在頁面上識別當前鼠標是在哪個DOM元素上然后將這個DOM元素高亮,給用戶提供一個快捷選區方式。
用戶自己用鼠標選區一個高亮區域。
第二點很容易實現,只有鼠標按下時記錄點擊點位置,然后隨著鼠標移動計算與初始點位置的差值就能得到一個區域了,那么怎么識別鼠標是放在哪個DOM元素上呢?有一個Web API可以輕松實現這個功能那就是elementsFromPoint。
elementsFromPoint() 方法可以獲取到當前視口內指定坐標處,由里到外排列的所有元素。
使用方法很簡單,只要給x,y坐標就行了。
var elements = document.elementsFromPoint(x, y);
這個方法返回的是一個包含當前鼠標所在位置的DOM元素數組。元素在數組中的位置與元素的z軸位置和元素包含關系有關,z軸越大位置越靠前,子元素比父元素靠前。
如果是這個結構那么當鼠標在img標簽上document.elementsFromPoint(x, y)返回的值是這樣的
[img, p, div]
得到元素后那么后續的操作就簡單了,在一個半透明的黑色區域上摳出透明部分,顯然css是實現不了的,那么就上canvas吧。
首先要畫一個半透明的遮罩:
let canvas = this.refs.canvas; if (!this.ctx) { this.ctx = canvas.getContext("2d"); } let docWidth = document.body.clientWidth, docHeight = document.body.clientHeight; if(docHeight < window.innerHeight) { docHeight = window.innerHeight; } canvas.width = docWidth; canvas.height = docHeight; canvas.style.width = docWidth; canvas.style.height = docHeight; this.ctx.fillStyle = "rgba(0,0,0,0.3)"; this.ctx.fillRect(0, 0, docWidth, docHeight);
準備完遮罩就可以開始扣圖了。通過elementsFromPoint的到元素后使用getBoundingClientRect()方法得到元素的位置信息。 getBoundingClientRect()用于獲得頁面中某個元素的左,上,右和下分別相對瀏覽器視窗的位置以及元素寬高。
寬高,位置信息都有了就可以開始繪制了:
this.ctx.lineWidth = "5"; this.ctx.strokeStyle = "#FEEA4E"; this.ctx.rect(x, y, width, height); this.ctx.stroke(); this.ctx.clearRect(x, y, width, height);
同理如果不是高亮而是遮擋只要把清除區域換成繪制一個半透明黑色區域就可以了。
要注意每次畫新區域時要清除上次繪制的內容所以每次都得初始化一次canvas內容。
由于手機頁面中的反饋界面與PC差距太大所以不能采用同一套模板,通過一個state來區分該渲染那種類型。在組件willMount的時候判斷設備類型
let device = "pc"; let ua = navigator.userAgent; let ipad = ua.match(/(iPad).*OSs([d_]+)/), isIphone = !ipad && ua.match(/(iPhonesOS)s([d_]+)/), isAndroid = ua.match(/(Android)s+([d.]+)/), isMobile = isIphone || isAndroid; if (isMobile) { device = "mobile"; this.setState({ device: device, }); }
得到設備后根據設備進行渲染
{ this.state.device == "pc"?: }
需要注意的是有些手機瀏覽器在打開輸入法后會導致頁面窗口變化所以需要監聽窗口變化去做適配調整
2.使用 1.安裝:使用npm
npm install react-googlefeedback --save-dev2.使用
react中:
import React from "react"; import ReactDOM from "react-dom"; import Feedback from "react-googlefeedback"; import "react-googlefeedback/dist/style.css"; const license = `如出于法律原因需要請求更改內容,請前往 法律幫助 頁面。系統可能已將部分 帳號和系統信息 發送給Google。我們將根據自己的 隱私權政策和服務條款 使用您提供的信息幫助解決技術問題和改進我們的服務。`; class Page extends React.Component { constructor() { super(); this.state = { open: false, } } open() { this.setState({ open: true, }) } cancel() { this.setState({ open: false, }) } send(data) { console.log(data) } render() { return ({ this.state.open?) } } ReactDOM.render(:null } , document.getElementById("main"));
在頁面中引入js文件使用:
3.參數說明
react 組件:
參數 | 功能 | 類型 | 是否必填 |
---|---|---|---|
theme | 設置組件主題顏色 | string | ? 默認值 #3986FF |
cancel | 取消按鈕處理函數 | function | ? |
send | 發送按鈕處理函數,會傳回收集的數據 | function | ? |
license | 協議內容 | html字符串 | ? 默認值為谷歌的隱私條款協議 |
proxy | 代理地址,如果頁面中存在跨域資源可以設置這個值 | string | ? 默認空值 |
頁面中直接引用:
參數 | 功能 | 類型 | 是否必填 |
---|---|---|---|
container | 組件容器元素 | element | ? |
trigger | 用于觸發組件打開的元素 | element | ? |
theme | 設置組件主題顏色 | string | ? 默認值 #3986FF |
license | 協議內容 | html字符串 | ? 默認值為谷歌的隱私條款協議 |
proxy | 代理地址,如果頁面中存在跨域資源可以設置這個值 | string | ? 默認空值 |
send | 發送按鈕處理函數,會傳回收集的數據 | function | ? |
需要啟動一個服務用于代理。
首先安裝html2canvas-proxy
npm install html2canvas-proxy --save
在node中使用代理
var proxy = require("html2canvas-proxy"); var express = require("express"); var app = express(); app.use("/", proxy());
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95083.html
摘要:實現不定期更新技巧前端掘金技巧,偶爾更新。統一播放效果實現打字效果動畫前端掘金前端開源項目周報前端掘金由出品的前端開源項目周報第四期來啦。 Web 推送技術 - 掘金騰訊云技術社區-掘金主頁持續為大家呈現云計算技術文章,歡迎大家關注! 作者:villainthr 摘自 前端小吉米 伴隨著今年 Google I/O 大會的召開,一個很火的概念--Progressive Web Apps ...
摘要:官網地址聊天機器人插件開發實例教程一創建插件在系統技巧使你的更加專業前端掘金一個幫你提升技巧的收藏集。我會簡單基于的簡潔視頻播放器組件前端掘金使用和實現購物車場景前端掘金本文是上篇文章的序章,一直想有機會再次實踐下。 2道面試題:輸入URL按回車&HTTP2 - 掘金通過幾輪面試,我發現真正那種問答的技術面,寫一堆項目真不如去刷技術文章作用大,因此刷了一段時間的博客和掘金,整理下曾經被...
摘要:你可以利用漸變和填充等功能來創建簡單的形狀,并且可以訪問幾乎所有蘋果默認提供的控件。可以幫你生成蘋果指導方針所說的各種分辨率圖標,包括設備和非設備。是一個用來管理蘋果推送通知的腳本。 這里推薦20個可以幫你簡化iOS app開發流程的工具。很多開發者都使用過這些工具,涉及原型和設計、編程、測試以及最后的營銷,基本上涵蓋了整個開發過程。 ? 原型和設計 有了一個很好的創意后,你要做...
閱讀 1048·2021-11-18 10:02
閱讀 1304·2021-09-23 11:22
閱讀 2607·2021-08-21 14:08
閱讀 1636·2019-08-30 15:55
閱讀 1720·2019-08-30 13:45
閱讀 3139·2019-08-29 16:52
閱讀 3091·2019-08-29 12:18
閱讀 1636·2019-08-26 13:36