Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
This article is a five-part series on creating interactive infographics with plain Javascript.
Previously we built a feature-rich User Interface (UI) to browse inter-connected information. In the final part of the series, weâll demonstrate why it is so easy to create UIs with a human touch.
Objective
Weâll highlight ten UI tweaks thatâll transform a casual visit into a superior user experience.
Concept
At its core, UI design is just two words: contextualise and communicate.
- If we can contextualise the story, we can identify the right problem to solve.
- If we can design a UI that communicates, we can guide users towards their goals.
To clarify, this story is not about design principals or axioms. It is about a focus on the needs and challenges of the user. As such, the âcorrect answersâ will vary from project to project.
Also, while we used Javascript extensively in our examples, this story is not about Javascript technologies. It is about an attitude to figure out a UI design that can âmake senseâ to its users.
Letâs see how that comes into play with practical examples.
Tweak #1
Contextualise: How to present the information architecture without cluttering the display?Communicate: Use transition effects to tell a story.
Before: The âusualâ way of highlighting information.
<div id="myElement"> <a href="myURL">Maps</a></div>
After: A CSS tweak will give new dimensions to the information architecture.
A simple tweak to highlight the information architecture
var myIcon = document.getElementById( "myElement" );
addEventListener("mouseover", mouseOver );function mouseOver(event) { myicon.style.transform = "scale3d(1.20, 1.20, 1.20)"; // node; mylink.style.border = "solid 1px black"; // link}
Tweak #2
Contextualise: How to reveal information hierarchy quickly?Communicate: Stagger the entrance of containers progressively.
Before: A âtypicalâ page load
After: A staggered entrance highlights the information hierarchy instantly.
Tier-one. The core content, comprising text and media, are wrapping within the larger container to the far-right so that its implied order is noticed.
Using staggered animation to reveal information architecture
Tier-two. The middle container shows summary information and related topics for users who are interested to find out more (after reading the core content).
Tier-three. If users are indeed engaged, they can trigger the far left container to reveal more information (see the demo from part-four of our story).
Initiate the âstart/hiddenâ position of all containers.
rightContainer.style.transform = "translate3d(50vw, 100vh, 0)";middleContainer.style.transform = "translate3d(25vw, 100vh, 0)";leftContainer.style.transform = "translate3d(0vw, 100vh, 0)";
Sequence the entrance towards the âend/showâ position.
rightContainer.style.transform = "translate3d(50vw, 0vh, 0)";setTimeout(() => { middleContainer.style.transform = "translate3d(25vw, 0vh, 0)";}, 200);setTimeout(() => { leftContainer.style.transform = "translate3d(0vw, 0vh, 0)";}, 400);
- setTimeout delays code execution to emulate the staggered animation effect.
- The âstart/hiddenâ position of each container is 100vh (from the top). The âend/showâ position will be 0vh.
- keyframes or transition-delay can produce similar results.
- Select an easing transition to create butter-smooth animations.
Tweak #3
Contextualise: How to maximise the view and navigation space.Communicate: Autohide unused UI elements during navigation events.
Before: Visible navigation space is halved. While users can view content on the âstickyâ container, it is not needed in the midst of a navigation event itself.
Visible navigation space is halved
After: Since users wonât need the sticky container while navigating, we can safely fadeout the container to maximise view and navigation space.
The sticky container fades out contextually to maximise navigation space
fadeOutSticky(){ rightContainer.style.opacity = "0";};
// reusing event listener (from part-one discussion)canvas.addEventListener("mousedown", handlerGrab, false);
function handlerGrab(event) {
if (event.which == 1) { ...fadeOutSticky(); }; ...}
Tweak #4
Contextualise: How to ânot-blockâ active elementsCommunicate: Autohide blocking elements in response to interaction events.
Fadeout the minimap so that it wonât âblockâ the mouse cursor when users are âpanningâ the canvas (a navigation feature discussed in part-two).
The minimap makes way for the mouse cursor contextually
canvas.addEventListener("mousemove", handlerMouseMove, false);function handlerMouseMove(event) { if (event.which == 3) { if ( boundingbox(event.clientX, event.clientY, minimap) != false) { minimap.style.visibility = "hidden"; } else { minimap.style.visibility = "visible"; } }}
boundingbox is a custom function to determine if the mouse cursor is currently hovering over the minimap.
function boundingbox(ClientX = 0, ClientY = 0, element) { if (element.getBoundingClientRect) { var rect = element.getBoundingClientRect (); y = rect.top; xR = rect.right; yB = rect.bottom; xL = rect.left; boxHeight = yB - y; boxWidth = xR - xL; } if ( ClientX <= (xR) && ClientY <= (yB) ) { return true; } else return false; }
Tweak #5
Contextualise: How to create an âextra dimensionâ to reveal more information architecture?Communicate: Emulate a see-through effect by manipulating the opacity level of the âaboveâ element. The content of both the above and underneath layers are visible to help users visualise a complete picture.
You can enhance the navigation view or create a sense of visual depth with just the opacity value. Notice the semi-visible layer underneath the minimap (top-left) and the sticky container (right-hand side)?
Good-old CSS opacity creates both information and visual depthTweak #6
Contextualise: How to show related information only when itâs relevant (without a page reload).Communicate: Hide the information by default, but show on mouse focus.
A little background on the Google Cloud Platform (GCP). In the GCP world, PubSub is tightly integrated with other GCP products. While PubSub may be categorised under Big Data, it is also the integration point for many GCP products. How can we feature this contextual relationship without cluttering the overall layout? Itâs not so complicated once we do this.
PubSub and Cloud Storage is the invisible glue that connects many GCPÂ products
The technique is similar to how we would highlight the nodes (discussed in part-one of the story).
âHideâ the dotted line.
dottedLine.style.borderRight = "1px dashed #FFF"; // opacity or visibility works well too
E.g. when users mouse-over the node of PubSub, the eventlistener for the dotted line applies a new style.
dottedLine.style.borderRight = "1px dashed #ddd";
Itâs almost mandatory to apply easing.
dottedLine.style.borderRight = â300ms easeâ;
Tweak #7
Contextualise: How to show the contextual usage of the mouse cursor?Communicate: Update the mouse cursor icon to signify different usage or behaviour.
Interacting with the minimap. Users drag the rectangular bracket (top left) within the minimap to update the canvas (main view). The cursor change from a default pointer to a four-way arrow.
Minimap navigation: updating mouse cursor from pointer to four-way arrow
canvas.style.cursor = âinheritâ; // default mouse pointercanvas.style.cursor = âmoveâ; // four-way arrow icon
Interacting with the main canvas. Users drag the main canvas. The location on the minimap updates concurrently. The cursor change from a âgrabâ(hand) icon to a âgrabbingâ(fist) icon.
Canvas navigation: updating mouse cursor from âgrabâ to âgrabbingâ
canvas.style.cursor = â-webkit-grabâ; // hand iconcanvas.style.cursor = â-webkit-grabbing"; // fist icon
Tweak #8
Contextualise: How to add contextual usage to the same mouse click?Communicate: Differentiate a mousedown from a mouse click.
We want a left-click to do this.
The stand-alone left-click: âmousedown" and âmouseupâ action in a rapid succession
We also want a prolonged left-click to do this.
The grab-and-drag action: a prolonged mousedown with a mousemove to drag things that end with a mouseup
As you can see, a left-click is not the same as a prolonged left-click. The later drags the canvas.
A mouse button can have dual usage and still feel intuitive. When a left-click is on mousedown, and not mouseup yet, it may mean either:
- click on something, or
- drag things.
Itâs trivial to implement. The trick is knowing what happens after the mousedown event is detected. Is there an immediate mouseup event or a mousemove event? The former suggests a âstandardâ click and the later a custom drag action.
If a mouseup is not detected within, say 300ms, then let the user drag the canvas.
In the main while loop (from part-one), listen to the mousedown event.
while (item[i]) { itemElementName[i].addEventListener("mousedown", clickTimer ); ...}
Add a custom function named clickTimer to determine whether itâs a click or a drag.
var mouseClick = true;function clickTimer(event) { ... // measure the time interval between mousedown and mouseup ...}
Since weâre only interested in knowing if the time interval is more than 300ms (not the same as the interval value itself), we can use a simple hack to do the job.
// measurement hacksetTimeout(function(){ mouseClick = false;}, 300);
On mousedown, set mouseClick to true. However, after 300ms, set it to false.
Tweak #9
Contextualise: How to transit from âin-browserâ to full-screen mode.Communicate: Provide a quick-toggle option.
Toggle-to-interact. Offer an option to go interactive. By default, the âin-browserâ mode wonât block users from scrolling pass the canvas (also see scroll from part-two). A toggle will enable navigation from within the canvas.
Toggle between âin-browserâ and âinteractiveâ mode
canvas.style.overflow = "hidden"; // default with scroll disabledcanvas.style.overflow = "scroll"; // enable scroll
Toggle to fullscreen. Offer an option to go fullscreen from âinlineâ mode to maximise navigation space.
Toggle between full-screen and inline mode
buttonFullScreen.addEventListener("click", handlerFullScreen, false);
function handlerFullScreen(event) { ... canvas.style.height = "100vh"; canvas.style.width = "100vw"; // transform to new canvas full-width and full height // handle new minimap placement position & adjust the new location position // Calculate relative scroll position after canvas turns full-screen fullScreenSize = true; // global var for other functions}
- buttonFullScreen references the HTML <button></button>.
- canvas.style.height and canvas.style.height toggles the canvas to full screen. Remember to account for changes in the minimap position.
- Finally, use a boolean flag to tell your down-stream functions to calculate based on full-screen dimensions (or not).
Adjust resolution (and stay high-def). Use the mouse-scroll button to zoom. Use SVG to achieve unlimited scaling in high-definition.
Zoom incrementally (without easing effect)
Use the zoom API to increment or decrement size.
canvas.style.zoom = zoomLevel;zoomLevel = zoomLevel + 0.01; //increment the zoom level
Tweak #10
Contextualise: How to make UIs respond in a fluid and human-like manner?
Communicate: Incorporate an easing function to create an intuitive experience.
Animation and easing effects work hand in hand to provide useful visual cues for users. One example is the original iPhone end-of-page âreboundâ effect.
Letâs try this on our zoom example (from Tweak #9).
function easeInOutQuad(t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t + b; return -c / 2 * ((--t) * (t - 2) - 1) + b;}
function spreadZoom(direction) { var time = 0; var diff = 1; var minTime = 5; var maxTime = 40;
for (var i = 0, len = diff; i <= len; i++) { (function(s) { setTimeout(function() { if (direction == 'zoomin') { ... } else if (direction == 'zoomout') { ... }; }, time); })(i); time = easeInOutQuad(i, minTime, maxTime, diff); } // for loop}
The result is a smoother start-stop curve that mimics a natural response.
- spreadZoom breaks a physical scroll action into a series of smaller virtual zooms âspread overâ a easeInOutQuad curve.
- easeInOutQuad creates the analogue effect. The formula is based on the Robert Pennerâs easing equation.
- The behaviour can be further configured via time, diff, minTime, and maxTime variables.
Concept aside:Â Easing
Why is easing a first-class citizen in UIÂ design?
A simple tweak that makes the difference between âjust okâ and âjust rightâ.
Perhaps due to its mathematical nature, as illustrated in the previous easeInOutQuad example (Tweak #10), easing may be an overlooked and underused feature. However, it can be very straightforward. One line of CSS usually gets the job done.
CSS usage
#myElement {transition: 1s ease;}
Customised usage
#myElement {transition: 1s cubic-bezier(0.25,0.1,0.25,1);}
Javascript equivalent
myElement.style.transition = "all 1s cubic-bezier(0.25,0.1,0.25,1)";
Easing is used extensively in our demo project. For example, the staggered entrance of the sticky containers are eased (Tweak #2). So are the scaling and highlighting effects of the SVG icons and connecting links (Tweak #1).
Letâs have more fun with easing.
The ballerina chases the mouse cursor, with easing effect.Next Steps
Some of the most complex UIs are built on top of the simplest ideas. Once we apply those ideas to contextualise the problem and design a UI that communicates with its users, we can create designs that are more relevant.
While weâve devoted five stories to talk about some of the most basic Javascript techniques, we are saying just one thing. Anyone can create compelling designs with simple ideas. Anyone can transform a casual visit into a superior user experience.
Links to other parts
Part-one sets the foundation for designing interactive infographics.
Part-two adds navigation features to browse content.
Part-three adds a dynamic mini-map to enhance navigation.
Part-four adds an inline UI to access layered content.
Part-five â Youâre are here. Yay!
If you enjoyed this story, you can find more at Pageii Studio.
10 UI tweaks for web developers was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.