之前本人使用React + AntDesign 實現了一個簡單的時序圖,但是后來有了更復雜的需求,并且要求同時展示2000個任務的展示,這就涉及到了性能問題,本人先使用React+antd+ts實現了一個基本滿足下面需求的demo,但是react的渲染機制造成了較大的性能問題,利用chrome自帶的Performance,測試發現demo的首次渲染高達10s以上,并且后續的操作也會使整個頁面非常卡。經過思索后決定使用原聲js+css+html去實現,因為原聲js下性能是最優的。下面先來說說新版本的需求:
效果圖
圖一:
圖二:
實現難點
鼠標縮放,x軸的縮放方式
鼠標縮放產生時序圖X軸的縮放。時序圖的縮放,在這里提供三種思路:
三種思路的優缺點:
// 計算寬度百分比的函數// endTime: 任務的結束時間// startTime: 任務的開始時間// maxTime: 所有任務結束時間最大的值// minTime: 所有任務開始時間最小的值// time: 所有任務開始時間與結束時間的排序 升序// task_width: 任務的長度、水平連接線的長度、垂直連接線的left值const widthFun = function (endTime, startTime, maxTime, minTime) { const task_width = (((Number (endTime) - Number (startTime)) / ((maxTime || time[time.length - 1]) - (minTime || time[0])) * (body_width - tree_box_dom.offsetWidth)) / dom.offsetWidth)*100; return task_width> 100 ? 100 : task_width; };
鼠標縮放,保持以鼠標為中心,往兩邊放大
先放推理過程圖:
// 上圖解釋// dom = 時序圖的dom元素// domL1, domeL2 = dom.scrollLeft;// domeL1表示前一次的dom.scrollLeft;// domeL2表示當前的dom.scrollLeft;// scale 表示當前的放大的比例// scale1 表示上一次的放大比例// tree_dom.offsetWidth表示左側樹的寬度// clientX1 表示上一次的鼠標位置距離時序圖左側的距離 = e.clientX - tree_dom.offsetWidth// clientX2 表示當前鼠標位置距離時序圖的距離// 以鼠標為中心的縮放,公式為:domL2 = domeL1(scale/scale1) + clientX1(scale/scale1) - e.clientX + tree_dom.offsetWidth// 公式講解:// 1. scale/scale1表示本次的縮放比例除以上一次的縮放比例,表示當前的縮放比例// 左側卷去的寬度在第二次縮放時也會跟著縮放,所以左側的寬度需要乘以縮放比例// 鼠標位置距離時序圖左側的寬度在縮放時也會跟著縮放,所以也要乘以縮放比例// 最后面減去鼠標位置距離時序圖左側的實際距離就等于縮放時左側卷去的長度// 頁面代碼time_box_parent.scrollLeft = (time_box_parent.scrollLeft + e.clientX - tree_box_dom.offsetWidth) * (scale_x / scale_x1) - e.clientX + tree_box_dom.offsetWidth;
使用連線表示任務之間的關系
方案:
優缺點:
實現思路:
用一個變量記錄每個任務的層級深度,層級深都以當前任務的父任務為起點,就是說是從哪個任務產生的當前任務,同級的子任務進行累加操作。用累加的變量按照一定的比例獲取垂直連線的高度以及水平連線的top值,水平連線的長度由任務的創建時間和開始時間決定。(使用上面的寬度百分比函數)
時間單位:天、時、分、秒
這個比較簡單,實現思路:
因為本demo的時間4刻度是個刻度,判斷最小時間戳與最大時間戳之間的差除以4,是否還有一天的時間(60 * 60 * 24,換算成秒),從大到小的降序獲取時間單位。
總結
以上所述是小編給大家介紹的原生 JS+CSS+HTML 實現時序圖的方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VeVb武林網網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!
新聞熱點
疑難解答