Progress indicator around the back-to-top button

Is it possible to make kind of a progress indicator around the button that shows how far you have reached on the respective page?

Thx and BR

3 Likes

I have added this code. It works, but has to be adapted:
Back to top with progress indicator - Ask the Community / Customization - Elfsight Community

could you pleae help to adapt for our version?

3 Likes

Hi there, @B.S :waving_hand:

Sure! Could you please send me a link to the page, where your widget is installed?

2 Likes

Send via chat. Thanks brother

2 Likes

Thanks! I’ve passed it on to the devs and will get back to you tomorrow :wink:

2 Likes

Our devs working on your request! I’ll update you once I have their response :slightly_smiling_face:

Thank you! I am waiting… :slight_smile:

1 Like

Hi there, @B.S :waving_hand:

Our devs adjusted the codes and saved them in your widget!

Custom JS

const waitForElement = (selector, root = document) =>
	new Promise((res) => {
		let i = 0;
		const check = () => {
			const component = root.querySelector(selector);
			if (component) res(component);
			else if (i++ < 100) setTimeout(check, 100);
		};
		check();
	});

const BUTTON_SIZE = 43;
const STROKE_WIDTH = 4;
const PADDING = 4;
const RADIUS = BUTTON_SIZE / 2 + PADDING;
const SVG_SIZE = (RADIUS + STROKE_WIDTH / 2) * 2;
const CIRCUMFERENCE = 2 * Math.PI * RADIUS;
const COLOR = '#F0000E';

waitForElement('[class*="Button__Inner-sc"]').then((button) => {
	button.style.position = 'relative';
	button.style.width = `${BUTTON_SIZE}px`;
	button.style.height = `${BUTTON_SIZE}px`;

	const createSVGWrapper = (className, isForeground) => {
		const wrapper = document.createElement('div');
		wrapper.className = className;
		wrapper.style.position = 'absolute';
		wrapper.style.top = `-${(SVG_SIZE - BUTTON_SIZE) / 2}px`;
		wrapper.style.left = `-${(SVG_SIZE - BUTTON_SIZE) / 2}px`;
		wrapper.style.width = `${SVG_SIZE}px`;
		wrapper.style.height = `${SVG_SIZE}px`;
		wrapper.style.pointerEvents = 'none';

		const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
		svg.setAttribute('width', SVG_SIZE);
		svg.setAttribute('height', SVG_SIZE);
		svg.setAttribute('viewBox', `0 0 ${SVG_SIZE} ${SVG_SIZE}`);

		const circle = document.createElementNS(
			'http://www.w3.org/2000/svg',
			'circle'
		);
		circle.setAttribute('cx', SVG_SIZE / 2);
		circle.setAttribute('cy', SVG_SIZE / 2);
		circle.setAttribute('r', RADIUS);
		circle.setAttribute(
			'class',
			isForeground ? 'progress-path' : 'progress-path2'
		);
		circle.setAttribute('stroke-width', STROKE_WIDTH);

		svg.appendChild(circle);
		wrapper.appendChild(svg);
		return wrapper;
	};

	const fg = createSVGWrapper('progress-ring', true);
	const bg = createSVGWrapper('progress-ring-bg', false);
	bg.style.display = 'none';

	button.appendChild(bg);
	button.appendChild(fg);

	const circle = fg.querySelector('circle');
	circle.style.strokeDasharray = CIRCUMFERENCE;
	circle.style.strokeDashoffset = CIRCUMFERENCE;

	window.addEventListener('scroll', () => {
		const scrollTop = window.scrollY;
		const docHeight =
			document.documentElement.scrollHeight -
			document.documentElement.clientHeight;
		const scrollPercent = Math.min(1, scrollTop / docHeight);

		const offset = CIRCUMFERENCE * (1 - scrollPercent);
		circle.style.strokeDashoffset = offset;
		circle.style.stroke = scrollTop > 0 ? COLOR : 'black';

		bg.style.display = scrollTop > 0 ? 'block' : 'none';
	});
});

Custom CSS

.progress-ring,
.progress-ring-bg {
	width: 100%;
	height: 100%;
}

.progress-path {
	fill: none;
	stroke: black;
	stroke-width: 4;
	stroke-dasharray: 999;
	stroke-dashoffset: 999;
	transition: stroke-dashoffset 0.25s linear;
}

.progress-path2 {
	fill: none;
	stroke: black;
	stroke-width: 4;
	opacity: 0.1;
}

[class*='Button__Inner-sc']::after {
  border: none !important;
}

Please check your website and let me know if you like the result :wink:

2 Likes

Thank you, very nice!

1 Like

It’s my pleasure!

Feel free to contact us here again if anything else comes up :wink:

1 Like