How to Unroll Images with Three.js

Do you like to roll up things? Or maybe you prefer rolling them out?

I spent my childhood doing crepes. I loved those rolls.

I guess, the time has come to unroll all kinds of things, including images. And to unroll as many rolls as possible I decided to automate this process with a bit of JavaScript and WebGL.

rolled crepe

The setup

I will be using Three.js for this animation, and set up a basic scene with some planes.

Just as in this tutorial by Paul Henschel, we will replace all the images with those PlaneGeometry objects. So, we will simply work with HTML images:

<img src="owl.jpg" class="js-image" />

Once the page loads and a “loaded” class is set to the body, we will hide those images:

.loaded .js-image {
	opacity: 0;
}

Then we’ll get the dimensions of each image and position them into our 3D Planes, exactly there where the DOM image elements were.

MY_SCENE.add(
	new THREE.Mesh(
		new PlaneGeometry(640,480),  // some size of image
		new Material({texture:’owl.jpg’) // texture i took from DOM
	)
)

Because rolling things with CSS or SVG is next to impossible, I needed all the power of WebGL, and I moved parts of my page into that world. But I like the idea of progressive enhancement, so we still have the usual images there in the markup, and if for some reason the JavaScript or WebGL isn’t working, we would still see them.

After that, its quite easy to sync the scroll of the page with the 3D scene position. For that I used a custom smooth scroll described in this tutorial. You should definitely check it out, as it works regardless of platform and actions that you use to scroll. You know this is usually the biggest pain with custom scrolling libraries.

Let’s rock and roll

So, we have what we want in 3D! Now, with power of shaders we can do anything!

Well, anything we are capable of, at least =).

Red parts are WebGL, everything else is HTML

I started from the end. I imagine every animation as some function which takes a number between 0 and 1 (I call it ‘progress’) and returns a visual. So the result of my imaginary RollFunction(0) should be something rolled. And RollFunction(1), should be just the default state of the plane. That’s how I got the last line of my animation:

vec3 finalPosition = mix(RolledPosition, DefaultPosition, progress);

I had DefaultPosition from the start, it’s usually called ‘position’. So all I needed is to create the RolledPosition and change my progress!

I figured out a couple of ways to do that. I could have had another object (like an .obj file) done in some editor, or even fully exported the animation from Blender or another program.

But I decided to transform DefaultPosition into RolledPosition with a couple of math functions inside my Vertex shader. So, imagine we have a plane lying in the Z plane, so, to roll something like that, you could do the following:

RolledPosition.x = RADIUS*cos(position.x);
RolledPosition.y = position.y; // stays the same
RolledPosition.z = RADIUS*sin(position.x);

If you ever tried to draw a circle yourself, you can easily guess where this is coming from. If not here is a famous GIF illustrating that visualizes that sheds some light on it:

See how those two functions are essentially part of circle

Of course this would just make a (not so) perfect tube out of our plane, but just adding a couple of parameters here, we can make it into a real roll:

RADIUS *= 1 - position.x; // so it gets smaller when we roll the plane
newposition.z =  RADIUS*sin(position.x*TWO_PI);
newposition.x =  RADIUS*cos(position.x*TWO_PI); 

And you will get something like that:

This is done with the help of the D3 library, but the idea is the same.

This two-dimensional animation has really helped me to get the idea of rolling things. So I recommend that you to dig into the code, it’s quite interesting!

After that step, it was a matter of time and arithmetics to play a bit with the progress, so I got this kind of animation for my plane:

There are a number of other steps, to make the angle parametric, and to make it a bit more beautiful with subtle shadows, but that’s the most important part right here. Sine and Cosine functions are often at the core of all the cool things you see on the web! =).

So let me know if you like these rolling effects, and how much time you have spent scrolling back and forth just to see ‘em roll! Have a nice day! =)

How to Unroll Images with Three.js was written by Yuriy Artyukh and published on Codrops.

How To Pass Data Between Components In Vue.js

How To Pass Data Between Components In Vue.js

How To Pass Data Between Components In Vue.js

Matt Maribojoc

Sharing data across components is one of the core functionalities of VueJS. It allows you to design a more modular project, control data scopes, and create a natural flow of data across your app.

Unless you’re creating your entire Vue app in one component (which wouldn’t make any sense), you’re going to encounter situations where you need to share data between components.

By the end of this tutorial, you will know three ways to get this done.

Okay — let’s get right into it!

Building An App With Nuxt

With Spotify, your friends can check out what you’re jamming to. What if the rest of the Internet could experience your algo-rhythm, too? Learn how to compose your own app to share what you’re listening to on Spotify using Vue.js and Nuxt. Read more →

1. Using Props To Share Data From Parent To Child

VueJS props are the simplest way to share data between components. Props are custom attributes that we can give to a component. Then, in our template, we can give those attributes values and — BAM — we’re passing data from a parent to a child component!

For example, let’s say we’re working on a user profile page and want to have a child component accept a username prop. We’ll need two components.

  1. The child component accepting the prop, let’s call this AccountInfo.vue.
  2. The parent component passing the prop, let’s call this ProfilePage.vue.

Inside AccountInfo.vue, we can declare the props it accepts using the props option. So, inside the component options, let’s make it look like the following.

// AccountInfo.vue

<template>
 <div id='account-info'>
   {{username}}
 </div>
</template>
 
<script>
export default {
 props: ['username']
}
</script>

Then, to actually pass the data from the parent (ProfilePage.vue), we pass it like a custom attribute.

// ProfilePage.vue
 
<account-info username='matt' />

Now if we load our page, we can see that our AccountInfo component properly renders the value passed in by its parent.

As when working with other VueJS directives, we can use v-bind to dynamically pass props. For example, let’s say we want to set the username prop to be equal to a variable. We can accomplish this by using shorthand for the v-bind directive (or just : for short). The code would look a little like this:

<template>
 <div>
   <account-info :username="user.username" />
 </div>
</template>
 
<script>
import AccountInfo from "@/components/AccountInfo.vue";
 
export default {
 components: {
   AccountInfo
 },
 data() {
   return {
     user: {
       username: 'matt'
     }
   }
 }
}
</script>

This means that we can change our data and have any child props using that value will also update.

Tip: Always Verify Your Props

If you’re looking to write clearer Vue code, an important technique is to verify your props. In short, this means that you need to specify the requirements for your prop (i.e. type, format, and so on). If one of these requirements is not met (e.g. if the prop is passed an incorrect type), Vue will print out a warning.

Let’s say we want our username prop to only accept Strings. We would have to modify our props object to look like this:

export default {
 props: {
   username: String
 }
}

Verifying props is essential when working in large-scale Vue apps or when designing plugins. It helps ensure that everyone is on the same page and use props the way that they were intended.

For a full list of the verifications we can include on props, I’d definitely recommend checking out the official documentation for an in-depth review.

Tip: Follow Prop Naming Conventions

According to the VueJS style guide, the best way to name your props is by using camelCase when declaring them in your script and kebab-case when referencing them in template code.

The reasoning behind this is actually quite simple. In Javascript, camelCase is the standard naming convention and in HTML, it’s kebab-case.

So, Vue recommends that we stick to the norms of each language. Thankfully, Vue is able to automatically convert between the two styles so there’s no additional setup for developers.

// GOOD
<account-info :my-username="user.username" />
props: {
   myUsername: String
}
 
// BAD
<account-info :myUsername="user.username" />
props: {
   "my-username": String
}

2. Emitting Events To Share Data From Child To Parent

Now that we have data passing down the hierarchy, let’s pass it the other way: from a child component to a parent. We can’t use props, but we can use custom events and listeners.

Every Vue instance can call a .$emit(eventName) method that triggers an event. Then, we can listen for this event in the same way as any other, using the v-on directive.

Creating a Custom Event

Let’s build on our user profile example by adding a button that changes the username. Inside our child component (AccountInfo.vue), let’s create the button.

Then, when this button is clicked, we’ll emit an event called changeUsername.

<template>
 <div id='account-info'>
   <button @click='changeUsername()'>Change Username</button>
   {{username}}
 </div>
</template>
 
<script>
export default {
 props: {
   username: String
 },
 methods: {
   changeUsername() {
     this.$emit('changeUsername')
   }
 }
}
</script>

Inside the parent, we handle this event and change the user.username variable. Like we were discussing earlier, we can listen to events using the v-on directive or "@" for short.

<template>
 <div>
   <account-info :username="user.username" @changeUsername="user.username = 'new name'"/>
 </div>
</template>

Let’s try it out. You should see that when you click the button, the username changes to "new name".

Tip: Custom Events Can Accept Arguments

The most common use case for passing arguments to your events is when you want a child component to be able to set a specific value for its prop. You never want to directly edit the value of a prop from the component itself.

However, luckily we can use pass arguments with our custom events to make the parent component change values.

Let’s say we want to modify the changeUsername event so that we can pass it a value.

The $emit method takes an optional second parameter for arguments. So all we do is add our new username value after the name of our event.

this.$emit('changeUsername', 'mattmaribojoc')

Then, in our parent component, we can either access these values inline by using a special $event variable, or we can write a handler method that takes a parameter.

<account-info :username="user.username" @changeUsername="user.username = $event"/>
 
OR 
 
<account-info :username="user.username" @changeUsername="changeUsername($event)"/>
 
export default {
...
methods: {
   changeUsername (username) {
     this.user.username = username;
   }
}
}

3. Using Vuex To Create An Application-Level Shared State

Okay — we know how to share data between parents/children, but what about other components? Do we have to create an extremely complex hierarchy system if we want to pass data?

Thankfully not. The wonderful Vuex state management library has been simplifying developers' lives for years. In short, it creates a centralized data store that is accessible by all components.

In the methods we used previously (props / emitting events), each component has its own data state that we then share between components. However, Vuex lets us extract all the shared data into a single state that each component can access easily. This shared state is called a store.

Let’s try it out.

Because Vuex is separate from the core code of Vue, we’ll first have to install and import it into our project. First, we’ll have to run npm install vuex --save inside our project CLI.

Then, create a src/store folder with an index.js file that contains the following code.

// store/index.js
 
import Vue from "vue";
import Vuex from "vuex";
 
Vue.use(Vuex);
 
export default new Vuex.Store({
 state: {},
 getters: {},
 mutations: {},
 actions: {}
});

To include this in our root Vue instance, we have to import our store/index.js file and pass it in our Vue constructor.

// main.js
 
import store from "./store";
 
new Vue({
  store,
  ...

Accessing Vue Store Inside Components

Since we added our Vuex store onto our root Vue instance, it gets injected into all of the root’s children. If we want to access the store from a component, we can via this.$store.

Now, let’s dive into the specifics of each of the four parts of a Vuec store.

1. State

The Vuex state is an object that contains application-level data. All Vue instances will be able to access this data.

For our store, let’s create a user object that stores some more user profile data.

export default new Vuex.Store({
 state: {
   user: {
     username: 'matt',
     fullName: 'Matt Maribojoc'
   }
 },
 getters: {},
 mutations: {},
 actions: {}
});

We can access this data inside any instance component like this.

mounted () {
   console.log(this.$store.state.user.username);
},

2. Getters

We use Vuex getters to return a modified value of state data. A good way to think of getters is to treat them like computed properties. For example, getters, like computed properties, cache their results and only re-evaluate when a dependency is modified.

Building onto our earlier store, let’s say we want to make a method that returns a user’s first name based off the full name attribute.

getters: {
   firstName: state => {
     return state.user.fullName.split(' ')[0]
   }
 }

Vuex getter properties are available to components on the store.getters object.

mounted () {
   console.log(this.$store.getters.firstName);
}

Tip: Know the Default Getter Arguments

By default, Vuex getters accept two arguments.

  1. state — the state object for our application;
  2. getters — the store.getters object, meaning that we can call other getters in our store.

Every getter you declare will require the first state argument. And depending on how you design your code, your getters can reference each other using the second 'getters' argument.

Let’s make a last name getter that simply removes our first name value from our full name state property. This example would require both the state and getters objects.

lastName (state, getters) {
     return state.user.fullName.replace(getters.firstName, '');
}
Tip: Pass Custom Arguments to Vuex Getters

Another cool feature of getters is that we can pass them custom arguments by making our getter return a method.

prefixedName: (state, getters) => (prefix) => {
     return prefix + getters.lastName;
}
 
// in our component
console.log(this.$store.getters.prefixedName("Mr."));

3. Mutations

Mutations are the only way to properly change the value of the state object. An important detail to note is that mutations must be synchronous.

Like getters, mutations always accept the Vuex state property as their first argument. They also accept a custom argument — called a payload — as the second argument.

For example, let’s make a mutation to change a user’s name to a specific value.

mutations: {
   changeName (state, payload) {
     state.user.fullName = payload
   }
},

Then, we can call this method from our component using the store.commit method, with our payload as the second argument.

this.$store.commit("changeName", "New Name");

More often than not, you are going to want your payload to be an object. Not only does this mean that you can pass several arguments to a mutation, but also, it makes your code more readable because of the property names in your object.

changeName (state, payload) {
     state.user.fullName = payload.newName
}

There are two different ways to call mutations with a payload.

  1. You can have the mutation type as the first argument and the payload as the second.
  2. You can declare pass a single object, with one property for the type and another for the payload.
this.$store.commit("changeName", {
       newName: "New Name 1",
});
 
     // or
 
 this.$store.commit({
       type: "changeName",
       newName: "New Name 2"
});

There isn’t a real difference between how the two work so it’s totally up to personal preference. Remember that it’s always best to be consistent throughout your entire project, so whichever one you choose, stick with it!

4. Actions

In Vuex, actions are fairly similar to mutations because we use them to change the state. However, actions don’t change the values themselves. Instead, actions commit mutations.

Also, while Vuex mutations have to be synchronous, actions do not. Using actions, we can call a mutation after an API call, for example.

Whereas most of the Vuex handlers we’ve seen accept state as their main parameter, actions accept a context object. This context object allows us to access the properties in our Vuex store (e.g. state, commit, getters).

Here’s an example of a Vuex action that waits two seconds and then commits the changeName mutation.

actions: {
   changeName (context, payload) {
     setTimeout(() => {
       context.commit("changeName", payload);
     }, 2000);
   }
}

Inside our components, we use the store.dispatch method in order to run our function. We pass arguments just like we did with mutations. We declare the type and we pass any custom arguments in the second argument.

this.$store.dispatch("changeName", {
      newName: "New Name from Action"
});

Wrapping Up

Now, you should know three different ways to share data across components in VueJS: props, custom events, and a Vuex store.

I hope this tutorial helped give you some more insight into some different Vue methods and best practices. Let me know how you’ve implemented them into your projects!

Further Reading

If you’re interested in going even deeper into the technical side/capabilities of each technique, here are some great places to start.

Smashing Editorial (dm, yk, il)

4 Tips on How to Simplify Your Website Design And Win Over New Customers

We’ve all seen a website so busy and unorganized that it literally makes every fiber in your being cringe.

I’m talking 0 effort in maintaining a color scheme, fonts galore, tons of pictures everywhere, no organization, and just terrible design overall.

That’s why today we’re going to go over 4 tips that explain how you can simplify your website and win over new customers!

4 Changes You Can Implement Today to Simplify Your Website Design and Make It Better 

You will lose clients faster than the speed of light with a terribly cluttered website design.

I mean, just take a look at the next two examples I’m gonna show you.

So here we have a busy website, with no specific focal point, and you don’t really know where to look, and it immediately stresses you out. You lose the client because he clicks off your site.

But then, we compare it to this…

[source]

When I look at this minimalist website design, especially compared to the other, my eyes are immediately set to ease. It’s literally like the inner designer in me just had the most amazing glass of wine and I’m just enjoying myself, admiring the design.

Alright, enough comparisons. Let’s just get things rolling over here.

Into the 4 tips we dive!

1. Simplify the Text

[source]

The most important page of all your website will be your homepage.

It’s the page that will set the tone for the rest of your site.

So it’s important that you get across what you’re trying to say quickly, efficiently, and simply.

There’s no need to clutter your website by writing so much text.

Most people just skim your website anyway! So, write your main text in bold headlines, add some details below, but not too much.

Only a small percentage of people will read the entire thing, so use your headlines to your advantage wisely!

2. Stick To A Color Scheme

[source]

A good color scheme always warms my heart, like grandma’s homemade apple pie on a summer’s day.

Maintaining a color scheme amongst your text, background elements, and images will automatically make you look more organized.

By using a color scheme, you can also bring focus to certain elements and manipulate the eye to go where you want it to.

By no means do you ever want a green font on a bright red background with orange and silver elements floating around the background. Unless you want you website to look like Christmas got a little wild at the Christmas staff party and vomited all over your website.

Go online or on any design inspiration website and type in popular color schemes on 2020, or color palettes, and save time and effort by finding beautiful palettes!

3. Limit Your Homepage To The Essentials

[source]

This kinda goes hand in hand with our first tip about limiting text.

Limit everything on the homepage and only keep what is essential.

Ask yourself, “What am I trying to achieve with this website and the homepage? What am I trying to show the customer?”

When you find the answer to that question, design your homepage accordingly.

Don’t add secondary/tertiary elements to the first bit of the homepage.

That’s what your menu tab and other secondary pages are for!

And speaking of menu tabs…

4. Scale Down Your Menu Tabs

[source]

For the love of simple design, keep your menu bar clean.

You don’t need a menu tab for 👏every 👏single 👏 element 👏of your website.

We’ve seen this way too many times than we’d personally like to admit, but some people give you the option of clicking on 20 different tabs.

As an alternative, create drop-down menu tabs where you have subcategories.

This will keep things squeaky-clean and peaceful for the eyes to look at.

No one will be frantically looking around for what they’re trying to find.

When things on your site and aesthetically pleasing and well-organized, your sales will go up.

And That’s It! 

I hope you found these 4 simple tips helpful and inspiring for your next minimalist website design.

Until next time,

Keep it simple and stay creative, folks!

 

Read More at 4 Tips on How to Simplify Your Website Design And Win Over New Customers