3
\$\begingroup\$

I'm interested in mimicking a simple version of Mathematica's Manipulate function in javascript. This is my first project in javascript, but I was hoping to make a library that I can use to quickly draw up several plots on several pages with manipulable parameters.

Here's what I came up with, using Plotly.js to draw the plots and jQuery UI for the sliders:

function Plotter(divName) {
    this.divName = divName;
    this.xMin = 0;
    this.xMax = Math.PI;
    this.xStep = Math.PI/100;
    this.xVals = range(this.xMin, this.xMax, this.xStep);
    this.params = [0, 0];
    this.yVals = [];
    this.layout = {};
}

Plotter.prototype = {
    constructor:Plotter,

    //creates the plot panel
    initializePlot: function() {
        Plotly.newPlot(this.divName, [{x:this.xVals, y:this.yVals}], this.layout);
    },

    //function that calculates y given x and parameters. This is hard-coded here, but ideally would be easily entered in the html page.
    yFunction(xVals, params) {
        var yVals = [];
        for (var ii = 0; ii < xVals.length; ii++) {
            yVals.push(params[0] * Math.sin(params[1] * xVals[ii]));
        }
        return yVals; 
    },

    //keeps the plot panel, but refreshes the y values.
    refreshPlot: function() {
        this.yVals = this.yFunction(this.xVals, this.params);
        Plotly.restyle(this.divName, {y: [this.yVals]});
    }  
}

//adds a slider to the element that controls a given parameter index
function addSlider(element, sliderName, paramIndex) {
     var slider = $("#" + sliderName).slider({
                orientation: "horizontal",             
                value: element.params[paramIndex],
                min: 0, //the slider range is hard-coded for now, but should be set in the html page eventually.
                max: 3 * Math.PI,
                step: Math.PI/32,
                slide: function( event, ui ) {
                    //when the slider moves, the element parameters are updated and the panel is refresehd
                    element.params[paramIndex] = ui.value;
                    element.refreshPlot();
                }
        });
}

//Generate array of evenly spaced points, from:
//http://stackoverflow.com/questions/3895478/does-javascript-have-a-method-like-range-to-generate-an-array-based-on-suppl
function range(start, stop, step){
    var a=[start], b=start;
    while(b<stop){b+=step;a.push(b)}
    return a;
};

Here is how I can implement a panel in HTML (after loading this library):

<body>
    <div id="div1" style="width: 480px; height: 400px;">
    <div id="slider1a"></div>
    <div id="slider1b"></div>
    <script>
        fig1 = new Plotter("div1");
        fig1.initializePlot();
        fig1.params = [1.5, Math.PI];
        addSlider(fig1, "slider1a", 0);
        addSlider(fig1, "slider1b", 1);
        fig1.refreshPlot();
    </script>
</body>

The good news is that I can add several manipulable panels to a page with relatively ease. I'd like to know:

  • am I following generally good practice in how I implement these functions?
  • what is a good way to assign a y-function to the plotter object from the HTML? For now, the y(x) is hard-coded while I get everything else working.

Thanks for your help.

\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.