highchart圖表的一個常見問題是不能複製文字php
好比官網的某個圖表例子,文字不能選擇,也沒法複製,有時產品會抓狂...vue
本文給出一個簡單的方案,包括一些解決的思路,但願能幫助到有須要的人web
初期想了蠻久也搜了蠻多,沒搜到,找到的結論是圖表使用的是svg實現,必然沒法選擇文字,彷佛是個死問題,已經瀕臨放棄chrome
不事後來又看到一篇討論,其實svg裏面的文字是能夠選擇複製的npm
頓時信心又來了,展開了新一輪思考ide
思考一:多是姿式不對svg
試試把標題配成 useHTML: true ,使用普通元素渲染,結果仍是沒法選測試
看看DOM結構,實際上已經和svg無關了this
思考二:會不會是設置了某些樣式呢spa
跟選擇複製有關的也就這倆了,直接賦上去,仍是無效
思考三:會不會是有事件影響,取消了點擊選擇效果呢
爲了測試的簡便與純粹性,最好直接使用官方提供的簡單例子
查看元素對應的事件列表,有幾個須要關注
選擇highchart.js ,跳的不許呀,代碼混淆以後貌似chrome的跳轉一致都不太可靠了
思考四:什麼js東西使得點擊選擇無效呢
多是事件禁止了冒泡 stopPropagation,或者是取消了元素的事件默認處理機制 preventDefault
一搜,發現前者沒找到,然後者有多處
定位到一個 mouseDown事件觸發的位置,柳暗花明的感受
試了一下能夠發現,上下兩處是關鍵點,直接形成文字選擇功能失效了(固然這多是做者的本意)
接下來就是驗證環節,把這文件下下來本地,改好後(註釋那倆地方)用Fiddler的文件映射功能,替換這個例子中的 highchart.js,妥妥的能夠進行選擇複製
思考五:如何運用在業務代碼中?
在vue中使用的是npm的包管理,因此確定不能直接改源代碼,可選的一個方案是覆蓋源代碼,即覆蓋這兩個方法
import Highcharts from "highcharts"; // 重寫Highcharts事件處理,使得內容可選擇複製 Highcharts.Pointer.prototype.onContainerMouseDown = function(a) { a = this.normalize(a); 2 !== a.button && (this.zoomOption(a), // a.preventDefault && a.preventDefault(), this.dragStart(a)) }; Highcharts.Pointer.prototype.onContainerMouseMove = function(b) { // 整理變量 let a = Highcharts; let B = Highcharts.charts; let q = function(a) { return "undefined" !== typeof a && null !== a }; var c = this.chart; q(a.hoverChartIndex) && B[a.hoverChartIndex] && B[a.hoverChartIndex].mouseIsDown || (a.hoverChartIndex = c.index); b = this.normalize(b); // b.preventDefault || (b.returnValue = !1); "mousedown" === c.mouseIsDown && this.drag(b); !this.inClass(b.target, "highcharts-tracker") && !c.isInsidePlot(b.chartX - c.plotLeft, b.chartY - c.plotTop) || c.openMenu || this.runPointActions(b) };
找到對象是誰,這一步能夠斷點調試看this,或往上翻代碼,實際上是個Pointer.
經過分析可知,這個對象的Highcharts對象的一個子對象,咱們也須要經過簡單的判斷來進行確認好
須要注意的是,代碼中有一段用到了其餘變量 q B a,因此在業務代碼中覆蓋的時候,咱們須要另外提早賦值
q(a.hoverChartIndex) && B[a.hoverChartIndex] && B[a.hoverChartIndex].mouseIsDown || (a.hoverChartIndex = c.index);
經過一系列分析和斷點查詢,以及確認值的一致,就能保證能覆蓋地正確
思考六:在vue中爲什麼沒有生效
然鵝並非順利的,在實際場景vue-highcharts中使用居然沒啥變化,一輪調試下來也沒有走斷點,
迫不得已只好去看下它的實現,看有沒有什麼突破口
源碼不多,就是一層包裝
但這裏能夠發現,若是沒有傳入highcharts,就會另外引入npm包來使用
因此很大多是沒傳入這個屬性,導致覆蓋的Pointer並非真正的圖表Pointer
仔細檢查代碼,才發現前人留個個坑,把大寫的屬性改爲小寫以後,便可匹配上
固然,這個覆蓋的方式是挺暴力的,能夠根據需求加些判斷處理,不過在現有業務中,不失爲一個好辦法