滑块上的约束jquery+在页面加载时调用javascript函数来调用javascript函数

Constraints on slider jquery + callng javascript function at page loadto call javascript function

本文关键字:调用 函数 javascript 加载 约束 jquery+      更新时间:2023-09-26

我有一些代码,它绘制了某个数学函数,并使用户能够实时更改函数的某些特定参数,从而使用户能够看到函数的变化。

我有两个问题需要帮助。

i) 我使用的是jquery UI库,它提供了一个滑块。我使用这个滑块来允许用户在特定范围内更改特定参数。通常情况下,参数没有约束。然而,在这种情况下,我需要以下等式保持min<=mode<=max。目前,我已经用滑块的slide事件中的一些代码解决了这个问题。代码基本上检查相等性,如果违反了,则将参数设置为其可能的最小值或最大值。

但是,从视觉上看,可以进一步滑动。但是,在用户释放滑块I之后,change事件已被调用,我将参数更改为其可能的最小值或最大值。是否可以确保滑块在视觉上也不会违反约束?

ii)当我加载页面时,页面上还没有可见的绘图。这是因为当页面加载时,我似乎无法调用函数redraw(),请参阅底部的代码。为什么没有调用redraw()

Snippet,请参阅下文或http://jsfiddle.net/qraLt1p3/11/

<!DOCTYPE html>
<html lang="en">
<head>
<title>MPERT</title>
<meta charset="utf-8">
<script src="//d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<style type="text/css">
svg {
    font: 10px sans-serif;
    shape-rendering: crispEdges;
}
  
rect {
    fill: transparent;
}
  
.axis path,
.axis line {
    fill: none;
    stroke: #000;
    shape-rendering: crispEdges;
}
  
.line {
    fill: none;
    stroke: steelblue;
    stroke-width: 1.5px;
    clip-path: url(#clip);
}
  
.grid .tick {
    stroke: lightgrey;
    opacity: 0.7;
}
  
.grid path {
    stroke-width: 0;
}
#slider-pertmin, #slider-pertmode, #slider-pertmax {
	float: right;
	width: 120px;
	margin: 7px;
}
.ui-slider-horizontal {
	height: 8px;
	width: 200px;
}
.ui-slider .ui-slider-handle {
	height: 15px;
	width: 5px;
	padding-left: 5px;
}
#plot {
  background-color:#f9f9f9;
	border:solid 1px #ddd;
	padding:10px;
  width:250px;
}
	
#plotOptions {
	background-color:#f9f9f9;
	border:solid 1px #ddd;
	padding:10px;
}
	
.block label { 
	display: inline-block; 
	width: 60px; 
	text-align: right; 
}
</style>
<script type="text/javascript">
	// Log-gamma function
	gammaln = function gammaln(x)
	{
		var cof = [ 76.18009172947146,  -86.50532032941677,      24.01409824083091,
				    -1.231739572450155,   0.1208650973866179e-2, -0.5395239384953e-5];
		var j = 0;
		var ser = 1.000000000190015;
		var xx, y, tmp;
		tmp = (y = xx = x) + 5.5;
		tmp -= (xx + 0.5) * Math.log(tmp);
		for (; j < 6; j++)
			ser += cof[j] / ++y;
		return Math.log(2.5066282746310005 * ser / xx) - tmp;
	};
	
	// Gamma function
	gammafn = function gammafn(x) 
	{
		var p = [    -1.716185138865495,    24.76565080557592,   -379.80425647094563,
				    629.3311553128184,     866.9662027904133,  -31451.272968848367,
			     -36144.413418691176,    66456.14382024054];
		var q = [    -30.8402300119739,     315.35062697960416, -1015.1563674902192,
				   -3107.771671572311,    22538.118420980151,    4755.8462775278811,
				 -134659.9598649693,    -115132.2596755535];
	  
		var fact = false,
			n = 0,
			xden = 0,
			xnum = 0,
			y = x,
			i, 
			z, 
			yi, 
			res, 
			sum, 
			ysq;
		if (y <= 0) {
			res = y % 1 + 3.6e-16;
			
			if (res) {
				fact = (!(y & 1) ? 1 : -1) * Math.PI / Math.sin(Math.PI * res);
				y = 1 - y;
			} else
				return Infinity;
		}
		yi = y;
		if (y < 1)
			z = y++;
		else
			z = (y -= n = (y | 0) - 1) - 1;
		for (i = 0; i < 8; ++i) {
			xnum = (xnum + p[i]) * z;
			xden = xden * z + q[i];
		}
		res = xnum / xden + 1;
		if (yi < y)
			res /= yi;
		else if (yi > y) {
			for (i = 0; i < n; ++i) {
				res *= y;
				y++;
			}
		}
		if (fact)
			res = fact / res;
		return res;
	};
	// Beta function
	betafn = function betafn(x,y) 
	{
		// ensure arguments are positive
		if (x <= 0 || y <= 0)
			return undefined;
		// make sure x + y doesn't exceed the upper limit of usable values
		return (x + y > 170)
			? Math.exp(betaln(x, y))
			: gammafn(x) * gammafn(y) / gammafn(x + y);
	};
	
	// Natural logarithm of Beta function
	betaln = function betaln(x, y) 
	{
		return gammaln(x) + gammaln(y) - gammaln(x + y);
	};
	
	$(function() {
		$("#slider-pertmin").slider({
			range: "min",
			value: 1,
			min: 1,
			max: 20,
			step: 0.1,
			slide: function(event,ui) {
				if (ui.value > $("#slider-pertmode").slider("value")) {
					$("#pertmin").val($("#slider-pertmode").slider("value") - 0.1);
					$("#slider-pertmin").slider("value",$("#slider-pertmode").slider("value") - 0.1)
				} else
					$("#pertmin").val(ui.value);
				redraw();	
			},
			change: function(event,ui) {
			  $("#slider-pertmin").slider("value",$("#pertmin").val());
			}
		});
		$("#slider-pertmode").slider({
			range: "min",
			value: 3,
			min: 1,
			max: 20,
			step: 0.1,
			slide: function(event,ui) {
				if (ui.value < $("#slider-pertmin").slider("value")) {
					$("#pertmode").val($("#slider-pertmin").slider("value") + 0.1);
					$("#slider-pertmode").slider("value",$("#slider-pertmin").slider("value") + 0.1);
				} else if (ui.value > $("#slider-pertmax").slider("value")) {
					$("#pertmode").val($("#slider-pertmax").slider("value") - 0.1);
					$("#slider-pertmode").slider("value",$("#slider-pertmax").slider("value") - 0.1);
				} else
					$("#pertmode").val(ui.value);
				redraw();
			},
			change: function(event,ui) {
			  $("#slider-pertmode").slider("value",$("#pertmode").val());
			}
		});
		$("#slider-pertmax").slider({
			range: "min",
			value: 6,
			min: 1,
			max: 20,
			step: 0.1,
			slide: function(event,ui) {
				if (ui.value < $("#slider-pertmode").slider("value")) {
					$("#pertmax").val($("#slider-pertmode").slider("value") + 0.1);
					$("#slider-pertmax").slider("value",$("#slider-pertmode").slider("value") + 0.1);
				} else
					$("#pertmax").val(ui.value);
				redraw();
			},
			change: function(event,ui) {
        $("#slider-pertmax").slider("value",$("#pertmax").val());
			}
		});
		$("#pertmin").val($("#slider-pertmin").slider("value"));
		$("#pertmode").val($("#slider-pertmode").slider("value"));
		$("#pertmax").val($("#slider-pertmax").slider("value"));
	});
</script>
</head>
<body>
<div id="plot"></div>
<div id="plotOptions" class="ui-widget" style="width:250px">
	<div class="block"> 
		<label for="pertmin">min:</label> <input type="value" id="pertmin" style="border:none; background: transparent; width:40px;" />
		<div class="ui-slider" id="slider-pertmin" />
	</div>
	<div class="block"> 
		<label for="pertmode">mode:</label> <input type="value" id="pertmode" style="border:none; background: transparent; width:40px;" />
		<div class="ui-slider" id="slider-pertmode" />
	</div>
	<div class="block">
		<label for="pertmax">max:</label> <input type="value" id="pertmax" style="border:none; background: transparent; width:40px;" />
		<div class="ui-slider" id="slider-pertmax" />
	</div>
</div>
<script type="text/javascript">
	var pert = {
		min: 2,
		mode: 4,
		max: 9
	};
	pert.mu   = (pert.min + 4*pert.mode + pert.max)/6;
	pert.a1   = 6*(pert.mu - pert.min)/(pert.max - pert.min);
	pert.a2   = 6*(pert.max - pert.mu)/(pert.max - pert.min);
	pert.beta = betafn(pert.a1,pert.a2);
    var data = [];
    for (var k = pert.min; k < pert.max; k += 0.1) {
      data.push({
        x: k,
        y: (1/pert.beta)*(Math.pow(k - pert.min,pert.a1 - 1) * 
		                  Math.pow(pert.max - k,pert.a2 - 1)) /
						  Math.pow(pert.max - pert.min,pert.a1 + pert.a2 - 1)
      });
    }
	var margin = {
        top: 20,
        right: 20,
        bottom: 35,
        left: 50
     },
		width = 250 - margin.left - margin.right,
		height = 250 - margin.top - margin.bottom;
    var x = d3.scale.linear()
      .domain([pert.min, pert.max])
      .range([0, width]);
    var y = d3.scale.linear()
      .domain([0, 1])
      .range([height, 0]);
    var xAxis1 = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .ticks(5)
      .innerTickSize(-6)
      .outerTickSize(0)
      .tickPadding(7);
    var yAxis1 = d3.svg.axis()
      .scale(y)
      .orient("left")
      .ticks(5)
      .innerTickSize(-6)
      .outerTickSize(0)
      .tickPadding(7);
    var xAxis2 = d3.svg.axis()
      .scale(x)
      .orient("top")
      .ticks(5)
      .innerTickSize(-6)
      .tickPadding(-20)
      .outerTickSize(0)
      .tickFormat("");
    var yAxis2 = d3.svg.axis()
      .scale(y)
      .orient("left")
      .ticks(5)
      .innerTickSize(6)
      .tickPadding(-20)
      .outerTickSize(0)
      .tickFormat("");
    var xGrid = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .tickSize(-height, -height, 0)
      .tickFormat("");
    var yGrid = d3.svg.axis()
      .scale(y)
      .orient("left")
      .ticks(5)
      .tickSize(-width, -width, 0)
      .tickFormat("");
	  
    var line = d3.svg.line()
      .x(function(d) {
        return x(d.x);
      })
      .y(function(d) {
        return y(d.y);
      })
      .interpolate("linear");
	  
    var zoom = d3.behavior.zoom()
      .x(x)
      .y(y)
      .scaleExtent([1, 1])
      .on("zoom",redraw);
      
    var svg = d3.select("#plot").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .call(zoom);
	  
    // Add x grid
    svg.append("g")
      .attr("class", "x grid")
      .attr("transform", "translate(0," + height + ")")
      .call(xGrid);
    // Add y grid
    svg.append("g")
      .attr("class", "y grid")
      .call(yGrid);
    svg.append("g")
      .attr("class", "x1 axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis1);
    svg.append("g")
      .attr("class", "y1 axis")
      .call(yAxis1);
    /* append additional X axis */
    svg.append("g")
      .attr("class", "x2 axis")
      .attr("transform", "translate(" + [0, 0] + ")")
      .call(xAxis2);
    /* append additional y axis */
    svg.append("g")
      .attr("class", "y2 axis")
      .attr("transform", "translate(" + [width, 0] + ")")
      .call(yAxis2);
    // Add x axis label  
    svg.append("text")
        .attr("transform", "translate(" + (width / 2) + "," + (height + margin.bottom) + ")")
        .style("font-size","15")
        .style("text-anchor", "middle")
        .text("x axis");
    // Add y axis label
    svg.append("text")
        .attr("transform", "rotate(-90)")
        .attr("y",0 - margin.left)
        .attr("x",0 - (height / 2))
        .attr("dy", "1em")
        .style("font-size","15")
        .style("text-anchor", "middle")
        .text("y axis");
    svg.append("defs").append("clipPath")
      .attr("id", "clip")
      .append("rect")
      .attr("width", width)
      .attr("height", height);
      
    svg.append("rect")
      .attr("width", width)
      .attr("height", height);
    svg.append("path")
      .attr("class", "line")
    function redraw() {
		pert.min  = $("#slider-pertmin").slider("value");
		pert.mode = $("#slider-pertmode").slider("value");
		pert.max  = $("#slider-pertmax").slider("value");
		pert.mu   = (pert.min + 4*pert.mode + pert.max)/6;
		pert.a1   = 6*(pert.mu - pert.min)/(pert.max - pert.min);
		pert.a2   = 6*(pert.max - pert.mu)/(pert.max - pert.min);
		pert.beta = betafn(pert.a1,pert.a2);
		
		x.domain([pert.min, pert.max]);
	
		svg.select(".x1.axis").call(xAxis1);
		svg.select(".y1.axis").call(yAxis1);
		svg.select(".x2.axis").call(xAxis2);
		svg.select(".y2.axis").call(yAxis2);
		svg.select(".x.grid").call(xGrid);
		svg.select(".y.grid").call(yGrid);
		
		var data = [];
		for (var k = pert.min; k < pert.max; k += 0.1) {
			data.push({
				x: k,
				y: (1/pert.beta)*(Math.pow(k - pert.min,pert.a1 - 1) * 
								  Math.pow(pert.max - k,pert.a2 - 1)) /
								  Math.pow(pert.max - pert.min,pert.a1 + pert.a2 - 1)
			});
		}
		d3.select(".line").attr("d",line(data));
    }
    
    redraw();
</script>
</body>
</html>

1.)关于UI问题,我会使用范围滑块来表示我的最小值/最大值。然后我会有点花哨,更新我的模式滑块的最小/最大(和宽度),使其始终在最小/最大之间。

2.)在滑块初始化之前,您正在调用您的初始redraw。这是因为滑块初始化是在document.ready事件中完成的,而您的初始redraw不是。一个简单的解决方案是:

$(function() {
  redraw();
});

为了进一步扩展我的回答,这里有一个我将如何实现你的第一个问题的粗略例子。注意,我在这个例子的基础上用d3替换了jquery滑块。我一直在寻找一个基于d3的答案。

<!DOCTYPE html>
<html lang="en">
<head>
  <title>MPERT</title>
  <meta charset="utf-8">
  <script src="//d3js.org/d3.v3.min.js"></script>
  <style type="text/css">
    svg {
      font: 10px sans-serif;
      shape-rendering: crispEdges;
    }
    
    rect {
      fill: transparent;
    }
    
    .axis path,
    .axis line {
      fill: none;
      stroke: #000;
      shape-rendering: crispEdges;
    }
    
    .line {
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;
      clip-path: url(#clip);
    }
    
    .grid .tick {
      stroke: lightgrey;
      opacity: 0.7;
    }
    
    .grid path {
      stroke-width: 0;
    }
    
    circle {
      -webkit-transition: fill-opacity 250ms linear;
    }
    
    .selecting circle {
      fill-opacity: .2;
    }
    
    .selecting circle.selected {
      stroke: #f00;
    }
    
    .resize path {
      fill: #666;
      fill-opacity: .8;
      stroke: #000;
      stroke-width: 1.5px;
    }
    
    .brush .extent {
      fill-opacity: .125;
      shape-rendering: crispEdges;
    }
    
    #plot {
      background-color: #f9f9f9;
      border: solid 1px #ddd;
      padding: 10px;
      width: 250px;
    }
    
    #plotOptions {
      background-color: #f9f9f9;
      border: solid 1px #ddd;
      padding: 10px;
    }
    
    .block label {
      display: inline-block;
      width: 60px;
      text-align: right;
    }
  </style>
  <script type="text/javascript">
    // Log-gamma function
    gammaln = function gammaln(x) {
      var cof = [76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5];
      var j = 0;
      var ser = 1.000000000190015;
      var xx, y, tmp;
      tmp = (y = xx = x) + 5.5;
      tmp -= (xx + 0.5) * Math.log(tmp);
      for (; j < 6; j++)
        ser += cof[j] / ++y;
      return Math.log(2.5066282746310005 * ser / xx) - tmp;
    };
    // Gamma function
    gammafn = function gammafn(x) {
      var p = [-1.716185138865495, 24.76565080557592, -379.80425647094563,
        629.3311553128184, 866.9662027904133, -31451.272968848367, -36144.413418691176, 66456.14382024054
      ];
      var q = [-30.8402300119739, 315.35062697960416, -1015.1563674902192, -3107.771671572311, 22538.118420980151, 4755.8462775278811, -134659.9598649693, -115132.2596755535];
      var fact = false,
        n = 0,
        xden = 0,
        xnum = 0,
        y = x,
        i,
        z,
        yi,
        res,
        sum,
        ysq;
      if (y <= 0) {
        res = y % 1 + 3.6e-16;
        if (res) {
          fact = (!(y & 1) ? 1 : -1) * Math.PI / Math.sin(Math.PI * res);
          y = 1 - y;
        } else
          return Infinity;
      }
      yi = y;
      if (y < 1)
        z = y++;
      else
        z = (y -= n = (y | 0) - 1) - 1;
      for (i = 0; i < 8; ++i) {
        xnum = (xnum + p[i]) * z;
        xden = xden * z + q[i];
      }
      res = xnum / xden + 1;
      if (yi < y)
        res /= yi;
      else if (yi > y) {
        for (i = 0; i < n; ++i) {
          res *= y;
          y++;
        }
      }
      if (fact)
        res = fact / res;
      return res;
    };
    // Beta function
    betafn = function betafn(x, y) {
      // ensure arguments are positive
      if (x <= 0 || y <= 0)
        return undefined;
      // make sure x + y doesn't exceed the upper limit of usable values
      return (x + y > 170) ? Math.exp(betaln(x, y)) : gammafn(x) * gammafn(y) / gammafn(x + y);
    };
    // Natural logarithm of Beta function
    betaln = function betaln(x, y) {
      return gammaln(x) + gammaln(y) - gammaln(x + y);
    };
  </script>
</head>
<body>
  <div id="plot"></div>
  <div id="plotOptions" class="ui-widget" style="width:250px">
  </div>
  <script>
var margin = {top: 5, right: 20, bottom: 5, left: 20},
    width = 250 - margin.left - margin.right,
    height = 50 - margin.top - margin.bottom
    min = 0, max = 20;
var brushX = d3.scale.linear()
    .range([0, width])
    .domain([min, max]);
var brush = d3.svg.brush()
    .x(brushX)
    .extent([0, 20])
    .on("brush", brushmove);
var arc = d3.svg.arc()
    .outerRadius(height / 3)
    .startAngle(0)
    .endAngle(function(d, i) { return i ? -Math.PI : Math.PI; });
var svg = d3.select("#plotOptions").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height/2 + ")")
    .call(d3.svg.axis().scale(brushX).orient("bottom"));
var brushg = svg.append("g")
    .attr("class", "brush")
    .call(brush);
brushg.selectAll(".resize").append("path")
    .attr("transform", "translate(0," +  height / 2 + ")")
    .attr("d", arc);
brushg.selectAll("rect")
    .attr("height", height);
var mode = 10;
var modeRect = svg.append("rect")
  .attr("height", height)
  .attr("width", 10)
  .attr("y", 0)
  .attr("x", brushX(mode) - 5)
  .style("fill", "steelblue")
  .style("opacity", 0.5);
  
var drag = d3.behavior.drag()
  .on("drag", modeDrag);
modeRect.call(drag);
function modeDrag(modeX){
  var xPos = d3.mouse(this)[0],
      tmp = brushX.invert(xPos);
  if (tmp > min && tmp < max){
    mode = tmp;
    modeRect
    .attr('x', xPos);
    redraw();
  }
}
function brushmove() {
  console.log(d3.event)
  var extent = brush.extent();
  min = extent[0];
  max = extent[1];
  if (min >= mode){
    mode = min;
    modeRect.attr('x', brushX(mode) - 5);
  } else if (max <= mode){
    mode = max;
    modeRect.attr('x', brushX(mode) - 5);
  }
  
  redraw();
}
  </script>
  <script type="text/javascript">
    var pert = {
      min: 2,
      mode: 4,
      max: 9
    };
    pert.mu = (pert.min + 4 * pert.mode + pert.max) / 6;
    pert.a1 = 6 * (pert.mu - pert.min) / (pert.max - pert.min);
    pert.a2 = 6 * (pert.max - pert.mu) / (pert.max - pert.min);
    pert.beta = betafn(pert.a1, pert.a2);
    var data = [];
    for (var k = pert.min; k < pert.max; k += 0.1) {
      data.push({
        x: k,
        y: (1 / pert.beta) * (Math.pow(k - pert.min, pert.a1 - 1) *
            Math.pow(pert.max - k, pert.a2 - 1)) /
          Math.pow(pert.max - pert.min, pert.a1 + pert.a2 - 1)
      });
    }
    var margin = {
        top: 20,
        right: 20,
        bottom: 35,
        left: 50
      },
      width = 250 - margin.left - margin.right,
      height = 250 - margin.top - margin.bottom;
    var x = d3.scale.linear()
      .domain([pert.min, pert.max])
      .range([0, width]);
    var y = d3.scale.linear()
      .domain([0, 1])
      .range([height, 0]);
    var xAxis1 = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .ticks(5)
      .innerTickSize(-6)
      .outerTickSize(0)
      .tickPadding(7);
    var yAxis1 = d3.svg.axis()
      .scale(y)
      .orient("left")
      .ticks(5)
      .innerTickSize(-6)
      .outerTickSize(0)
      .tickPadding(7);
    var xAxis2 = d3.svg.axis()
      .scale(x)
      .orient("top")
      .ticks(5)
      .innerTickSize(-6)
      .tickPadding(-20)
      .outerTickSize(0)
      .tickFormat("");
    var yAxis2 = d3.svg.axis()
      .scale(y)
      .orient("left")
      .ticks(5)
      .innerTickSize(6)
      .tickPadding(-20)
      .outerTickSize(0)
      .tickFormat("");
    var xGrid = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .tickSize(-height, -height, 0)
      .tickFormat("");
    var yGrid = d3.svg.axis()
      .scale(y)
      .orient("left")
      .ticks(5)
      .tickSize(-width, -width, 0)
      .tickFormat("");
    var line = d3.svg.line()
      .x(function(d) {
        return x(d.x);
      })
      .y(function(d) {
        return y(d.y);
      })
      .interpolate("linear");
    var zoom = d3.behavior.zoom()
      .x(x)
      .y(y)
      .scaleExtent([1, 1])
      .on("zoom", redraw);
    var svg = d3.select("#plot").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .call(zoom);
    // Add x grid
    svg.append("g")
      .attr("class", "x grid")
      .attr("transform", "translate(0," + height + ")")
      .call(xGrid);
    // Add y grid
    svg.append("g")
      .attr("class", "y grid")
      .call(yGrid);
    svg.append("g")
      .attr("class", "x1 axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis1);
    svg.append("g")
      .attr("class", "y1 axis")
      .call(yAxis1);
    /* append additional X axis */
    svg.append("g")
      .attr("class", "x2 axis")
      .attr("transform", "translate(" + [0, 0] + ")")
      .call(xAxis2);
    /* append additional y axis */
    svg.append("g")
      .attr("class", "y2 axis")
      .attr("transform", "translate(" + [width, 0] + ")")
      .call(yAxis2);
    // Add x axis label  
    svg.append("text")
      .attr("transform", "translate(" + (width / 2) + "," + (height + margin.bottom) + ")")
      .style("font-size", "15")
      .style("text-anchor", "middle")
      .text("x axis");
    // Add y axis label
    svg.append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 0 - margin.left)
      .attr("x", 0 - (height / 2))
      .attr("dy", "1em")
      .style("font-size", "15")
      .style("text-anchor", "middle")
      .text("y axis");
    svg.append("defs").append("clipPath")
      .attr("id", "clip")
      .append("rect")
      .attr("width", width)
      .attr("height", height);
    svg.append("rect")
      .attr("width", width)
      .attr("height", height);
    svg.append("path")
      .attr("class", "line")
    function redraw() {
      pert.min = min - 0.001;
      pert.mode = mode;
      pert.max = max + 0.001;
      pert.mu = (pert.min + 4 * pert.mode + pert.max) / 6;
      pert.a1 = 6 * (pert.mu - pert.min) / (pert.max - pert.min);
      pert.a2 = 6 * (pert.max - pert.mu) / (pert.max - pert.min);
      pert.beta = betafn(pert.a1, pert.a2);
      x.domain([pert.min, pert.max]);
      svg.select(".x1.axis").call(xAxis1);
      svg.select(".y1.axis").call(yAxis1);
      svg.select(".x2.axis").call(xAxis2);
      svg.select(".y2.axis").call(yAxis2);
      svg.select(".x.grid").call(xGrid);
      svg.select(".y.grid").call(yGrid);
      var data = [];
      for (var k = pert.min; k < pert.max; k += 0.1) {
        data.push({
          x: k,
          y: (1 / pert.beta) * (Math.pow(k - pert.min, pert.a1 - 1) *
              Math.pow(pert.max - k, pert.a2 - 1)) /
            Math.pow(pert.max - pert.min, pert.a1 + pert.a2 - 1)
        });
      }
      d3.select(".line").attr("d", line(data));
    }
    redraw();
  </script>
</body>
</html>