8 Rules To Writing Blog Titles Your Readers Can’t Resist

Original Source: http://feedproxy.google.com/~r/Designrfix/~3/Ortmv0DPJJE/8-rules-to-writing-blog-titles-your-readers-cant-resist

Do you want to entice more prospects and boost your website traffic drastically? Well, there’s something that can help. Catchy blog titles to a well-written blog can make all the difference. It’s one thing to write high-quality, well-researched content, but it’s a completely different thing to earn clicks and views — which is where the […]

The post 8 Rules To Writing Blog Titles Your Readers Can’t Resist appeared first on designrfix.com.

The Amazing Polestar Precept Concept Car

Original Source: http://feedproxy.google.com/~r/abduzeedo/~3/o2ib596A4bg/amazing-polestar-precept-concept-car

The Amazing Polestar Precept Concept Car
The Amazing Polestar Precept Concept Car

abduzeedoFeb 27, 2020

Electric cars are the future, at least that’s what it looks like from all the amazing electric car companies and models being announced. I am a fan and the desire of having a Tesla keeps coming and going. Now Polestar announces this amazing concept car, the Polestar Precept and boy it’s a thing of beauty. Tiago Aiello shared some images on his Behance profile and I was blown away. Maybe I will hold on a bit longer to see how many more car makers announce, there’s the new Hummer coming as well. As I said, it looks like the future is going to be electric.

Precet: a rule intended to inform behaviour or thought. In other words, a way of declaring how you mean to proceed. Starting as you mean to go on. Stating your intentions up top. A manifesto. It’s also the name for something that takes all of our ambitions and combines them.

Concept Car


10+ Examples of Responsive Websites That Got It Right

Original Source: http://feedproxy.google.com/~r/tympanus/~3/P-nysxxXwVI/

When designing a new website, there’s a long list of specifications and requirements you have to fulfill. It’s just the nature of web design these days. And at the top of that list sits responsive web design.

Thankfully, high-quality WordPress themes like BeTheme make it insanely easy to check off all the technical requirements you’re expected to meet — including responsive design. But why does it matter so much?

Well, for starters, more than half of all website traffic takes place on mobile according to data from StatCounter.

While desktop has put up a good fight for a couple years, mobile has prevailed as the winner. It will continue to do so, too, considering how much more convenient it is to access the web from the palm of one’s hand.

Plus, Google has made it clear that it rewards responsive web designs and mobile-friendly websites with better search rankings, so there’s no hiding from it now.

Responsive web design is a must.

Just keep in mind that following the rules for good mobile design doesn’t mean you ignore desktop users. By prioritizing the mobile experience, you can design more beautiful and efficient websites for all users.

Let’s look at some examples that demonstrate how to do this well.

Responsive web designs that encourage leaner desktop experiences

Just because you have more space to work with when designing for desktop users doesn’t mean you need to make the most of every pixel.

In fact, as Internet-enabled devices have grown smaller in size, it’s encouraged many designers to create leaner and more efficient experiences on desktop.

Take the website for designer/developer Rob Grabowski, for example.

This is how his website appears on a mobile screen:

With minimized logo and navigation out of the way, this allows the focus to remain on his photo and welcome message. Desktop visitors encounter the same thing:

This consistency in design is great because it enables visitors to seamlessly transition from viewing a website on one device to another (which happens often).

Mobile web designs that improve the decision-making process

Consumers today struggle with an overabundance of choice. It might be easier to find that thing or service they’re looking for, but that doesn’t make choosing between similar options any easier.

One of the benefits of responsive design is that it forces web designers to create websites in a modular fashion so that, as the screen size shrinks, each section falls in line beneath the others.

In turn, this makes it easier for customers to review options one-by-one. BeRepair, one of the 500+ pre-built sites from BeTheme, demonstrates this point really well:

This is one of the services offered. Notice how the responsive layout allows the visitor to really focus on the details before them and not get distracted by too much information.

This works well for other types of websites. Take, for instance, the BeRestaurant pre-built desktop site:

It’s a great-looking restaurant website. The mobile counterpart looks just as great, but minimizes the distractions so the core elements can really shine:

Rather than try to fit the menu to the right of the food images, the responsive website maintains the integrity of the original design by tucking it into the hamburger menu icon in the top-right.

Again, this is all about giving your visitors the ability to pause and really focus on the key actions you’re asking them to take. A navigation bar in full view would only distract from that.

Responsive designs that cut out the excess

Think about the last time you went to an art gallery or museum and the kinds of paintings you encountered:

The landscape murals that have a central focus but beautiful details surrounding it.The portraits with a singular focus that’s chock-full of intimate details.

What’s cool about responsive websites is that they allow us to display the same web page in both formats.

Desktop screens thereby display landscape murals and mobile screens display portraits. But it’s important to know where the excess is in the desktop view so you can trim it back enough to make the mobile experience worthwhile.

For instance, this is the desktop site for BeITService:

This is a great looking hero banner on the home page. It’s well-balanced, the colors are carefully chosen, and the message is crystal-clear.

This is a good example of how smart designers have become when it comes to choosing responsive images for websites.

Here’s that same image and banner from above, but now displayed on mobile:

The image may not appear in full, but there’s nothing lost in this translation from desktop to mobile. What’s more, the message remains front and center.

Culturally Connected does something similar:

On desktop, it shows an elaborate background graphic that enhances the overall design. On mobile, however, it turns into this:

Even with the image now reduced and placed at the bottom, it’s still a striking design that allows the message to really shine through.

Another great example is BeTutor. This is how the desktop version looks like:

Here we have the main title and some more info using smaller text. In order not to cramp the mobile view, the design omits the extra content and focuses on the primary message:

The mobile view stays uncluttered without loosing any of the important subject matter that reveals the type of service offered.

Responsive websites that leverage their space

While a small screen requires reducing content in most of the cases, some responsive web designs leverage the space and use the different ratio to their advantage.

Take 1987 Masters for example:

While the desktop version focuses on their main tagline, the mobile version makes use of the vertical space and shows more content, giving the mobile visitor an option to learn more about the company right away:

So a mobile design don’t necessarily have to show less content in order to work well.

The mobile screen ratio allows for making use of the vertical space, like it’s shown in this example of BeCosmetics. Check out the desktop view:

The mobile view has more vertical space so the introductory content can be shown along with the button that invites the user to explore all products:

Once again, these examples demonstrate that less space doesn’t need to mean less useful content for the mobile website user.

Responsive websites that enhance readability

When laying out text on a desktop website, you have to be careful about how much you show to a reader at once. Put too many words on a line or not include enough spacing between letters, and your visitors might skip reading it altogether.

It’s a tricky balance to maintain and usually requires visual elements to balance out the text. Take, for example, the BeDanceSchool site:

Thanks to the funky designs and eye-catching graphics around the text, it’s easy for visitors to focus on the content and read it all the way through.

This won’t work on mobile though, which is why it’s important to understand the strengths of each screen size. Here you can see how that same text from above should be handled on mobile:

The design is paired back immensely so that all the visitor can see is the content. But that’s okay because the text is still beautifully styled which helps keep attention.

That said, text presented to mobile visitors doesn’t always have to be so heavily styled. If you select the right font size and type, you can create something that’s readable and engaging just as Base Coat does:

Just be mindful of the vertical length of text on mobile. While it might be easy to see where it ends on desktop, it can seem daunting on mobile if it appears to go on and on.

Mobile sites that put a spotlight on visual content

Responsive web designs aren’t just useful for websites with lots of text. Because of the way content responds to smaller screen sizes, visual storytelling elements look great on mobile, too.

Here’s what visitors see on the BeBand website on desktop:

Mobile screens don’t have the ability to play with balance as in the example above, but they do have the ability to shine a spotlight on the images you’ve chosen:

Websites that contain eye-catching images like this one would certainly benefit from responsive web design.

It’s not just static images that this works with either. The Scott Resort, for example, invites first-time visitors to watch a video:

Regardless of what kind of device the visitor is on, the video automatically conforms to the width of the screen.

This is the video on desktop:

And this is the video on mobile:

With a mobile responsive design, you really allow your content to adapt to the device and experience your users want.

Mobile responsive sites that collect more leads

Although more website traffic comes from mobile devices, it’s still quite difficult to get mobile users to convert as much as they do on desktop. That’ll come with time, but we’re not there just yet.

In the meantime, your responsive site needs to be prepared to capture leads whenever it can to improve those conversion rates.

Let’s take a look at how this works.

This is the pre-built site for BeClub:

This “Newsletter” section stands out beautifully on the homepage. And because it’s so convenient (e.g. it’s light on text and requires only one field be filled out), it’s likely to get a ton of subscribers.

This is how that same subscriber form appears on mobile:

Again, it’s really well done — and the smaller, dedicated space on mobile might be an even more effective way to catch the attention of potential subscribers.

So, if you can design your responsive site to collect visitors’ email addresses, you’ll empower them to reconnect with your website from their preferred device. As a result, you can increase the number of conversions it gets.

Responsive web designs for the win

When WordPress users go looking for a theme to design their website with, they look for qualities like:

Ease of useCost efficiencyFeaturesCustomizabilityOverall design quality

It’s easy to take responsive web designs for granted because we see them everywhere, but, the truth is, not every WordPress theme is built with the mobile user in mind.

BeTheme is different. Each of its 500+ pre-built sites comes with mobile responsiveness baked in.

So, when you use BeTheme, you can spend less time stressing over how to make your website look like the responsive designs above and more time getting your new website online and in front of consumers.

10+ Examples of Responsive Websites That Got It Right was written by Bogdan Sandu and published on Codrops.

How To Build A Music Manager With Nuxt.js And Express.js

Original Source: https://www.smashingmagazine.com/2020/02/music-manager-nuxtjs-expressjs/

How To Build A Music Manager With Nuxt.js And Express.js

How To Build A Music Manager With Nuxt.js And Express.js

Deven Rathore

2020-02-27T13:00:00+00:00
2020-02-27T18:37:26+00:00

Handling digital media assets such as audio and video in your application can be tricky because of the considerations that have to be made server-side (e.g. networking, storage and the asynchronous nature of handling file uploads). However, we can use libraries like Multer and Express.js to simplify our workflow on the backend while using Nuxt.js (Vue framework) to build out the front-end interactions.

Whenever a web client uploads a file to a server, it is generally submitted through a form and encoded as multipart/form-data. Multer is a middleware for Express.js and Node.js that makes it easy to handle this so-called multipart/form-data whenever your users upload files. In this tutorial, I will explain how you can build a music manager app by using Express.js with Multer to upload music and Nuxt.js (Vue framework) for our frontend.

Prerequisites

Familiarity with HTML, CSS, and JavaScript (ES6+);
Node.js, npm and MongoDB installed on your development machine;
VS code or any code editor of your choice;
Basic Knowledge of Express.js.

Building The Back-End Service

Let’s start by creating a directory for our project by navigating into the directory, and issuing npm init -y on your terminal to create a package.json file that manages all the dependencies for our application.

mkdir serverside && cd serverside
npm init -y

Next, install multer, express, and the other dependencies necessary to Bootstrap an Express.js app.

npm install express multer nodemon mongoose cors morgan body-parser –save

Next, create an index.js file:

touch index.js

Then, in the index.js file, we will initialize all the modules, create an Express.js app, and create a server for connecting to browsers:

const express = require(“express”);
const PORT = process.env.PORT || 4000;
const morgan = require(“morgan”);
const cors = require(“cors”);
const bodyParser = require(“body-parser”);
const mongoose = require(“mongoose”);
const config = require(“./config/db”);
const app = express();
//configure database and mongoose
mongoose.set(“useCreateIndex”, true);
mongoose
.connect(config.database, { useNewUrlParser: true })
.then(() => {
console.log(“Database is connected”);
})
.catch(err => {
console.log({ database_error: err });
});
// db configuaration ends here
//registering cors
app.use(cors());
//configure body parser
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//configure body-parser ends here
app.use(morgan(“dev”)); // configire morgan
// define first route
app.get(“/”, (req, res) => {
res.json(“Hola MEVN devs…Assemble”);
});
app.listen(PORT, () => {
console.log(`App is running on ${PORT}`);
});

We, first of all, bring in Express.js into the project and then define a port that our application will be running on. Next, we bring in the body-parser, morgan ,mongoose and the cors dependencies.

We then save the express instance in a variable called app. We can use the app instance to configure middleware in our application just as we configured the cors middleware. We also use the app instance to set up the root route that will run in the port we defined.

Let’s now create a /config folder for our database config and multer config:

mkdir config and cd config
touch multer.js && touch db.js

Then open config/db.js and add the following code to configure our database:

module.exports = {
database: “mongodb://localhost:27017/”,
secret: “password”
};

(This is actually an object that holds the database URL and the database secret.)

Running nodemon and navigating to localhost:4000 on your browser should give you this message:

“Hola MEVN devs…Assemble”

Also, this is what your terminal should now look like:

Running Nodemon using Terminal

Terminal preview (Large preview)

Setting Up Model, Routes, And Controllers

Let’s set up a file structure by typing in the following:

mkdir api && cd api
mkdir model && cd model && touch Music.js
cd ..
mkdir controller && cd controller && touch musicController.js
cd ..
mkdir routes && cd routes && touch music.js

In our terminal, we use mkdir to create a new directory, and then cd to move into a directory. So we start by creating a directory called api and then move into the api directory.

The touch command is used to create a new file inside a directory using the terminal, while the cd command is used to move out of a directory.

Now let’s head on over to our api/model/Music.js file to create a music schema. A model is a class with which we construct documents. In this case, each document will be a piece of music with properties and behaviors as declared in our schema:

let mongoose = require(“mongoose”);
let musicSchema = mongoose.Schema({
title: {
type: String,
required: true
},
music: {
type: Object,
required: true
},
artist: {
type: String,
required: true
},
created: {
type: Date,
default: Date.now()
}
});
let Music = mongoose.model(“Music”, musicSchema);
module.exports = Music;

Let’s head over to config/multer to configure Multer:

let multer = require(“multer”);
const path = require(“path”);
const storage = multer.diskStorage({
destination: (req, res, cb) => {
cb(null, “./uploads”);
},
filename: (req, file, cb) => {
cb(null, new Date().toISOString() + file.originalname);
}
});
const fileFilter = (req, file, cb) => {
if (
file.mimetype === “audio/mpeg” ||
file.mimetype === “audio/wave” ||
file.mimetype === “audio/wav” ||
file.mimetype === “audio/mp3”
) {
cb(null, true);
} else {
cb(null, false);
}
};
exports.upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: fileFilter
});

In the multer.js file, we start by setting up a folder where all the uploaded music files will be uploaded. We need to make this file static by defining that in the index.js file:

app.use(‘/uploads’, express.static(‘uploads’));

After that, we write a simple validator that will check the file mimetype before uploading. We then define the multer instance by adding the storage location, the limits of each file, and the validator that we created.

Create The Necessary Routes

Now let’s create our routes. Below is the list of endpoints we will be creating.

HTTP POST /music
Add new music

HTTP GET /music
Get all music

HTTP DELETE /music/:blogId
Delete a music

Let’s start by creating the blog route. Head over to api/routes/music.js and write the following code:

const express = require(“express”);
const router = express.Router();
const musicController = require(“../controller/musicController”);
const upload = require(“../../config/multer”);
router.get(“/”, musicController.getAllMusics);
router.post(“/”, upload.upload.single(“music”), musicController.addNewMusic);
router.delete(“/:musicId”, musicController.deleteMusic);
module.exports = router;

Note: Now whenever we make a get request to /music. the route calls the getAllMusic function that is located in the ‘controllers’ file.

Let’s move on over to api/controllers/musicController to define the controllers. We start by writing a function to get all the music in our database using the mongoose db.collection.find method which will return all the items in that collection.

After doing that, we write another function that will create a piece of new music in the database. We need to create a new music instance using the new keyword and then define the music object. After doing this, we will use the mongoose save method to add new music to the database.

In order to delete a piece of music, we need to use the mongoose remove method by simply passing the music ID as a parameter in the remove instance. This results to mongoose looking into the music collection that has that particular ID and then removing it from that collection.

let mongoose = require(“mongoose”);
const Music = require(“../model/Music”);
exports.getAllMusics = async (req, res) => {
try {
let music = await Music.find();
res.status(200).json(music);
} catch (err) {
res.status(500).json(err);
}
};
exports.addNewMusic = async (req, res) => {
try {
const music = new Music({
title:req.body.title,
artist:req.body.artist,
music:req.file
});

let newMusic = await music.save();
res.status(200).json({ data: newMusic });
} catch (err) {
res.status(500).json({ error: err });
}
};
exports.deleteMusic = async (req, res) => {
try {
const id = req.params.musicId;
let result = await Music.remove({ _id: id });
res.status(200).json(result);
} catch (err) {
res.status(500).json(err);
}
};

Last but not least, in order to test the routes, we need to register the music routes in our index.js file:

const userRoutes = require(“./api/user/route/user”); //bring in our user routes
app.use(“/user”, userRoutes);

Testing The End Points

To test our endpoints, we will be using POSTMAN.

Adding New Music

To test the Add Music functionality, set the method of the request by clicking on the methods drop-down. After doing this, type the URL of the endpoint and then click on the body tab to select how you want to send your data. (In our case, we will be using the form-data method.)

So click on the form-data and set up your model key. As you set it up, give the keys some value as shown in the image below:

Testing Adding new music API using Postman

Testing Adding new music API in Postman dashboard (Large preview)

After doing this, click on ‘Send’ to make the request.

Listing All Music

To list all of the music in our database, we have to type the endpoint URL in the URL section provided. After doing this, click on the ‘Send’ button to make the request.

Testing Listing API using Postman

Testing Listing API in Postman dashboard (Large preview)

Deleting Music

To delete a piece of music, we need to pass the music id as a parameter.

Testing Delete API using Postman

Testing Delete API Postman dashboard (Large preview)

That’s it!

Building The Frontend

For our frontend, we will be using a Vue framework: Nuxt.js.

“Nuxt is a progressive framework based on Vue.js to create modern web applications. It is based on Vue.js official libraries (vue, vue-router and vuex) and powerful development tools (webpack, Babel and PostCSS).”

— NuxtJS Guide

To create a new Nuxt.js application, open up your terminal and type in the following (with musicapp as the name of the app we will be building):

$ npx create-nuxt-app musicapp

During the installation process, we will be asked some questions regarding the project setup:

Project name
musicapp

project description
A Simple music manager app

Author name
<your name>

Package manager
npm

UI framework
Bootstrap vue

custom ui framework
none

Nuxt modules
Axios,pwa (use the spacebar on your keyboard to select items)

Linting tool
Prettier

test framework
None

Rendering Mode
Universal (SSR)

development tool
Jsonconfig.json

After selecting all of this, we have to wait a little while for the project to be set up. Once it’s ready, move into the /project folder and serve the project as follows:

cd musicapp && npm run dev

Open up the project in any code editor of your choice and then open the project in the browser by accessing localhost:3000.

Preview Of Nuxt.js project

Nuxt.js Project Preview (Large preview)

Configuring Axios

We will be using axios to make an HTTP request to our back-end server. Axios is already installed in our project, so we just have to configure the baseURL- to our backend server.

To do this, open the nuxt.config.js file in the root directory and add the baseURL in the axios object.

axios: {
baseURL:’http://localhost:4000′
},

Building The Music Manager

Setting Up The UI

Let’s start by cleaning up the UI. Open up the pages/index.vue file and remove all of the code in there with the following:

<template>
<div>Hello</div>
</template>

After doing this, you should only be able to see a “Hello” in the browser.

In the root directory, create a /partials folder. Inside the /partials folder, create a navbar.vue file and add the following code:

<template>
<header>
<nav class=”navbar navbar-expand-lg navbar-light bg-info”>
<div class=”container”>
<a class=”navbar-brand” href=”#”>Music App</a>
<button
class=”navbar-toggler”
type=”button”
data-toggle=”collapse”
data-target=”#navbarNav”
aria-controls=”navbarNav”
aria-expanded=”false”
aria-label=”Toggle navigation”
>
<span class=”navbar-toggler-icon”></span>
</button>
<div class=”collapse navbar-collapse justify-content-end” id=”navbarNav”>
<ul class=”navbar-nav”>
<li class=”nav-item active”>
<a class=”nav-link” href=”#”>Player</a>
</li>
<li class=”nav-item”>
<a class=”nav-link” href=”#”>Manager</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
</template>
<style scoped>
.nav-link,
.navbar-brand {
color: #ffff !important;
}
</style>

Note: We will be using the component to navigate through pages in our application. This is just going to be a simple component made up of Bootstrap navbar. Check out the official Bootstrap documentation for more reference.

Next, let’s define a custom layout for the application. Open the /layouts folder, replace the code in the default.vue file with the code below.

<template>
<div>
<navbar />
<nuxt />
</div>
</template>
<script>
import navbar from ‘@/partial/navbar’
export default {
components: {
navbar
}
}
</script>

We import the navbar into this layout, meaning that all the pages in our application will have that navbar component in it. (This is going to be the component that all other component in our application will be mounted.)

After this, you should be able to see this in your browser:

Nuxt.js Navbar component after modification

Nuxt.js Navbar component (Large preview)

Now let’s setup the UI for our manager. To do this, we need to create a /manager folder within the components folder and then add a file into the folder named manager.vue.

In this file, add the following code:

<template>
<section class=”mt-5″>
<div class=”container mb-4″>
<div class=”row”>
<div class=”col-md-12″>
<div class=”card”>
<div class=”card-body”>
<div class=”card-title mb-4″>
<h4>Add Music</h4>
</div>
<form>
<div class=”form-group”>
<label for=”title”>Title</label>
<input type=”text” class=”form-control” />
</div>
<div class=”form-group”>
<label for=”artist”>Artist</label>
<input type=”text” class=”form-control” />
</div>
<div class=”form-group”>
<label for=”artist”>Music</label>
<div class=”custom-file”>
<input type=”file” class=”custom-file-input” id=”customFile” />
<label class=”custom-file-label” for=”customFile”>Choose file</label>
</div>
</div>
<div class=”form-group”>
<button class=”btn btn-primary”>Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div class=”container”>
<div class=”row”>
<div class=”col-md-12″>
<div class=”card bg-light p-1 showdow-sm”>
<div class=”card-title”>
<button class=”btn btn-info m-3″>Add Music</button>
</div>
<div class=”card-body”>
<table class=”table”>
<thead>
<tr>
<th scope=”col”>#</th>
<th scope=”col”>Title</th>
<th scope=”col”>Artist</th>
<th scope=”col”>Date created</th>
<th scope=”col”>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Demo Title</td>
<td>Wisdom.vue</td>
<td>12/23/13</td>
<td>
<button class=”btn btn-info”>Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</section>
</template>

Note: This is just a simple Bootstrap template for adding music into our application. The form will define a table template that will list all os the music that can be found in our database.

After defining this component, we need to register it in the /pages folder to initailize routing.

Nuxt.js doesn’t have a ‘router.js’ file like Vue.js. It uses the pages folder for routing. For more details, visit the Nuxt.js website.

To register the component, create a /manager folder within the /pages folder and create an index.vue file. Then, place the following code inside the file:

<template>
<div>
<manager />
</div>
</template>
<script>
import manager from ‘@/components/manager/manager’
export default {
components: {
manager
}
}
</script>

This is the component that will render in our pages route.

After doing this, head over to your browser and navigate to /manager — you should be seeing this:

UI of music Manager

Music manager UI (Large preview)

Listing All Music

Let’s continue by creating a function that will fetch all of the music. This function will be registered in the created life cycle hook, so that whenever the component is created, the function will be called.

Let’s start by creating a variable in the vue instance that will hold all of the music:

allmusic = [];
musicLoading: false,

Then, define a getAllMusics function and add the following code:

async getAllMusics() {
this.musicLoading = true
try {
let data = await this.$axios.$get(‘/music’)
this.allmusic = data
this.musicLoading = false
} catch (err) {
this.musicLoading = false
swal(‘Error’, ‘Error Fetting Musics’, ‘error’)
}
}

Next, register within the created life cycle hook:

created() {
this.getAllMusics()
}

Outputting The Data

Now it’s time to output all of the songs on the table which we’ve created earlier:

<table class=”table”>
<thead>
<tr>
<th scope=”col”>#</th>
<th scope=”col”>Title</th>
<th scope=”col”>Artist</th>
<th scope=”col”>Date created</th>
<th scope=”col”>Action</th>
</tr>
</thead>
<div
v-if=”musicLoading”
class=”spinner-border”
style=”width: 3rem; height: 3rem;”
role=”status”
>
<span class=”sr-only”>Loading…</span>
</div>
<tbody v-else>
<tr v-for=”(music, index) in allmusic” :key=”index”>
<td>{{ index + 1 }}</td>
<td>{{ music.title }}</td>
<td>{{ music.artist }}</td>
<td>{{ music.created }}</td>
<td>
<button class=”btn btn-info” @click=”deleteMusic(music._id)”>Delete</button>
</td>
</tr>
</tbody>
</table>

Remember that table we created earlier? Well, we will need to loop through the response we get back from our backend to list all of the music received back from the database.

Adding Music

To add a new piece of music we need to make an HTTP request to the back-end server with the music details. To do this, let’s start by modifying the form and handling of the file uploads.

On the form, we need to add an event listener that will listen to the form when it is submitted. On the input field, we add a v- model to bind the value to the input field.

<form @submit.prevent=”addNewMusic”>
<div class=”form-group”>
<label for=”title”>Title</label>
<input type=”text” v-model=”musicDetails.title” class=”form-control” />
</div>
<div class=”form-group”>
<label for=”artist”>Artist</label>
<input type=”text” v-model=”musicDetails.artist” class=”form-control” />
</div>
<div class=”form-group”>
<label for=”artist”>Music</label>
<div class=”custom-file”>
<input
type=”file”
id=”customFile”
ref=”file”
v-on:change=”handleFileUpload()”
class=”custom-file-input”
/>
<label class=”custom-file-label” for=”customFile”>Choose file</label>
</div>
</div>
<div class=”form-group”>
<button class=”btn btn-primary” :disabled=”isDisabled”>
<span
class=”spinner-border spinner-border-sm”
v-if=”addLoading”
role=”status”
aria-hidden=”true”
></span>Submit
</button>
</div>
</form>

And the script section should look like this:

<script>
export default {
data() {
return {
musicDetails: {
title: ”,
artist: ”,
music: ”
},
allmusic = [],
musicLoading: false,
isValid: false;
addLoading: false,
}
},
computed: {
isDisabled: function() {
if (
this.musicDetails.title === ” ||
this.musicDetails.artist === ” ||
this.musicDetails.music === ”
) {
return !this.isValid
}
}
},
methods: {
handleFileUpload() {
this.musicDetails.music = this.$refs.file.files[0]
console.log(this.musicDetails.music.type)
},
addNewMusic() {
let types = /(.|/)(mp3|mp4)$/i
if (
types.test(this.musicDetails.music.type) ||
types.test(this.musicDetails.music.name)
) {
console.log(‘erjkb’)
} else {
alert(‘Invalid file type’)
return !this.isValid
}
}
}
}
</script>

We will define a function that will send a request to our back-end service to create any new music that has been added to the list. Also. we need to write a simple validation function that will check for the file type so that the users can only upload files with an extention of .mp3 and .mp4.

It’s important to define a computed property to make sure that our input field isn’t empty. We also need to add a simple validator that will make sure the the file we are trying to upload is actually a music file.

Let’s continue by editing the addMusic function to make a request to our back-end service. But before we do this, let’s first install sweetalert which will provide us with a nice modal window. To do this this, open up your terminal and type in the following:

npm i sweetalert

After installing the package, create a sweetalert.js file in the /plugins folder and add this:

import Vue from ‘vue’;
import swal from ‘sweetalert’;

Vue.prototype.$swal = swal;

Then, register the plugin in the nuxt.config.js file inside the plugin instace like this:

plugins: [
{
src: ‘~/plugins/sweetalert’
}
],

We have now successfully configured sweetalert in our application, so we can move on and edit the addmusic function to this:

addNewMusic() {
let types = /(.|/)(mp3|mp4)$/i
if (
types.test(this.musicDetails.music.type) ||
types.test(this.musicDetails.music.name)
) {
let formData = new FormData()
formData.append(‘title’, this.musicDetails.title)
formData.append(‘artist’, this.musicDetails.artist)
formData.append(‘music’, this.musicDetails.music)
this.addLoading = true
this.$axios
.$post(‘/music’, formData)
.then(response => {
console.log(response)
this.addLoading = false
this.musicDetails = {}
this.getAllMusics() // we will create this function later
swal(‘Success’, ‘New Music Added’, ‘success’)
})
.catch(err => {
this.addLoading = false
swal(‘Error’, ‘Something Went wrong’, ‘error’)
console.log(err)
})
} else {
swal(‘Error’, ‘Invalid file type’, ‘error’)
return !this.isValid
}
},

Let’s write a simple script that will toggle the form, i.e it should only display when we want to add new music.

We can do this by editing the ‘Add Music’ button in the table that displays all of the music that can be found:

<button
class=”btn btn-info m-3″
@click=”initForm”>
{{addState?”Cancel”:”Add New Music”}}
</button>

Then, add a state that will hold the state of the form in the data property:

addState: false

After doing this, let’s define the initForm function:

initForm() {
this.addState = !this.addState
},

And then add v-if="addState" to the div that holds the form:

<div class=”card” v-if=”addState”>

Deleting Music

To delete music, we need to call the delete endpoint and pass the music id as a param. Let’s add a click event to the ‘Delete’ button that will trigger the function to delete a function:

<button class=”btn btn-info” @click=”deleteMusic(music._id)”>Delete</button>

The delete function will be making an HTTP request to our back-end service. After getting the music ID from the deleteMusic function parameter, we will add the ID in the URL that we are using to send the request. This specifies the exact piece of music that ought to be removed from the database.

deleteMusic(id) {
swal({
title: ‘Are you sure?’,
text: ‘Once deleted, you will not be able to recover this Music!’,
icon: ‘warning’,
buttons: true,
dangerMode: true
}).then(willDelete => {
if (willDelete) {
this.$axios
.$delete(‘/music/’ + id)
.then(response => {
this.getAllMusics()
swal(‘Poof! Your Music file has been deleted!’, {
icon: ‘success’
})
})
.catch(err => {
swal(‘Error’, ‘Somethimg went wrong’, ‘error’)
})
} else {
swal(‘Your Music file is safe!’)
}
})
}

With all of this, we have just built our music manager. Now it’s time to build the music player.

Let’s start by creating a new folder in the components folder named /player. Then, create a player.vue file within this folder and add this:

<template>
<section>
<div class=”container”>
<div class=”row”>
<div class=”col-md-12″>
<h3 class=”text-center”>Player</h3>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
<style scoped>
</style>

Next, let’s import this component into the index.vue file in the /pages folder. Replace the code in index.vue file to this:

<template>
<div>
<player />
</div>
</template>
<script>
import player from ‘@/components/player/player’
export default {
components: {
player
}
}
</script>

Let’s configure routing in our navbar component to enable routing between our pages.

To route in a Nuxt.js application, the nuxt-link is used after which you have specified the page for that route to a particular instance. So let’s edit the code in the partials/navbar component to this:

<template>
<header>
<nav class=”navbar navbar-expand-lg navbar-light bg-info”>
<div class=”container”>
<nuxt-link to=”/” class=”navbar-brand”>Music App</nuxt-link>
<button
class=”navbar-toggler”
type=”button”
data-toggle=”collapse”
data-target=”#navbarNav”
aria-controls=”navbarNav”
aria-expanded=”false”
aria-label=”Toggle navigation”
>
<span class=”navbar-toggler-icon”></span>
</button>
<div class=”collapse navbar-collapse justify-content-end” id=”navbarNav”>
<ul class=”navbar-nav”>
<li class=”nav-item active”>
<nuxt-link to=”/” class=”nav-link”>Player</nuxt-link>
</li>
<li class=”nav-item”>
<nuxt-link to=”/manager” class=”nav-link”>Manager</nuxt-link>
</li>
</ul>
</div>
</div>
</nav>
</header>
</template>
<style scoped>
.nav-link,
.navbar-brand {
color: #ffff !important;
}
</style>

With this, we can navigate through our pages by using the navbar.

Building The Player

Before we begin, we need to extend Webpack to load audio files. Audio files should be processed by file-loader. This loader is already included in the default Webpack configuration, but it is not set up to handle audio files.

To do this, go to the nuxt.config.js file and modify the build object to this:

build: {
extend(config, ctx) {
config.module.rules.push({
test: /.(ogg|mp3|mp4|wav|mpe?g)$/i,
loader: ‘file-loader’,
options: {
name: ‘[path][name].[ext]’
}
})
}
}

Next, let’s write a function that will get all songs and then use the Audio constructor to play the first song in the allMusic array.

For starters, let’s modify our player.vue file to this:

<template>
<section v-if=”allMusic”>
<div class=”container”>
<div class=”row”>
<div class=”col-md-12″>
<h3 class=”text-center”>Player</h3>
</div>
</div>
<div class=”row”>
<div class=”col-md-6″>
<span>{{this.current.title}} – {{this.current.artist}}</span>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
data() {
return {
current: {
title: ”,
artist: ”
},
song: true,
isplaying: false,
allMusic: null,
index: 0,
player: ”
}
},
methods: {
async initPlayer() {
if (this.allMusic !== []) {
this.current = await this.allMusic[this.index]
this.player.src = `http://localhost:4000/${this.current.music.path}`
} else {
this.song = true
}
},
async getAllSongs() {
try {
let response = await this.$axios.$get(‘/music’)
console.log(response)
if (response === []) {
this.song = true
this.current = null
} else {
this.song = false
this.allMusic = response
}
await this.initPlayer()
} catch (err) {
this.current = null
console.log(err)
}
}
},
created() {
if (process.client) {
this.player = new Audio()
}
this.getAllSongs()
}
}
</script>
<style scoped>
</style>

Once the file is served, the music will play in the background and then you should be able to see this in your browser:

UI of Music player

Music player UI (Large preview)

To stop the music, all you need to do is comment out the await player.play() in the initPlayer function.

Creating The Player UI

Let’s now define our music player UI by replacing the template in our player.vue file with the following:

<template>
<section v-if=”allMusic”>
<div class=”container”>
<div class=”row mb-5″>
<div class=”col-md-12″>
<h3 class=”text-center”>Player</h3>
</div>
</div>
<div class=”row mt-5″>
<div class=”col-md-6″>
<img
src=”https://images.pexels.com/photos/3624281/pexels-photo-3624281.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500″
class=”image”
/>
<div class=”card player_card”>
<div class=”card-body”>
<h6 class=”card-title”>
<b>{{this.current.title}} – {{this.current.artist}}</b>
</h6>
<div>
<i class=”fas fa-backward control mr-4″></i>
<i class=”fas fa-play play”></i>
<i class=”fas fa-pause play”></i>
<i class=”fas fa-forward control ml-4″></i>
</div>
</div>
</div>
</div>
<div class=”col-md-6″>
<div class=”card shadow”>
<table class=”table”>
<thead>
<tr>
<th scope=”col”>#</th>
<th scope=”col”>Title</th>
<th scope=”col”>Artist</th>
<th scope=”col”>Action</th>
</tr>
</thead>
<tbody>
<tr>
<th scope=”row”>1</th>
<td>Mark</td>
<td>Otto</td>
<td>
<button class=”btn btn-primary”>Play</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
</template>

Then, add the following style into the style section:

<style scoped>
.image {
border-radius: 5px !important;
position: relative;
height: 300px;
width: 100%;
}
.player_card {
text-align: center;
bottom: 20px;
margin: 0px 40px;
}
.text-muted {
font-size: 15px;
}
.play {
font-size: 40px;
}
.control {
font-size: 25px;
}
</style>

After modifying this, the player should look like this:

Music player final UI

Final UI of music player (Large preview)

Adding The Play Function

We’ll continue by displaying the music description on the table. In order to do this, replace the table with the code below:

<table class=”table”>
<thead>
<tr>
<th scope=”col”>#</th>
<th scope=”col”>Title</th>
<th scope=”col”>Artist</th>
<th scope=”col”>Action</th>
</tr>
</thead>
<tbody>
<tr v-for=”(music,index) in allMusic” :key=”index”>
<th scope=”row”>{{index+1}}</th>
<td>{{music.title}}</td>
<td>{{music.artist}}</td>
<td>
<button class=”btn btn-primary”>Play</button>
</td>
</tr>
</tbody>
</table>

We don’t want to display the ‘Play’ and ‘Pause’ icons at the same time. Instead, we want a situation that when the song is playing, the ‘Pause’ icon is displayed. Also, when the song is paused, the play icon should be displayed.

To achieve this, we need to set a isPlaying state to the false instance and then use this instance to toggle the icons. After that, we will add a function to our ‘Play’ icon.

isplaying:false

After doing this, modify your ‘Play’ and ‘Pause’ icon to this:

<i class=”fas fa-play play” v-if=”!isplaying” @click=”play”></i>
<i class=”fas fa-pause play” v-else></i>

With all this let’s define the play method:

play(song) {
console.log(song)
if (song) {
this.current = song
this.player.src = `http://localhost:4000/${this.current.music.path}`
}
this.player.play()
this.isplaying = true
},

We, first of all, get the current song and pass it into the function parameter. We then define the JavaScript Audio() instance. Next, we check if the song is null: If it isn’t, we set this.current to the song we passed in the parameter, and then we call the Audio player instance. (Also, don’t forget that we have to set the isPlaying state to true when the music is playing.)

Adding The Pause Function

To pause a song, we will use the Audio pause method. We need to add a click event to the pause icon:

<i class=”fas fa-pause play” @click=”pause” v-else></i>

And then define the function in the methods instance:

pause() {
this.player.pause()
this.isplaying = false
},

Playing A Song From The Music List

This is quite simple to implement. All we have to do is add a click event that will change the song parameter in the play method to the song we just created.

Simply modify the play button on the music list table to this:

<button class=”btn btn-primary” @click=”play(music)”>Play</button>

And there you have it!

Adding The Next Function

To add the next function, we need to increment the index by one. To do this, add a click event to the next icon:

@click=”next”

And then define the prev function in the methods instance:

next() {
this.index++
if (this.index > this.allMusic.length – 1) {
this.index = 0
}
this.current = this.allMusic[this.index]
this.play(this.current)
},

This conditional is responsible for replaying all of the songs whenever the last song in the list has been played.

Adding The previous Function

This is actually the opposite of the next function, so let’s add a click event to the previous function:

@click=”prev”

Next, we define the previous function:

prev() {
this.index–
if (this.index < 0) {
this.index = this.allMusic.length – 1
}
this.current = this.allMusic[this.index]
this.play(this.current)
},

Our music player app is now complete!

Conclusion

In this article, we looked at how we can build a music manager with Nuxt.js and Express.js. Along the way, we saw how Multer streamlines the process of handling file uploads and how to use Mongoose to interact without a database. Finally, we used Nuxt.js to build the client app which gives it a fast and snappy feel.

Unlike other frameworks, building an application with Nuxt.js and Express.js is quite easy and fast. The cool part about Nuxt.js is the way it manages your routes and makes you structure your apps better.

You can access more information about Nuxt.js here.
You can access the source code on Github here

Smashing Editorial
(dm, il)

Adobe MAX Creativity Tour: Catch up on all the action

Original Source: http://feedproxy.google.com/~r/CreativeBloq/~3/d8ohOhx-ch4/adobe-max-creativity-tour-catch-up-on-all-the-action

Adobe MAX Creativity Tour London was packed with inspiring stories, jaw-dropping demos and fascinating creative insights. And if you missed out on the main event, you can catch up on all the talks from the comfort of your own home (or desk) right here. It's ideal for a shot of inspiration and motivation in these dingy winter days. Whether you're a designer, illustrator, blogger, photographer or budding student creative, there's something here for you.

The evening kicked off with a fascinating and useful insight into the tools you're almost certainly using to bring your projects to life: Adobe Creative Cloud. There have been several headline-grabbing updates to flagship tools, as well as exciting additions to the CC family, but you might not be quite clued up on all the changes. 

Principal Creative Cloud evangelist Rufus Deuchler offered a speedy tour of the most exciting updates, from the Sensei-powered brushes in new art app Adobe Fresco, to XD's powerful new co-editing capabilities, to Photoshop's downright amazing Object Selection tool. Get up to speed below.

The second talk shone a light on the incredible showcase of talent that was the McDonald's 2019 Christmas advert. Designers from Leo Burnett and Passion Animation Studios took to the stage to reveal how they came up with a concept that would capture the nation's hearts, and share how they brought it all to life. Catch up on their presentation below.

Rounding off the evening in style, Jamal Edwards MBE joined Adobe's Claire Darley on stage to chat about how he made the journey from getting his first camera aged 15 to curating stages at Wireless and recording interviews at 10 Downing Street. It makes for incredibly inspiring viewing – it's worth tuning in to hear the section on Edwards' hilariously cheeky guerilla marketing tactics alone [2 mins 50].

For more insight and inspiration, plus information on those Adobe Creative Cloud updates, head to the Adobe website.

Adobe MAX is heading to Europe

There's more exciting news for designers who can't make it across the pond for Adobe's annual US bash – in 2020, MAX will be coming to Europe for the first time! 

Adobe MAX Europe will take place 15-16 June 2020 at the Feira Internacional in Lisbon, Portugal. The festival will bring together the world’s biggest brands and most inspiring minds to celebrate Adobe’s vision of ‘Creativity for All’ – as well as, of course, revealing the latest innovations coming to Creative Cloud. 

To register, head to the Adobe MAX Europe site. Don't hang about though – there's a special launch discount that means if you pick up your ticket before the end of February, you'll pay less than half price!


Branding and Visual Identity for Bestside Films

Original Source: http://feedproxy.google.com/~r/abduzeedo/~3/2zxv3kg8Ffo/branding-and-visual-identity-bestside-films

Branding and Visual Identity for Bestside Films
Branding and Visual Identity for Bestside Films

abduzeedoFeb 26, 2020

Massimo Studio shared an awesome branding and visual identity project for Bestside Films.  Bestside’s main goal is to make history. They believe in the core pillars upon brands are created: Relationship, Movement and History. Always seeking to understand what is the needs of each project, aligning technique, sensitivity, and creativity. We will make history!

For the brand identity, the amazing people at Massimo Studio explored Bestside’s versatility to approach any kind of film project to create strong key visuals and a dynamic logo which can transform itself to attend the type of work they’re playing at the time. The bold applications relate to the ambitions the company has in their scope and with the purpose of no one passing to some piece of Bestside’s work without noticing them.

It’s dynamic logo which can transform itself depending on the client

Design Services: Brand Identity; Key Visuals; Goods
Sector: Film; Audio-visual
Website: bestside.com.br
Branding & Visual Identity


Animating SVG Text on a Path

Original Source: http://feedproxy.google.com/~r/tympanus/~3/TgvvW-zgNkY/

Animating SVG text on a path on scroll has been explained really well in this great video tutorial by the keyframers. The basic idea is to couple the startOffset value of a textPath element with the scroll position, allowing the text to move along its path while scrolling.

We wanted to take this a step further and integrate it in a real website example with some more features.

In our experiment, we made the animation smoother and used SVG filters, while also using different paths. Additionally, we worked with the Intersection Observer API for animating only the texts that are in the viewport. The intensity of the SVG filters depends on the scroll speed.

If you want to learn more about SVG filters and how to use them to create interesting effects, have a look at our dedicated series written by Sara Soueidan:

SVG Filters 101Outline Text with <feMorphology>Poster Image Effect with <feComponentTransfer>Duotone Images with <feComponentTransfer>Conforming Text to Surface Texture with <feDisplacementMap>Creating Texture with <feTurbulence>SVG Filter Effects: Moving Forward

Please be aware that animating SVG filters in Firefox has dreadful performance. This has been like that for years, unfortunately. There are a number of bugs filed regarding animating SVG filters and even rendering SVG filters:

Bug 1456932: SVG blur filter is slowBug 422371: SVG feTurbulence filter is far too slowBug 1583828: Slow SVG filter animationBug 483868: Firefox much less responsive than Chrome while scrolling/enlarging SVG map with filters

Sadly, the outlook on solving these issues in Firefox don’t look too good as these have all been marked with priority P3, which means:

“This isn’t a bad idea, and maybe we’ll want to implement it at some point in the future, but it’s not near-term roadmap material. Some core Bugzilla developer may work on it.”

So it’s a good idea to keep in mind that if you are working with SVG filters and plan to animate them, it’s probably best if you leave Firefox out of the equation. This is exactly what we did in our example, so you won’t see the fancy filter magic if you open the demo in Firefox. However, if you do want to try it out, you can do so with smaller areas, i.e. smaller texts. Although it won’t be as smooth as in Chrome, it will work better than with larger texts.

We hope you enjoy our examples and find them useful!

References & Credits

Animate Text on Scroll | SVG textPath Tutorial | Keyssentials: Quick Tips by @keyframersMoving Text on a Curved Path on CSS-TricksPerfecting Paths for <textPath> by Amelia Bellamy-RoydsImages from UnsplashimagesLoaded by Dave DeSandro

Animating SVG Text on a Path was written by Mary Lou and published on Codrops.

Motion Design Monday: Faceversary by Buck

Original Source: http://feedproxy.google.com/~r/abduzeedo/~3/MpkorMXaDHo/motion-design-monday-faceversary-buck

Motion Design Monday: Faceversary by Buck
Motion Design Monday: Faceversary by Buck

abduzeedoFeb 24, 2020

Yas NV and the incredible people at Buck keep delivering amazing work. What is a wonderful surprise for me is that I didn’t know much about Buck since a month ago. I guess I have been too busy with other things. To celebrate my admiration for Buck, here’s the motion design work they did for Facebook titled Faceversary. More information make sure to check out Buck’s website or visit Yas’ Behance profile.

Motion Design

Animation tests


Take your Adobe CC skills to the next level

Original Source: http://feedproxy.google.com/~r/CreativeBloq/~3/kBde5td-FAY/take-your-adobe-cc-skills-to-the-next-level

If you've been thinking about ways to continue your creative education this year, you've come to the right place. It's never too late to continue learning and finesse your personal and professional objectives. 

You can brush up on your design skills with the All-in-One Adobe Creative Cloud Suite Certification Bundle, now with 97% off. To extend your Adobe skills even further, you could check out our range of tutorials that include the best Photoshop tutorials, and Illustrator tutorials out there. 

All levels of expertise can benefit

With 60 hours of content and hundreds of tutorials, this updated Adobe CC bundle is the perfect way to get more out of the programs you already use or are interested in learning. The eight-course package is geared toward various levels of experience, so no matter what your expertise, you're bound to get something out of it and master your skills in Photoshop, Indesign, Illustrator, Lightroom, After Effects, and more. One of the best parts of the bundle is a certification upon completion, making it a valuable asset to add to your résumé and portfolio that will give you an edge over the competition.

Step your content up a gear

With endless amounts of lessons, you'll get the guidance you need to build your design portfolio with the latest updates in motion graphics, logo design, user interface design, photography, and so much more. This popular bundle is available 24/7, allowing you to come back and visit when you need to reference a specific tool or need a spark of inspiration for your latest project. Take your content to the next level, explore the latest updates on tool panels for each program, and even learn how to maximize your creative workflow to save you precious time. You'll be exposed to real-life exercises that test your understanding of the content, empowering you to practice what you learn.

While lifetime access to this bundle is priced at almost $2,000, The All-in-One Adobe Creative Cloud Suite Certification Bundle is currently price-dropped to only $34 - that's 97% off. It's certainly a great way to learn the latest and greatest in design artistry and continue to grow your career in 2020.

Read more:

The 5 best InDesign alternativesHow to add fonts in PhotoshopThe 6 best laptops for Photoshop in 2020

Audio-based Image Distortion Effects with WebGL

Original Source: http://feedproxy.google.com/~r/tympanus/~3/i6_NN9VRgWA/

We’ve covered in the past how we can read data from Audio, using the p5.sound library and how we can use that data, to draw things in the canvas, using p5.js.

Well, what if instead of drawing a sketch, we used audio to distort an image? Today we want to show you some demos that play around that idea.

We’ve created some experiments using the theme of movie trailers where the background image of the movie poster is being distorted using a sound sample. It kind of adds some drama to an otherwise static image in this case.

Here’s a short video of the beginning of one of the effects:

How it works

We analyze the sound and map the range of frequencies, to some uniforms we pass in our fragment shader. Then depending on the effect/distortion we have, we can tweak different parameters, using the audio frequencies which constantly change overtime.

In our first demo, we create a simple sinewave in our fragment shader, by using the bass frequencies of the audio track to control its frequency and the mid frequencies to control its amplitude. Then we add the distortion in both axes (x & y) of our uv and add that distortion to the initial texture coordinates.

It looks like this:

float wave = sin(uv.y * u_bass + u_time) * u_mid;
vec2 d = vec2(wave); // could be vec2(wave, 0.0) or vec2(0.0, wave) for distortion only in 1 axis.
vec4 image = texture2D(u_texture, uv + d);
gl_FragColor = image;

The possibilities are endless if you want to play around that idea, it’s just a matter of what effect you’re after. Make sure you’re mapping values to your uniforms, that are within a range that can distort your visual, and you can always use some generic uniforms like u_time, that can put some ‘overdrive’ to your distortion.

Head over to the demos and check out the variations we’ve made.

Hope you’ll have fun with this one and be sure to share any of your own versions!

Reference & Credits

p5.jsp5.soundp5jsShaderExamples

Audio-based Image Distortion Effects with WebGL was written by Yannis Yannakopoulos and published on Codrops.