New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More

@flourish/legend

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@flourish/legend - npm Package Compare versions

Comparing version 1.3.2 to 2.0.0

{
"name": "@flourish/legend",
"version": "1.3.2",
"version": "2.0.0",
"description": "Flourish module for making legend",

@@ -17,2 +17,3 @@ "main": "legend.js",

"dependencies": {
"d3-scale": "^3.2.1",
"d3-selection": "^1.4.0"

@@ -19,0 +20,0 @@ },

@@ -0,1 +1,6 @@

# 2.0.0
* Support binned legend labels
* Adjust alignment
* Size legends tweaks
# 1.3.2

@@ -2,0 +7,0 @@ * Unblur canvas elements

@@ -44,2 +44,3 @@ function appendTo(container) {

.style("font-size", this._state.text_size + "rem")
.style("line-height", "1em")
.style("margin-top", 0)

@@ -46,0 +47,0 @@ .style("margin-bottom", 0)

import { select } from "d3-selection";
import { scaleLinear } from "d3-scale";
import { appendTo, format, getContainer, visible, _updateTitle } from "../common";

@@ -17,3 +18,6 @@ import { remToPx } from "../utils";

text_color: null,
text_size: 1
text_size: 1,
binned_label_mode: "thresholds",
binned_label_custom: ""
});

@@ -34,3 +38,5 @@

this._container.append("div").classed("min label", true);
this._container.append("canvas").classed("color-range", true);
this._container.append("div").classed("color-range-container", true);
this._container.select(".color-range-container").append("canvas").classed("color-range", true);
this._container.select(".color-range-container").append("canvas").classed("color-range-labels", true);
this._container.append("div").classed("max label", true);

@@ -50,3 +56,2 @@

ContinuousColorLegend.prototype.data = function(items_, colorFunction_) {

@@ -77,56 +82,187 @@ // items_ must be a 2-element domain array [minValue, maxValue]

ContinuousColorLegend.prototype._updateLegend = function() {
this._scale_type = "continuous";
if (this._colorFunction.midpoint) this._scale_type = "diverging";
else if (this._colorFunction.thresholds) this._scale_type = "binned";
var domain = this._legend_domain;
var format = this._formatFunction;
var s = this._state;
var pixel_ratio = window.devicePixelRatio || 1;
var label_padding = this._scale_type == "continuous" ? 0 : remToPx(s.text_size);
var w = remToPx(s.color_band_width), h = remToPx(s.color_band_height), label_h = Math.ceil(remToPx(s.text_size) * 0.95), label_w = w + label_padding * 2;
this._container.style("display", "flex")
.style("align-items", "center");
this._container.select(".color-range-container")
.style("display", "inline-block");
var canvas = this._container
.select(".color-range")
.attr("width", w * pixel_ratio)
.attr("height", h * pixel_ratio)
.style("margin", "0 " + label_padding + "px")
.style("border-radius", s.color_band_radius + "px")
.style("width", w + "px")
.style("height", h + "px")
.style("display", "block");
this._container
.select(".color-range-labels")
.attr("width", label_w * pixel_ratio)
.attr("height", label_h * pixel_ratio)
.style("width", label_w + "px")
.style("height", label_h + "px")
.style("display", this._scale_type == "continuous" ? "none" : "block")
.style("margin-top", s.text_size * 0.25 + "rem")
.node().getContext("2d").scale(pixel_ratio, pixel_ratio);
// Update canvas
var ctx = canvas.node().getContext("2d");
ctx.scale(pixel_ratio, pixel_ratio);
function xToVal(x) {
return domain[0] + (x / w) * (domain[1] - domain[0]);
}
for (var x = 0; x < w; x++) {
ctx.fillStyle = this._colorFunction(xToVal(x));
ctx.fillRect(x, 0, 1, h);
}
this._updateLegendLabels();
};
ContinuousColorLegend.prototype._updateLegendLabels = function () {
var label_canvas = this._container.select(".color-range-labels");
var format = this._formatFunction;
var domain = this._legend_domain;
var s = this._state;
this._container
.select(".min.label")
.style("display", "inline-block")
.style("display", this._scale_type == "continuous" ? "inline-block" : "none")
.style("vertical-align", "middle")
.style("user-select", "none")
.style("margin-right", s.text_size * 0.25 + "rem")
.style("margin-right", s.text_size * 0.5 + "rem")
.style("font-size", s.text_size + "rem")
.style("line-height", "1em")
.style("color", s.text_color)
.text(function() {
.text(function () {
return format ? format(domain[0]) : domain[0];
});
var w = remToPx(s.color_band_width), h = remToPx(s.color_band_height);
var canvas = this._container
.select(".color-range")
.style("width", w + "px")
.style("height", h + "px")
.attr("width", w * pixel_ratio)
.attr("height", h * pixel_ratio)
.style("vertical-align", "middle")
.style("border-radius", s.color_band_radius + "px");
this._container
.select(".max.label")
.style("display", "inline-block")
.style("display", this._scale_type == "continuous" ? "inline-block" : "none")
.style("vertical-align", "middle")
.style("user-select", "none")
.style("margin-left", s.text_size * 0.25 + "rem")
.style("margin-left", s.text_size * 0.5 + "rem")
.style("font-size", s.text_size + "rem")
.style("line-height", "1em")
.style("color", s.text_color)
.text(function() {
.text(function () {
return format ? format(domain[1]) : domain[1];
});
var labels = [];
if (this._scale_type === "diverging") labels = this._getDivergingLabels();
else if (this._scale_type === "binned") labels = this._getBinnedLabels();
// Update canvas
var ctx = canvas.node().getContext("2d");
ctx.scale(pixel_ratio, pixel_ratio);
if (labels.length) {
var template = window.template || undefined;
var layout = template ? template.state.layout : undefined;
var font_family = layout ? layout.body_font.name : "sans-serif";
var font_color = s.text_color || (template && layout.font_color) || "#333333";
var ctx = label_canvas.node().getContext("2d");
ctx.textAlign = "center";
ctx.textBaseline = "top";
ctx.fillStyle = font_color;
ctx.font = remToPx(s.text_size) + "px " + font_family;
function xToVal(x) {
return domain[0] + (x / w) * (domain[1] - domain[0]);
var prepLabel = (function () {
var placed_labels = [];
var label_padding = remToPx(s.text_size);
var inRange = getInRangeFunction([0, label_canvas.node().width]);
return function (value) {
var scale = scaleLinear().domain(domain).range([label_padding, remToPx(s.color_band_width) + label_padding]);
var center = scale(value);
if (!inRange(center)) return;
var text = format ? format(value) : value;
var half_width = ctx.measureText(text).width / 2 + 1;
var left = center - half_width;
var right = center + half_width;
if (!inRange(left) || !inRange(right)) return;
var index = 0;
var n = placed_labels.length;
for (var i = 0; i < n; i++) {
if (center > placed_labels[i].center) index++;
else break;
}
var at_start = index === 0;
var at_end = index === n;
if (!at_start && placed_labels[index - 1].right > left) return;
if (!at_end && placed_labels[index].left < right) return;
placed_labels.splice(index, 0, { left: left, center: center, right: right });
return { text: text, position: center };
};
})();
labels.forEach(function (value) {
var label = prepLabel(value);
if (label) ctx.fillText(label.text, label.position, 0);
});
}
};
for (var x = 0; x < w; x++) {
ctx.fillStyle = this._colorFunction(xToVal(x));
ctx.fillRect(x, 0, 1, h);
ContinuousColorLegend.prototype._getDivergingLabels = function() {
var legend_domain = this._legend_domain;
var inRange = getInRangeFunction(legend_domain);
var labels = [];
if (inRange(this._colorFunction.midpoint)) labels.push(this._colorFunction.midpoint);
var gradient_domain = this._colorFunction.domain;
if (inRange(gradient_domain[0])) labels.push(gradient_domain[0]);
if (inRange(gradient_domain[1])) labels.push(gradient_domain[1]);
if (legend_domain[0] !== gradient_domain[0]) labels.push(legend_domain[0]);
if (legend_domain[1] !== gradient_domain[1]) labels.push(legend_domain[1]);
return labels;
};
ContinuousColorLegend.prototype._getBinnedLabels = function () {
var s = this._state;
var legend_domain = this._legend_domain;
var inRange = getInRangeFunction(legend_domain);
var labels;
if (s.binned_label_mode === "thresholds") {
labels = this._colorFunction.thresholds.slice().filter(inRange);
if (legend_domain[0] < labels[0]) labels.push(legend_domain[0]);
if (legend_domain[1] > labels[labels.length - 1]) labels.push(legend_domain[1]);
}
else if (s.binned_label_mode === "centers") {
labels = this._colorFunction.centers.slice().filter(inRange);
if (labels.length) {
var thresholds = this._colorFunction.thresholds;
var first_threshold = thresholds[0];
var last_threshold = thresholds[thresholds.length - 1];
if (first_threshold > legend_domain[0]) labels.push((legend_domain[0] + first_threshold) / 2);
if (last_threshold < legend_domain[1]) labels.push((last_threshold + legend_domain[1]) / 2);
}
else labels.push((legend_domain[0] + legend_domain[1]) / 2);
}
else labels = s.binned_label_custom.split(";").map(parseFloat);
return labels;
};
function getInRangeFunction(legend_domain) {
return function (val) { return val >= legend_domain[0] && val <= legend_domain[1]; };
}
export default ContinuousColorLegend;

@@ -13,2 +13,3 @@ import { select } from "d3-selection";

clip_height: 1,
small_circle_size: 0.5,

@@ -82,3 +83,3 @@ text_color: null,

.style("align-items", "center")
.style("height", h + "px");
.style("min-height", h + "px");

@@ -103,5 +104,7 @@ if (!should_display || !this._scaleFunction) return this;

var domain = this._scaleFunction.domain();
var range = this._scaleFunction.range();
var format = this._formatFunction;
var s = this._state;
var h = Math.ceil(remToPx(s.clip_height));
var h = remToPx(s.clip_height);
h = Math.ceil(Math.min(h, range[1] * 2));
var pixel_ratio = window.devicePixelRatio || 1;

@@ -112,4 +115,10 @@

// Calculate max circle size
var val_max_unrounded = this._scaleFunction.invert(h/2);
val_max_unrounded = Math.min(val_max_unrounded, domain[1]);
var val_max = roundDown(val_max_unrounded) || 0;
// Min circle
var r_min = 1;
var val_min = val_max * s.small_circle_size;
var r_min = this._scaleFunction(val_min);
var w_min = Math.ceil(2 * r_min) + 2;

@@ -122,3 +131,3 @@ var canvas_min = this._container

.attr("height", h * pixel_ratio)
.style("margin-right", "0.1rem");
.style("margin-right", "0.05rem");

@@ -133,3 +142,3 @@ this._container

.text(function () {
return format ? format(domain[0]) : domain[0];
return format ? format(val_min) : val_min;
});

@@ -140,15 +149,15 @@

ctx_min.fillStyle = fill;
ctx_min.strokeStyle = stroke;
ctx_min.clearRect(0, 0, 2 * r_min, 2 * r_min);
ctx_min.beginPath();
ctx_min.fillStyle = stroke;
ctx_min.arc(0.5 * w_min, 0.5 * h, r_min, 0, 2 * Math.PI);
ctx_min.fill();
ctx_min.stroke();
ctx_min.beginPath();
ctx_min.fillStyle = fill;
ctx_min.arc(0.5 * w_min, 0.5 * h, Math.max(r_min - 1, 0), 0, 2 * Math.PI);
ctx_min.fill();
// Max circle
var val_max_unrounded = this._scaleFunction.invert(h / 2);
val_max_unrounded = Math.min(val_max_unrounded, domain[1]);
var val_max = roundDown(val_max_unrounded);
var r_max = this._scaleFunction(val_max);

@@ -163,3 +172,3 @@ var w_max = Math.ceil(2 * r_max) + 2;

.attr("height", h * pixel_ratio)
.style("margin-left", "0.1rem");
.style("margin-left", "0.05rem");

@@ -191,3 +200,3 @@ this._container

ctx_max.fillStyle = fill;
ctx_max.arc(0.5 * w_max, 0.5 * h, r_max - 0.5, 0, 2 * Math.PI);
ctx_max.arc(0.5 * w_max, 0.5 * h, Math.max(r_max - 1, 0), 0, 2 * Math.PI);
ctx_max.fill();

@@ -194,0 +203,0 @@ };

@@ -133,2 +133,5 @@ import { select, event as d3_event } from "d3-selection";

var _this = this;
this._container.style("line-height", "0")
.style("display", "inline-flex")
.style("align-items", "center");

@@ -153,2 +156,4 @@ var legend_item_data;

})
.style("line-height", "0")
.style("vertical-align", "top")
.style("margin-right", this._state.orientation == "horizontal" ? this._state.text_size * 0.5 + "rem" : "");

@@ -167,2 +172,3 @@

.style("font-size", this._state.text_size + "rem")
.style("line-height", "1em")
.style("color", this._state.text_color)

@@ -169,0 +175,0 @@ .text(function(d) { return d.label; })

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display