In the chapter “The psychopathology of everyday things”, Don Norman brings up a multitude of examples of bad design that hinders human experience with the object of said design. He proposes the idea of human-centered design as the ultimate goal of a good design. I do not think that the bad design in some cases is a problem that desperately needs to be fixed. For instance, confusing buttons of a dryer-washing machine is an example the author gives for bad design choices. I agree that the design is not human-centered and can be improved, but I find the emphasis on it being a problem unnecessary. The sales of such machines are profitable and people still buy the complicated technology despite the bad design, otherwise the production of such machines would be terminated. This could indicate that human-centered design is not the primary concern of the businesses selling the complicated technology. This also might suggest that creating a machine with more of a human-centered design is not beneficial to the company. Moreover, consumer can use fridges and washing machines for decades and I think the designers bet on the longevity of the product – it can be confusing at first, but not after 10 years of using the device and it is my understanding that the consumers are attracted to the bursting variety of features rather than the ease of use.
That being said, the author mentions that the good design choices come at an expense and have their fair share of constraints, but it is only discussed in chapter 6, therefore to make a conclusive judgement of the topic I would need to read about what author has to say in chapter 6. I hope the author can prove me wrong by offering worthy alternatives that would benefit the consumer and be feasible for the producers. Disclaimer: my points mentioned in the previous paragraph would apply to consumable goods, but not necessarily other products with bad design.
Category: Spring 2024 – Aya (Section 003)
Assignment # 4 Magnetic Effect Text
Concept
The magnetic effects and trails that I have come across a lot while looking for inspiration for this project served as my motivation. After doing some research, I came to Professor Aron’s website, which featured several interactive elements related to text manipulation. And it was these pictures on Pinterest that inspired me. The primary concept was kinetic typography, which used particles to smoothly transition between words to depict the unpredictable character of the natural world. It demonstrates how basic components can come together to create meaningful expressions when they are directed by physics and a little bit of randomness.
Code
The part of the assignment I’m most proud of is the creation of the Vehicle class. This piece of code is special because it makes each dot on the screen move like it has its mind, heading towards a goal. It combines simple rules of movement and direction to bring letters on the screen. What makes this class stand out is how it turns basic coding concepts into something that feels alive and interactive.
let font; let vehicles = []; let originalPoints = []; let cycleDuration = 5000; // Duration of one cycle in milliseconds let lastResetTime = 0; // Tracks the last time the positions were reset let words = ["SHOK", "SHAK", "SHOK"]; // Array of words to cycle through let currentWordIndex = 0; // Index of the current word in the array function preload() { font = loadFont('myfont.otf'); } function setup() { createCanvas(800, 300); background(255); textFont(font); textSize(192); setupWord(words[currentWordIndex]); } function draw() { let currentTime = millis(); if (currentTime - lastResetTime > cycleDuration) { // Move to the next word in the array, cycling back to the start if necessary currentWordIndex = (currentWordIndex + 1) % words.length; setupWord(words[currentWordIndex]); // Setup points for the new word resetPositions(); lastResetTime = currentTime; } else { background(255, 20); // Semi-transparent background for trail effect } for (let v of vehicles) { let noiseForce = getNoise(v.pos.x, v.pos.y); v.applyForce(noiseForce); v.update(); v.show(); } } function setupWord(word) { vehicles = []; // Clear the current vehicles let bounds = font.textBounds(word, 0, 0, 192); let posX = width / 2 - bounds.w / 2; let posY = height / 2 + bounds.h / 4; let points = font.textToPoints(word, posX, posY, 192, { sampleFactor: 0.5 }); originalPoints = points; for (let pt of points) { let vehicle = new Vehicle(pt.x, pt.y); vehicles.push(vehicle); } } function getNoise(x, y) { let noiseVal = noise(x * 0.01, y * 0.01); let angle = map(noiseVal, 0, 1, 0, TWO_PI); let force = p5.Vector.fromAngle(angle); force.mult(0.1); return force; } function resetPositions() { for (let i = 0; i < vehicles.length; i++) { vehicles[i].pos = createVector(originalPoints[i].x, originalPoints[i].y); vehicles[i].vel = p5.Vector.random2D().mult(0); // Reset velocity } } class Vehicle { constructor(x, y) { this.pos = createVector(random(width), random(height)); // Start with random positions this.target = createVector(x, y); this.vel = p5.Vector.random2D(); this.acc = createVector(); this.r = 4; this.maxspeed = 4; this.maxforce = 1; } applyForce(force) { this.acc.add(force); } update() { this.vel.add(this.acc); this.vel.limit(this.maxspeed); this.pos.add(this.vel); this.acc.mult(0); } show() { stroke(0); strokeWeight(this.r); point(this.pos.x, this.pos.y); } }
Embedded Sketch
Reflection and ideas for future work or improvements
Reflecting on this assignment, I’m considering the introduction of interactivity, allowing viewers to influence the flow and form of the animation in real-time. Additionally, refining the transitions between words to be even smoother would elevate the visual fluidity, creating a seamless blend from one word to the next. These improvements aim to turn the animation into a more immersive one.
Week 4 Reading Reflection
I enjoyed reading Don Normam’s “The Design of Everyday Things.” After reading Crawford’s definition’s of interactivity in “The Art of Interactive Design,” it was necessary to understand the fundamentals of interactions themselves, which go beyond the definition and importance. To me, the fundamental principles of interactivity were very well put in Don Norman’s book. I liked the text, probably because the examples were very grounded in our day-to-day interactions. The way Norman advocated for human-centric design seemed very similar to Myron Krueger’s philosophy that technology should serve human needs and desires (What Should You Wear to an Artificial Reality?). This also prompted the benchmark of calling a design good or bad. The reading really helped me to understand the importance of intuitive design. I always wondered why all the cars, phones, and computers looked similar. Norman’s examples of the learning curves of the users and intuitive design pretty much answered that question. However, I felt the examples lacked the presence of age groups. It would have been interesting to explore how intuitive design changes through time and generations. Norman’s illustration of the distinction between affordances and signifiers was very thought-provoking for me, as I had never explored the dimension of interactivity this much.
Reading Reflection | Week 4 | Aadil
In the design of everyday things, Don Norman discussed many interesting ideas and perspectives of design thinking. His example of doors – was quite thought provoking. Last week’s reading had this idea of ‘form and function’ in interactivity design. Thinking about something as simple as doors made this concept clear to me – both form and function are essential to develop a good design.
Norman’s idea of Human Centered Design that focuses on making machines discoverable and understandable was quite interesting too. He stated several things that I relate with – particularly about us taking shortcuts when a product is too complex. Thinking about this, I thought that maybe there is an ideal level of complexity for all products and the designer has to think about how much complexity is enough? In general, I would say that there should be as little complexity as possible and as much complexity as necessary.
The ideas of affordance, signifiers, constraints, mapping, feedback were all new to me. I had heard about affordance previously but never though t of it as a “relationship” between people and objects. This reading compelled me to think about some designs I encounter in everyday life (such as a lift or a chair). I hope to integrate these principles into any future design projects that I undertake , so that I can find solutions that are user-friendly and intuitive.
Reading Reflection 4 – Pavly Halim
Reflecting on Chapter One of “The Psychopathology of Everyday Things,” the text really made me think differently about the stuff we use every day. It’s like, we’ve all been there, struggling with something that’s supposed to be simple, like a door that doesn’t make it clear if you should push or pull. The author talks about how these design fails aren’t just annoying, but they actually show a more significant problem: designers sometimes focus more on making things look cool or high-tech instead of making them easy for us to use.
It made me question why design often misses the mark on user-friendliness. Is it because designers are trying too hard to impress other designers instead of thinking about regular people? Reading this has definitely changed how I look at things around me. Now, I catch myself wondering how something could be designed better to avoid confusion or frustration. It’s interesting to think about how much smoother our day could be if more things were designed with the user in mind. This chapter has sparked a lot of questions for me about what else in my daily life could be improved with better design.
Assignment 4 – Pavly Halim
The Concept:
My project is centered around the visualization of stock market data, specifically designed to help users visually track the fluctuations in stock prices over time. The idea was to create an interactive graph that could display a moving window of stock prices, allowing users to see trends and changes as they happen.
A Highlight of the Code:
One snippet of code that stands out to me for its simplicity and effectiveness is the drawGraph function. This function renders the graph on the screen, mapping the stock prices to visual elements that can be easily understood.
function drawGraph(startIndex) { const graphWidth = 700; const graphHeight = 300; const startY = height - graphHeight - 50; const endY = startY + graphHeight; const startX = (width - graphWidth) / 2; const endX = startX + graphWidth; //Calculate the subset of prices to display let displayedPrices = prices.slice(startIndex, Math.min(startIndex + windowSize, prices.length)); const minValue = Math.min(...displayedPrices); const maxValue = Math.max(...displayedPrices); const latestPrice = displayedPrices[displayedPrices.length - 1]; // The last price in the displayed subset push(); stroke(0); noFill(); rect(startX - 10, startY - 10, graphWidth + 20, graphHeight + 20); pop(); push(); stroke(25, 118, 210); strokeWeight(2); noFill(); beginShape(); for (let i = 0; i < displayedPrices.length; i++) { let x = map(i, 0, displayedPrices.length - 1, startX, endX); let y = map(displayedPrices[i], minValue, maxValue, endY, startY); vertex(x, y); } endShape();
Embedded Sketch:
Showcasing the dynamic visualization of stock prices over time
Code:
let stockData; let currentIndex = 0; let windowSize = 15; //Data points to display let prices = []; function preload() { stockData = loadTable('stock_prices.csv', 'csv', 'header'); } function setup() { createCanvas(800, 400); frameRate(1); // Framerate loadPrices(); // Load data } function draw() { background(255); drawGraph(currentIndex); currentIndex++; // Move the window forward if (currentIndex > prices.length - windowSize) currentIndex = 0; // Loop back if we reach the end } function loadPrices() { //Extract prices and store it in array for (let r = 0; r < stockData.getRowCount(); r++) { let price = stockData.getNum(r, 'price'); prices.push(price); } } function drawGraph(startIndex) { const graphWidth = 700; const graphHeight = 300; const startY = height - graphHeight - 50; const endY = startY + graphHeight; const startX = (width - graphWidth) / 2; const endX = startX + graphWidth; //Calculate the subset of prices to display let displayedPrices = prices.slice(startIndex, Math.min(startIndex + windowSize, prices.length)); const minValue = Math.min(...displayedPrices); const maxValue = Math.max(...displayedPrices); const latestPrice = displayedPrices[displayedPrices.length - 1]; // The last price in the displayed subset push(); stroke(0); noFill(); rect(startX - 10, startY - 10, graphWidth + 20, graphHeight + 20); pop(); push(); stroke(25, 118, 210); strokeWeight(2); noFill(); beginShape(); for (let i = 0; i < displayedPrices.length; i++) { let x = map(i, 0, displayedPrices.length - 1, startX, endX); let y = map(displayedPrices[i], minValue, maxValue, endY, startY); vertex(x, y); } endShape(); pop(); push(); textSize(17); fill(0); noStroke(); textAlign(CENTER); text(`Current Price: $${latestPrice.toFixed(2)}`, width / 2, startY - 25); pop(); }
Reflection and Future Work:
This project has allowed me to refine my skills in processing and presenting data in an informative and aesthetically pleasing way. The feedback loop provided by visually tracking the effectiveness of the code in real time has been incredibly rewarding.
Moving forward, I see several avenues for improvement and expansion. For instance, integrating real-time data feeds to allow the graph to update with live market data would significantly enhance its utility. Additionally, incorporating user input to select different stocks or adjust the window size and time frame could make the tool more versatile and user-friendly.
Week 4: Reading response
Norman’s chapter on the design of everyday things was very relatable to me as I completely understand his frustration of poorly designed daily objects, especially doors that don’t clearly indicate a way of opening them. On the topic of doors, I also think that they should have some sort of design that one can immediately tell how they function. One thing I kept looking forward to in this reading was for Norman to propose a solution to this, by showing us a prototype or just writing down a way in which designers can make doors better. However, he never gives us a clear idea of how he would want a door to be designed like.
On another note, I also understand his struggle with instruction manuals as first of all, humans usually try to mess around with the object rather than actually reading what is written in the manual. Secondly, most instruction manuals are not really that clear. Overall, I agree with a lot of what Norman is telling us in this chapter.
Week 4: Generative Text
For this assignment, I decided to explore generating text in p5.js. I created a CSV file that contains words that are part of a meal such as the topping, side, drink and main. The blackboard generates a new and random “special meal” on every mouse click.
A part that I struggled with is making every meal generate randomly, which I tackled by writing the code below:
Row = split(strings[int(random(strings.length))], ',');
For improvements, I want to add more visuals. In addition, I want the topping to be randomized for every part of the meal rather than having the same topping for the main, side and drink.
Reading Response: The Psychopathology of Everyday Things, #Week4
Reflecting on Norman’s insights from “The Psychopathology of Everyday Things, Chapter:1” I find myself deeply considering the complexity hidden within simple everyday objects like doors, refrigerators, and watches. Norman points out that the designs meant to simplify our lives can sometimes make them more complicated instead. This resonates with me because I’ve often found myself frustrated by appliances and gadgets (like smart watches, bluetooth coffee maker) that have too many features. These features, instead of making the device better, can make it harder to use. Norman’s argument makes me rethink the belief that having more features means better functionality. My own experiences support this idea, as I’ve struggled with devices that seem to prioritize complexity over ease of use.
Yaakulya’s Assignment 4: Loading Data & Displaying text
Concept: I always wanted to understand the graphs and math revolve behind Real Estates, so for my Data Visualization assignment, I created a data visualization using the Boston Housing dataset. (Dataset URL: https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv)
This Dataset is available to public.
The resultant visualization displays the relationship between the average number of rooms per dwelling (RM) and the median home value ($1000s) for various suburbs in Boston. Each data point on the graph represents a suburb, with the x-axis indicating the average number of rooms and the y-axis indicating the median home value. Additionally, I implemented an interactive tooltip that provides detailed information about each data point when the user hovers over it, including the suburb name, crime rate, and median home value.
To make my concept work, I found inspiration from these sources and moreover I learnt a lot about attributes and functions used for loading the required data from the datasets precisely:
Highlight of Code: One part of the code that I’m particularly proud of is the implementation of the interactive tooltip, initially I found it very difficult. This feature enhances the user experience by providing additional information about the data points in a user-friendly manner. Here’s the code snippet responsible for displaying the tooltip:
function draw() { // Check if mouse is over a data point let overPoint = false; for (let i = 0; i < data.getRowCount(); i++) { let rm = map(data.getNum(i, 5), 3, 9, 100, width - 100); let medv = map(data.getNum(i, 13), 5, 50, height - 100, 100); let d = dist(mouseX, mouseY, rm, medv); if (d < 5) { overPoint = true; let suburb = data.getString(i, 0); let crimeRate = data.getNum(i, 1); let medianValue = data.getNum(i, 13); tooltip.html(`Suburb: ${suburb}<br>Crime Rate: ${crimeRate.toFixed(2)}<br>Median Home Value: $${medianValue.toFixed(2)}k`); tooltip.position(rm + 20, medv - 20); tooltip.show(); break; } } if (!overPoint) { tooltip.hide(); } }
Explanation – How this Interactive feature works?: In the draw()
function, which updates the canvas continuously, the code iterates through each data point in the dataset. It calculates the distance between the mouse cursor position and the position of each data point using the dist()
function. If this distance is within a threshold of 5 pixels, indicating that the mouse is hovering over a data point, the code retrieves information such as suburb name, crime rate, and median home value using functions like getString()
and getNum()
. These functions extract specific values from the dataset based on row and column indices. The tooltip’s content is then updated to display this information, and its position is adjusted slightly from the data point using the position()
function. Finally, the tooltip is shown to the user with show()
. If the mouse is not over any data point, the tooltip is hidden using hide()
. This process allows for interactive display of detailed information when the user hovers over data points on the visualization.
Complete Embedded Sketch:
let data; let tooltip; function preload() { // Load the Boston Housing dataset data = loadTable('https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv', 'csv', 'header'); } function setup() { createCanvas(800, 600); background(240); // Plot the data points with black color for (let i = 0; i < data.getRowCount(); i++) { let rm = map(data.getNum(i, 5), 3, 9, 100, width - 100); let medv = map(data.getNum(i, 13), 5, 50, height - 100, 100); fill('rgb(197,134,88)'); // Change color to black noStroke(); ellipse(rm, medv, 10, 10); } // Add x and y axes drawAxes(); // Add interactive tooltip tooltip = createDiv(''); tooltip.style('position', 'absolute'); tooltip.style('background-color', 'rgba(255, 255, 255, 0.8)'); tooltip.style('padding', '8px'); tooltip.style('border-radius', '4px'); tooltip.hide(); } function drawAxes() { // Draw x-axis stroke(0); line(100, height - 100, width - 100, height - 100); for (let i = 4; i <= 9; i++) { let x = map(i, 3, 9, 100, width - 100); textAlign(CENTER, CENTER); textSize(12); fill(0); text(i, x, height - 80); } textAlign(CENTER, CENTER); textSize(16); fill(0); text('Average Number of Rooms per Dwelling (RM)', width / 2, height - 40); // Draw y-axis stroke(0); line(100, 100, 100, height - 100); for (let i = 5; i <= 50; i += 5) { let y = map(i, 5, 50, height - 100, 100); textAlign(RIGHT, CENTER); textSize(12); fill(0); text(i, 90, y); } textAlign(CENTER, CENTER); textSize(19); fill(0) text('Boston Housing Dataset Visualization (Year:1970-2006)', 400, 40); rotate(-HALF_PI); textSize(16); text('Median Home Value ($1000s)', -height / 2, 50); } function draw() { // Check if mouse is over a data point let overPoint = false; for (let i = 0; i < data.getRowCount(); i++) { let rm = map(data.getNum(i, 5), 3, 9, 100, width - 100); let medv = map(data.getNum(i, 13), 5, 50, height - 100, 100); let d = dist(mouseX, mouseY, rm, medv); if (d < 5) { overPoint = true; let suburb = data.getString(i, 0); let crimeRate = data.getNum(i, 1); let medianValue = data.getNum(i, 13); tooltip.html(`Suburb: ${suburb}<br>Crime Rate: ${crimeRate.toFixed(2)}<br>Median Home Value: $${medianValue.toFixed(2)}k`); tooltip.position(rm + 20, medv - 20); tooltip.show(); break; } } if (!overPoint) { tooltip.hide(); } }
Generated Output:
Reflection and Ideas for Future Work: Overall, I’m satisfied with how the assignment turned out. The visualization effectively communicates the relationship between the number of rooms in a dwelling and the median home value in different suburbs of Boston. The interactive tooltip adds an extra layer of interactivity and information, enhancing the user experience.
For future work or improvements, I could consider adding more features to the visualization, such as:
1. Implementing color encoding for an additional variable, such as crime rate or pupil-teacher ratio, to provide more insights into the data.
2. Enhancing the design of the visualization by adding axis labels, a title, and a legend to improve clarity and understanding.
3. Exploring different types of visualizations, such as scatter plots or line charts, to represent the data in alternative ways and uncover additional patterns or trends in addition working with latest datasets.
Overall, this assignment has been a valuable learning experience, and I look forward to applying these skills to future assignments ad projects.
Related P5 References:
1. https://p5js.org/reference/#/p5/map
2. https://p5js.org/reference/#/p5.Element/style
3. https://p5js.org/reference/#/p5.Table/getNum
4. https://p5js.org/reference/#/p5.Element/hide
5. https://p5js.org/reference/#/p5.Element/position
6. https://p5js.org/reference/#/p5.Table/getString