mirror of
https://github.com/kamranahmedse/driver.js.git
synced 2026-10-31 03:52:13 +08:00
Handle scrollable elements for highlighting
This commit is contained in:
+87
-2
@@ -94,6 +94,15 @@
|
||||
padding: 10px;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
#scrollable-area {
|
||||
height: 300px;
|
||||
overflow: auto;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
margin: 50px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -110,6 +119,8 @@
|
||||
<button id="disallow-close">Disallow Close</button>
|
||||
<button id="dark-highlight-btn">Super Dark Highlight</button>
|
||||
<button id="dim-highlight-btn">Super Dim Highlight</button>
|
||||
<button id="scrollable-area-btn">Scrollable Area</button>
|
||||
<button id="inner-scroll-area-btn">Inner Scroll Area</button>
|
||||
<button id="tour-btn">Start Tour</button>
|
||||
<button id="destroy-btn">Destroy</button>
|
||||
</div>
|
||||
@@ -131,14 +142,14 @@
|
||||
off the Lights" widgets that you might have seen on video players
|
||||
online, etc.
|
||||
</p>
|
||||
<p>
|
||||
<p class="second-para">
|
||||
Driver.js is written in Vanilla JS, has zero dependencies and is highly
|
||||
customizable. It has several options allowing you to manipulate how it
|
||||
behaves and also provides you the hooks to manipulate the elements as
|
||||
they are highlighted, about to be highlighted, or deselected.
|
||||
</p>
|
||||
|
||||
<h2>Installation</h2>
|
||||
<h2 id="installation-head">Installation</h2>
|
||||
<p>You can install it using yarn or npm, whatever you prefer.</p>
|
||||
|
||||
<pre>
|
||||
@@ -175,6 +186,62 @@ npm install driver.js</pre
|
||||
libero, minus molestias necessitatibus nesciunt non omnis, quasi
|
||||
recusandae tempore voluptates!
|
||||
</p>
|
||||
<div id="scrollable-area">
|
||||
<p>
|
||||
First -> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
|
||||
Consequuntur dicta ipsum labore quod tempora ullam? Alias consequatur
|
||||
doloremque laborum maxime necessitatibus nostrum odio, officiis
|
||||
quibusdam veniam! Doloribus eos id quaerat.
|
||||
</p>
|
||||
<p>
|
||||
Second -> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
|
||||
Consequuntur dicta ipsum labore quod tempora ullam? Alias consequatur
|
||||
doloremque laborum maxime necessitatibus nostrum odio, officiis
|
||||
quibusdam veniam! Doloribus eos id quaerat.
|
||||
</p>
|
||||
<p id="third-scroll-paragraph">
|
||||
Third -> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
|
||||
Consequuntur dicta ipsum labore quod tempora ullam? Alias consequatur
|
||||
doloremque laborum maxime necessitatibus nostrum odio, officiis
|
||||
quibusdam veniam! Doloribus eos id quaerat.
|
||||
</p>
|
||||
<p>
|
||||
Fourth -> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
|
||||
Consequuntur dicta ipsum labore quod tempora ullam? Alias consequatur
|
||||
doloremque laborum maxime necessitatibus nostrum odio, officiis
|
||||
quibusdam veniam! Doloribus eos id quaerat.
|
||||
</p>
|
||||
<p>
|
||||
Fifth -> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
|
||||
Consequuntur dicta ipsum labore quod tempora ullam? Alias consequatur
|
||||
doloremque laborum maxime necessitatibus nostrum odio, officiis
|
||||
quibusdam veniam! Doloribus eos id quaerat.
|
||||
</p>
|
||||
<p>
|
||||
Sixth -> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
|
||||
Consequuntur dicta ipsum labore quod tempora ullam? Alias consequatur
|
||||
doloremque laborum maxime necessitatibus nostrum odio, officiis
|
||||
quibusdam veniam! Doloribus eos id quaerat.
|
||||
</p>
|
||||
<p>
|
||||
Seventh -> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
|
||||
Consequuntur dicta ipsum labore quod tempora ullam? Alias consequatur
|
||||
doloremque laborum maxime necessitatibus nostrum odio, officiis
|
||||
quibusdam veniam! Doloribus eos id quaerat.
|
||||
</p>
|
||||
<p>
|
||||
Eighth -> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
|
||||
Consequuntur dicta ipsum labore quod tempora ullam? Alias consequatur
|
||||
doloremque laborum maxime necessitatibus nostrum odio, officiis
|
||||
quibusdam veniam! Doloribus eos id quaerat.
|
||||
</p>
|
||||
<p>
|
||||
Ninth -> Lorem ipsum dolor sit amet, consectetur adipisicing elit.
|
||||
Consequuntur dicta ipsum labore quod tempora ullam? Alias consequatur
|
||||
doloremque laborum maxime necessitatibus nostrum odio, officiis
|
||||
quibusdam veniam! Doloribus eos id quaerat.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
|
||||
blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
|
||||
@@ -249,6 +316,24 @@ npm install driver.js</pre
|
||||
window.setTimeout(() => {
|
||||
driverObj.highlight({ element: ".buttons" });
|
||||
}, 1000);
|
||||
|
||||
window.setTimeout(() => {
|
||||
driverObj.highlight({ element: "#installation-head" });
|
||||
}, 1500);
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("scrollable-area-btn")
|
||||
.addEventListener("click", () => {
|
||||
const driverObj = driver({ animate: true });
|
||||
driverObj.highlight({ element: "#scrollable-area" });
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("inner-scroll-area-btn")
|
||||
.addEventListener("click", () => {
|
||||
const driverObj = driver({ animate: true });
|
||||
driverObj.highlight({ element: "#third-scroll-paragraph" });
|
||||
});
|
||||
|
||||
document
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export type Config = {
|
||||
animate?: boolean;
|
||||
smoothScroll?: boolean;
|
||||
allowClose?: boolean;
|
||||
opacity?: number;
|
||||
};
|
||||
@@ -11,6 +12,7 @@ export function configure(config: Config = {}) {
|
||||
animate: true,
|
||||
allowClose: true,
|
||||
opacity: 0.7,
|
||||
smoothScroll: true,
|
||||
...config,
|
||||
};
|
||||
}
|
||||
|
||||
+3
-25
@@ -2,6 +2,7 @@ import { DriveStep } from "./driver";
|
||||
import { refreshStage, trackActiveElement, transitionStage } from "./stage";
|
||||
import { getConfig } from "./config";
|
||||
import { refreshPopover, renderPopover } from "./popover";
|
||||
import { bringInView } from "./utils";
|
||||
|
||||
let previousHighlight: Element | undefined;
|
||||
let activeHighlight: Element | undefined;
|
||||
@@ -48,7 +49,6 @@ function transferHighlight(from: Element, to: Element) {
|
||||
if (getConfig("animate") && elapsed < duration) {
|
||||
transitionStage(elapsed, duration, from, to);
|
||||
} else {
|
||||
bringInView(to);
|
||||
trackActiveElement(to);
|
||||
renderPopover(to);
|
||||
|
||||
@@ -63,34 +63,12 @@ function transferHighlight(from: Element, to: Element) {
|
||||
currentTransitionCallback = animate;
|
||||
window.requestAnimationFrame(animate);
|
||||
|
||||
bringInView(to);
|
||||
|
||||
from.classList.remove("driver-active-element");
|
||||
to.classList.add("driver-active-element");
|
||||
}
|
||||
|
||||
function bringInView(element: Element) {
|
||||
if (!element || isElementInView(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
element.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
inline: "center",
|
||||
block: "center",
|
||||
});
|
||||
}
|
||||
|
||||
function isElementInView(element: Element) {
|
||||
const rect = element.getBoundingClientRect();
|
||||
|
||||
return (
|
||||
rect.top >= 0 &&
|
||||
rect.left >= 0 &&
|
||||
rect.bottom <=
|
||||
(window.innerHeight || document.documentElement.clientHeight) &&
|
||||
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
||||
);
|
||||
}
|
||||
|
||||
export function destroyHighlight() {
|
||||
activeHighlight = undefined;
|
||||
currentTransitionCallback = undefined;
|
||||
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
export function easeInOutQuad(
|
||||
elapsed: number,
|
||||
initialValue: number,
|
||||
amountOfChange: number,
|
||||
duration: number
|
||||
): number {
|
||||
if ((elapsed /= duration / 2) < 1) {
|
||||
return (amountOfChange / 2) * elapsed * elapsed + initialValue;
|
||||
}
|
||||
return (-amountOfChange / 2) * (--elapsed * (elapsed - 2) - 1) + initialValue;
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { easeInOutQuad } from "./math";
|
||||
import { easeInOutQuad } from "./utils";
|
||||
import { onDriverClick } from "./events";
|
||||
import { trigger } from "./hooks";
|
||||
import { getConfig } from "./config";
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import { getConfig } from "./config";
|
||||
|
||||
export function easeInOutQuad(
|
||||
elapsed: number,
|
||||
initialValue: number,
|
||||
amountOfChange: number,
|
||||
duration: number
|
||||
): number {
|
||||
if ((elapsed /= duration / 2) < 1) {
|
||||
return (amountOfChange / 2) * elapsed * elapsed + initialValue;
|
||||
}
|
||||
return (-amountOfChange / 2) * (--elapsed * (elapsed - 2) - 1) + initialValue;
|
||||
}
|
||||
|
||||
export function bringInView(element: Element) {
|
||||
if (!element || isElementInView(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shouldSmoothScroll = getConfig("smoothScroll");
|
||||
|
||||
element.scrollIntoView({
|
||||
// Removing the smooth scrolling for elements which exist inside the scrollable parent
|
||||
// This was causing the highlight to not properly render
|
||||
behavior:
|
||||
!shouldSmoothScroll || hasScrollableParent(element) ? "auto" : "smooth",
|
||||
inline: "center",
|
||||
block: "center",
|
||||
});
|
||||
}
|
||||
|
||||
function hasScrollableParent(e: Element) {
|
||||
if (!e || !e.parentElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parent = e.parentElement as HTMLElement & { scrollTopMax?: number };
|
||||
|
||||
return parent.scrollHeight > parent.clientHeight;
|
||||
}
|
||||
|
||||
function isElementInView(element: Element) {
|
||||
const rect = element.getBoundingClientRect();
|
||||
|
||||
return (
|
||||
rect.top >= 0 &&
|
||||
rect.left >= 0 &&
|
||||
rect.bottom <=
|
||||
(window.innerHeight || document.documentElement.clientHeight) &&
|
||||
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user