parent
f29c758ac8
commit
2e23d57d8d
@ -1,249 +1,335 @@ |
||||
<html> |
||||
<head> |
||||
<!-- Ignore Favicon -> Solved the warning... --> |
||||
|
||||
<!-- Ignore Favicon -> Solved the warning in console of the browser. --> |
||||
<link rel="icon" href="data:;base64,iVBORw0KGgo="> |
||||
|
||||
<!-- Importing D3 module --> |
||||
<script src='./modules/d3v3/d3.min.js'></script> |
||||
<script src='./modules/d3/d3.min.js'></script> |
||||
|
||||
<script src='./modules/d3-star/d3-starPlot.js'></script> |
||||
<script src='./modules/d3-annotations/d3-annotator.js'></script> |
||||
<script src="./modules/d3-tip/tip.js"></script> |
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.13.0/d3-legend.js"></script> |
||||
<script src="./modules/savage.toggle-switch.js" type="text/javascript"></script> |
||||
|
||||
<script src="./modules/papa/papaparse.min.js"></script> |
||||
<script src="./modules/jquery/jquery.min.js"></script> |
||||
|
||||
<!-- Basic scripts --> |
||||
<script src="./js/tsne.js"></script> |
||||
<script src="./js/checkbox.js"></script> |
||||
<script src="./js/data_form_handler.js"></script> |
||||
<script src="./lasso.js"></script> |
||||
|
||||
<!-- CSS --> |
||||
<link rel="stylesheet" href="./css/style.css"/> |
||||
<link rel="stylesheet" href="./css/bootstrap.min.css"/> |
||||
<link rel="stylesheet" href="./css/dc.css"/> |
||||
|
||||
<!-- Bootstrap --> |
||||
<script src="./modules/bootstrap.min.js"></script> |
||||
|
||||
<!-- To be removed!!!--> |
||||
<script src='./modules/three.js-r101/three.js'></script> |
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js'></script> |
||||
|
||||
</head> |
||||
<!-- Importing D3 minified versions v3 and v5. --> |
||||
<script src='./modules/d3v3/d3.min.js'></script> |
||||
<script src='./modules/d3/d3.min.js'></script> |
||||
|
||||
<!-- Importing additional modules such as starPlot, annotator, tip, legend, switch, papaParse, and Jquery. --> |
||||
<script src='./modules/d3-star/d3-starPlot.js'></script> |
||||
<script src='./modules/d3-annotations/d3-annotator.js'></script> |
||||
<script src="./modules/d3-tip/tip.js"></script> |
||||
<script src="./modules/d3-legend/d3-legend.min.js"></script> |
||||
<script src="./modules/savage.toggle-switch.js" type="text/javascript"></script> |
||||
|
||||
<script src="./modules/papa/papaparse.min.js"></script> |
||||
<script src="./modules/jquery/jquery.min.js"></script> |
||||
|
||||
<body> |
||||
<!-- Basic scripts that we execute. --> |
||||
<script src="./js/tsne.js"></script> |
||||
<script src="./js/checkbox.js"></script> |
||||
<script src="./js/data_form_handler.js"></script> |
||||
<script src="./lasso.js"></script> |
||||
|
||||
<!-- CSS - Styling --> |
||||
<link rel="stylesheet" href="./css/style.css"/> |
||||
<link rel="stylesheet" href="./css/bootstrap.min.css"/> |
||||
<link rel="stylesheet" href="./css/dc.css"/> |
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css"> |
||||
|
||||
<!-- Bootstrap --> |
||||
<script src="./modules/bootstrap.min.js"></script> |
||||
|
||||
</head> |
||||
|
||||
<div class="container-fluid"> |
||||
<div class="row"> |
||||
<div class="col-md-3"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">t-SNE Overview</h3> |
||||
<body> |
||||
|
||||
<div class="container-fluid"> |
||||
<div class="row"> |
||||
<div class="col-md-3"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">t-SNE Overview</h3> |
||||
</div> |
||||
<div class="row"> |
||||
<div class="panel-body"> |
||||
<div class="col-md-6"> |
||||
<canvas id = "tSNEcanvas"></canvas> |
||||
</div> |
||||
<div class="col-md-2"> |
||||
<div class="legend" id = "legend3"></div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div id="control-panel"> |
||||
<div class="param"> |
||||
<label for="param-lim">Points radius scaling factor</label> |
||||
<input id="param-lim" type="range" min="0.25" max="4" value="2", step="0.25"> |
||||
<output for="param-lim" id="param-lim-value">2</output> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="row"> |
||||
<div class="panel-body"> |
||||
<div class="col-md-6"> |
||||
<canvas id = "tSNEcanvas"></canvas> |
||||
</div> |
||||
<div class="col-md-2"> |
||||
<div class="legend" id = "legend3"></div> |
||||
<div class="col-md-6"> |
||||
<svg id="SvgAnnotator"></svg> |
||||
<svg id="modtSNEcanvas_svg"></svg> |
||||
<div id="modtSNEDiv"> |
||||
<canvas id = "modtSNEcanvas" ></canvas> |
||||
</div> |
||||
</div> |
||||
<div class="col-md-1" style="width: 3.499999995%"> |
||||
<svg id="legend1"></svg> |
||||
</div> |
||||
<div class="col-md-2" style="width: 21.499999995%"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">Select different modes</h3> |
||||
</div> |
||||
<div class="panel-body"> |
||||
<div id="resetAllFilters" style="margin-bottom: 40px"> |
||||
<button class="btn btn-info btn-block active" onclick="setLayerProj();">Layer: t-SNE projection</button> |
||||
<button class="btn btn-info btn-block" onclick="setLayerComp();">Layer: kNN limiter and data features comparison</button> |
||||
<button class="btn btn-info btn-block" onclick="setLayerSche();">Layer: Schema investigation</button> |
||||
</div> |
||||
</div> |
||||
<button class="btn btn-info btn-block" onclick="setReset();">Reset all filters</button> |
||||
<label style="margin-top: 15px"> |
||||
<input id="controls" type="checkbox"> |
||||
Hide annotations' controllers |
||||
</label> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div id="control-panel"> |
||||
<div class="param"> |
||||
<label for="param-lim">Points radius scaling factor</label> |
||||
<input id="param-lim" type="range" min="0.25" max="4" value="2", step="0.25"> |
||||
<output for="param-lim" id="param-lim-value">2</output> |
||||
</div> |
||||
<div class="row"> |
||||
<div class="col-md-3"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">Shepard Heatmap</h3> |
||||
</div> |
||||
<div class="panel-body"> |
||||
<div class="row"> |
||||
<div class="col-md-6"> |
||||
<svg id="sheparheat"></svg> |
||||
</div> |
||||
<div class="col-md-2"> |
||||
<svg id="legend4"></svg> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="col-md-3 col-md-offset-6"> |
||||
<svg id="correlation"></svg> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="col-md-6"> |
||||
<svg id="SvgAnnotator"></svg> |
||||
<svg id="modtSNEcanvas_svg"></svg> |
||||
<canvas id = "modtSNEcanvas" ></canvas> |
||||
</div> |
||||
<div class="col-md-1"> |
||||
<svg id="legend1"></svg> |
||||
</div> |
||||
<div class="col-md-2"> |
||||
<div id="ThumbNailsList"> |
||||
<label for="male">Neighborhood Preservation</label> |
||||
<select id="param-neighborHood" name ="param-neighborHood"> |
||||
<option selected="selected" value="color">Color</option> |
||||
<option value="size">Size</option> |
||||
</select> |
||||
<output for="param-neighborHood" id="param-neighborHood-value"></output> |
||||
<label for="male">Final Cost (Kullback-Leibler)</label> |
||||
<label>Vice versa</label> |
||||
<div id="param-correlation"> |
||||
<div class="param"> |
||||
<label for="param-corr">Correlation threshold</label> |
||||
<input id="param-corr" type="range" min="0" max="750" value="150", step="50"> |
||||
<output for="param-corr" id="param-corr-value">150</output> |
||||
</div> |
||||
Type the text of the form: <textarea type="text" id="comment" name="textforAnnotator">Please, provide your comment.</textarea> |
||||
<div class="row"> |
||||
<div class="col-md-3"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">t-SNE Parameters</h3> |
||||
</div> |
||||
<div class="panel-body"> |
||||
<div id="control-panel" data-sr="enter left over 8s"> |
||||
<div class="param"> |
||||
<label id="data" for="param-dataset">Data sets</label> |
||||
<select id="param-dataset" name="param-dataset" onChange="changeDataset(this.value);"> |
||||
<option value="winequality-red.csv">Red Wine - Quality</option> |
||||
<option value="iris.csv" selected>Iris</option> |
||||
<option value="mnist.csv" >Mnist</option> |
||||
<option value="Frogs_MFCCs_s.csv" >Frogs</option> |
||||
<option value="empty">Add New File</option> |
||||
</select> |
||||
</div> |
||||
<div class="param"> |
||||
<label for="param-perplexity">Perplexity</label> |
||||
<input id="param-perplexity" type="range" min="2" max="100" value="30", step="1"> |
||||
<output for="param-perplexity" id="param-perplexity-value">30</output> |
||||
</div> |
||||
<div class="param"> |
||||
<label for="param-learningrate">Learning rate</label> |
||||
<input id="param-learningrate" type="range" min="1" max="300" value="10", step="1"> |
||||
<output for="param-learningrate" id="param-learningrate-value">10</output> |
||||
</div> |
||||
<div class="param"> |
||||
<label for="param-maxiter">Max iterations</label> |
||||
<input id="param-maxiter" type="range" min="10" max="1000" value="10", step="10"> |
||||
<output for="param-maxiter" id="param-maxiter-value">10</output> |
||||
</div> |
||||
<div class="param"> |
||||
<label for="param-distance">Distance metric</label> |
||||
<select id="param-distance" name="param-distance"> |
||||
<option value="euclideanDist" selected>Euclidean distance</option> |
||||
<option value="jaccardDist">Jaccard dissimilarity</option> |
||||
</select> |
||||
<output for="param-distance" id="param-distance-value"></output> |
||||
</div> |
||||
<div class="param"> |
||||
<label for="param-transform">Data transform</label> |
||||
<select id="param-transform" name="param-transform"> |
||||
<option value="noTrans" selected>No transform</option> |
||||
<option value="logTrans">Log10</option> |
||||
<option value="asinhTrans">asinh</option> |
||||
<option value="binTrans">Binarize</option> |
||||
</select> |
||||
<output for="param-transform" id="param-transform-value"></output> |
||||
</div> |
||||
<p><div id="run-button"><button class="btn btn-primary btn-block" onclick="getData();">Run New t-SNE</button></div></p> |
||||
</div> |
||||
<p><div id="toggleAnnotator"><button class="btn btn-primary btn-block" onclick="setAnnotator();">Add a new comment</button></div></p> |
||||
<p><div id="continue"><button class="btn btn-primary btn-block" onclick="setContinue();">Continue with the analysis</button></div></p> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="col-md-3 col-md-offset-6"> |
||||
<div id="starPlot"></div> |
||||
</div> |
||||
</div> |
||||
<div class="row"> |
||||
<div class="col-md-3"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">Shepard Heatmap</h3> |
||||
</div> |
||||
<div class="panel-body"> |
||||
</div> |
||||
<div class="row"> |
||||
<div class="col-md-6"> |
||||
<svg id="sheparheat"></svg> |
||||
<div class="col-md-3"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">Visual Mapping Parameters</h3> |
||||
</div> |
||||
<div class="row"> |
||||
<div class="panel-body"> |
||||
<div class="col-md-12"> |
||||
<div id="ThumbNailsList"> |
||||
<label for="male">Neighborhood Preservation</label> |
||||
<select id="param-neighborHood" name ="param-neighborHood"> |
||||
<option selected="selected" value="color">Color</option> |
||||
<option value="size">Size</option> |
||||
</select> |
||||
<output for="param-neighborHood" id="param-neighborHood-value"></output> |
||||
<label for="male">Final Cost (Kullback-Leibler)</label> |
||||
<label id="selectionLabel" style="margin-top:4px">Vice versa</label> |
||||
<div id="param-correlation"> |
||||
<div class="param"> |
||||
<label for="param-corr">Correlation threshold</label> |
||||
<input id="param-corr" type="range" min="0" max="750" value="150", step="50"> |
||||
<output for="param-corr" id="param-corr-value">150</output> |
||||
</div> |
||||
Visualization annotating form: <textarea type="text" id="comment" name="textforAnnotator" style="margin-top:4px" placeholder="Please, provide your comment."></textarea> |
||||
</div> |
||||
<div id="commBtn"> |
||||
<div class="param" style="margin-top:4px"> |
||||
<div id="toggleAnnotator"><button class="btn btn-default btn-block" onclick="setAnnotator();">Add a new comment</button></div> |
||||
</div> |
||||
<div class="param" style="margin-top:4px"> |
||||
<div id="continue"><button class="btn btn-default btn-block active" onclick="setContinue();">Continue with the analysis</button></div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="col-md-2"> |
||||
<svg id="legend4"></svg> |
||||
<div class = col-md-6> |
||||
<svg id="knnBarChart"></svg> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="col-md-3 col-md-offset-6"> |
||||
<svg id="correlation"></svg> |
||||
</div> |
||||
</div> |
||||
<div class="row"> |
||||
<div class="col-md-3"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">t-SNE Parameters</h3> |
||||
</div> |
||||
<div class="panel-body"> |
||||
<div id="control-panel" data-sr="enter left over 8s"> |
||||
<div class="param"> |
||||
<label id="data" for="param-dataset">Data sets</label> |
||||
<select id="param-dataset" name="param-dataset" onChange="changeDataset(this.value);"> |
||||
<option value="winequality-red.csv">Red Wine - Quality</option> |
||||
<option value="iris.csv" selected>Iris</option> |
||||
<option value="mnist.csv" >Mnist</option> |
||||
<option value="Frogs_MFCCs_s.csv" >Frogs</option> |
||||
<option value="empty">Add New File</option> |
||||
</select> |
||||
<div class="col-md-3" id="extra-information" style="width: 24.5999995%"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">t-SNE and data set's extra information</h3> |
||||
</div> |
||||
<div class="panel-body"> |
||||
<div id="cost"></div> |
||||
<br> |
||||
<div id="datasetDetails"></div> |
||||
</div> |
||||
</div> |
||||
<div class="panel panel-default" id="kNNInfo"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">kNN barchart information</h3> |
||||
</div> |
||||
<div class="panel-body"> |
||||
<div id="cost"></div> |
||||
<br> |
||||
<div id="datasetDetails"></div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="param"> |
||||
<label for="param-perplexity">Perplexity</label> |
||||
<input id="param-perplexity" type="range" min="2" max="100" value="30", step="1"> |
||||
<output for="param-perplexity" id="param-perplexity-value">30</output> |
||||
</div> |
||||
<div class="param"> |
||||
<label for="param-learningrate">Learning rate</label> |
||||
<input id="param-learningrate" type="range" min="1" max="300" value="10", step="1"> |
||||
<output for="param-learningrate" id="param-learningrate-value">10</output> |
||||
</div> |
||||
<div class="param"> |
||||
<label for="param-maxiter">Max iterations</label> |
||||
<input id="param-maxiter" type="range" min="10" max="1000" value="10", step="10"> |
||||
<output for="param-maxiter" id="param-maxiter-value">10</output> |
||||
</div> |
||||
<div class="param"> |
||||
<label for="param-distance">Distance metric</label> |
||||
<select id="param-distance" name="param-distance"> |
||||
<option value="euclideanDist" selected>Euclidean distance</option> |
||||
<option value="jaccardDist">Jaccard dissimilarity</option> |
||||
</select> |
||||
<output for="param-distance" id="param-distance-value"></output> |
||||
</div> |
||||
<div class="param"> |
||||
<label for="param-transform">Data transform</label> |
||||
<select id="param-transform" name="param-transform"> |
||||
<option value="noTrans" selected>No transform</option> |
||||
<option value="logTrans">Log10</option> |
||||
<option value="asinhTrans">asinh</option> |
||||
<option value="binTrans">Binarize</option> |
||||
</select> |
||||
<output for="param-transform" id="param-transform-value"></output> |
||||
</div> |
||||
<p><div id="run-button"><button class="btn btn-primary btn-block" onclick="getData();">Run New tSNE</button></div></p> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="col-md-3 col-md-offset-6"> |
||||
<div id="starPlot"></div> |
||||
</div> |
||||
</div> |
||||
<div class="row"> |
||||
<div class="col-md-3"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">Switch Mode</h3> |
||||
</div> |
||||
<div class="panel-body"> |
||||
<div id="cost"></div> |
||||
<div id="datasetDetails"></div> |
||||
<div id="toggleLassoAndLine"></div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class = col-md-6> |
||||
<svg id="knnBarChart"></svg> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<script> |
||||
$('#param-lim').bind('input', function () { $('#param-lim-value').text($('#param-lim').val()); }); |
||||
|
||||
/* This script is used in order to give functionalities to the different buttons provide through the front-end. */ |
||||
$('#param-lim').bind('input', function () { $('#param-lim-value').text($('#param-lim').val()); }); |
||||
$('#param-corr').bind('input', function () { $('#param-corr-value').text($('#param-corr').val()); }); |
||||
$('#param-perplexity').bind('input', function () { $('#param-perplexity-value').text($('#param-perplexity').val()); }); |
||||
$('#param-earlyexag').bind('input', function () { $('#param-earlyexag-value').text($('#param-earlyexag').val()); }); |
||||
$('#param-learningrate').bind('input', function () { $('#param-learningrate-value').text($('#param-learningrate').val()); }); |
||||
$('#param-maxiter').bind('input', function () { $('#param-maxiter-value').text($('#param-maxiter').val()); }); |
||||
SaVaGe.ToggleSwitch({container: "#toggleLassoAndLine", onChange: function(toggler){ setToggle(toggler.getValue()); }} ); |
||||
|
||||
// Get the container element |
||||
var btnContainer = document.getElementById("commBtn"); |
||||
|
||||
// Get all buttons with class="btn" inside the container |
||||
var btns = btnContainer.getElementsByClassName("btn"); |
||||
for (var i = 0; i < btns.length; i++) { |
||||
btns[i].addEventListener("click", function() { |
||||
let current = document.getElementById("commBtn").getElementsByClassName("active"); |
||||
console.log(current); |
||||
current[0].className = current[0].className.replace("btn btn-default btn-block active", "btn btn-default btn-block"); |
||||
this.className += " active"; |
||||
}); |
||||
} |
||||
|
||||
// Get the container element |
||||
var btnContainer2 = document.getElementById("resetAllFilters"); |
||||
|
||||
// Get all buttons with class="btn" inside the container |
||||
var btns2 = btnContainer2.getElementsByClassName("btn"); |
||||
|
||||
for (var i = 0; i < btns2.length; i++) { |
||||
btns2[i].addEventListener("click", function() { |
||||
let current = document.getElementsByClassName("active"); |
||||
console.log(current); |
||||
current[0].className = current[0].className.replace("btn btn-info btn-block active", "btn btn-info btn-block"); |
||||
this.className += " active"; |
||||
}); |
||||
} |
||||
|
||||
</script> |
||||
<script> |
||||
/* On resize refresh the shepardHeatmap */ |
||||
window.onresize = function(event) { |
||||
if ( document.getElementById('cost').hasChildNodes() ) { |
||||
// Clear legend for the shepardHeatmap |
||||
var svgLegend = d3.select("#legend4"); |
||||
svgLegend.selectAll("*").remove(); |
||||
|
||||
// Clear the SheapHeardmap before refreshing |
||||
var svg = d3.select("#sheparheat"); |
||||
svg.selectAll("*").remove(); |
||||
|
||||
// Call the ShepardHeatmap again to be redrawn |
||||
ShepardHeatMap(); |
||||
|
||||
<script> |
||||
/* On resize refresh the shepardHeatmap */ |
||||
window.onresize = function(event) { |
||||
if ( document.getElementById('cost').hasChildNodes() ) { |
||||
|
||||
// Clear legend for the shepardHeatmap |
||||
var svgLegend = d3.select("#legend4"); |
||||
svgLegend.selectAll("*").remove(); |
||||
|
||||
// Clear the SheapHeardmap before refreshing |
||||
var svg = d3.select("#sheparheat"); |
||||
svg.selectAll("*").remove(); |
||||
|
||||
// Call the ShepardHeatmap again to be redrawn |
||||
ShepardHeatMap(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
/* When the user clicks on the button, |
||||
toggle between hiding and showing the dropdown content */ |
||||
function myFunction() { |
||||
document.getElementById("myDropdown").classList.toggle("show"); |
||||
} |
||||
|
||||
// Close the dropdown menu if the user clicks outside of it |
||||
window.onclick = function(event) { |
||||
if (!event.target.matches('.dropbtn')) { |
||||
var dropdowns = document.getElementsByClassName("dropdown-content"); |
||||
var i; |
||||
for (i = 0; i < dropdowns.length; i++) { |
||||
var openDropdown = dropdowns[i]; |
||||
if (openDropdown.classList.contains('show')) { |
||||
openDropdown.classList.remove('show'); |
||||
/* When the user clicks on the button, |
||||
toggle between hiding and showing the dropdown content */ |
||||
function myFunction() { |
||||
document.getElementById("myDropdown").classList.toggle("show"); |
||||
} |
||||
|
||||
// Close the dropdown menu if the user clicks outside of it |
||||
window.onclick = function(event) { |
||||
if (!event.target.matches('.dropbtn')) { |
||||
var dropdowns = document.getElementsByClassName("dropdown-content"); |
||||
var i; |
||||
for (i = 0; i < dropdowns.length; i++) { |
||||
var openDropdown = dropdowns[i]; |
||||
if (openDropdown.classList.contains('show')) { |
||||
openDropdown.classList.remove('show'); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
</script> |
||||
|
||||
<!-- |
||||
Load the visualization script |
||||
--> |
||||
<script src="./js/tsne_vis.js"></script> |
||||
<!-- Load the core visualization script. --> |
||||
<script src="./js/tsne_vis.js"></script> |
||||
|
||||
</body> |
||||
|
||||
</html> |
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,5 +1,203 @@ |
||||
Copyright (c) 2015, Susie Lu |
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. |
||||
Apache License |
||||
Version 2.0, January 2004 |
||||
http://www.apache.org/licenses/ |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||
|
||||
1. Definitions. |
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, |
||||
and distribution as defined by Sections 1 through 9 of this document. |
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by |
||||
the copyright owner that is granting the License. |
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all |
||||
other entities that control, are controlled by, or are under common |
||||
control with that entity. For the purposes of this definition, |
||||
"control" means (i) the power, direct or indirect, to cause the |
||||
direction or management of such entity, whether by contract or |
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||
outstanding shares, or (iii) beneficial ownership of such entity. |
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity |
||||
exercising permissions granted by this License. |
||||
|
||||
"Source" form shall mean the preferred form for making modifications, |
||||
including but not limited to software source code, documentation |
||||
source, and configuration files. |
||||
|
||||
"Object" form shall mean any form resulting from mechanical |
||||
transformation or translation of a Source form, including but |
||||
not limited to compiled object code, generated documentation, |
||||
and conversions to other media types. |
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or |
||||
Object form, made available under the License, as indicated by a |
||||
copyright notice that is included in or attached to the work |
||||
(an example is provided in the Appendix below). |
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object |
||||
form, that is based on (or derived from) the Work and for which the |
||||
editorial revisions, annotations, elaborations, or other modifications |
||||
represent, as a whole, an original work of authorship. For the purposes |
||||
of this License, Derivative Works shall not include works that remain |
||||
separable from, or merely link (or bind by name) to the interfaces of, |
||||
the Work and Derivative Works thereof. |
||||
|
||||
"Contribution" shall mean any work of authorship, including |
||||
the original version of the Work and any modifications or additions |
||||
to that Work or Derivative Works thereof, that is intentionally |
||||
submitted to Licensor for inclusion in the Work by the copyright owner |
||||
or by an individual or Legal Entity authorized to submit on behalf of |
||||
the copyright owner. For the purposes of this definition, "submitted" |
||||
means any form of electronic, verbal, or written communication sent |
||||
to the Licensor or its representatives, including but not limited to |
||||
communication on electronic mailing lists, source code control systems, |
||||
and issue tracking systems that are managed by, or on behalf of, the |
||||
Licensor for the purpose of discussing and improving the Work, but |
||||
excluding communication that is conspicuously marked or otherwise |
||||
designated in writing by the copyright owner as "Not a Contribution." |
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||
on behalf of whom a Contribution has been received by Licensor and |
||||
subsequently incorporated within the Work. |
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
copyright license to reproduce, prepare Derivative Works of, |
||||
publicly display, publicly perform, sublicense, and distribute the |
||||
Work and such Derivative Works in Source or Object form. |
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
(except as stated in this section) patent license to make, have made, |
||||
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||
where such license applies only to those patent claims licensable |
||||
by such Contributor that are necessarily infringed by their |
||||
Contribution(s) alone or by combination of their Contribution(s) |
||||
with the Work to which such Contribution(s) was submitted. If You |
||||
institute patent litigation against any entity (including a |
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||
or a Contribution incorporated within the Work constitutes direct |
||||
or contributory patent infringement, then any patent licenses |
||||
granted to You under this License for that Work shall terminate |
||||
as of the date such litigation is filed. |
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the |
||||
Work or Derivative Works thereof in any medium, with or without |
||||
modifications, and in Source or Object form, provided that You |
||||
meet the following conditions: |
||||
|
||||
(a) You must give any other recipients of the Work or |
||||
Derivative Works a copy of this License; and |
||||
|
||||
(b) You must cause any modified files to carry prominent notices |
||||
stating that You changed the files; and |
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works |
||||
that You distribute, all copyright, patent, trademark, and |
||||
attribution notices from the Source form of the Work, |
||||
excluding those notices that do not pertain to any part of |
||||
the Derivative Works; and |
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its |
||||
distribution, then any Derivative Works that You distribute must |
||||
include a readable copy of the attribution notices contained |
||||
within such NOTICE file, excluding those notices that do not |
||||
pertain to any part of the Derivative Works, in at least one |
||||
of the following places: within a NOTICE text file distributed |
||||
as part of the Derivative Works; within the Source form or |
||||
documentation, if provided along with the Derivative Works; or, |
||||
within a display generated by the Derivative Works, if and |
||||
wherever such third-party notices normally appear. The contents |
||||
of the NOTICE file are for informational purposes only and |
||||
do not modify the License. You may add Your own attribution |
||||
notices within Derivative Works that You distribute, alongside |
||||
or as an addendum to the NOTICE text from the Work, provided |
||||
that such additional attribution notices cannot be construed |
||||
as modifying the License. |
||||
|
||||
You may add Your own copyright statement to Your modifications and |
||||
may provide additional or different license terms and conditions |
||||
for use, reproduction, or distribution of Your modifications, or |
||||
for any such Derivative Works as a whole, provided Your use, |
||||
reproduction, and distribution of the Work otherwise complies with |
||||
the conditions stated in this License. |
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||
any Contribution intentionally submitted for inclusion in the Work |
||||
by You to the Licensor shall be under the terms and conditions of |
||||
this License, without any additional terms or conditions. |
||||
Notwithstanding the above, nothing herein shall supersede or modify |
||||
the terms of any separate license agreement you may have executed |
||||
with Licensor regarding such Contributions. |
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade |
||||
names, trademarks, service marks, or product names of the Licensor, |
||||
except as required for reasonable and customary use in describing the |
||||
origin of the Work and reproducing the content of the NOTICE file. |
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or |
||||
agreed to in writing, Licensor provides the Work (and each |
||||
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||
implied, including, without limitation, any warranties or conditions |
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||
appropriateness of using or redistributing the Work and assume any |
||||
risks associated with Your exercise of permissions under this License. |
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, |
||||
whether in tort (including negligence), contract, or otherwise, |
||||
unless required by applicable law (such as deliberate and grossly |
||||
negligent acts) or agreed to in writing, shall any Contributor be |
||||
liable to You for damages, including any direct, indirect, special, |
||||
incidental, or consequential damages of any character arising as a |
||||
result of this License or out of the use or inability to use the |
||||
Work (including but not limited to damages for loss of goodwill, |
||||
work stoppage, computer failure or malfunction, or any and all |
||||
other commercial damages or losses), even if such Contributor |
||||
has been advised of the possibility of such damages. |
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing |
||||
the Work or Derivative Works thereof, You may choose to offer, |
||||
and charge a fee for, acceptance of support, warranty, indemnity, |
||||
or other liability obligations and/or rights consistent with this |
||||
License. However, in accepting such obligations, You may act only |
||||
on Your own behalf and on Your sole responsibility, not on behalf |
||||
of any other Contributor, and only if You agree to indemnify, |
||||
defend, and hold each Contributor harmless for any liability |
||||
incurred by, or claims asserted against, such Contributor by reason |
||||
of your accepting any such warranty or additional liability. |
||||
|
||||
END OF TERMS AND CONDITIONS |
||||
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work. |
||||
|
||||
To apply the Apache License to your work, attach the following |
||||
boilerplate notice, with the fields enclosed by brackets "[]" |
||||
replaced with your own identifying information. (Don't include |
||||
the brackets!) The text should be enclosed in the appropriate |
||||
comment syntax for the file format. We also recommend that a |
||||
file or class name and description of purpose be included on the |
||||
same "printed page" as the copyright notice for easier |
||||
identification within third-party archives. |
||||
|
||||
Copyright (c) 2015, Susie Lu |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,75 +1,103 @@ |
||||
d3.legend.**color()** |
||||
d3.**legendColor()** |
||||
|
||||
Constructs a new color legend. The legend component expects a d3 scale as the basic input, but also has a number of optional parameters for changing the default display such as vertical or horizontal orientation, shape of the symbol next to the label, symbol sizing, and label formatting. |
||||
|
||||
color.**scale(d3.scale)** |
||||
legendColor.**scale(d3.scale)** |
||||
|
||||
Creates a new d3 legend based on the scale. The code determines the type of scale and generates the appropriate symbol and label pairs. |
||||
|
||||
color.**cells(number or [numbers])** |
||||
legendColor.**cells(number or [numbers])** |
||||
|
||||
This parameter is only valid for continuous scales (like linear and log). When there is no indication from the domain or range for the number of steps in the legend you may want to display, it defaults to five steps in equal increments. You can pass the cells function a single number which will create equal increments for that number of steps, or an array of the [specific steps](#color-linear-custom) you want the legend to display. |
||||
|
||||
color.**orient(string)** |
||||
legendColor.**cellFilter(function)** |
||||
|
||||
This function is run as a filter function against the array of cells. If you have a function(d){ return true or false }, d has a .data and a .label property as it iterates over each cell it will display. Create a false condition for any cells you want to exclude from being displayed. An example: [Color - Ordinal Scale Legend, custom shape](#color-ordinal). |
||||
|
||||
legendColor.**orient(string)** |
||||
|
||||
Accepts "vertical" or "horizontal" for legend orientation. Default set to "vertical." |
||||
|
||||
color.**ascending(boolean)** |
||||
legendColor.**ascending(boolean)** |
||||
|
||||
If you pass this a true, it will reverse the order of the scale. |
||||
|
||||
color.**shape(string[, path-string])** |
||||
legendColor.**shape(string[, path-string])** |
||||
|
||||
Accepts "rect", "circle", "line", or "path". If you choose "path," you must also pass a second parameter as a path string. Defaults to "rect." An example: [Color - Ordinal Scale Legend, custom shape](#color-ordinal). |
||||
|
||||
color.**shapeWidth(number)** |
||||
legendColor.**shapeWidth(number)** |
||||
|
||||
Only applies to shape of "rect" or "line." Default set to 15px. |
||||
|
||||
color.**shapeHeight(number)** |
||||
legendColor.**shapeHeight(number)** |
||||
|
||||
Only applies to shape of "rect." Default set to 15px. |
||||
|
||||
color.**shapeRadius(number)** |
||||
legendColor.**shapeRadius(number)** |
||||
|
||||
Only applies to shape of "circle." Default set to 10px. |
||||
|
||||
color.**shapePadding(number)** |
||||
legendColor.**shapePadding(number)** |
||||
|
||||
Applies to all shapes. Determines vertical or horizontal spacing between shapes depending on the respective orient setting. Default set to 2px. |
||||
|
||||
color.**useClass(boolean)** |
||||
legendColor.**useClass(boolean)** |
||||
|
||||
The default behavior is for the legend to set the fill of the legend's symbols (except for the "line" shape which uses stroke). If you set useClass to `true` then it will apply the scale's output as classes to the shapes instead of the fill or stroke. An example: [Color - Quantile Scale Legend](#color-quant). |
||||
|
||||
color.**classPrefix(string)** |
||||
legendColor.**classPrefix(string)** |
||||
|
||||
Adds this string to the beginning of all of the components of the legend that have a class. This allows for namespacing of the classes. |
||||
|
||||
color.**title(string)** |
||||
legendColor.**title(string)** |
||||
|
||||
Sets the legend's title to the string. Automatically moves the legend cells down based on the size of the title. An example: [Symbol - Ordinal Scale](#symbol-ordinal). |
||||
|
||||
color.**labels([string])** |
||||
legendColor.**titleWidth(number)** |
||||
|
||||
Will break the legend title into multiple lines based on the width in pixels. An example: [Color - Quantile Scale Legend](#color-quant). |
||||
|
||||
legendColor.**labels([string] or function(options))** |
||||
|
||||
Passing a string: |
||||
Sets the legend labels to the array of strings passed to the legend. If the array is not the same length as the array the legend calculates, it merges the values and gives the calculated labels for the remaining items. An example: [Size - Linear Scale Legend, Lines](#size-line). |
||||
|
||||
color.**labelAlign(string)** |
||||
Passing a function: |
||||
This function is called for each generated label and gives you the options: |
||||
- i: current index |
||||
- genLength: total length of generated labels |
||||
- generatedLabels: array of generated labels |
||||
- domain: array from input scale |
||||
- range: array from input scale |
||||
This allows you to make any custom functions to handle labels. An example: [Color - Threshold Scale, Custom Labels](#color-threshold) |
||||
|
||||
List of [helper functions](#helpers). |
||||
|
||||
legendColor.**labelAlign(string)** |
||||
|
||||
Only used if the legend's orient is set to "horizontal." Accepts "start", "middle", or "end" as inputs to determine if the labels are aligned on the left, middle or right under the symbol in a horizontal legend. An example: [Size - Linear Scale Legend, Lines](#size-line). |
||||
|
||||
color.**labelFormat(d3.format)** |
||||
legendColor.**labelFormat(d3.format or d3.format string)** |
||||
|
||||
Takes a [d3.format](https://github.com/mbostock/d3/wiki/Formatting) and applies that styling to the legend labels. Default is set to `d3.format(".01f")`. |
||||
|
||||
color.**labelOffset(number)** |
||||
legendColor.**locale(d3.format locale)** |
||||
|
||||
Takes a [d3.format locale](https://github.com/d3/d3-format/tree/master/locale) and applies it to the legend labels. Default is set to [US english](https://github.com/d3/d3-format/blob/master/locale/en-US.json). |
||||
|
||||
legendColor.**labelOffset(number)** |
||||
|
||||
A value that determines how far the label is from the symbol in each legend item. Default set to 10px. |
||||
|
||||
color.**labelDelimiter(string)** |
||||
legendColor.**labelDelimiter(string)** |
||||
|
||||
Change the default "to" text when working with a quant scale. |
||||
|
||||
color.**on(string, function)** |
||||
legendColor.**labelWrap(number)** |
||||
|
||||
Add text wrapping to the cell labels. In orient horizontal you can use this in combination with shapePadding to get the desired spacing. An exampe: [Size - Linear Scale](#size-line). In orient vertical this will automatically scale the cells to fit the label.An example: [Symbol - Ordinal Scale](#symbol-ordinal) |
||||
|
||||
legendColor.**on(string, function)** |
||||
|
||||
There are three custom event types you can bind to the legend: "cellover", "cellout", and "cellclick" An exampe: [Symbol - Ordinal Scale](#symbol-ordinal) |
||||
There are three custom event types you can bind to the legend: "cellover", "cellout", and "cellclick" An example: [Symbol - Ordinal Scale](#symbol-ordinal) |
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@ |
||||
d3.**legendHelpers()** |
||||
|
||||
Convenience functions for using this module |
||||
|
||||
legendHelpers.**thresholdLabels** |
||||
|
||||
Changes the labels so the first one label says "Less than _first-threshold_" and the last one says "More than _last-threshold_". |
||||
Example: [Color - Threshold Scale, Custom Labels](#color-threshold) |
@ -1,175 +1,267 @@ |
||||
|
||||
|
||||
//Color: Quantile #svg-color-quant
|
||||
|
||||
var svg = d3.select("#svg-color-quant"); |
||||
|
||||
var quantize = d3.scale.quantize() |
||||
.domain([ 0, 0.15 ]) |
||||
.range(d3.range(9).map(function(i) { return "q" + i + "-9"; })); |
||||
|
||||
svg.append("g") |
||||
var svg = d3.select("#svg-color-quant") |
||||
|
||||
var quantize = d3 |
||||
.scaleQuantize() |
||||
.domain([0, 0.15]) |
||||
.range( |
||||
d3.range(9).map(function(i) { |
||||
return "q" + i + "-9" |
||||
}) |
||||
) |
||||
|
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendQuant") |
||||
.attr("transform", "translate(20,20)"); |
||||
|
||||
var legend = d3.legend.color() |
||||
.labelFormat(d3.format(".2f")) |
||||
.useClass(true) |
||||
.scale(quantize); |
||||
|
||||
svg.select(".legendQuant") |
||||
.call(legend); |
||||
.attr("transform", "translate(20,20)") |
||||
|
||||
var legend = d3 |
||||
.legendColor() |
||||
.labelFormat(d3.format(".2f")) |
||||
.useClass(true) |
||||
.title("A really really really really really long title") |
||||
.titleWidth(100) |
||||
.scale(quantize) |
||||
|
||||
svg.select(".legendQuant").call(legend) |
||||
|
||||
//Color: Treshold #svg-color-threshold
|
||||
|
||||
var svg = d3.select("#svg-color-threshold") |
||||
|
||||
var thresholdScale = d3 |
||||
.scaleThreshold() |
||||
.domain([0, 1000, 2500, 5000, 10000]) |
||||
.range( |
||||
d3.range(6).map(function(i) { |
||||
return "q" + i + "-9" |
||||
}) |
||||
) |
||||
|
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendThreshold") |
||||
.attr("transform", "translate(20,20)") |
||||
|
||||
var legend = d3 |
||||
.legendColor() |
||||
.labelFormat(d3.format(".2f")) |
||||
.labels(d3.legendHelpers.thresholdLabels) |
||||
.useClass(true) |
||||
.shapeWidth(30) |
||||
.scale(thresholdScale) |
||||
|
||||
svg.select(".legendThreshold").call(legend) |
||||
|
||||
//Color: Log #svg-color-log
|
||||
var svg = d3.select("#svg-color-log"); |
||||
var svg = d3.select("#svg-color-log") |
||||
|
||||
var log = d3.scale.log() |
||||
.domain([ 0.1, 100, 1000 ]) |
||||
.range(["rgb(46, 73, 123)", "rgb(71, 187, 94)"]); |
||||
var log = d3 |
||||
.scaleLog() |
||||
.domain([0.1, 100, 1000]) |
||||
.range(["rgb(46, 73, 123)", "rgb(71, 187, 94)"]) |
||||
|
||||
svg.append("g") |
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendLog") |
||||
.attr("transform", "translate(20,20)"); |
||||
.attr("transform", "translate(20,20)") |
||||
|
||||
var logLegend = d3.legend.color() |
||||
.cells([0.1, 5, 10, 50, 100, 500, 1000]) |
||||
.scale(log); |
||||
var logLegend = d3 |
||||
.legendColor() |
||||
.cells([0.1, 5, 10, 50, 100, 500, 1000]) |
||||
.scale(log) |
||||
|
||||
svg.select(".legendLog") |
||||
.call(logLegend); |
||||
svg.select(".legendLog").call(logLegend) |
||||
|
||||
//Color Linear #svg-color-linear
|
||||
var linear = d3.scale.linear().domain([0,10]).range(["rgb(46, 73, 123)", "rgb(71, 187, 94)"]); |
||||
var linear = d3 |
||||
.scaleLinear() |
||||
.domain([0, 10]) |
||||
.range(["rgb(46, 73, 123)", "rgb(71, 187, 94)"]) |
||||
|
||||
svg = d3.select("#svg-color-linear"); |
||||
svg = d3.select("#svg-color-linear") |
||||
|
||||
svg.append("g") |
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendLinear") |
||||
.attr("transform", "translate(20,20)"); |
||||
.attr("transform", "translate(20,20)") |
||||
|
||||
var legendLinear = d3.legend.color() |
||||
.shapeWidth(30) |
||||
.orient('horizontal') |
||||
.scale(linear); |
||||
var legendLinear = d3 |
||||
.legendColor() |
||||
.shapeWidth(30) |
||||
.orient("horizontal") |
||||
.scale(linear) |
||||
|
||||
//Color Linear #svg-color-linear-10
|
||||
svg.select(".legendLinear") |
||||
.call(legendLinear); |
||||
svg.select(".legendLinear").call(legendLinear) |
||||
|
||||
svg = d3.select("#svg-color-linear-10"); |
||||
svg = d3.select("#svg-color-linear-10") |
||||
|
||||
svg.append("g") |
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendLinear") |
||||
.attr("transform", "translate(20,20)"); |
||||
.attr("transform", "translate(20,20)") |
||||
|
||||
legendLinear.cells(10); |
||||
legendLinear.cells(10) |
||||
|
||||
svg.select(".legendLinear") |
||||
.call(legendLinear); |
||||
svg.select(".legendLinear").call(legendLinear) |
||||
|
||||
//Linear #svg-color-linear-custom
|
||||
svg.select(".legendLinear") |
||||
.call(legendLinear); |
||||
svg.select(".legendLinear").call(legendLinear) |
||||
|
||||
svg = d3.select("#svg-color-linear-custom"); |
||||
svg = d3.select("#svg-color-linear-custom") |
||||
|
||||
svg.append("g") |
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendLinear") |
||||
.attr("transform", "translate(20,20)"); |
||||
|
||||
legendLinear.cells([1, 2, 3, 6, 8]); |
||||
.attr("transform", "translate(20,20)") |
||||
|
||||
svg.select(".legendLinear") |
||||
.call(legendLinear); |
||||
legendLinear.cells([1, 2, 3, 6, 8]) |
||||
|
||||
svg.select(".legendLinear").call(legendLinear) |
||||
|
||||
//Ordinal #svg-color-ordinal
|
||||
var ordinal = d3.scale.ordinal() |
||||
var ordinal = d3 |
||||
.scaleOrdinal() |
||||
.domain(["a", "b", "c", "d", "e"]) |
||||
.range([ "rgb(153, 107, 195)", "rgb(56, 106, 197)", "rgb(93, 199, 76)", "rgb(223, 199, 31)", "rgb(234, 118, 47)"]); |
||||
.range([ |
||||
"rgb(153, 107, 195)", |
||||
"rgb(56, 106, 197)", |
||||
"rgb(93, 199, 76)", |
||||
"rgb(223, 199, 31)", |
||||
"rgb(234, 118, 47)" |
||||
]) |
||||
|
||||
svg = d3.select("#svg-color-ordinal") |
||||
|
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendOrdinal") |
||||
.attr("transform", "translate(20,20)") |
||||
|
||||
var legendOrdinal = d3 |
||||
.legendColor() |
||||
.shape( |
||||
"path", |
||||
d3 |
||||
.symbol() |
||||
.type(d3.symbolTriangle) |
||||
.size(150)() |
||||
) |
||||
.shapePadding(10) |
||||
.cellFilter(function(d) { |
||||
return d.label !== "e" |
||||
}) |
||||
.scale(ordinal) |
||||
|
||||
svg = d3.select("#svg-color-ordinal"); |
||||
svg.select(".legendOrdinal").call(legendOrdinal) |
||||
|
||||
svg.append("g") |
||||
.attr("class", "legendOrdinal") |
||||
.attr("transform", "translate(20,20)"); |
||||
var sequentialScale = d3.scaleSequential(d3.interpolateRainbow).domain([0, 10]) |
||||
svg = d3.select("#svg-color-sequential") |
||||
|
||||
var legendOrdinal = d3.legend.color() |
||||
.shape("path", d3.svg.symbol().type("triangle-up").size(150)()) |
||||
.shapePadding(10) |
||||
.scale(ordinal); |
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendSequential") |
||||
.attr("transform", "translate(20,20)") |
||||
|
||||
svg.select(".legendOrdinal") |
||||
.call(legendOrdinal); |
||||
var legendSequential = d3 |
||||
.legendColor() |
||||
.shapeWidth(30) |
||||
.cells(10) |
||||
.orient("horizontal") |
||||
.scale(sequentialScale) |
||||
|
||||
svg.select(".legendSequential").call(legendSequential) |
||||
|
||||
//Size: Linear Circle #svg-size-linear
|
||||
var linearSize = d3.scale.linear().domain([0,10]).range([10, 30]); |
||||
var linearSize = d3 |
||||
.scaleLinear() |
||||
.domain([0, 10]) |
||||
.range([10, 30]) |
||||
|
||||
svg = d3.select("#svg-size-linear"); |
||||
svg = d3.select("#svg-size-linear") |
||||
|
||||
svg.append("g") |
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendSize") |
||||
.attr("transform", "translate(20, 40)"); |
||||
|
||||
|
||||
var legendSize = d3.legend.size() |
||||
.scale(linearSize) |
||||
.shape('circle') |
||||
.shapePadding(15) |
||||
.labelOffset(20) |
||||
.orient('horizontal'); |
||||
.attr("transform", "translate(20, 40)") |
||||
|
||||
var legendSize = d3 |
||||
.legendSize() |
||||
.scale(linearSize) |
||||
.shape("circle") |
||||
.shapePadding(15) |
||||
.labelOffset(20) |
||||
.orient("horizontal") |
||||
.on("cellover", function() { |
||||
console.log("cellover", d3.event, d3.event.type) |
||||
}) |
||||
|
||||
svg.select(".legendSize") |
||||
.call(legendSize); |
||||
svg.select(".legendSize").call(legendSize) |
||||
|
||||
//Size: Linear Line #svg-size-line
|
||||
var lineSize = d3.scale.linear().domain([0,10]).range([2, 10]); |
||||
var lineSize = d3 |
||||
.scaleLinear() |
||||
.domain([0, 10]) |
||||
.range([2, 10]) |
||||
|
||||
svg = d3.select("#svg-size-line"); |
||||
svg = d3.select("#svg-size-line") |
||||
|
||||
svg.append("g") |
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendSizeLine") |
||||
.attr("transform", "translate(0, 20)"); |
||||
.attr("transform", "translate(0, 20)") |
||||
|
||||
var legendSizeLine = d3.legend.size() |
||||
.scale(lineSize) |
||||
.shape("line") |
||||
.orient("horizontal") |
||||
.labels(["tiny", "small", "medium", "large", "grand"]) |
||||
.shapeWidth(50) |
||||
.labelAlign("start") |
||||
.shapePadding(10); |
||||
var legendSizeLine = d3 |
||||
.legendSize() |
||||
.scale(lineSize) |
||||
.shape("line") |
||||
.orient("horizontal") |
||||
.labels([ |
||||
"tiny testing at the beginning", |
||||
"small", |
||||
"medium", |
||||
"large", |
||||
"grand, all the way long label" |
||||
]) |
||||
.labelWrap(30) |
||||
.shapeWidth(50) |
||||
.labelAlign("start") |
||||
.shapePadding(10) |
||||
|
||||
svg.select(".legendSizeLine") |
||||
.call(legendSizeLine); |
||||
svg.select(".legendSizeLine").call(legendSizeLine) |
||||
|
||||
//Symbol: Ordinal #svg-symbol-ordinal
|
||||
svg = d3.select("#svg-symbol-ordinal"); |
||||
svg = d3.select("#svg-symbol-ordinal") |
||||
|
||||
svg.append("g") |
||||
svg |
||||
.append("g") |
||||
.attr("class", "legendSymbol") |
||||
.attr("transform", "translate(20, 20)"); |
||||
.attr("transform", "translate(20, 20)") |
||||
|
||||
var triangleU = d3.svg.symbol().type('triangle-up')(), |
||||
circle = d3.svg.symbol().type('circle')(), |
||||
cross = d3.svg.symbol().type('cross')(), |
||||
diamond = d3.svg.symbol().type('diamond')(), |
||||
triangleD = d3.svg.symbol().type('triangle-down')(); |
||||
var triangleU = d3.symbol().type(d3.symbolTriangle)(), |
||||
circle = d3.symbol().type(d3.symbolCircle)(), |
||||
cross = d3.symbol().type(d3.symbolCross)(), |
||||
diamond = d3.symbol().type(d3.symbolDiamond)(), |
||||
star = d3.symbol().type(d3.symbolStar)() |
||||
|
||||
//example output of d3.svg.symbol().type('circle')();
|
||||
//"M0,4.51351666838205A4.51351666838205,4.51351666838205 0 1,1 0,
|
||||
//-4.51351666838205A4.51351666838205,4.51351666838205 0 1,1 0,4.51351666838205Z"
|
||||
|
||||
var symbolScale = d3.scale.ordinal() |
||||
.domain(['a','b','c', 'd', 'e']) |
||||
.range([ triangleU, circle, cross, diamond, triangleD] ); |
||||
var symbolScale = d3 |
||||
.scaleOrdinal() |
||||
.domain(["a longer label", "b", "c", "d", "e"]) |
||||
.range([triangleU, circle, cross, diamond, star]) |
||||
|
||||
var legendPath = d3.legend.symbol() |
||||
var legendPath = d3 |
||||
.legendSymbol() |
||||
.scale(symbolScale) |
||||
.orient("horizontal") |
||||
.title('Symbol Legend Title') |
||||
.on("cellclick", function(d){alert("clicked " + d);}); |
||||
|
||||
svg.select(".legendSymbol") |
||||
.call(legendPath); |
||||
//.orient("horizontal")
|
||||
.labelWrap(30) |
||||
.title("Symbol Legend Title") |
||||
.on("cellclick", function(d) { |
||||
alert("clicked " + d) |
||||
}) |
||||
|
||||
svg.select(".legendSymbol").call(legendPath) |
||||
|
@ -1,63 +1,93 @@ |
||||
d3.legend.**size()** |
||||
d3.**legendSize()** |
||||
|
||||
Constructs a new size legend. The legend component expects a d3 scale as the basic input, but also has a number of optional parameters for changing the default display such as vertical or horizontal orientation, shape of the symbol next to the label, symbol sizing, and label formatting. |
||||
|
||||
size.**scale(d3.scale)** |
||||
legendSize.**scale(d3.scale)** |
||||
|
||||
Creates a new d3 legend based on the scale. The code determines the type of scale and generates the different symbol and label pairs. Expects a scale that has a numerical range. |
||||
|
||||
size.**cells(number or [numbers])** |
||||
legendSize.**cells(number or [numbers])** |
||||
|
||||
This parameter is only valid for continuous scales (like linear and log). When there is no indication from the domain or range for the number of steps in the legend you may want to display, it defaults to five steps in equal increments. You can pass the cells function a single number which will create equal increments for that number of steps, or an array of the [specific steps](#color-linear-custom) you want the legend to display. |
||||
|
||||
size.**orient(string)** |
||||
legendSize.**cellFilter(function)** |
||||
|
||||
This function is run as a filter function against the array of cells. If you have a function(d){ return true or false }, d has a .data and a .label property as it iterates over each cell it will display. Create a false condition for any cells you want to exclude from being displayed. An example: [Color - Ordinal Scale Legend, custom shape](#color-ordinal). |
||||
|
||||
legendSize.**orient(string)** |
||||
|
||||
Accepts "vertical" or "horizontal" for legend orientation. Default set to "vertical." |
||||
|
||||
size.**ascending(boolean)** |
||||
legendSize.**ascending(boolean)** |
||||
|
||||
If you pass this a true, it will reverse the order of the scale. |
||||
|
||||
size.**shape(string)** |
||||
legendSize.**shape(string)** |
||||
|
||||
Accepts "rect", "circle", or "line". Defaults to "rect." The assumption is that the scale's output will be used for the width and height if you select "rect," the radius if you select "circle," and the stroke-width if you select "line." If you want to have a custom shape of different sizes in your legend, use the symbol legend and make each path string for the sizes you want as the range array. |
||||
|
||||
size.**shapeWidth(number)** |
||||
legendSize.**shapeWidth(number)** |
||||
|
||||
Only applies to shape "line." Default set to 15px. |
||||
|
||||
size.**shapePadding(number)** |
||||
legendSize.**shapePadding(number)** |
||||
|
||||
Applies to all shapes. Determines vertical or horizontal spacing between shapes depending on the respective orient setting. Default set to 2px. |
||||
|
||||
size.**classPrefix(string)** |
||||
legendSize.**classPrefix(string)** |
||||
|
||||
Adds this string to the beginning of all of the components of the legend that have a class. This allows for namespacing of the classes. |
||||
|
||||
size.**title(string)** |
||||
legendSize.**title(string)** |
||||
|
||||
Sets the legend's title to the string. Automatically moves the legend cells down based on the size of the title. An example: [Symbol - Ordinal Scale](#symbol-ordinal). |
||||
|
||||
size.**labels([string])** |
||||
legendSize.**titleWidth(number)** |
||||
|
||||
Will break the legend title into multiple lines based on the width in pixels. An example: [Color - Quantile Scale Legend](#color-quant). |
||||
|
||||
legendSize.**labels([string] or function(options))** |
||||
|
||||
Passing a string: |
||||
Sets the legend labels to the array of strings passed to the legend. If the array is not the same length as the array the legend calculates, it merges the values and gives the calculated labels for the remaining items. An example: [Size - Linear Scale Legend, Lines](#size-line). |
||||
|
||||
Passing a function: |
||||
This function is called for each generated label and gives you the options: |
||||
- i: current index |
||||
- genLength: total length of generated labels |
||||
- generatedLabels: array of generated labels |
||||
- domain: array from input scale |
||||
- range: array from input scale |
||||
This allows you to make any custom functions to handle labels. An example: [Color - Threshold Scale, Custom Labels](#color-threshold) |
||||
|
||||
Sets the legend labels to the array of strings passed to the legend. If the array is not the same length as the array the legend calculates, it merges the values and gives the calculated labels for the remaining items. An example: [Size - Linear Scale Legend, Lines](#size-line) |
||||
List of [helper functions](#helpers). |
||||
|
||||
size.**labelAlign(string)** |
||||
|
||||
legendSize.**labelAlign(string)** |
||||
|
||||
Only used if the legend's orient is set to "horizontal." Accepts "start", "middle", or "end" as inputs to determine if the labels are aligned on the left, middle or right under the symbol in a horizontal legend. An example: [Size - Linear Scale Legend, Lines](#size-line). |
||||
|
||||
size.**labelFormat(d3.format)** |
||||
legendSize.**labelFormat(d3.format or d3.format string)** |
||||
|
||||
|
||||
Takes a [d3.format](https://github.com/mbostock/d3/wiki/Formatting) and applies that styling to the legend labels. Default is set to `d3.format(".01f")`. |
||||
|
||||
size.**labelOffset(number)** |
||||
legendSize.**locale(d3.format locale)** |
||||
|
||||
Takes a [d3.format locale](https://github.com/d3/d3-format/tree/master/locale) and applies it to the legend labels. Default is set to [US english](https://github.com/d3/d3-format/blob/master/locale/en-US.json). |
||||
|
||||
legendSize.**labelOffset(number)** |
||||
|
||||
A value that determines how far the label is from the symbol in each legend item. Default set to 10px. |
||||
|
||||
size.**labelDelimiter(string)** |
||||
legendSize.**labelDelimiter(string)** |
||||
|
||||
Change the default "to" text when working with a quant scale. |
||||
|
||||
size.**on(string, function)** |
||||
legendColor.**labelWrap(number)** |
||||
|
||||
Add text wrapping to the cell labels. In orient horizontal you can use this in combination with shapePadding to get the desired spacing. An exampe: [Size - Linear Scale](#size-line). In orient vertical this will automatically scale the cells to fit the label.An example: [Symbol - Ordinal Scale](#symbol-ordinal) |
||||
|
||||
legendSize.**on(string, function)** |
||||
|
||||
There are three custom event types you can bind to the legend: "cellover", "cellout", and "cellclick" An exampe: [Symbol - Ordinal Scale](#symbol-ordinal) |
||||
|
@ -1,55 +1,83 @@ |
||||
d3.legend.**symbol()** |
||||
d3.**legendSymbol()** |
||||
|
||||
Constructs a new symbol legend. The legend component expects a d3 scale as the basic input, but also has a number of optional parameters for changing the default display such as vertical or horizontal orientation, shape of the symbol next to the label, symbol sizing, and label formatting. |
||||
|
||||
symbol.**scale()** |
||||
legendSymbol.**scale()** |
||||
|
||||
Creates a new d3 legend based on the scale. The code determines the type of scale and generates the different symbol and label pairs. The scale's range will be used as the d-attribute in an svg path for each symbol in the legend. |
||||
|
||||
symbol.**cells()** |
||||
legendSymbol.**cells()** |
||||
|
||||
This parameter is only valid for continuous scales (like linear and log). When there is no indication from the domain or range for the number of steps in the legend you may want to display, it defaults to five steps in equal increments. You can pass the cells function a single number which will create equal increments for that number of steps, or an array of the [specific steps](#color-linear-custom) you want the legend to display. |
||||
|
||||
symbol.**orient(string)** |
||||
legendSymbol.**cellFilter(function)** |
||||
|
||||
This function is run as a filter function against the array of cells. If you have a function(d){ return true or false }, d has a .data and a .label property as it iterates over each cell it will display. Create a false condition for any cells you want to exclude from being displayed. An example: [Color - Ordinal Scale Legend, custom shape](#color-ordinal). |
||||
|
||||
legendSymbol.**orient(string)** |
||||
|
||||
Accepts "vertical" or "horizontal" for legend orientation. Default set to "vertical." |
||||
|
||||
symbol.**ascending(boolean)** |
||||
legendSymbol.**ascending(boolean)** |
||||
|
||||
If you pass this a true, it will reverse the order of the scale. |
||||
|
||||
symbol.**shapePadding()** |
||||
legendSymbol.**shapePadding()** |
||||
|
||||
Applies to all shapes. Determines vertical or horizontal spacing between shapes depending on the respective orient setting. Default set to 2px. |
||||
|
||||
symbol.**classPrefix(string)** |
||||
legendSymbol.**classPrefix(string)** |
||||
|
||||
Adds this string to the beginning of all of the components of the legend that have a class. This allows for namespacing of the classes. |
||||
|
||||
symbol.**title(string)** |
||||
legendSymbol.**title(string)** |
||||
|
||||
Sets the legend's title to the string. Automatically moves the legend cells down based on the size of the title. An example: [Symbol - Ordinal Scale](#symbol-ordinal). |
||||
|
||||
symbol.**labels([string])** |
||||
legendSymbol.**titleWidth(number)** |
||||
|
||||
Will break the legend title into multiple lines based on the width in pixels. An example: [Color - Quantile Scale Legend](#color-quant). |
||||
|
||||
legendSymbol.**labels([string] or function(options))** |
||||
|
||||
Passing a string: |
||||
Sets the legend labels to the array of strings passed to the legend. If the array is not the same length as the array the legend calculates, it merges the values and gives the calculated labels for the remaining items. An example: [Size - Linear Scale Legend, Lines](#size-line). |
||||
|
||||
symbol.**labelAlign(string)** |
||||
Passing a function: |
||||
This function is called for each generated label and gives you the options: |
||||
- i: current index |
||||
- genLength: total length of generated labels |
||||
- generatedLabels: array of generated labels |
||||
- domain: array from input scale |
||||
- range: array from input scale |
||||
This allows you to make any custom functions to handle labels. An example: [Color - Threshold Scale, Custom Labels](#color-threshold) |
||||
|
||||
List of [helper functions](#helpers). |
||||
|
||||
legendSymbol.**labelAlign(string)** |
||||
|
||||
Only used if the legend's orient is set to "horizontal." Accepts "start", "middle", or "end" as inputs to determine if the labels are aligned on the left, middle or right under the symbol in a horizontal legend. An example: [Size - Linear Scale Legend, Lines](#size-line). |
||||
|
||||
symbol.**labelFormat(d3.format)** |
||||
legendSymbol.**labelFormat(d3.format or d3.format string)** |
||||
|
||||
Takes a [d3.format](https://github.com/mbostock/d3/wiki/Formatting) and applies that styling to the legend labels. Default is set to `d3.format(".01f")`. |
||||
|
||||
symbol.**labelOffset(number)** |
||||
legendSymbol.**locale(d3.format locale)** |
||||
|
||||
Takes a [d3.format locale](https://github.com/d3/d3-format/tree/master/locale) and applies it to the legend labels. Default is set to [US english](https://github.com/d3/d3-format/blob/master/locale/en-US.json). |
||||
|
||||
legendSymbol.**labelOffset(number)** |
||||
|
||||
A value that determines how far the label is from the symbol in each legend item. Default set to 10px. |
||||
|
||||
symbol.**labelDelimiter(string)** |
||||
legendSymbol.**labelDelimiter(string)** |
||||
|
||||
Change the default "to" text when working with a quant scale. |
||||
|
||||
symbol.**on(string, function)** |
||||
legendColor.**labelWrap(number)** |
||||
|
||||
Add text wrapping to the cell labels. In orient horizontal you can use this in combination with shapePadding to get the desired spacing. An exampe: [Size - Linear Scale](#size-line). In orient vertical this will automatically scale the cells to fit the label.An example: [Symbol - Ordinal Scale](#symbol-ordinal) |
||||
|
||||
legendSymbol.**on(string, function)** |
||||
|
||||
There are three custom event types you can bind to the legend: "cellover", "cellout", and "cellclick" An exampe: [Symbol - Ordinal Scale](#symbol-ordinal) |
||||
|
@ -1,5 +1,13 @@ |
||||
var d3 = require('d3'); |
||||
import legendColor from './src/color' |
||||
import legendSize from './src/size' |
||||
import legendSymbol from './src/symbol' |
||||
import legendHelpers from './src/helpers' |
||||
|
||||
d3.legend = require('./no-extend'); |
||||
export { legendColor, legendSize, legendSymbol, legendHelpers } |
||||
|
||||
module.exports = d3; |
||||
export default { |
||||
legendColor, |
||||
legendSize, |
||||
legendSymbol, |
||||
legendHelpers |
||||
}; |
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@ |
||||
import babel from 'rollup-plugin-babel'; |
||||
import babelrc from 'babelrc-rollup'; |
||||
|
||||
let pkg = require('./package.json'); |
||||
let external = Object.keys(pkg.dependencies); |
||||
|
||||
export default { |
||||
entry: 'index.js', |
||||
plugins: [ |
||||
babel(babelrc()) |
||||
], |
||||
external: external, |
||||
targets: [ |
||||
{ |
||||
dest: pkg['main'], |
||||
format: 'umd', |
||||
moduleName: 'indexRollup', |
||||
sourceMap: true |
||||
}, |
||||
{ |
||||
dest: pkg['jsnext:main'], |
||||
format: 'es', |
||||
sourceMap: true |
||||
} |
||||
] |
||||
}; |
@ -1,206 +1,308 @@ |
||||
var helper = require('./legend'); |
||||
import helper from "./legend" |
||||
import { dispatch } from "d3-dispatch" |
||||
import { scaleLinear } from "d3-scale" |
||||
import { formatLocale, formatSpecifier } from "d3-format" |
||||
|
||||
module.exports = function(){ |
||||
import { sum } from "d3-array" |
||||
|
||||
var scale = d3.scale.linear(), |
||||
export default function color() { |
||||
let scale = scaleLinear(), |
||||
shape = "rect", |
||||
shapeWidth = 15, |
||||
shapeHeight = 15, |
||||
shapeRadius = 10, |
||||
shapePadding = 2, |
||||
cells = [5], |
||||
cellFilter, |
||||
labels = [], |
||||
classPrefix = "", |
||||
useClass = false, |
||||
title = "", |
||||
labelFormat = d3.format(".01f"), |
||||
locale = helper.d3_defaultLocale, |
||||
specifier = helper.d3_defaultFormatSpecifier, |
||||
labelOffset = 10, |
||||
labelAlign = "middle", |
||||
labelDelimiter = "to", |
||||
labelDelimiter = helper.d3_defaultDelimiter, |
||||
labelWrap, |
||||
orient = "vertical", |
||||
ascending = false, |
||||
path, |
||||
legendDispatcher = d3.dispatch("cellover", "cellout", "cellclick"); |
||||
|
||||
function legend(svg){ |
||||
|
||||
var type = helper.d3_calcType(scale, ascending, cells, labels, labelFormat, labelDelimiter), |
||||
legendG = svg.selectAll('g').data([scale]); |
||||
|
||||
legendG.enter().append('g').attr('class', classPrefix + 'legendCells'); |
||||
|
||||
|
||||
var cell = legendG.selectAll("." + classPrefix + "cell").data(type.data), |
||||
cellEnter = cell.enter().append("g", ".cell").attr("class", classPrefix + "cell").style("opacity", 1e-6), |
||||
shapeEnter = cellEnter.append(shape).attr("class", classPrefix + "swatch"), |
||||
shapes = cell.select("g." + classPrefix + "cell " + shape); |
||||
|
||||
//add event handlers
|
||||
helper.d3_addEvents(cellEnter, legendDispatcher); |
||||
|
||||
cell.exit().transition().style("opacity", 0).remove(); |
||||
|
||||
helper.d3_drawShapes(shape, shapes, shapeHeight, shapeWidth, shapeRadius, path); |
||||
|
||||
helper.d3_addText(legendG, cellEnter, type.labels, classPrefix) |
||||
|
||||
// sets placement
|
||||
var text = cell.select("text"), |
||||
shapeSize = shapes[0].map( function(d){ return d.getBBox(); }); |
||||
titleWidth, |
||||
legendDispatcher = dispatch("cellover", "cellout", "cellclick") |
||||
|
||||
function legend(svg) { |
||||
const type = helper.d3_calcType( |
||||
scale, |
||||
ascending, |
||||
cells, |
||||
labels, |
||||
locale.format(specifier), |
||||
labelDelimiter |
||||
), |
||||
legendG = svg.selectAll("g").data([scale]) |
||||
|
||||
legendG |
||||
.enter() |
||||
.append("g") |
||||
.attr("class", classPrefix + "legendCells") |
||||
|
||||
if (cellFilter) { |
||||
helper.d3_filterCells(type, cellFilter) |
||||
} |
||||
|
||||
//sets scale
|
||||
//everything is fill except for line which is stroke,
|
||||
if (!useClass){ |
||||
if (shape == "line"){ |
||||
shapes.style("stroke", type.feature); |
||||
} else { |
||||
shapes.style("fill", type.feature); |
||||
} |
||||
let cell = svg |
||||
.select("." + classPrefix + "legendCells") |
||||
.selectAll("." + classPrefix + "cell") |
||||
.data(type.data) |
||||
|
||||
const cellEnter = cell |
||||
.enter() |
||||
.append("g") |
||||
.attr("class", classPrefix + "cell") |
||||
cellEnter.append(shape).attr("class", classPrefix + "swatch") |
||||
|
||||
let shapes = svg |
||||
.selectAll( |
||||
"g." + classPrefix + "cell " + shape + "." + classPrefix + "swatch" |
||||
) |
||||
.data(type.data) |
||||
|
||||
//add event handlers
|
||||
helper.d3_addEvents(cellEnter, legendDispatcher) |
||||
|
||||
cell |
||||
.exit() |
||||
.transition() |
||||
.style("opacity", 0) |
||||
.remove() |
||||
shapes |
||||
.exit() |
||||
.transition() |
||||
.style("opacity", 0) |
||||
.remove() |
||||
|
||||
shapes = shapes.merge(shapes) |
||||
|
||||
helper.d3_drawShapes( |
||||
shape, |
||||
shapes, |
||||
shapeHeight, |
||||
shapeWidth, |
||||
shapeRadius, |
||||
path |
||||
) |
||||
const text = helper.d3_addText( |
||||
svg, |
||||
cellEnter, |
||||
type.labels, |
||||
classPrefix, |
||||
labelWrap |
||||
) |
||||
|
||||
// we need to merge the selection, otherwise changes in the legend (e.g. change of orientation) are applied only to the new cells and not the existing ones.
|
||||
cell = cellEnter.merge(cell) |
||||
|
||||
// sets placement
|
||||
const textSize = text.nodes().map(d => d.getBBox()), |
||||
shapeSize = shapes.nodes().map(d => d.getBBox()) |
||||
//sets scale
|
||||
//everything is fill except for line which is stroke,
|
||||
if (!useClass) { |
||||
if (shape == "line") { |
||||
shapes.style("stroke", type.feature) |
||||
} else { |
||||
shapes.attr("class", function(d){ return classPrefix + "swatch " + type.feature(d); }); |
||||
shapes.style("fill", type.feature) |
||||
} |
||||
} else { |
||||
shapes.attr("class", d => `${classPrefix}swatch ${type.feature(d)}`) |
||||
} |
||||
|
||||
var cellTrans, |
||||
let cellTrans, |
||||
textTrans, |
||||
textAlign = (labelAlign == "start") ? 0 : (labelAlign == "middle") ? 0.5 : 1; |
||||
|
||||
//positions cells and text
|
||||
if (orient === "vertical"){ |
||||
cellTrans = function(d,i) { return "translate(0, " + (i * (shapeSize[i].height + shapePadding)) + ")"; }; |
||||
textTrans = function(d,i) { return "translate(" + (shapeSize[i].width + shapeSize[i].x + |
||||
labelOffset) + "," + (shapeSize[i].y + shapeSize[i].height/2 + 5) + ")"; }; |
||||
|
||||
} else if (orient === "horizontal"){ |
||||
cellTrans = function(d,i) { return "translate(" + (i * (shapeSize[i].width + shapePadding)) + ",0)"; } |
||||
textTrans = function(d,i) { return "translate(" + (shapeSize[i].width*textAlign + shapeSize[i].x) + |
||||
"," + (shapeSize[i].height + shapeSize[i].y + labelOffset + 8) + ")"; }; |
||||
} |
||||
textAlign = labelAlign == "start" ? 0 : labelAlign == "middle" ? 0.5 : 1 |
||||
|
||||
helper.d3_placement(orient, cell, cellTrans, text, textTrans, labelAlign); |
||||
helper.d3_title(svg, legendG, title, classPrefix); |
||||
//positions cells and text
|
||||
if (orient === "vertical") { |
||||
const cellSize = textSize.map((d, i) => |
||||
Math.max(d.height, shapeSize[i].height) |
||||
) |
||||
|
||||
cell.transition().style("opacity", 1); |
||||
cellTrans = (d, i) => { |
||||
const height = sum(cellSize.slice(0, i)) |
||||
return `translate(0, ${height + i * shapePadding})` |
||||
} |
||||
|
||||
textTrans = (d, i) => |
||||
`translate( ${shapeSize[i].width + |
||||
shapeSize[i].x + |
||||
labelOffset}, ${shapeSize[i].y + shapeSize[i].height / 2 + 5})` |
||||
} else if (orient === "horizontal") { |
||||
cellTrans = (d, i) => |
||||
`translate(${i * (shapeSize[i].width + shapePadding)},0)` |
||||
textTrans = (d, i) => `translate(${shapeSize[i].width * textAlign + |
||||
shapeSize[i].x}, |
||||
${shapeSize[i].height + shapeSize[i].y + labelOffset + 8})` |
||||
} |
||||
|
||||
helper.d3_placement(orient, cell, cellTrans, text, textTrans, labelAlign) |
||||
helper.d3_title(svg, title, classPrefix, titleWidth) |
||||
|
||||
cell.transition().style("opacity", 1) |
||||
} |
||||
|
||||
legend.scale = function(_) { |
||||
if (!arguments.length) return scale; |
||||
scale = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return scale |
||||
scale = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.cells = function(_) { |
||||
if (!arguments.length) return cells; |
||||
if (_.length > 1 || _ >= 2 ){ |
||||
cells = _; |
||||
if (!arguments.length) return cells |
||||
if (_.length > 1 || _ >= 2) { |
||||
cells = _ |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.cellFilter = function(_) { |
||||
if (!arguments.length) return cellFilter |
||||
cellFilter = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.shape = function(_, d) { |
||||
if (!arguments.length) return shape; |
||||
if (_ == "rect" || _ == "circle" || _ == "line" || (_ == "path" && (typeof d === 'string')) ){ |
||||
shape = _; |
||||
path = d; |
||||
if (!arguments.length) return shape |
||||
if ( |
||||
_ == "rect" || |
||||
_ == "circle" || |
||||
_ == "line" || |
||||
(_ == "path" && typeof d === "string") |
||||
) { |
||||
shape = _ |
||||
path = d |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.shapeWidth = function(_) { |
||||
if (!arguments.length) return shapeWidth; |
||||
shapeWidth = +_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return shapeWidth |
||||
shapeWidth = +_ |
||||
return legend |
||||
} |
||||
|
||||
legend.shapeHeight = function(_) { |
||||
if (!arguments.length) return shapeHeight; |
||||
shapeHeight = +_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return shapeHeight |
||||
shapeHeight = +_ |
||||
return legend |
||||
} |
||||
|
||||
legend.shapeRadius = function(_) { |
||||
if (!arguments.length) return shapeRadius; |
||||
shapeRadius = +_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return shapeRadius |
||||
shapeRadius = +_ |
||||
return legend |
||||
} |
||||
|
||||
legend.shapePadding = function(_) { |
||||
if (!arguments.length) return shapePadding; |
||||
shapePadding = +_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return shapePadding |
||||
shapePadding = +_ |
||||
return legend |
||||
} |
||||
|
||||
legend.labels = function(_) { |
||||
if (!arguments.length) return labels; |
||||
labels = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return labels |
||||
labels = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.labelAlign = function(_) { |
||||
if (!arguments.length) return labelAlign; |
||||
if (!arguments.length) return labelAlign |
||||
if (_ == "start" || _ == "end" || _ == "middle") { |
||||
labelAlign = _; |
||||
labelAlign = _ |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.locale = function(_) { |
||||
if (!arguments.length) return locale |
||||
locale = formatLocale(_) |
||||
return legend |
||||
} |
||||
|
||||
legend.labelFormat = function(_) { |
||||
if (!arguments.length) return labelFormat; |
||||
labelFormat = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return legend.locale().format(specifier) |
||||
specifier = formatSpecifier(_) |
||||
return legend |
||||
} |
||||
|
||||
legend.labelOffset = function(_) { |
||||
if (!arguments.length) return labelOffset; |
||||
labelOffset = +_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return labelOffset |
||||
labelOffset = +_ |
||||
return legend |
||||
} |
||||
|
||||
legend.labelDelimiter = function(_) { |
||||
if (!arguments.length) return labelDelimiter; |
||||
labelDelimiter = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return labelDelimiter |
||||
labelDelimiter = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.labelWrap = function(_) { |
||||
if (!arguments.length) return labelWrap |
||||
labelWrap = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.useClass = function(_) { |
||||
if (!arguments.length) return useClass; |
||||
if (_ === true || _ === false){ |
||||
useClass = _; |
||||
if (!arguments.length) return useClass |
||||
if (_ === true || _ === false) { |
||||
useClass = _ |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.orient = function(_){ |
||||
if (!arguments.length) return orient; |
||||
_ = _.toLowerCase(); |
||||
legend.orient = function(_) { |
||||
if (!arguments.length) return orient |
||||
_ = _.toLowerCase() |
||||
if (_ == "horizontal" || _ == "vertical") { |
||||
orient = _; |
||||
orient = _ |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.ascending = function(_) { |
||||
if (!arguments.length) return ascending; |
||||
ascending = !!_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return ascending |
||||
ascending = !!_ |
||||
return legend |
||||
} |
||||
|
||||
legend.classPrefix = function(_) { |
||||
if (!arguments.length) return classPrefix; |
||||
classPrefix = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return classPrefix |
||||
classPrefix = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.title = function(_) { |
||||
if (!arguments.length) return title; |
||||
title = _; |
||||
return legend; |
||||
}; |
||||
|
||||
d3.rebind(legend, legendDispatcher, "on"); |
||||
|
||||
return legend; |
||||
|
||||
}; |
||||
if (!arguments.length) return title |
||||
title = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.titleWidth = function(_) { |
||||
if (!arguments.length) return titleWidth |
||||
titleWidth = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.textWrap = function(_) { |
||||
if (!arguments.length) return textWrap |
||||
textWrap = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.on = function() { |
||||
const value = legendDispatcher.on.apply(legendDispatcher, arguments) |
||||
return value === legendDispatcher ? legend : value |
||||
} |
||||
|
||||
return legend |
||||
} |
||||
|
@ -0,0 +1,12 @@ |
||||
export const thresholdLabels = function({ i, genLength, generatedLabels }) { |
||||
if (i === 0) { |
||||
return generatedLabels[i].replace("NaN to", "Less than") |
||||
} else if (i === genLength - 1) { |
||||
return `${generatedLabels[genLength - 1].replace(" to NaN", "")} or more` |
||||
} |
||||
return generatedLabels[i] |
||||
} |
||||
|
||||
export default { |
||||
thresholdLabels |
||||
} |
@ -1,199 +1,286 @@ |
||||
var helper = require('./legend'); |
||||
|
||||
module.exports = function(){ |
||||
|
||||
var scale = d3.scale.linear(), |
||||
import helper from "./legend" |
||||
import { dispatch } from "d3-dispatch" |
||||
import { scaleLinear } from "d3-scale" |
||||
import { formatLocale, formatSpecifier } from "d3-format" |
||||
import { sum, max } from "d3-array" |
||||
|
||||
export default function size() { |
||||
let scale = scaleLinear(), |
||||
shape = "rect", |
||||
shapeWidth = 15, |
||||
shapePadding = 2, |
||||
cells = [5], |
||||
cellFilter, |
||||
labels = [], |
||||
useStroke = false, |
||||
classPrefix = "", |
||||
title = "", |
||||
labelFormat = d3.format(".01f"), |
||||
locale = helper.d3_defaultLocale, |
||||
specifier = helper.d3_defaultFormatSpecifier, |
||||
labelOffset = 10, |
||||
labelAlign = "middle", |
||||
labelDelimiter = "to", |
||||
labelDelimiter = helper.d3_defaultDelimiter, |
||||
labelWrap, |
||||
orient = "vertical", |
||||
ascending = false, |
||||
path, |
||||
legendDispatcher = d3.dispatch("cellover", "cellout", "cellclick"); |
||||
|
||||
function legend(svg){ |
||||
|
||||
var type = helper.d3_calcType(scale, ascending, cells, labels, labelFormat, labelDelimiter), |
||||
legendG = svg.selectAll('g').data([scale]); |
||||
|
||||
legendG.enter().append('g').attr('class', classPrefix + 'legendCells'); |
||||
|
||||
|
||||
var cell = legendG.selectAll("." + classPrefix + "cell").data(type.data), |
||||
cellEnter = cell.enter().append("g", ".cell").attr("class", classPrefix + "cell").style("opacity", 1e-6), |
||||
shapeEnter = cellEnter.append(shape).attr("class", classPrefix + "swatch"), |
||||
shapes = cell.select("g." + classPrefix + "cell " + shape); |
||||
|
||||
//add event handlers
|
||||
helper.d3_addEvents(cellEnter, legendDispatcher); |
||||
titleWidth, |
||||
legendDispatcher = dispatch("cellover", "cellout", "cellclick") |
||||
|
||||
function legend(svg) { |
||||
const type = helper.d3_calcType( |
||||
scale, |
||||
ascending, |
||||
cells, |
||||
labels, |
||||
locale.format(specifier), |
||||
labelDelimiter |
||||
), |
||||
legendG = svg.selectAll("g").data([scale]) |
||||
|
||||
if (cellFilter) { |
||||
helper.d3_filterCells(type, cellFilter) |
||||
} |
||||
|
||||
cell.exit().transition().style("opacity", 0).remove(); |
||||
legendG |
||||
.enter() |
||||
.append("g") |
||||
.attr("class", classPrefix + "legendCells") |
||||
|
||||
let cell = svg |
||||
.select("." + classPrefix + "legendCells") |
||||
.selectAll("." + classPrefix + "cell") |
||||
.data(type.data) |
||||
const cellEnter = cell |
||||
.enter() |
||||
.append("g") |
||||
.attr("class", classPrefix + "cell") |
||||
cellEnter.append(shape).attr("class", classPrefix + "swatch") |
||||
|
||||
let shapes = svg.selectAll( |
||||
"g." + classPrefix + "cell " + shape + "." + classPrefix + "swatch" |
||||
) |
||||
|
||||
//add event handlers
|
||||
helper.d3_addEvents(cellEnter, legendDispatcher) |
||||
|
||||
cell |
||||
.exit() |
||||
.transition() |
||||
.style("opacity", 0) |
||||
.remove() |
||||
|
||||
shapes |
||||
.exit() |
||||
.transition() |
||||
.style("opacity", 0) |
||||
.remove() |
||||
shapes = shapes.merge(shapes) |
||||
|
||||
//creates shape
|
||||
if (shape === "line") { |
||||
helper.d3_drawShapes(shape, shapes, 0, shapeWidth) |
||||
shapes.attr("stroke-width", type.feature) |
||||
} else { |
||||
helper.d3_drawShapes( |
||||
shape, |
||||
shapes, |
||||
type.feature, |
||||
type.feature, |
||||
type.feature, |
||||
path |
||||
) |
||||
} |
||||
|
||||
//creates shape
|
||||
if (shape === "line"){ |
||||
helper.d3_drawShapes(shape, shapes, 0, shapeWidth); |
||||
shapes.attr("stroke-width", type.feature); |
||||
} else { |
||||
helper.d3_drawShapes(shape, shapes, type.feature, type.feature, type.feature, path); |
||||
} |
||||
const text = helper.d3_addText( |
||||
svg, |
||||
cellEnter, |
||||
type.labels, |
||||
classPrefix, |
||||
labelWrap |
||||
) |
||||
|
||||
helper.d3_addText(legendG, cellEnter, type.labels, classPrefix) |
||||
// we need to merge the selection, otherwise changes in the legend (e.g. change of orientation) are applied only to the new cells and not the existing ones.
|
||||
cell = cellEnter.merge(cell) |
||||
|
||||
//sets placement
|
||||
var text = cell.select("text"), |
||||
shapeSize = shapes[0].map( |
||||
function(d, i){ |
||||
var bbox = d.getBBox() |
||||
var stroke = scale(type.data[i]); |
||||
//sets placement
|
||||
|
||||
if (shape === "line" && orient === "horizontal") { |
||||
bbox.height = bbox.height + stroke; |
||||
} else if (shape === "line" && orient === "vertical"){ |
||||
bbox.width = bbox.width; |
||||
} |
||||
const textSize = text.nodes().map(d => d.getBBox()), |
||||
shapeSize = shapes.nodes().map((d, i) => { |
||||
const bbox = d.getBBox() |
||||
const stroke = scale(type.data[i]) |
||||
|
||||
return bbox; |
||||
}); |
||||
if (shape === "line" && orient === "horizontal") { |
||||
bbox.height = bbox.height + stroke |
||||
} else if (shape === "line" && orient === "vertical") { |
||||
bbox.width = bbox.width |
||||
} |
||||
return bbox |
||||
}) |
||||
|
||||
var maxH = d3.max(shapeSize, function(d){ return d.height + d.y; }), |
||||
maxW = d3.max(shapeSize, function(d){ return d.width + d.x; }); |
||||
const maxH = max(shapeSize, d => d.height + d.y), |
||||
maxW = max(shapeSize, d => d.width + d.x) |
||||
|
||||
var cellTrans, |
||||
let cellTrans, |
||||
textTrans, |
||||
textAlign = (labelAlign == "start") ? 0 : (labelAlign == "middle") ? 0.5 : 1; |
||||
|
||||
//positions cells and text
|
||||
if (orient === "vertical"){ |
||||
|
||||
cellTrans = function(d,i) { |
||||
var height = d3.sum(shapeSize.slice(0, i + 1 ), function(d){ return d.height; }); |
||||
return "translate(0, " + (height + i*shapePadding) + ")"; }; |
||||
|
||||
textTrans = function(d,i) { return "translate(" + (maxW + labelOffset) + "," + |
||||
(shapeSize[i].y + shapeSize[i].height/2 + 5) + ")"; }; |
||||
textAlign = labelAlign == "start" ? 0 : labelAlign == "middle" ? 0.5 : 1 |
||||
|
||||
//positions cells and text
|
||||
if (orient === "vertical") { |
||||
const cellSize = textSize.map((d, i) => |
||||
Math.max(d.height, shapeSize[i].height) |
||||
) |
||||
const y = |
||||
shape == "circle" || shape == "line" ? shapeSize[0].height / 2 : 0 |
||||
cellTrans = (d, i) => { |
||||
const height = sum(cellSize.slice(0, i)) |
||||
|
||||
return `translate(0, ${y + height + i * shapePadding})` |
||||
} |
||||
|
||||
} else if (orient === "horizontal"){ |
||||
cellTrans = function(d,i) { |
||||
var width = d3.sum(shapeSize.slice(0, i + 1 ), function(d){ return d.width; }); |
||||
return "translate(" + (width + i*shapePadding) + ",0)"; }; |
||||
textTrans = (d, i) => `translate( ${maxW + labelOffset},
|
||||
${shapeSize[i].y + shapeSize[i].height / 2 + 5})` |
||||
} else if (orient === "horizontal") { |
||||
cellTrans = (d, i) => { |
||||
const width = sum(shapeSize.slice(0, i), d => d.width) |
||||
const y = shape == "circle" || shape == "line" ? maxH / 2 : 0 |
||||
return `translate(${width + i * shapePadding}, ${y})` |
||||
} |
||||
|
||||
textTrans = function(d,i) { return "translate(" + (shapeSize[i].width*textAlign + shapeSize[i].x) + "," + |
||||
(maxH + labelOffset ) + ")"; }; |
||||
const offset = shape == "line" ? maxH / 2 : maxH |
||||
textTrans = (d, i) => { |
||||
return `translate( ${shapeSize[i].width * textAlign + shapeSize[i].x},
|
||||
${offset + labelOffset})` |
||||
} |
||||
} |
||||
|
||||
helper.d3_placement(orient, cell, cellTrans, text, textTrans, labelAlign); |
||||
helper.d3_title(svg, legendG, title, classPrefix); |
||||
helper.d3_placement(orient, cell, cellTrans, text, textTrans, labelAlign) |
||||
helper.d3_title(svg, title, classPrefix, titleWidth) |
||||
|
||||
cell.transition().style("opacity", 1); |
||||
|
||||
} |
||||
cell.transition().style("opacity", 1) |
||||
} |
||||
|
||||
legend.scale = function(_) { |
||||
if (!arguments.length) return scale; |
||||
scale = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return scale |
||||
scale = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.cells = function(_) { |
||||
if (!arguments.length) return cells; |
||||
if (_.length > 1 || _ >= 2 ){ |
||||
cells = _; |
||||
if (!arguments.length) return cells |
||||
if (_.length > 1 || _ >= 2) { |
||||
cells = _ |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.cellFilter = function(_) { |
||||
if (!arguments.length) return cellFilter |
||||
cellFilter = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.shape = function(_, d) { |
||||
if (!arguments.length) return shape; |
||||
if (_ == "rect" || _ == "circle" || _ == "line" ){ |
||||
shape = _; |
||||
path = d; |
||||
if (!arguments.length) return shape |
||||
if (_ == "rect" || _ == "circle" || _ == "line") { |
||||
shape = _ |
||||
path = d |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.shapeWidth = function(_) { |
||||
if (!arguments.length) return shapeWidth; |
||||
shapeWidth = +_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return shapeWidth |
||||
shapeWidth = +_ |
||||
return legend |
||||
} |
||||
|
||||
legend.shapePadding = function(_) { |
||||
if (!arguments.length) return shapePadding; |
||||
shapePadding = +_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return shapePadding |
||||
shapePadding = +_ |
||||
return legend |
||||
} |
||||
|
||||
legend.labels = function(_) { |
||||
if (!arguments.length) return labels; |
||||
labels = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return labels |
||||
labels = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.labelAlign = function(_) { |
||||
if (!arguments.length) return labelAlign; |
||||
if (!arguments.length) return labelAlign |
||||
if (_ == "start" || _ == "end" || _ == "middle") { |
||||
labelAlign = _; |
||||
labelAlign = _ |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.locale = function(_) { |
||||
if (!arguments.length) return locale |
||||
locale = formatLocale(_) |
||||
return legend |
||||
} |
||||
|
||||
legend.labelFormat = function(_) { |
||||
if (!arguments.length) return labelFormat; |
||||
labelFormat = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return legend.locale().format(specifier) |
||||
specifier = formatSpecifier(_) |
||||
return legend |
||||
} |
||||
|
||||
legend.labelOffset = function(_) { |
||||
if (!arguments.length) return labelOffset; |
||||
labelOffset = +_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return labelOffset |
||||
labelOffset = +_ |
||||
return legend |
||||
} |
||||
|
||||
legend.labelDelimiter = function(_) { |
||||
if (!arguments.length) return labelDelimiter; |
||||
labelDelimiter = _; |
||||
return legend; |
||||
}; |
||||
|
||||
legend.orient = function(_){ |
||||
if (!arguments.length) return orient; |
||||
_ = _.toLowerCase(); |
||||
if (!arguments.length) return labelDelimiter |
||||
labelDelimiter = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.labelWrap = function(_) { |
||||
if (!arguments.length) return labelWrap |
||||
labelWrap = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.orient = function(_) { |
||||
if (!arguments.length) return orient |
||||
_ = _.toLowerCase() |
||||
if (_ == "horizontal" || _ == "vertical") { |
||||
orient = _; |
||||
orient = _ |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.ascending = function(_) { |
||||
if (!arguments.length) return ascending; |
||||
ascending = !!_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return ascending |
||||
ascending = !!_ |
||||
return legend |
||||
} |
||||
|
||||
legend.classPrefix = function(_) { |
||||
if (!arguments.length) return classPrefix; |
||||
classPrefix = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return classPrefix |
||||
classPrefix = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.title = function(_) { |
||||
if (!arguments.length) return title; |
||||
title = _; |
||||
return legend; |
||||
}; |
||||
|
||||
d3.rebind(legend, legendDispatcher, "on"); |
||||
|
||||
return legend; |
||||
|
||||
}; |
||||
if (!arguments.length) return title |
||||
title = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.titleWidth = function(_) { |
||||
if (!arguments.length) return titleWidth |
||||
titleWidth = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.on = function() { |
||||
const value = legendDispatcher.on.apply(legendDispatcher, arguments) |
||||
return value === legendDispatcher ? legend : value |
||||
} |
||||
|
||||
return legend |
||||
} |
||||
|
@ -1,158 +1,239 @@ |
||||
var helper = require('./legend'); |
||||
|
||||
module.exports = function(){ |
||||
|
||||
var scale = d3.scale.linear(), |
||||
import helper from "./legend" |
||||
import { dispatch } from "d3-dispatch" |
||||
import { scaleLinear } from "d3-scale" |
||||
import { formatLocale, formatSpecifier } from "d3-format" |
||||
import { sum, max } from "d3-array" |
||||
|
||||
export default function symbol() { |
||||
let scale = scaleLinear(), |
||||
shape = "path", |
||||
shapeWidth = 15, |
||||
shapeHeight = 15, |
||||
shapeRadius = 10, |
||||
shapePadding = 5, |
||||
cells = [5], |
||||
cellFilter, |
||||
labels = [], |
||||
classPrefix = "", |
||||
useClass = false, |
||||
title = "", |
||||
labelFormat = d3.format(".01f"), |
||||
locale = helper.d3_defaultLocale, |
||||
specifier = helper.d3_defaultFormatSpecifier, |
||||
labelAlign = "middle", |
||||
labelOffset = 10, |
||||
labelDelimiter = "to", |
||||
labelDelimiter = helper.d3_defaultDelimiter, |
||||
labelWrap, |
||||
orient = "vertical", |
||||
ascending = false, |
||||
legendDispatcher = d3.dispatch("cellover", "cellout", "cellclick"); |
||||
|
||||
function legend(svg){ |
||||
|
||||
var type = helper.d3_calcType(scale, ascending, cells, labels, labelFormat, labelDelimiter), |
||||
legendG = svg.selectAll('g').data([scale]); |
||||
|
||||
legendG.enter().append('g').attr('class', classPrefix + 'legendCells'); |
||||
|
||||
var cell = legendG.selectAll("." + classPrefix + "cell").data(type.data), |
||||
cellEnter = cell.enter().append("g", ".cell").attr("class", classPrefix + "cell").style("opacity", 1e-6), |
||||
shapeEnter = cellEnter.append(shape).attr("class", classPrefix + "swatch"), |
||||
shapes = cell.select("g." + classPrefix + "cell " + shape); |
||||
|
||||
//add event handlers
|
||||
helper.d3_addEvents(cellEnter, legendDispatcher); |
||||
|
||||
//remove old shapes
|
||||
cell.exit().transition().style("opacity", 0).remove(); |
||||
|
||||
helper.d3_drawShapes(shape, shapes, shapeHeight, shapeWidth, shapeRadius, type.feature); |
||||
helper.d3_addText(legendG, cellEnter, type.labels, classPrefix) |
||||
|
||||
// sets placement
|
||||
var text = cell.select("text"), |
||||
shapeSize = shapes[0].map( function(d){ return d.getBBox(); }); |
||||
|
||||
var maxH = d3.max(shapeSize, function(d){ return d.height; }), |
||||
maxW = d3.max(shapeSize, function(d){ return d.width; }); |
||||
titleWidth, |
||||
legendDispatcher = dispatch("cellover", "cellout", "cellclick") |
||||
|
||||
function legend(svg) { |
||||
const type = helper.d3_calcType( |
||||
scale, |
||||
ascending, |
||||
cells, |
||||
labels, |
||||
locale.format(specifier), |
||||
labelDelimiter |
||||
), |
||||
legendG = svg.selectAll("g").data([scale]) |
||||
|
||||
if (cellFilter) { |
||||
helper.d3_filterCells(type, cellFilter) |
||||
} |
||||
|
||||
var cellTrans, |
||||
legendG |
||||
.enter() |
||||
.append("g") |
||||
.attr("class", classPrefix + "legendCells") |
||||
|
||||
let cell = svg |
||||
.select("." + classPrefix + "legendCells") |
||||
.selectAll("." + classPrefix + "cell") |
||||
.data(type.data) |
||||
const cellEnter = cell |
||||
.enter() |
||||
.append("g") |
||||
.attr("class", classPrefix + "cell") |
||||
cellEnter.append(shape).attr("class", classPrefix + "swatch") |
||||
|
||||
let shapes = svg.selectAll("g." + classPrefix + "cell " + shape + "." + classPrefix + "swatch") |
||||
|
||||
//add event handlers
|
||||
helper.d3_addEvents(cellEnter, legendDispatcher) |
||||
|
||||
//remove old shapes
|
||||
cell |
||||
.exit() |
||||
.transition() |
||||
.style("opacity", 0) |
||||
.remove() |
||||
shapes |
||||
.exit() |
||||
.transition() |
||||
.style("opacity", 0) |
||||
.remove() |
||||
shapes = shapes.merge(shapes) |
||||
|
||||
helper.d3_drawShapes( |
||||
shape, |
||||
shapes, |
||||
shapeHeight, |
||||
shapeWidth, |
||||
shapeRadius, |
||||
type.feature |
||||
) |
||||
const text = helper.d3_addText( |
||||
svg, |
||||
cellEnter, |
||||
type.labels, |
||||
classPrefix, |
||||
labelWrap |
||||
) |
||||
|
||||
// we need to merge the selection, otherwise changes in the legend (e.g. change of orientation) are applied only to the new cells and not the existing ones.
|
||||
cell = cellEnter.merge(cell) |
||||
|
||||
// sets placement
|
||||
const textSize = text.nodes().map(d => d.getBBox()), |
||||
shapeSize = shapes.nodes().map(d => d.getBBox()) |
||||
|
||||
const maxH = max(shapeSize, d => d.height), |
||||
maxW = max(shapeSize, d => d.width) |
||||
|
||||
let cellTrans, |
||||
textTrans, |
||||
textAlign = (labelAlign == "start") ? 0 : (labelAlign == "middle") ? 0.5 : 1; |
||||
|
||||
//positions cells and text
|
||||
if (orient === "vertical"){ |
||||
cellTrans = function(d,i) { return "translate(0, " + (i * (maxH + shapePadding)) + ")"; }; |
||||
textTrans = function(d,i) { return "translate(" + (maxW + labelOffset) + "," + |
||||
(shapeSize[i].y + shapeSize[i].height/2 + 5) + ")"; }; |
||||
|
||||
} else if (orient === "horizontal"){ |
||||
cellTrans = function(d,i) { return "translate(" + (i * (maxW + shapePadding)) + ",0)"; }; |
||||
textTrans = function(d,i) { return "translate(" + (shapeSize[i].width*textAlign + shapeSize[i].x) + "," + |
||||
(maxH + labelOffset ) + ")"; }; |
||||
} |
||||
textAlign = labelAlign == "start" ? 0 : labelAlign == "middle" ? 0.5 : 1 |
||||
|
||||
helper.d3_placement(orient, cell, cellTrans, text, textTrans, labelAlign); |
||||
helper.d3_title(svg, legendG, title, classPrefix); |
||||
cell.transition().style("opacity", 1); |
||||
//positions cells and text
|
||||
if (orient === "vertical") { |
||||
const cellSize = textSize.map((d, i) => Math.max(maxH, d.height)) |
||||
|
||||
cellTrans = (d, i) => { |
||||
const height = sum(cellSize.slice(0, i)) |
||||
return `translate(0, ${height + i * shapePadding} )` |
||||
} |
||||
textTrans = (d, i) => `translate( ${maxW + labelOffset},
|
||||
${shapeSize[i].y + shapeSize[i].height / 2 + 5})` |
||||
} else if (orient === "horizontal") { |
||||
cellTrans = (d, i) => `translate( ${i * (maxW + shapePadding)},0)` |
||||
textTrans = (d, i) => `translate( ${shapeSize[i].width * textAlign + |
||||
shapeSize[i].x}, |
||||
${maxH + labelOffset})` |
||||
} |
||||
|
||||
helper.d3_placement(orient, cell, cellTrans, text, textTrans, labelAlign) |
||||
helper.d3_title(svg, title, classPrefix, titleWidth) |
||||
cell.transition().style("opacity", 1) |
||||
} |
||||
|
||||
legend.scale = function(_) { |
||||
if (!arguments.length) return scale; |
||||
scale = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return scale |
||||
scale = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.cells = function(_) { |
||||
if (!arguments.length) return cells; |
||||
if (_.length > 1 || _ >= 2 ){ |
||||
cells = _; |
||||
if (!arguments.length) return cells |
||||
if (_.length > 1 || _ >= 2) { |
||||
cells = _ |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.cellFilter = function(_) { |
||||
if (!arguments.length) return cellFilter |
||||
cellFilter = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.shapePadding = function(_) { |
||||
if (!arguments.length) return shapePadding; |
||||
shapePadding = +_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return shapePadding |
||||
shapePadding = +_ |
||||
return legend |
||||
} |
||||
|
||||
legend.labels = function(_) { |
||||
if (!arguments.length) return labels; |
||||
labels = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return labels |
||||
labels = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.labelAlign = function(_) { |
||||
if (!arguments.length) return labelAlign; |
||||
if (!arguments.length) return labelAlign |
||||
if (_ == "start" || _ == "end" || _ == "middle") { |
||||
labelAlign = _; |
||||
labelAlign = _ |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.locale = function(_) { |
||||
if (!arguments.length) return locale |
||||
locale = formatLocale(_) |
||||
return legend |
||||
} |
||||
|
||||
legend.labelFormat = function(_) { |
||||
if (!arguments.length) return labelFormat; |
||||
labelFormat = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return legend.locale().format(specifier) |
||||
specifier = formatSpecifier(_) |
||||
return legend |
||||
} |
||||
|
||||
legend.labelOffset = function(_) { |
||||
if (!arguments.length) return labelOffset; |
||||
labelOffset = +_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return labelOffset |
||||
labelOffset = +_ |
||||
return legend |
||||
} |
||||
|
||||
legend.labelDelimiter = function(_) { |
||||
if (!arguments.length) return labelDelimiter; |
||||
labelDelimiter = _; |
||||
return legend; |
||||
}; |
||||
|
||||
legend.orient = function(_){ |
||||
if (!arguments.length) return orient; |
||||
_ = _.toLowerCase(); |
||||
if (!arguments.length) return labelDelimiter |
||||
labelDelimiter = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.labelWrap = function(_) { |
||||
if (!arguments.length) return labelWrap |
||||
labelWrap = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.orient = function(_) { |
||||
if (!arguments.length) return orient |
||||
_ = _.toLowerCase() |
||||
if (_ == "horizontal" || _ == "vertical") { |
||||
orient = _; |
||||
orient = _ |
||||
} |
||||
return legend; |
||||
}; |
||||
return legend |
||||
} |
||||
|
||||
legend.ascending = function(_) { |
||||
if (!arguments.length) return ascending; |
||||
ascending = !!_; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return ascending |
||||
ascending = !!_ |
||||
return legend |
||||
} |
||||
|
||||
legend.classPrefix = function(_) { |
||||
if (!arguments.length) return classPrefix; |
||||
classPrefix = _; |
||||
return legend; |
||||
}; |
||||
if (!arguments.length) return classPrefix |
||||
classPrefix = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.title = function(_) { |
||||
if (!arguments.length) return title; |
||||
title = _; |
||||
return legend; |
||||
}; |
||||
|
||||
d3.rebind(legend, legendDispatcher, "on"); |
||||
|
||||
return legend; |
||||
|
||||
}; |
||||
if (!arguments.length) return title |
||||
title = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.titleWidth = function(_) { |
||||
if (!arguments.length) return titleWidth |
||||
titleWidth = _ |
||||
return legend |
||||
} |
||||
|
||||
legend.on = function() { |
||||
const value = legendDispatcher.on.apply(legendDispatcher, arguments) |
||||
return value === legendDispatcher ? legend : value |
||||
} |
||||
|
||||
return legend |
||||
} |
||||
|
@ -1,5 +1,9 @@ |
||||
d3.legend = { |
||||
color: require('./color'), |
||||
size: require('./size'), |
||||
symbol: require('./symbol') |
||||
}; |
||||
import color from './color' |
||||
import size from './size' |
||||
import symbol from './symbol' |
||||
import helpers from './helpers' |
||||
|
||||
d3.legendColor = color |
||||
d3.legendSize = size |
||||
d3.legendSymbol = symbol |
||||
d3.legendHelpers = helpers |
||||
|
@ -0,0 +1 @@ |
||||
--require reify |
@ -1,20 +0,0 @@ |
||||
const chai = require('chai') |
||||
const expect = chai.expect |
||||
|
||||
describe('d3-legend', function () { |
||||
var d3Legend |
||||
|
||||
beforeEach(function () { |
||||
d3Legend = require('../no-extend') |
||||
}) |
||||
|
||||
it('should export an object', function () { |
||||
expect(d3Legend).to.be.an('object') |
||||
}) |
||||
|
||||
it('should have color, size & symbol functions', function () { |
||||
['color','size','symbol'].forEach(function (fieldName) { |
||||
expect(d3Legend[fieldName]).to.be.a('function') |
||||
}) |
||||
}) |
||||
}) |
@ -0,0 +1,153 @@ |
||||
/*eslint-env mocha*/ |
||||
const chai = require('chai'); |
||||
const { expect } = chai; |
||||
import color from '../src/color'; |
||||
import helper from '../src/legend'; |
||||
import { formatLocale, format } from 'd3-format' |
||||
|
||||
// describe('d3-legend', function () {
|
||||
// var d3Legend
|
||||
|
||||
// beforeEach(function () {
|
||||
// d3Legend = require('../no-extend')
|
||||
// })
|
||||
|
||||
// it('should export an object', function () {
|
||||
// expect(d3Legend).to.be.an('object')
|
||||
// })
|
||||
|
||||
// it('should have color, size & symbol functions', function () {
|
||||
// ['color','size','symbol'].forEach(function (fieldName) {
|
||||
// expect(d3Legend[fieldName]).to.be.a('function')
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
describe('d3-legend #legendColor', function() { |
||||
it('exports a function', function() { |
||||
expect(color).to.be.a('function'); |
||||
}); |
||||
it('invoking exported function does not throw an error and returns a legend function', function() { |
||||
let result; |
||||
expect(color).to.be.a('function'); |
||||
expect(function() { |
||||
result = color(); |
||||
}).to.not.throw(); |
||||
expect(result).to.be.a('function'); |
||||
expect(result.name).to.equal('legend'); |
||||
}); |
||||
it('errors when not passed a SVG', function() { |
||||
let result; |
||||
expect(color).to.be.a('function'); |
||||
expect(function() { |
||||
result = color(); |
||||
}).to.not.throw(); |
||||
expect(result).to.be.a('function'); |
||||
expect(result.name).to.equal('legend'); |
||||
// TODO add formal error handling and assert on error message
|
||||
// }).to.throw('need to provide SVG');
|
||||
expect(function() { |
||||
result(); |
||||
}).to.throw(); |
||||
}); |
||||
// TODO renable to create failing assertion to verify shapes.data is rebound
|
||||
it.skip('properly rebinds the updated range data for the legend shapes', function() { |
||||
let result, aLegend; |
||||
let mockSvg = { |
||||
attr(key, val) { |
||||
this._attrs[key] = val; |
||||
return this; |
||||
}, |
||||
select() { return this; }, |
||||
append() { return this; }, |
||||
enter() { return this; }, |
||||
data() { return this; }, |
||||
selectAll() { |
||||
return this; |
||||
} |
||||
}; |
||||
mockSvg._attrs = {}; |
||||
this._copied = helper.d3_calcType; |
||||
helper.d3_calcType = null; |
||||
helper.d3_calcType = function() { |
||||
expect(arguments.length).to.equal(6); |
||||
return {}; |
||||
}; |
||||
|
||||
|
||||
expect(color).to.be.a('function'); |
||||
expect(function() { |
||||
result = color(); |
||||
}).to.not.throw(); |
||||
expect(result).to.be.a('function'); |
||||
expect(result.name).to.equal('legend'); |
||||
// TODO add formal error handling and assert on error message
|
||||
// }).to.throw('need to provide SVG');
|
||||
expect(function() { |
||||
aLegend = result(mockSvg); |
||||
}).to.not.throw(); |
||||
expect(aLegend).to.be.an('Object'); |
||||
}); |
||||
|
||||
it('should have a locale', function () { |
||||
let result = color(); |
||||
expect(result.locale).to.be.a('function'); |
||||
}); |
||||
|
||||
it('should redefine label\'s format with a string', function () { |
||||
let result = color(); |
||||
let testValue = 1.00; |
||||
let initial = result.labelFormat(); |
||||
|
||||
result.labelFormat('.2f'); |
||||
|
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1.00'); |
||||
}); |
||||
|
||||
it('should redefine label\'s format with a format function', function () { |
||||
let result = color(); |
||||
let testValue = 1.00; |
||||
let initial = result.labelFormat(); |
||||
result.labelFormat(format('.2f')); |
||||
|
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1.00'); |
||||
}); |
||||
|
||||
it('should redefine the locale with a new locale definition', function () { |
||||
let result = color(); |
||||
let testValue = 1.00; |
||||
|
||||
let initial = result.labelFormat(); |
||||
let frFr = { |
||||
decimal: ',', |
||||
thousands: '.', |
||||
grouping: [3], |
||||
currency: ['', '\u00a0€'], |
||||
percent: "\u202f%" |
||||
}; |
||||
|
||||
result.locale(frFr) |
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1,0') |
||||
}) |
||||
|
||||
it('should keep the format specifier after a locale update', function () { |
||||
let result = color(); |
||||
let testValue = 1.00; |
||||
|
||||
let initial = result.labelFormat(); |
||||
let frFr = { |
||||
decimal: ',', |
||||
thousands: '.', |
||||
grouping: [3], |
||||
currency: ['', '\u00a0€'], |
||||
percent: "\u202f%" |
||||
}; |
||||
|
||||
result.labelFormat(format('.2f')); |
||||
result.locale(frFr) |
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1,00') |
||||
}) |
||||
}); |
@ -0,0 +1,75 @@ |
||||
/*eslint-env mocha*/ |
||||
const chai = require('chai'); |
||||
const { expect } = chai; |
||||
import size from '../src/size'; |
||||
import helper from '../src/legend'; |
||||
import { formatLocale, format } from 'd3-format' |
||||
|
||||
describe('d3-legend #legendSize', function() { |
||||
it('exports a function', function() { |
||||
expect(size).to.be.a('function'); |
||||
}); |
||||
|
||||
it('should have a locale', function () { |
||||
let result = size(); |
||||
expect(result.locale).to.be.a('function'); |
||||
}); |
||||
|
||||
it('should redefine label\'s format with a string', function () { |
||||
let result = size(); |
||||
let testValue = 1.00; |
||||
let initial = result.labelFormat(); |
||||
|
||||
result.labelFormat('.2f'); |
||||
|
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1.00'); |
||||
}); |
||||
|
||||
it('should redefine label\'s format with a format function', function () { |
||||
let result = size(); |
||||
let testValue = 1.00; |
||||
let initial = result.labelFormat(); |
||||
result.labelFormat(format('.2f')); |
||||
|
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1.00'); |
||||
}); |
||||
|
||||
it('should redefine the locale with a new locale definition', function () { |
||||
let result = size(); |
||||
let testValue = 1.00; |
||||
|
||||
let initial = result.labelFormat(); |
||||
let frFr = { |
||||
decimal: ',', |
||||
thousands: '.', |
||||
grouping: [3], |
||||
currency: ['', '\u00a0€'], |
||||
percent: "\u202f%" |
||||
}; |
||||
|
||||
result.locale(frFr) |
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1,0') |
||||
}) |
||||
|
||||
it('should keep the format specifier after a locale update', function () { |
||||
let result = size(); |
||||
let testValue = 1.00; |
||||
|
||||
let initial = result.labelFormat(); |
||||
let frFr = { |
||||
decimal: ',', |
||||
thousands: '.', |
||||
grouping: [3], |
||||
currency: ['', '\u00a0€'], |
||||
percent: "\u202f%" |
||||
}; |
||||
|
||||
result.labelFormat(format('.2f')); |
||||
result.locale(frFr) |
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1,00') |
||||
}) |
||||
}); |
@ -0,0 +1,75 @@ |
||||
/*eslint-env mocha*/ |
||||
const chai = require('chai'); |
||||
const { expect } = chai; |
||||
import symbol from '../src/symbol'; |
||||
import helper from '../src/legend'; |
||||
import { formatLocale, format } from 'd3-format' |
||||
|
||||
describe('d3-legend #legendSymbol', function() { |
||||
it('exports a function', function() { |
||||
expect(symbol).to.be.a('function'); |
||||
}); |
||||
|
||||
it('should have a locale', function () { |
||||
let result = symbol(); |
||||
expect(result.locale).to.be.a('function'); |
||||
}); |
||||
|
||||
it('should redefine label\'s format with a string', function () { |
||||
let result = symbol(); |
||||
let testValue = 1.00; |
||||
let initial = result.labelFormat(); |
||||
|
||||
result.labelFormat('.2f'); |
||||
|
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1.00'); |
||||
}); |
||||
|
||||
it('should redefine label\'s format with a format function', function () { |
||||
let result = symbol(); |
||||
let testValue = 1.00; |
||||
let initial = result.labelFormat(); |
||||
result.labelFormat(format('.2f')); |
||||
|
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1.00'); |
||||
}); |
||||
|
||||
it('should redefine the locale with a new locale definition', function () { |
||||
let result = symbol(); |
||||
let testValue = 1.00; |
||||
|
||||
let initial = result.labelFormat(); |
||||
let frFr = { |
||||
decimal: ',', |
||||
thousands: '.', |
||||
grouping: [3], |
||||
currency: ['', '\u00a0€'], |
||||
percent: "\u202f%" |
||||
}; |
||||
|
||||
result.locale(frFr) |
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1,0') |
||||
}) |
||||
|
||||
it('should keep the format specifier after a locale update', function () { |
||||
let result = symbol(); |
||||
let testValue = 1.00; |
||||
|
||||
let initial = result.labelFormat(); |
||||
let frFr = { |
||||
decimal: ',', |
||||
thousands: '.', |
||||
grouping: [3], |
||||
currency: ['', '\u00a0€'], |
||||
percent: "\u202f%" |
||||
}; |
||||
|
||||
result.labelFormat(format('.2f')); |
||||
result.locale(frFr) |
||||
expect(initial(testValue)).to.be.not.equal(result.labelFormat()(testValue)); |
||||
expect(result.labelFormat()(testValue)).to.be.equal('1,00') |
||||
}) |
||||
}); |
@ -0,0 +1,7 @@ |
||||
{ |
||||
"compilerOptions": { |
||||
"typeRoots": ["./types"], |
||||
"allowJs": true |
||||
}, |
||||
"include": ["types/*"] |
||||
} |
@ -0,0 +1,84 @@ |
||||
import { BaseType, Selection } from 'd3-selection'; |
||||
|
||||
type Orientation = 'vertical' | 'horizontal'; |
||||
type Alignment = 'start' | 'middle' | 'end'; |
||||
type Shape = 'rect' | 'circle' | 'line' | 'path'; |
||||
type EventType = 'cellover' | 'cellout' | 'cellclick'; |
||||
|
||||
export interface LegendColor { |
||||
scale(scale: (any)): (selection: Selection<BaseType, any, any, any>, ...args: any[]) => void; |
||||
cells(steps: number): LegendColor; |
||||
cells(steps: number[]): LegendColor; |
||||
cellFilter(filter: () => boolean): LegendColor; |
||||
orient(orientation: Orientation): LegendColor; |
||||
ascending(ascending: boolean): LegendColor; |
||||
shape(shape: Shape, path?: string): LegendColor; |
||||
shapeWidth(width: number): LegendColor; |
||||
shapeHeight(height: number): LegendColor; |
||||
shapeRadius(radius: number): LegendColor; |
||||
shapePadding(padding: number): LegendColor; |
||||
useClass(useClass: boolean): LegendColor; |
||||
classPrefix(prefix: string): LegendColor; |
||||
title(title: string): LegendColor; |
||||
titleWidth(width: number): LegendColor; |
||||
labels(labels: string[]): LegendColor; |
||||
labels(labelGenerator: Function): LegendColor; |
||||
labelAlign(alignment: Alignment): LegendColor; |
||||
labelFormat(format: (n: number) => string): LegendColor; |
||||
labelOffset(offset: number): LegendColor; |
||||
labelDelimiter(delimiter: string): LegendColor; |
||||
on(eventType: EventType, event: Function): LegendColor; |
||||
} |
||||
|
||||
export interface LegendSize { |
||||
scale(scale: (any)): (selection: Selection<BaseType, any, any, any>, ...args: any[]) => void; |
||||
cells(steps: number): LegendColor; |
||||
cells(steps: number[]): LegendColor; |
||||
cellFilter(filter: () => boolean): LegendColor; |
||||
orient(orientation: Orientation): LegendColor; |
||||
ascending(ascending: boolean): LegendColor; |
||||
shape(shape: Shape, path?: string): LegendColor; |
||||
shapeWidth(width: number): LegendColor; |
||||
shapePadding(padding: number): LegendColor; |
||||
classPrefix(prefix: string): LegendColor; |
||||
title(title: string): LegendColor; |
||||
titleWidth(width: number): LegendColor; |
||||
labels(labels: string[]): LegendColor; |
||||
labels(labelGenerator: Function): LegendColor; |
||||
labelAlign(alignment: Alignment): LegendColor; |
||||
labelFormat(format: (n: number) => string): LegendColor; |
||||
labelOffset(offset: number): LegendColor; |
||||
labelDelimiter(delimiter: string): LegendColor; |
||||
on(eventType: EventType, event: Function): LegendColor; |
||||
} |
||||
|
||||
export interface LegendSymbol { |
||||
scale(scale: (any)): (selection: Selection<BaseType, any, any, any>, ...args: any[]) => void; |
||||
cells(steps: number): LegendColor; |
||||
cells(steps: number[]): LegendColor; |
||||
cellFilter(filter: () => boolean): LegendColor; |
||||
orient(orientation: Orientation): LegendColor; |
||||
ascending(ascending: boolean): LegendColor; |
||||
shapePadding(padding: number): LegendColor; |
||||
classPrefix(prefix: string): LegendColor; |
||||
title(title: string): LegendColor; |
||||
titleWidth(width: number): LegendColor; |
||||
labels(labels: string[]): LegendColor; |
||||
labels(labelGenerator: Function): LegendColor; |
||||
labelAlign(alignment: Alignment): LegendColor; |
||||
labelFormat(format: (n: number) => string): LegendColor; |
||||
labelOffset(offset: number): LegendColor; |
||||
labelDelimiter(delimiter: string): LegendColor; |
||||
on(eventType: EventType, event: Function): LegendColor; |
||||
} |
||||
|
||||
export function legendColor(...args: any[]): LegendColor; |
||||
|
||||
export function legendSize(...args: any[]): LegendSize; |
||||
|
||||
export function legendSymbol(...args: any[]): LegendSymbol; |
||||
|
||||
export namespace legendHelpers { |
||||
function thresholdLabels(_ref: any): any; |
||||
|
||||
} |
@ -0,0 +1,3 @@ |
||||
# Set the default behavior, in case people don't have core.autocrlf set. |
||||
* text=auto |
||||
|
@ -0,0 +1,28 @@ |
||||
|
||||
# Help |
||||
#### The issues section is for bug reports and feature requests only. If you need help, please use the [forum](http://discourse.threejs.org/) or [stackoverflow](http://stackoverflow.com/questions/tagged/three.js). |
||||
--- |
||||
# Bugs |
||||
#### Before reporting a bug |
||||
|
||||
1. Search issue tracker for similar issues. |
||||
2. Try the latest dev branch version of three.js. |
||||
3. Refer to the [Migration Guide](https://github.com/mrdoob/three.js/wiki/Migration) when upgrading to the dev version. |
||||
|
||||
#### How to report a bug |
||||
|
||||
1. Specify the revision number of the three.js library where the bug occurred. |
||||
2. Specify your browser version, operating system, and graphics card. (for example, Chrome 23.0.1271.95, Windows 7, Nvidia Quadro 2000M) |
||||
3. Describe the problem in detail. Explain what happened, and what you expected would happen. |
||||
4. Provide a small test-case (http://jsfiddle.net). [Here is a fiddle](https://jsfiddle.net/3foLr7sn/) you can edit that runs the current version. [And here is a fiddle](https://jsfiddle.net/qgu17w5o/) that uses the dev branch. If a test-case is not possible, provide a link to a live version of your application. |
||||
5. If helpful, include a screenshot. Annotate the screenshot for clarity. |
||||
|
||||
--- |
||||
# Contribution |
||||
#### How to contribute to three.js |
||||
|
||||
1. Make sure you have a GitHub account. |
||||
2. Fork the repository on GitHub. |
||||
3. Check the [Contribution Guidelines](https://github.com/mrdoob/three.js/wiki/How-to-contribute-to-three.js). |
||||
4. Make changes to your clone of the repository. |
||||
5. Submit a pull request. Don't include build files in the PR. |
@ -0,0 +1,41 @@ |
||||
##### Description of the problem |
||||
|
||||
This form is for three.js bug reports and feature requests only. |
||||
|
||||
This is NOT a help site. Do not ask help questions here. |
||||
If you need help, please use the [forum](https://discourse.threejs.org/) or [stackoverflow](http://stackoverflow.com/questions/tagged/three.js). |
||||
|
||||
Describe the bug or feature request in detail. |
||||
|
||||
Always include a code snippet, screenshots, and any relevant models or textures to help us understand your issue. |
||||
|
||||
Please also include a live example if possible. You can start from these templates: |
||||
|
||||
* [jsfiddle](https://jsfiddle.net/3foLr7sn/) (latest release branch) |
||||
* [jsfiddle](https://jsfiddle.net/qgu17w5o/) (dev branch) |
||||
* [codepen](https://codepen.io/anon/pen/aEBKxR) (latest release branch) |
||||
* [codepen](https://codepen.io/anon/pen/BJWzaN) (dev branch) |
||||
|
||||
##### Three.js version |
||||
|
||||
- [ ] Dev |
||||
- [ ] r101 |
||||
- [ ] ... |
||||
|
||||
##### Browser |
||||
|
||||
- [x] All of them |
||||
- [ ] Chrome |
||||
- [ ] Firefox |
||||
- [ ] Internet Explorer |
||||
|
||||
##### OS |
||||
|
||||
- [x] All of them |
||||
- [ ] Windows |
||||
- [ ] macOS |
||||
- [ ] Linux |
||||
- [ ] Android |
||||
- [ ] iOS |
||||
|
||||
##### Hardware Requirements (graphics card, VR Device, ...) |
@ -0,0 +1,10 @@ |
||||
.DS_Store |
||||
*.swp |
||||
.project |
||||
node_modules |
||||
.idea/ |
||||
.vscode/ |
||||
npm-debug.log |
||||
.jshintrc |
||||
.vs/ |
||||
test/unit/three.*.unit.js |
@ -0,0 +1,8 @@ |
||||
examples/* |
||||
!examples/js/ |
||||
src/ |
||||
test/ |
||||
utils/ |
||||
docs/ |
||||
editor/ |
||||
.DS_Store |
@ -0,0 +1,5 @@ |
||||
language: node_js |
||||
node_js: |
||||
- node |
||||
script: |
||||
- npm run travis |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 2.2 KiB |
Loading…
Reference in new issue