Giter Club home page Giter Club logo

meanderer's Introduction

Meanderer

A micro-library for scaling CSS motion path strings ✨

popsicle with "stay cool..." lettering travelling around its path

Installation

CDN

https://unpkg.com/[email protected]/dist/meanderer{.min}.js

NPM

npm i meanderer

Usage

// Our path string
const PATH = "M32.074 13.446s-2.706-2.965-4.158-4.349c-2.003-1.908-3.941-3.942-6.268-5.437C19.33..."
// The bounds of our path
const WIDTH = 65
const HEIGHT = 30
// Generate a responsive path
const responsivePath = new Meanderer({
  path: PATH,
  width: WIDTH,
  height: HEIGHT
})
// Generate a new scaled path when required. Here we are using ResizeObserver
// with a container that uses viewport units
const setPath = () => {
  const scaledPath = responsivePath.generatePath(
    CONTAINER.offsetWidth,
    CONTAINER.offsetHeight
  )
  // Here, we apply the path to an element through a CSS variable.
  // And then an element picks up on that. We could apply the motion path straight to the element though.
  CONTAINER.style.setProperty("--path", `"${scaledPath}"`)
}
// Set up our Resize Observer that will get the ball rolling
const SizeObserver = new ResizeObserver(setPath)
// Observe! Done!
SizeObserver.observe(CONTAINER)

First things first. We need a path. Unless you're constructing one by hand, it's likely you'll be extracting one from an SVG.

Before extracting one from an SVG, it's wise to run that SVG through an optimizer like SVGOMG(Use the precision slider for extra gains! 💪). This will normalize coordinates, etc. removing any translations which could skew the path translation.

Now you've got a path string, it's time to use it!

  1. Create variables for the path, and a desired width and height for the path bounds. The width and height are in most cases going to be the x2 and y2 of your SVG's viewBox attribute.
  const PATH = "M32.074 13.446s-2.706-2.965-4.158-4.349c-2.003-1.908-3.941-3.942-6.268-5.437C19.33..."
  // The bounds of our path
  const WIDTH = 65
  const HEIGHT = 30
  1. Create a new responsive path by passing those variables inside an Object to a new Meanderer instance.
  // Generate a responsive path
  const responsivePath = new Meanderer({
    path: PATH,
    width: WIDTH,
    height: HEIGHT
  })
  1. Use your instance to generate scaled path strings for a given width and height 👍
  responsivePath.generatePath(200, 400)
  1. Pass that to your element either directly or via CSS variable, etc. 🎉

Caveats

Meanderer will do its best to maintain aspect ratio of your paths. If the container dimensions passed in to generatePath don't match the aspect ratio of the path, Meanderer will handle this. It will do this by padding out the container and centering the path for you.

A way to enforce the correct aspect ratio for your container is to use your defined width and height in your CSS. Consider a container with a width of 25vmin. You've specified a width and height of 64 and 35.

.container {
  height: calc((64 / 35) * 25vmin);
  width: 25vmin;
}

stroke-path isn't currently taken into consideration. There have been experiments trying it out though. They didn't seem to affect the overall experience/result though.

Contributing

I'd love some contributions if you think this micro-library could be useful for you! Leave an issue or open a PR 👍


MIT Licensed | Made with 💻 by @jh3y 2020

meanderer's People

Contributors

jh3y avatar

Stargazers

krby.algo avatar Garbage Cat avatar a_i_918 avatar v1rtl avatar Sofian Mejjoute avatar  avatar  avatar W-Kentaro avatar yama-dev avatar Lee Valenzuela avatar Iryna avatar  avatar ivcsuu13 avatar Michael Cox avatar Carter avatar Papi Peppers avatar  avatar Janis avatar setusb avatar  avatar wwmin avatar Alexander avatar Alexey avatar Maxwell Hutt avatar James Musgrave avatar Rafa Cobiella avatar Fi Bennett avatar Gérard Mathiuet avatar  avatar justgu.us avatar Adriana Toledo Santiago avatar Ihor Burenko avatar Konstantin Baklaev avatar Alexandr avatar Nikolay Astakhayev avatar  avatar Dmitry Zhigalov avatar  avatar b avatar PR 花蜜 avatar Alex M avatar Sudeesh Pabbathi avatar  avatar Hillarydalie avatar REGE avatar Peeyush Raj avatar Howard Chiam avatar Aftab Parvez avatar Denis Denisov avatar Nikita avatar Adam Argyle avatar Frederick Thomas avatar Azim Kurt avatar Jafar Rezaei avatar  avatar Anjolaoluwa avatar Marshall avatar David Sanderson avatar Ketyra Sai avatar C.OG avatar undefined avatar Van Ribeiro avatar  avatar Daniel avatar  avatar GustavoEspíndola avatar Katherine avatar  avatar Zeh Fernandes avatar 仿生狮子 avatar Sunny avatar Cien Lim avatar Franco Monsalvo avatar David M. avatar  avatar Emmanuel Salomon avatar Andrea avatar Andrew G. avatar Nicola Di Marco avatar Michael Raguse avatar Roman avatar  avatar TsubasaHiga avatar Elliott avatar Moh avatar Bruno avatar Oğuz Çelikdemir avatar Steven Verbiest avatar Christian Boyle avatar  avatar Code Cowboy avatar vaibhav avatar Nikolas Evers avatar Acampbell avatar  avatar Caleb Fristoe avatar Onur Can avatar Alan Garcia avatar J.N. Breuer avatar Ihor Vorotnov avatar

Watchers

 avatar timelyportfolio avatar James Cloos avatar  avatar Emmanuel Ulloa Arguello avatar  avatar Frederick Thomas avatar  avatar

meanderer's Issues

[DEMO] Add a confirm before dropping a file

Currently, a user can drag and drop a file onto the page and the first path is processed from the SVG 👍

This SVG ideally needs to be optimized though. If it isn't, the results can be wild 😭

Add a little confirm popup using the confirm function that repeats to the user that it's wise to drop an optimized SVG onto the page 👍

Lottie Animation on Path

Hi Jhey,

Big fan of this package, really saved my ass. I'm going to use it to make a Lottie-animation walk on a path, and a dog is running on the path. Really simple in theory, but the relative path-lenght needs to be responsive, as Lottie handles itself.

I would love to make a contribution so you can use Lottie in conjunction with Meanderer, and Lottie interactions so you have a scroll-based offset path that is fully responsive and supports technical artists from start to finish.

I'm not that gifted with "contributions" on Github, so don't feel sad about sending some pointers if I do. Hope to see more of my "brilliant idea" soon, and this sets a marker so I have too ;)

Greetings,
Guus

Switch from d3.js to svgpath package

After some conversation in the CSS Tricks article comment thread, it seems there's a node package out there that could do some of this transformation for us.

It also has the potential to be more performant/accurate.

Try out svgpath with Meanderer 👍 I've tried it with a node script and a test path with good results 👍

Meanderer then becomes a very small micro-library for this kinda stuff acting as a browser shell for svgpath. Maybe we can include the CSS scaling technique under a inclusiveScaling option?

One thing to note. Use of svgpath with rollup will require @rollup/plugin-commonjs and the class tweaked slightly.

Create an internal interpolation function

The package currently uses d3.scaleLinear for interpolating the domain against the range of path values.

It works great. But, it's hefty in size. It pulls in a whopping 32.9Kb unzipped according to Import Cost 😭 And all we are doing is interpolating values against each other.

Use a simpler interpolation function. You could even grab one from any of the examples online and drop it into the script files 👍

It will reduce the size of the package immensely!

Test different aspect ratios

"Most" of the paths I've tested work 👍

But every so often I come across one that doesn't quite fit in the container. I guess the goal here is to make sure your containers use the same aspect ratio as your paths. That's the quickest win in every case.

Test an array of paths and log settings for paths that might fail.

[TESTING] Introduce testing

Add some form of testing.

Initial ideas are

  • unit testing for the basic internal functions like getMaximums etc.
  • puppeteer screenshot testing for scaled paths potentially?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.