The main functions at work here provided by Snap are:

Snap(...)

//Identifies or creates a new svg element to work with as a snap object Paper.circle( x, y, r )

//Creates a circle object which can be appended to the snap object

//The x and y coordinates are relative to the parent element. Paper.line( x1, y1, x2, y2 )

//Create a line from the first to second (x,y) coordinates relative to the parent container Element.attr(...)

//Sets attributes for any elements within the snap object. This function takes in an argument of an object with key value pairs corresponding to the different attributes you can apply to any given element. Element.limitDrag() is a custom function which is probably not the nicest implementation of this code, but it works. Element.drag(onmove, onstart, onend, [mcontext], [scontext], [econtext])

//This is called inside of the Element.limitDrag() function in the code pen above. It takes three callback functions that are required.

For a more thorough example of how to write the callback functions for Element.drag() see this demo . For this specific slider I had to add another function to the Element.prototype within Snap to get the slider to stop. Luckily I was able to find some code that limited the drag in the Snap docs.

Creating Components

In the folder called src I created another folder called animations . Here is where I will pull all of my individual SVG components from.

Inside of my animations folder I create a new file called Slider.js which is where I will create my component. First I import React and Snap:

import React from 'react';

import Snap from 'snapsvg-cjs';

Next I create a smart component for this slider to live in. At first I tried to create a dumb component for this slider since I don’t need to do anything with it’s state, but I’ll get back to why I chose to use a smart component in a bit.

import React from 'react';

import Snap from 'snapsvg-cjs'; class Slider extends React.Component{ let s = Snap('#svg') render () {

return(

<svg id='svg'/>

)

}

export default Slider

So the Snap() function works by either finding an SVG element by it’s id or by creating a new one. Once it finds the element it creates a snap object that can referenced to change the SVG element. Initially I tried just returning ‘s’, however React kept giving me an error that the component could not return an object. Instead I decided to return an SVG. The next issue I ran into was that when I tried applying elements to ‘s’, React kept telling me that ‘s’ was undefined. It turns out my Snap related code was running before the React component was rendered.

To fix this I wrap all of the Snap elements inside of React’s lifecycle method componentDidMount() . This blocks running code inside of this method until the component is rendered and ready to use. Now, there is an SVG with the correct id on the page before Snap tries to find said SVG.

import React from 'react';

import Snap from 'snapsvg-cjs'; //insert Element.prototype.limitDrag function here class Slider extends React.Component{ componentDidMount() {

var s = Snap("#svg" + this.props.keyId.toString()) s.line(30, 30, this.props.width-30, 30).attr({stroke: '#000'}) var myCircle2 = s.circle(30,30,20) myCircle.attr({ stroke: '#123456', 'strokeWidth': 3,

fill: this.props.fill, 'opacity': 0.2 }) myCircle2.limitDrag({ x: 0, y: 0, minx: 0, miny: 0,

maxx: this.props.width-20, maxy: 0 })

} render () {

const idKey = "svg" + this.props.keyId.toString()

return (

<svg style={this.props.style}

width={this.props.width} height="60" id={idKey}/>

)

}

} export default Slider

For this component I import the Snap library at the top of the file so that it is available to the class. I figured this decision made sense since use of this library is specific to this component. In order to keep this component flexible I added some props that can be passed down to it when it is called. Let’s look at the App container:

import React, { Component } from 'react';

import Slider from './animations/Slider' class App extends Component { render() {

return (

<div>

<Slider keyId={1} width={400} fill={'green'}/>

<Slider keyId={2} width={400} fill={'red'}/>

<Slider keyId={3} width={400} fill={'yellow'}/>

</div>

);

}

} export default App;

You’ll notice at the top that I import Slider from my animations folder. When the Slider component is called, I pass it three props that can be unique to each slider. You’ll also notice that there is a unique keyId prop for each Slider. This is used to uniquely identify the SCG that is rendered by the component, so that Snap() knows where to place each element.

Happy Sliding!