This week’s reading has been incredibly enlightening, offering valuable insights into the realm of interaction and design. It prompted me to reconsider the intricacies of design processes and their impact on user experience. The discussion on the challenges of everyday interactions, particularly with objects like doors, emphasized the pivotal role of effective design in usability. The concept of “Norman doors” sheds light on the common struggle users face in navigating poorly designed interfaces, a challenge I’ve personally encountered.
Similar to the confusion of push and pull doors, I also get confused every time I try to open my curtains. It annoys me when I pull the curtain string to open and it gets closer even further instead.
the white curtain string, you need to pull one (I don’t know which till this day ;)) to open or close the curtain
Through engaging anecdotes and examples, the reading emphasized the importance of discoverability and understanding in design, advocating for intuitive products that require minimal instruction. One aspect that stood out to me and that I believe is crucial to keep in mind for my future career in IM is the exploration of human-centered design and its integration of psychology and technology. Understanding how to prioritize human needs, capabilities, and behavior in design solutions is paramount, as it ensures products are not only aesthetically pleasing but also functional and user-friendly. This insight is something I find both intriguing and essential to carry forward as I pursue my career in IM.
This kinetic typography transforms static text into an interactive visual display. By treating each point of the font’s letters as a vehicle, the sketch brings the text “Dream” to life, allowing it to respond dynamically to the viewer’s mouse movements. Vehicles “arrive” at their designated spots to form the letters of the word and “flee” when the mouse comes close, creating an engaging effect that feels both chaotic and ordered. The addition of the gradient background adds depth and visual interest, making the typography a part of an aesthetically pleasing composition of a sunset.
Use your mouse to go through the word to interact with it:
Font Points Extraction and Vehicle Initialization:
//Extract points from the font
let points = font.textToPoints(textString, 75, 320, fontSize, {
sampleFactor: 0.1
});
//Initialize vehicles for each point
for (let i = 0; i < points.length; i++) {
let pt = points[i];
let vehicle = new Vehicle(pt.x, pt.y);
vehicles.push(vehicle);
}
Extracting points from text and converting them into “vehicles” was a bit complex due to the need to handle font rendering and point manipulation. The textToPoints() function is used to get the vector points for each letter, which are then used to create vehicle objects that simulate motion.
Also for the Vehicle class, implementing behaviors such as “arrive” and “flee” required understanding of steering behaviors and force accumulation in a physics-based simulation. Balancing these forces to achieve smooth and natural movement was challenging, especially when trying to simulate both attraction to a target point and repulsion from the mouse cursor.
Full code:
//Preload the font
let font;
let vehicles = []; //Array to hold the 'vehicle' objects
function preload() {
//Load the font from the assets
font = loadFont('Hogfish DEMO.otf');
}
function setup() {
createCanvas(700, 500); //Set up the canvas
//Create a background gradient
setGradient(0, 0, width, height, color('#EBC249'), color('#A52D56'), Y_AXIS);
//Define the text properties
let textString = 'Dream';
let fontSize = 180;
//Convert the text to a series of points
let points = font.textToPoints(textString, 75, 330, fontSize, {
sampleFactor: 0.1 //Determines the density of the points
});
//Create a vehicle object for each point
for (let i = 0; i < points.length; i++) {
let pt = points[i];
let vehicle = new Vehicle(pt.x, pt.y);
vehicles.push(vehicle);
}
}
function draw() {
//Refresh the gradient background each frame
setGradient(0, 0, width, height, color('#EBC249'), color('#A52D56'), Y_AXIS);
//Update and display each vehicle
for (let i = 0; i < vehicles.length; i++) {
let v = vehicles[i];
v.behaviors();
v.update();
v.show();
}
}
//Constants for gradient direction
const Y_AXIS = 1;
const X_AXIS = 2;
//Function to create a gradient background
function setGradient(x, y, w, h, c1, c2, axis) {
noFill();
//Create a vertical gradient
if (axis === Y_AXIS) {
for (let i = y; i <= y + h; i++) {
let inter = map(i, y, y + h, 0, 1);
let c = lerpColor(c1, c2, inter);
stroke(c);
line(x, i, x + w, i);
}
}
//Create a horizontal gradient
else if (axis === X_AXIS) {
for (let i = x; i <= x + w; i++) {
let inter = map(i, x, x + w, 0, 1);
let c = lerpColor(c1, c2, inter);
stroke(c);
line(i, y, i, y + h);
}
}
}
//The Vehicle class
class Vehicle {
constructor(x, y) {
this.pos = createVector(random(width), random(height)); // Start position
this.target = createVector(x, y); //Target position
this.vel = p5.Vector.random2D(); //Initial velocity
this.acc = createVector(); //Acceleration
this.r = 8; //Radius
this.maxspeed = 10; //Maximum speed
this.maxforce = 1; //Maximum steering force
}
//Combine behaviors
behaviors() {
let arrive = this.arrive(this.target);
let mouse = createVector(mouseX, mouseY);
let flee = this.flee(mouse);
arrive.mult(1);
flee.mult(5);
this.applyForce(arrive);
this.applyForce(flee);
}
//Apply a force to the vehicle
applyForce(f) {
this.acc.add(f);
}
//Update the vehicle's position
update() {
this.pos.add(this.vel);
this.vel.add(this.acc);
this.acc.mult(0); //Reset acceleration each frame
}
//Display the vehicle
show() {
stroke(255);
strokeWeight(8);
point(this.pos.x, this.pos.y);
}
//Steer the vehicle towards a target
arrive(target) {
let desired = p5.Vector.sub(target, this.pos); //A vector pointing from the position to the target
let d = desired.mag();
let speed = this.maxspeed;
if (d < 100) {
//Adjust speed based on distance to the target
speed = map(d, 0, 100, 0, this.maxspeed);
}
desired.setMag(speed);
let steer = p5.Vector.sub(desired, this.vel);
steer.limit(this.maxforce);
return steer;
}
//Make the vehicle flee from the mouse
flee(target) {
let desired = p5.Vector.sub(target, this.pos);
let d = desired.mag();
if (d < 50) {
desired.setMag(this.maxspeed);
desired.mult(-1); //Go in the opposite direction
let steer = p5.Vector.sub(desired, this.vel);
steer.limit(this.maxforce);
return steer;
} else {
return createVector(0, 0); //No force if the mouse is far away
}
}
}
For this week’s assignment I decided to do aa text with an interactive part.
First, I did the sketch and put the text in. I have to admit, it was difficult to choose the background color because I wanted something that would suit every single random color generated when you press the button. At first I thought of a beige, sand color but it did not look right. So, I decided to stick with black.
After that, I created a function for the mouse interaction.
I have to admit, I did not have much time to do this but this is the end result! All in all, I am pretty proud of my improvement on coding giving the fact that I started 4 weeks ago.
For the future, I want to figure out how to use other fonts as well.
The banality of evil design is everywhere. Don Norman’s argument is trying to prove that there should be thought behind every new idea. On top of that, there is also a need for some boxes to be checked before coming out with a new product.
This first chapter of his work reminded me of the book ‘Universal Principles of Graphic Design’ by Jill Butler and how there are certain instructions when it comes to good design.
Since my arrival at NYUAD in August, I have encountered several instances of design oversights within the campus environment. For instance, the positioning of football court seats on the incorrect side of the field exposes them to relentless sunlight, diminishing their utility and comfort. Similarly, the placement of the alarm button adjacent to the toilet flush button presents a comical yet concerning scenario, where inadvertent activation could disrupt the tranquility of the Arts Center.
All in all, I believe that good designers think ten times before coming out with a product. It is better to think twice at first than having to deal with redesigning it over and over again.
After delving into the first chapter of Don Norman’s “The Design of Everyday Things,” I find myself resonating deeply with his emphasis on the significance of understanding human behavior and psychology in design. Norman’s argument about the importance of putting ourselves in the shoes of users resonates with my own approach to design. I firmly believe that creating anything without considering the end user’s perspective is futile. Design should always prioritize usability and functionality to ensure a seamless interaction between users, systems, and designers.
Norman’s discussion on the paradox of technology also caught my attention, particularly his insight into how experiences shape users’ perceptions of interactions. It serves as a reminder that even the most aesthetically pleasing designs must prioritize functionality and user experience above all else. This resonates with me as I reflect on instances where overly complex features have hindered rather than enhanced my experience with products.
Moreover, Norman’s critique challenges the prevailing notion that more features equate to better functionality. It prompts me to reconsider what truly defines a good design and the balance between form, complexity, simplicity, and functionality. As I continue to contemplate Norman’s insights, I aim to adopt a dual perspective—as both a user and a designer—to ensure that my designs are not only visually appealing but also intuitive and user-friendly. Norman’s work serves as a valuable guide for navigating the complexities of design and human interaction, prompting me to strive for designs that enhance users’ lives without adding unnecessary complexity.
The concept I aimed to replicate the captivating streams of 1s and 0s that are frequently shown in movies or GIFs, which represent the fundamentals of digital computing and communication. I wanted to achieve something similar to seeing a complex dance of binary digits, therefore I represented these streams with random characters.
Inspiration
Sketch
Code
function draw() {
background(0);
// Display and animate characters
for (let x = 0; x < cols; x++) {
for (let y = 0; y < rows; y++) {
let yOffset = (millis() * speed + x * 50 + y * 50) % (height + 200) - 100;
if (grid[x][y].bright) {
// Set bright neon blue color for highlighted characters
fill(0, 255, 255);
} else {
// Set light neon blue color for other characters
fill(0, 150, 255);
}
text(grid[x][y].char, x * charSize, y * charSize + yOffset);
}
}
}
In the draw() method, I have a nested loop that iterates over each cell of the 2D grid array. The location of the characters are calculated and its appearance based on its coordinates and a time-based offset (yOffset). This offset is computed given the cell coordinates, a predetermined speed value, and the current value of millis(), which indicates the milliseconds since the sketch began operating.
if (grid[x][y].bright) {
// Set bright neon blue color for highlighted characters
fill(0, 255, 255);
} else {
// Set light neon blue color for other characters
fill(0, 150, 255);
}
Each character’s color is chosen according to the entry that corresponds to it in the grid array. fill() method applies a bright neon blue color to a cell if its bright attribute is set to true. Otherwise, ordinary characters are shown in a lighter neon blue hue.
Full Code
// 2D array to display the characters
let grid;
// the font size of the characters
let charSize = 20;
// columns and rows for the 2D array (grid)
let cols, rows;
// speed of the characters falling
let speed = 0.2;
function setup() {
print(windowWidth,windowHeight)
createCanvas(windowWidth, windowHeight);
//creating the 2D array
cols = floor(width / charSize);
rows = floor(height / charSize);
grid = create2DArray(cols, rows);
// initializing the characters font size
textSize(charSize);
// Initialize grid with random characters
for (let x = 0; x < cols; x++) {
for (let y = 0; y < rows; y++) {
grid[x][y] = {
// calling the characters randomly
char: randomChar(),
// Randomly determine if the character should be brighter or not
bright: random(1) > 0.8
};
}
}
}
function draw() {
background(0);
// Display and animate characters
for (let x = 0; x < cols; x++) {
for (let y = 0; y < rows; y++) {
let yOffset = (millis() * speed + x * 50 + y * 50) % (height + 200) - 100;
if (grid[x][y].bright) {
// Set bright neon blue color for highlighted characters
fill(0, 255, 255);
} else {
// Set light neon blue color for other characters
fill(0, 150, 255);
}
text(grid[x][y].char, x * charSize, y * charSize + yOffset);
}
}
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
cols = floor(width / charSize);
rows = floor(height / charSize);
grid = create2DArray(cols, rows);
// Reinitialize grid with random characters
for (let x = 0; x < cols; x++) {
for (let y = 0; y < rows; y++) {
grid[x][y] = {
char: randomChar(),
// Randomly determine if the character should be brighter or not
bright: random(1) > 0.8
};
}
}
}
// function to create the 2D array grid
function create2DArray(cols, rows) {
let arr = new Array(cols);
for (let i = 0; i < arr.length; i++) {
arr[i] = new Array(rows);
}
return arr;
}
// function to generate a random character
function randomChar() {
return String.fromCharCode(floor(random(65, 91)));
}
Challenges
The significant challenge was how to keep the characters’ animation in a fluid and synced motion along with the shifting grid placements while maintaining readability and visual consistency.
Another challenge was assigning different brightness levels to different characters. This required careful coordination to make sure the highlighted characters shone out without overshadowing other characters or creating visual clutter.
Improvements
There is one improvement that I would like to implement in the future. I would want to improve the animation algorithm’s efficiency that may result in more fluid and flawless visual transitions, particularly when working with bigger grids or faster animation rates.
Another improvement could be the inclusion of user interactivity. The user could disrupt the falling characters using mouse hover and the characters trying to get back into the original stream.
Pi’s Some sort of data visualization is literally some sort of data visualization and trying to remove things that are not necessary. Inspired by Saturay Morning Breakfast Cereal, this data shows true, but useless facts.
2) ⚙️ Technical Plan of Attack & Implementation
Once we get the data, drawing the bar is just defining some parameters and working with the rectangles accordingly.
// Calculate dynamic dimensions
let padding = 200;
let graphWidth = width - 2 * padding;
let barWidth = graphWidth / data.length;
let colors = []; // Array to hold the bar colors
for (let i = 0; i < data.length; i++) {
colors.push(color(255, 105 + i * 10, 0)); // Gradually changing the color
}
// Draw the bars
for (let i = 0; i < data.length; i++) {
fill(colors[i]);
noStroke();
rect(padding + i * barWidth, height - padding - data[i] * barWidth, barWidth - 1, data[i] * barWidth);
}
// ... and so on
I could have loaded from the csv file, but the data is small enough.
3) 🎨 Artistic Plan of Attack & Implementation
Just to keep things not boring, I played with some automatic orange gradient for the bar colors by using
let colors = []; // Array to hold the bar colors
for (let i = 0; i < data.length; i++) {
colors.push(color(255, 105 + i * 10, 0)); // Gradually changing the color
}
4) 💪 Challenges
No challenge.
5) 💡 Potential Improvements
No further improvements are needed, I need to learn to restrain yourself.
“The problem with the designs of most engineers is that they are too logical.”
😱 Ouch ouch! Don Norman’s quote above from “The Psychopathology of Everyday Things” was harsh enough to get my blood boiling. Despite feeling personally attacked, both the devil and the angel on my shoulders say “Wait, wait, he has got a point”. I fully join Don in standing ovation for his idea of Human-Centered Design. When I wrote in my last post “The good design speaks for itself, the learning curve is so smooth such that the users enlightens themselves without any guidance and hitting F1 for user manuals.” I was saying exactly the same points. Discoverability is a vital concept… the user should be able to discover how the thing works, without it being explicitly stated… and how do you mainly achieve this? Nudges!! Although Don has not mentioned it in Chapter 1, I would like to highlight the Nudge Theory to the rescue… and some examples.
The Nudge Theory
I don’t have a human kid, but I know for a fact that at one point, they have to stop breast milk 🍼 and start to eat actual solid food 🍗. This process is called weaning and back home, they start to train babies to stop feeding on breast milk around 6 months to 1 year of age. Like cocaine addicts with withdrawal symptoms, the babies will cry endlessly and become super desperate whenever they come into close contact with their mother… then these little zombies will reach out for the breast.
This behavior has to change, of course. Back home, they have a traditional method of weaning… where you literally “spice 🌶️ things up” by putting turmeric powder on the mother’s nipples so that when the baby gets its breastmilk next time, it goes “What the blistering barnacles?” with eyes popping out 😳. Next time, it learnt its lesson… “Chicken wings are tastier than breastmilk from now on”.
Woah woah Pi, how is this spice powered weaning method related to Human-Centered Design?
Wait wait, I am just explaining the idea of a “nudge theory”.
This is an example of nudge theory in action – a nudge is a gentle push towards a desirable behavior without any force or mandate. Here, the baby discovers on its own that it should switch from breastmilk to chicken by itself.
Don Norman’s discoverability in action!
In similar, but less spicy ways, the nudges can be applied to aid discoverability in a lot of human centered designs, to gaslight the humans into figuring stuff out on their own. In the rest of the post, I would like to share 3 of my favorite examples of this discoverability in action.
Applying Nudge Theory to Everyday Design
Flies 🪰
My personal favorite of all time solves the age-old problem of men’s restrooms: the messy urinal area. The aftermath is a nightmare for anyone tasked with cleanup. But here comes the nudge solution, as simple as it is ingenious.
A tiny sticker of a fly, or sometimes a target, is placed strategically in the urinal. It’s almost laughable how such a small thing can redirect a grown man’s attention. Yet, it works!
Men, either out of amusement or subliminal inclination, aim at the sticker.
The result? A cleaner urinal area, less spillage, and a sigh of relief from janitors everywhere.
It’s fun, it’s effective, and the best part? It doesn’t need a user manual or a ‘how-to’ guide. Men just get it, and they go along with it, often without even realizing they’re being nudged into better behavior.
World’s Deepest Bin 🗑️
Traditional bins are all but invisible to the average person. Enter the world’s deepest bin – not literally the deepest, but it sure sounds like it.
The nudge here is a bin that, when used, emits a humorous, exaggerated deep sound. It’s like dropping a piece of trash into a never-ending well. The sound is so unexpected, so comically over the top, that it draws people in. The result is as effective as it is entertaining: people actually look for things to throw away just to hear that sound again.
It turns an ordinary act of disposing of trash into a mini-adventure. And just like that, littering is reduced.
People are engaged, amused, and more importantly, they are nudging themselves and others to keep the surroundings clean.
Piano Stairs 🎹
The last example is a delightful play on human nature’s love for music: the piano stairs. The problem is clear: given the choice, most people opt for escalators or elevators, shunning the stairs, missing out on an easy opportunity for some physical activity.
The nudge solution? Transform a staircase next to an escalator into a giant working piano. Each step is a piano key that makes a sound when you step on it. The result is magical. People are drawn to the stairs, curious and excited. They hop, skip, and jump on the stairs, creating music as they go. What was once a mundane climb turns into a playful experience.
People actually go out of their way to use the stairs, sometimes repeatedly.
It’s human-centered design at its most whimsical and effective.
Conclusion
In each of these examples, the key factor is the design’s ability to communicate and guide behavior without explicit instructions. The fly in the urinal doesn’t need a sign explaining what to do. The World’s Deepest Bin doesn’t have a manual on how to use it. Piano Stairs don’t come with a user guide. They work because they tap into human instincts and make the desired action the more appealing choice. This is the essence of human-centered design – creating solutions that are so in tune with human behavior and needs that they guide us subtly towards better habits.
In this weeks reading I really had fun exploring the composition of designing and the elements, complexity and usefulness of design with an example of a door. Yes, a single door was used to explain the whole theory of the design of everyday things.
A door is a perfect example of confusion in design. Even though simple, we always find a way to confuse ourselves and pull a door if we should push it, push a door if we should pull it, or neither of those, maybe we just needed to slide the door open.
A good way to fix that is to look at the hinge (or if you are a designer: don’t hide the hinge please) or give the “user” proper information on how they should handle the door. That leads to us talking about the two big aspects of good design:
Discoverability
Understanding
A story that the author mentions is a story of a friend that got trapped in a doorway of a Post Office in an European system. The door system, which was made out of six doors, is a perfect example of failed discoverability since it did not provide enough information for the “user” and it just led to confusion.
Another topic that comes into conversation is the complexity of modern devices. The theory is that modern devices and machines are made by humans so they are quite limited in what they can do. At the same time, proper guidance (aid, manuals) must be provided in these complex devices since they are created by engineers who have deeper understanding of the device, unlike the people that operate it.
In the first chapter of “The Design of Everyday Things,” Don Norman talks about the concept of affordances and their importance in shaping how users interact with products and environments, overall leading to the product’s success or doom. He emphasizes the importance of intuitive design, where the objects function should be to the point. Norman uses the example of a well-designed door handle to illustrate. A good handle should make it obvious whether to push or pull through its shape and positioning. Norman summarizes it pretty well here, “The design of the door should indicate how to work it without any need for signs, certainly without any need for trial and error.”(2) On the other hand, poorly designed handles without clear affordances often frustrate users and lead to confusion. He argues that intuitive design creates a seamless relationship between users and products, reducing cognitive load. Overall, Norman’s approach enhances the experience while minimizing mistakes and accidents. Furthermore, a well-designed smartphone interface intuitively guides users to access different functions and features. For instance, users understand that tapping an icon opens an app, swiping left or right navigates between screens, and pinching or spreading fingers zooms in or out. These intuitive interactions reduce the learning curve for users and enhance their overall experience with the device, to the point where even toddlers use tablets nowadays without any trouble. Yet interfaces with unclear design can confuse users and lead to frustration. Therefore, prioritizing intuitive design in smartphone interfaces is crucial for ensuring seamless interaction and user satisfaction. Intuitive design should be the key priority to every product development process. By understanding users’ needs, we can create products that enchance not cause trouble in our daily lives. In today’s world of complex technology, prioritizing intuitive design isn’t just a design approach but a necessity for creating products that are truely successful.