垂直時間軸控件,主要用來描述企業發展歷程大事件,或者軟件版本迭代歷史等,通過時間節點和事件描述來直觀的展示發展的過程,一般在web網頁或者app中經常看到此類控件,尤其是公司的官網關于公司部分,著重在一些獨角獸公司或者正處于蓬勃發展的公司,用來展示自己多牛逼,發展多么迅猛等。
垂直時間軸控件主要存儲的數據包含兩個,一個是時間節點,一個是事件描述,為了后期的拓展性,采用結構體來存放這個數據,比如后期還可能增加該事件是否屬于重大事件標記,是的話則繪制的時候突出顯示比如加大字號加粗,本控件的主要難點在于自動計算和排列來繪制時間和事件描述,默認采用對等分的機制來處理繪制,還有部分時間軸控件是左側時間右側事件描述,這個可以在源碼基礎上自行更改或者增加樣式,為了能夠展示所有的事件,本控件主體是繼承自滾動條區域控件,超過高度自動產生滾動條。
#ifndef TIMEAXIS_H
#define TIMEAXIS_H
/**
* 垂直時間軸控件 作者:雨田哥(QQ:3246214072) 整理:feiyangqingyun(QQ:517216493) 2019-10-07
* 1:可設置節點邊距
* 2:可設置節點高度
* 3:可設置信息邊框邊距
* 4:可設置信息所占高度
* 5:可設置基準顏色/線條顏色
* 6:可設置標題/信息集合
* 7:自動產生滾動條
* 8:支持字符串形式設置數據
*/
#include <QScrollArea>
class TimeAxisWidget;
#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif
class QDESIGNER_WIDGET_EXPORT TimeAxis : public QScrollArea
#else
class TimeAxis : public QScrollArea
#endif
{
Q_OBJECT
Q_PROPERTY(int itemMargin READ getItemMargin WRITE setItemMargin)
Q_PROPERTY(int itemHeight READ getItemHeight WRITE setItemHeight)
Q_PROPERTY(int infoPadding READ getInfoPadding WRITE setInfoPadding)
Q_PROPERTY(int infoHeight READ getInfoHeight WRITE setInfoHeight)
Q_PROPERTY(QColor baseColor READ getBaseColor WRITE setBaseColor)
Q_PROPERTY(QColor lineColor READ getLineColor WRITE setLineColor)
Q_PROPERTY(QString title READ getTitle WRITE setTitle)
Q_PROPERTY(QString infos READ getInfos WRITE setInfos)
public:
explicit TimeAxis(QWidget *parent=0);
private:
int itemMargin; //節點邊距
int itemHeight; //節點高度
int infoPadding; //信息邊距
int infoHeight; //信息高度
QColor baseColor; //基準顏色
QColor lineColor; //線條顏色
QString title; //標題
QString infos; //信息集合
//時間軸主控件
TimeAxisWidget *timeAxisWidget;
public:
int getItemMargin() const;
int getItemHeight() const;
int getInfoPadding() const;
int getInfoHeight() const;
QColor getBaseColor() const;
QColor getLineColor() const;
QString getTitle() const;
QString getInfos() const;
QSize sizeHint() const;
QSize minimumSizeHint() const;
TimeAxisWidget *getWidget();
public Q_SLOTS:
//設置節點邊距+節點高度
void setItemMargin(int itemMargin);
void setItemHeight(int itemHeight);
//設置信息邊距+信息高度
void setInfoPadding(int infoPadding);
void setInfoHeight(int infoHeight);
//設置基準顏色+線條顏色
void setBaseColor(const QColor &baseColor);
void setLineColor(const QColor &lineColor);
//設置標題+信息集合
void setTitle(const QString &title);
void setInfos(const QString &infos);
};
class TimeAxisWidget : public QWidget
{
Q_OBJECT
public:
//可以自行拓展其他信息
struct TimeAxisInfo {
QString time; //時間
QString info; //信息
};
explicit TimeAxisWidget(QWidget *parent=0);
protected:
void paintEvent(QPaintEvent *);
void drawTitle(QPainter *painter);
void drawLine(QPainter *painter);
void drawInfo(QPainter *painter);
void drawInfoRight(QPainter *painter, const QRectF &infoRect, int infoHeight);
void drawInfoLeft(QPainter *painter, const QRectF &infoRect, int infoHeight);
private:
int itemMargin; //節點邊距
int itemHeight; //節點高度
int infoPadding; //信息邊距
int infoHeight; //信息高度
QColor baseColor; //基準顏色
QColor lineColor; //線條顏色
QString title; //標題
QString infos; //信息集合
//信息集合結構體
QList<TimeAxisInfo> itemInfos;
public:
int getItemMargin() const;
int getItemHeight() const;
int getInfoPadding() const;
int getInfoHeight() const;
QColor getBaseColor() const;
QColor getLineColor() const;
QString getTitle() const;
QString getInfos() const;
QSize sizeHint() const;
QSize minimumSizeHint() const;
public Q_SLOTS:
//設置節點邊距+節點高度
void setItemMargin(int itemMargin);
void setItemHeight(int itemHeight);
//設置信息邊距+信息高度
void setInfoPadding(int infoPadding);
void setInfoHeight(int infoHeight);
//設置基準顏色+線條顏色
void setBaseColor(const QColor &baseColor);
void setLineColor(const QColor &lineColor);
//設置標題+信息集合
void setTitle(const QString &title);
void setInfos(const QString &infos);
//設置信息集合,結構體方式
void setItemInfos(const QList<TimeAxisInfo> &itemInfos);
};
#endif // TIMEAXIS_H
【領QT開發教程學習資料,點擊下方鏈接莬費領取↓↓,先碼住不迷路~】
點擊這里:Qt資料領取(視頻教程+文檔+代碼+項目實戰)
void TimeAxisWidget::drawTitle(QPainter *painter)
{
painter->save();
QFont font;
font.setBold(true);
font.setPointSize(16);
painter->setFont(font);
painter->setPen(baseColor);
painter->drawText(itemMargin, itemMargin, width() - 2 * itemMargin, 40, Qt::AlignCenter, title);
painter->restore();
}
void TimeAxisWidget::drawLine(QPainter *painter)
{
painter->save();
painter->setPen(QPen(lineColor, 6));
int startY=itemMargin + 50;
int endY=startY + itemInfos.size() * itemHeight;
painter->drawLine(width() / 2.0, startY, width() / 2.0, endY);
painter->restore();
//設置下固定高度
this->setFixedHeight(endY + itemMargin);
}
void TimeAxisWidget::drawInfo(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
QFont font;
font.setPointSize(12);
painter->setFont(font);
int startY=itemMargin + 50;
int centerX=this->width() / 2.0;
int spacer=itemMargin + 10;
//追個繪制時間軸信息集合,偶數行左側繪制時間右側繪制信息
for (int i=0; i < itemInfos.size(); i++) {
painter->setBrush(Qt::white);
painter->setPen(QPen(baseColor, 2));
if (i % 2==0) {
//繪制時間
QRectF textRect(0, startY, centerX - spacer, itemHeight);
painter->drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, itemInfos.at(i).time);
//繪制信息邊框
QRectF infoRect(centerX + spacer, textRect.center().y() - infoHeight / 2.0, centerX - spacer - itemMargin - infoHeight / 2.0, infoHeight);
drawInfoRight(painter, infoRect, infoHeight);
//繪制信息背景
painter->setBrush(baseColor);
drawInfoRight(painter, infoRect.adjusted(infoPadding, infoPadding, 0, -infoPadding), infoHeight - infoPadding * 2);
//繪制信息文字
painter->setPen(Qt::white);
painter->drawText(infoRect.adjusted(infoPadding, infoPadding, 0, -infoPadding), Qt::AlignCenter, itemInfos.at(i).info);
} else {
//繪制時間
QRectF textRect(centerX + spacer, startY, centerX - spacer, itemHeight);
painter->drawText(centerX + spacer, startY, centerX - spacer, itemHeight, Qt::AlignLeft | Qt::AlignVCenter, itemInfos.at(i).time);
//繪制信息邊框
QRectF infoRect(itemMargin + infoHeight / 2.0, textRect.center().y() - infoHeight / 2.0, centerX - spacer - itemMargin - infoHeight / 2.0, infoHeight);
drawInfoLeft(painter, infoRect, infoHeight);
//繪制信息背景
painter->setBrush(baseColor);
drawInfoLeft(painter, infoRect.adjusted(0, infoPadding, -infoPadding, -infoPadding), infoHeight - infoPadding * 2);
//繪制信息文字
painter->setPen(Qt::white);
painter->drawText(infoRect.adjusted(0, infoPadding, -infoPadding, -infoPadding), Qt::AlignCenter, itemInfos.at(i).info);
}
//繪制垂直線對應的圓
painter->setPen(Qt::NoPen);
painter->setBrush(baseColor);
painter->drawEllipse(centerX - 8, startY + itemHeight / 2.0 - 8, 16, 16);
painter->setBrush(Qt::white);
painter->drawEllipse(centerX - 4, startY + itemHeight / 2.0 - 4, 8, 8);
//Y軸往下移一個高度
startY +=itemHeight;
}
painter->restore();
}
原文鏈接:https://www.cnblogs.com/feiyangqingyun/p/11639987.html
【領QT開發教程學習資料,點擊下方鏈接莬費領取↓↓,先碼住不迷路~】
點擊這里:「鏈接」
本教程中,您將通過幾個簡短的步驟學習如何使用 CSS 插入簡寫和原生 JavaScript 創建滾動到頂部按鈕。
滾動到頂部按鈕對于具有大量內容的網站、無限滾動的頁面或具有可能導致內容滾動擴展的小屏幕的移動設備非常有用。
第一步,創建按鈕
要創建滾動按鈕,請使用帶 href="#" 的錨標記,這會使瀏覽器在單擊時返回頁面頂部,或者您可以使用自定義 Id 返回頁面的特定部分。
<a href="#">scroll-to-top</a>
第二步,按鈕的位置和樣式
要使按鈕位置相對于視口固定,您需要在錨標記上設置位置:固定。 當元素位置固定時,它會從正常的文檔流中移除,然后使用相對于視口的 top、right、bottom 和 left 屬性進行定位。
雖然,有一個用于定位屬性的簡寫,稱為 inset。
Inset 的作用類似于 margin 簡寫,用于將 margin-top、margin-right、margin-bottom 和 margin-left 設置為一體。
句法
inset: top right bottom left
當 auto 用作 inset 的值時,它認為該值被省略。
因此,您可以使用下面的插圖將按鈕放置在視口的右下角。
inset: auto 2em 2em auto;
要將所有內容放在一起,請將類 scrollToTopBtn 添加到錨標記并設置按鈕的樣式,如下所示。
.scrollToTopBtn {
color: #f2f2f2;
background-color: #151515;
text-decoration: none;
border-radius: 25px;
position: fixed;
outline: none;
z-index: 100;
padding: 0.75em 1.5em;
inset: auto 2em 2em auto;
}
第三步,讓按鈕響應
現在滾動到頂部按鈕的樣式已正確放置,并且可以正常工作。但是有一個問題,按鈕總是可見的。要解決這個問題,您需要使用 JavaScript 根據頁面滾動來隱藏和顯示按鈕。
為此,首先,獲取按鈕并將其存儲在變量中。
const scrollToTopBtn=document.querySelector(".scrollToTopBtn");
然后獲取偏移值的文檔的根元素。
const rootElement=document.documentElement;
接下來,您應該在滾動事件上注冊一個事件偵聽器來計算按鈕的可見性狀態。
const handleScroll=()=> {}
document.addEventListener("scroll", handleScroll);
每次用戶滾動時都會調用 handleScroll 函數。
之后,您需要可以滾動的像素總數,并且要在 handleScroll 函數中得到它,您需要通過 clientHeight 減去 scrollHeight 以獲得可以滾動的像素總數。
const scrollTotal=rootElement.scrollHeight - rootElement.clientHeight;
現在您已經擁有可以滾動的最大像素數,您需要將其除以頁面已滾動的數量,以獲得介于 0 和 1 之間的滾動比率。使用滾動比率,您可以調整要隱藏的位置并顯示按鈕。越接近 1,用戶在看到按鈕之前滾動的次數就越多。
if ((rootElement.scrollTop / scrollTotal) > 0.25) {
// Show the button
scrollToTopBtn.classList.add("isVisible")
} else {
// Hide the button
scrollToTopBtn.classList.remove("isVisible")
}
最后,要使其工作,首先需要添加 opacity: 0; 到 scrollToTopBtn 類以在頁面加載時隱藏按鈕。 然后添加類 isVisible 與 opacity: 1; 當頁面滾動通過您選擇的比率時,按鈕。 最后但同樣重要的是,添加過渡:所有 250 毫秒的緩入緩出; 為按鈕設置動畫的 scrollToTopBtn 類。
.scrollToTopBtn {
color: #f2f2f2;
background-color: #151515;
text-decoration: none;
border-radius: 25px;
position: fixed;
outline: none;
z-index: 100;
opacity: 0;
padding: 0.75em 1.5em;
inset: auto 2em 2em auto;
transition: all 250ms ease-in-out;
}.isVisible {
opacity: 1;
}
第四步,修復不需要的點擊
當滾動到頂部按鈕被隱藏時,它仍然可以被點擊,這是不應該發生的。 要解決這個問題,請添加指針事件:無; 類 scrollToTopBtn 忽略點擊事件并添加指針事件:自動; 類 isVisible 以在按鈕可見時將點擊事件帶回按鈕。
.scrollToTopBtn {
color: #f2f2f2;
background-color: #151515;
text-decoration: none;
border-radius: 25px;
position: fixed;
outline: none;
z-index: 100;
opacity: 0;
pointer-events: none;
padding: 0.75em 1.5em;
inset: auto 2em 2em auto;
transition: all 250ms ease-in-out;
}.isVisible {
pointer-events: auto;
opacity: 1;
}
第五步,給頁面添加平滑滾動
現在滾動到頂部按鈕仍然可以正常工作,您可以通過平滑滾動為您的網站添加漂亮的觸感。 為此,只需添加 scroll-behavior: smooth; 到 html 標簽。
html {
scroll-behavior: smooth;
}
總結
滾動到頂部按鈕是一個簡單而有用的功能,可以極大地改善您網站的用戶體驗。 在本教程中,我向您展示了如何在沒有任何庫的情況下使用幾行代碼構建滾動到頂部按鈕。
天發現index寫漏了一個功能,為了給用戶更好的體驗一般網站右邊都會提供一個返回頂部的按鈕,正常頁面載入時不顯示該按鈕,當我們往下移動網頁時這個按鈕就顯示出來了,點擊這個按鈕我們就可以快速的滾回到頂部位置(這里是滾動回去,2345中的是直接跳回頂部的,不怎么友好,而且返回按鈕一加載網頁就有了,都沒動何來的返回,這里明顯不合邏輯),我適當的改動了下,下面是功能演示。
?
首先我們還是來寫HTML代碼,還是模仿2345來做的,提供了2個按鈕:留言板和回頂部,這里我用的很簡單,直接用一個div包裹了2個a標簽,分別在a標簽中嵌套了一個圖標和文字內容(用到了i標簽和em標簽)。
<div class="Floating"> <a href="javascript:;"><i class="fa fa-pencil-square"></i><em>留言板</em></a> <a href="javascript:;"><i class="fa fa-chevron-up"></i><em>回頂部</em></a> </div>
接下來我們給DOM元素來寫樣式,寫樣式需要給點耐心,邊看邊調整,這樣才能獲取你想要的效果了,這里我用到的是position的fixed屬性:生成絕對定位的元素,相對于瀏覽器窗口進行定位(固定定位),然后給定一個z-index屬性讓他永遠放在其他元素上方。顏色切換我放在了a標簽,直接用:hover就可以實現,圖標和內容別忘了使用display: block;將其設置成塊級元素。
.Floating{ width:65px; position: fixed; z-index:600; right:20px; bottom: 280px; } .Floating a{ text-decoration: none; margin-bottom: 5px; display: block; opacity: 0.9; background-color: rgb(130,130,130); } .Floating a:hover{ background-color:#33AAFF; } .Floating a i{ font-size: 24px; } .Floating a i,.Floating a em{ padding:4px; width:56px; height:24px; text-align: center; color:rgb(253, 252, 252); z-index:5; cursor: pointer; font-style: normal; display: block; }
這樣我們就得到如下圖所示的內容樣式了,當鼠標放上去的時候背景就變成了藍色選中狀態,移出時恢復背景色即可。前面說了當頁面載入時“回頂部”按鈕是隱藏的,當移動后方才顯示的,所里這里我們可以v-show或者v-if來控制按鈕的隱藏功能,這里我們定義了一個v-show="backFlag",默認backFlag :false。
?
接下來我們就要開始給按鈕添加事件了,我給“回頂部”添加一個@click="backTop"事件,我們在methods中實現backTop這個方法,既然是通過滾動來觸發事件的,所以我們在頁面載入時就應該對頁面進行滾動監聽,并指定事件觸發時要執行的函數showBtn,這樣當我們滾動頁面的時候就對應的觸發了showBtn方法,當滿足條件時顯示“回頂部”按鈕。
// window對象表示瀏覽器窗口,監聽滾動事件(所有瀏覽器都支持window對象) mounted () { window.addEventListener('scroll', this.showBtn) //scroll 滾動事件 }, methods:{ showBtn () { // 計算距離頂部的高度,當高度大于40顯示回頂部,小于40則隱藏(默認隱藏) /*獲取當前頁面滾動條縱坐標的位置 IE9及以上:可以使用window.pageYOffset或者document.documentElement.scrollTop , safari: window.pageYOffset 與document.body.scrollTop都可以 Chrome:谷歌瀏覽器只認識document.body.scrollTop;*/ let that=this let scrollTop=window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop that.scrollTop=scrollTop if (that.scrollTop > 40) { let that=this that.backFlag=true } else { that.backFlag=false } }
這個應該很好理解吧,我把注釋都寫在代碼中了,主要思路就是獲取當前滾動條縱坐標的位置,當這個值大于40時就將backFlag改成true讓“回頂部”按鈕顯示出來即可,當當前滾動條縱坐標的位置小于40時再次隱藏“回頂部”按鈕。
?
接著給“回頂部”按鈕添加點擊事件,在methods:{}中實現backTop()方法,這里為了有個移動的過程,我給事件添加了定時器,將當前滾動條的垂直位置減去每次移動的距離賦給當前滾動條縱坐標的位置,這樣就可以實現自動滾動的效果了,當移動到頂部時別忘了清除定時器(不然牛后面就沒法玩了,只要一移動就會自動滾回頂部了)。
backTop(){ // 點擊返回頂部方法,計時器是為了過渡順滑 let that=this let timer=setInterval(()=> { let speed=Math.floor(-that.scrollTop /10) //scrollTop獲取元素的滾動條的垂直位置,Math.floor() 向下取整 document.documentElement.scrollTop=document.body.scrollTop=that.scrollTop + speed //document.documentElement.scrollTop 獲取當前頁面的滾動條縱坐標位置 if (that.scrollTop===0) { clearInterval(timer) } }, 20) },
最后別忘了銷毀監聽事件,使用destroyed ()方法調用銷毀監聽事件,這樣當我們離開這個頁面的時候,便會調用這個函數移除監聽,釋放內存,到這里我們的功能就全部實現了,是不是效果不錯,有興趣的可以試試。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。