d3plus-shape
Version:
Fancy SVG shapes for visualizations
1,131 lines (1,066 loc) • 46.2 kB
JavaScript
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
/**
@external BaseClass
@see https://github.com/d3plus/d3plus-common#BaseClass
*/
import { min } from "d3-array";
import { color } from "d3-color";
import { pointer, select as _select, selectAll } from "d3-selection";
import { transition } from "d3-transition";
import { accessor, assign, attrize, BaseClass, configPrep, constant, elem, isObject, unique } from "d3plus-common";
import { colorContrast } from "d3plus-color";
import * as paths from "d3-shape";
import { strip, TextBox } from "d3plus-text";
import textures from "textures";
import Image from "../Image.js";
import pointDistance from "../geom/pointDistance.js";
/**
@class Shape
@extends external:BaseClass
@desc An abstracted class for generating shapes.
*/
var Shape = /*#__PURE__*/function (_BaseClass) {
_inherits(Shape, _BaseClass);
var _super = _createSuper(Shape);
/**
@memberof Shape
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Shape() {
var _this;
var tagName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "g";
_classCallCheck(this, Shape);
_this = _super.call(this);
_this._activeOpacity = 0.25;
_this._activeStyle = {
"stroke": function stroke(d, i) {
var c = _this._fill(d, i);
if (["transparent", "none"].includes(c)) c = _this._stroke(d, i);
return color(c).darker(1);
},
"stroke-width": function strokeWidth(d, i) {
var s = _this._strokeWidth(d, i) || 1;
return s * 3;
}
};
_this._ariaLabel = constant("");
_this._backgroundImage = constant(false);
_this._backgroundImageClass = new Image();
_this._data = [];
_this._duration = 600;
_this._fill = constant("black");
_this._fillOpacity = constant(1);
_this._hoverOpacity = 0.5;
_this._hoverStyle = {
"stroke": function stroke(d, i) {
var c = _this._fill(d, i);
if (["transparent", "none"].includes(c)) c = _this._stroke(d, i);
return color(c).darker(0.5);
},
"stroke-width": function strokeWidth(d, i) {
var s = _this._strokeWidth(d, i) || 1;
return s * 2;
}
};
_this._id = function (d, i) {
return d.id !== void 0 ? d.id : i;
};
_this._label = constant(false);
_this._labelClass = new TextBox();
_this._labelConfig = {
fontColor: function fontColor(d, i) {
return colorContrast(_this._fill(d, i));
},
fontSize: 12,
padding: 5
};
_this._name = "Shape";
_this._opacity = constant(1);
_this._pointerEvents = constant("visiblePainted");
_this._role = constant("presentation");
_this._rotate = constant(0);
_this._rx = constant(0);
_this._ry = constant(0);
_this._scale = constant(1);
_this._shapeRendering = constant("geometricPrecision");
_this._stroke = function (d, i) {
return color(_this._fill(d, i)).darker(1).formatHex();
};
_this._strokeDasharray = constant("0");
_this._strokeLinecap = constant("butt");
_this._strokeOpacity = constant(1);
_this._strokeWidth = constant(0);
_this._tagName = tagName;
_this._textAnchor = constant("start");
_this._texture = constant(false);
_this._textureDefault = {};
_this._textureDefs = {};
_this._vectorEffect = constant("non-scaling-stroke");
_this._verticalAlign = constant("top");
_this._x = accessor("x", 0);
_this._y = accessor("y", 0);
return _this;
}
/**
@memberof Shape
@desc Given a specific data point and index, returns the aesthetic properties of the shape.
@param {Object} *data point*
@param {Number} *index*
@private
*/
_createClass(Shape, [{
key: "_aes",
value: function _aes() {
return {};
}
/**
@memberof Shape
@desc Adds event listeners to each shape group or hit area.
@param {D3Selection} *update* The update cycle of the data binding.
@private
*/
}, {
key: "_applyEvents",
value: function _applyEvents(handler) {
var _this2 = this;
var events = Object.keys(this._on);
var _loop = function _loop(e) {
handler.on(events[e], function (event, d, i) {
if (!_this2._on[events[e]]) return;
if (d.i !== void 0) i = d.i;
if (d.nested && d.values) {
var calcPoint = function calcPoint(d, i) {
if (_this2._discrete === "x") return [_this2._x(d, i), cursor[1]];else if (_this2._discrete === "y") return [cursor[0], _this2._y(d, i)];else return [_this2._x(d, i), _this2._y(d, i)];
};
var cursor = pointer(event, _this2._select.node()),
values = d.values.map(function (d) {
return pointDistance(cursor, calcPoint(d, i));
});
i = values.indexOf(min(values));
d = d.values[i];
}
_this2._on[events[e]].bind(_this2)(d, i, undefined, event);
});
};
for (var e = 0; e < events.length; e++) {
_loop(e);
}
}
/**
@memberof Shape
@desc Provides the updated styling to the given shape elements.
@param {HTMLElement} *elem*
@param {Object} *style*
@private
*/
}, {
key: "_updateStyle",
value: function _updateStyle(elem, style) {
var that = this;
if (elem.size() && elem.node().tagName === "g") elem = elem.selectAll("*");
/**
@desc Determines whether a shape is a nested collection of data points, and uses the appropriate data and index for the given function context.
@param {Object} *d* data point
@param {Number} *i* index
@private
*/
function styleLogic(d, i) {
return typeof this !== "function" ? this : d.nested && d.key && d.values ? this(d.values[0], that._data.indexOf(d.values[0])) : this(d, i);
}
var styleObject = {};
for (var key in style) {
if ({}.hasOwnProperty.call(style, key)) {
styleObject[key] = styleLogic.bind(style[key]);
}
}
elem.transition().duration(0).call(attrize, styleObject);
}
/**
@memberof Shape
@desc Provides the default styling to the shape elements.
@param {HTMLElement} *elem*
@private
*/
}, {
key: "_applyStyle",
value: function _applyStyle(elem) {
var _this3 = this;
var that = this;
if (elem.size() && elem.node().tagName === "g") elem = elem.selectAll("*");
/**
@desc Determines whether a shape is a nested collection of data points, and uses the appropriate data and index for the given function context.
@param {Object} *d* data point
@param {Number} *i* index
@private
*/
function styleLogic(d, i) {
return typeof this !== "function" ? this : d.nested && d.key && d.values ? this(d.values[0], that._data.indexOf(d.values[0])) : this(d, i);
}
elem.attr("fill", function (d, i) {
var texture = _this3._getTextureKey.bind(_this3)(d, i);
return texture ? _this3._textureDefs[texture].url() : styleLogic.bind(_this3._fill)(d, i);
}).attr("fill-opacity", styleLogic.bind(this._fillOpacity)).attr("rx", styleLogic.bind(this._rx)).attr("ry", styleLogic.bind(this._ry)).attr("stroke", styleLogic.bind(this._stroke)).attr("stroke-dasharray", styleLogic.bind(this._strokeDasharray)).attr("stroke-linecap", styleLogic.bind(this._strokeLinecap)).attr("stroke-opacity", styleLogic.bind(this._strokeOpacity)).attr("stroke-width", styleLogic.bind(this._strokeWidth)).attr("vector-effect", styleLogic.bind(this._vectorEffect));
}
/**
@memberof Shape
@desc Calculates the transform for the group elements.
@param {HTMLElement} *elem*
@private
*/
}, {
key: "_applyTransform",
value: function _applyTransform(elem) {
var _this4 = this;
elem.attr("transform", function (d, i) {
return "\n translate(".concat(d.__d3plusShape__ ? d.translate ? d.translate : "".concat(_this4._x(d.data, d.i), ",").concat(_this4._y(d.data, d.i)) : "".concat(_this4._x(d, i), ",").concat(_this4._y(d, i)), ")\n scale(").concat(d.__d3plusShape__ ? d.scale || _this4._scale(d.data, d.i) : _this4._scale(d, i), ")\n rotate(").concat(d.__d3plusShape__ ? d.rotate ? d.rotate : _this4._rotate(d.data || d, d.i) : _this4._rotate(d.data || d, d.i), ")");
});
}
/**
@memberof Shape
@desc Returns a full JSON string of the texture config for a given data point.
@param {Object} *d*
@param {Number} *i*
@private
*/
}, {
key: "_getTextureKey",
value: function _getTextureKey(d, i) {
var _this5 = this;
var texture = this._texture(d, i);
if (!texture) return false;
/**
@desc Determines whether a shape is a nested collection of data points, and uses the appropriate data and index for the given function context.
@private
*/
var styleLogic = function styleLogic(_) {
return typeof _ !== "function" ? _ : d.nested && d.key && d.values ? _(d.values[0], _this5._data.indexOf(d.values[0])) : _(d, i);
};
var fallback = this._textureDefault;
if (!isObject(texture)) texture = {
texture: texture
};
if (!texture.background) texture.background = styleLogic(this._fill);
if (!texture.stroke && !fallback.stroke) texture.stroke = styleLogic(this._stroke);
var paths = ["squares", "nylon", "waves", "woven", "crosses", "caps", "hexagons"];
if (paths.includes(texture.texture) || typeof texture.texture === "function") {
texture.d = texture.texture;
texture.texture = "paths";
} else if (texture.texture === "grid") {
if (!texture.orientation && !fallback.orientation) texture.orientation = ["vertical", "horizontal"];
texture.texture = "lines";
}
if (!texture.fill && texture.texture !== "paths") texture.fill = texture.stroke;
var retObj = assign({}, fallback, texture);
if (typeof retObj.d === "function") {
retObj.d = retObj.d(retObj.size || 20);
}
return JSON.stringify(retObj);
}
/**
@memberof Shape
@desc Checks for nested data and uses the appropriate variables for accessor functions.
@param {HTMLElement} *elem*
@private
*/
}, {
key: "_nestWrapper",
value: function _nestWrapper(method) {
return function (d, i) {
return method(d.__d3plusShape__ ? d.data : d, d.__d3plusShape__ ? d.i : i);
};
}
/**
@memberof Shape
@desc Modifies existing shapes to show active status.
@private
*/
}, {
key: "_renderActive",
value: function _renderActive() {
var that = this;
this._group.selectAll(".d3plus-Shape, .d3plus-Image, .d3plus-textBox").each(function (d, i) {
if (!d) d = {};
if (!d.parentNode) d.parentNode = this.parentNode;
var parent = d.parentNode;
if (_select(this).classed("d3plus-textBox")) d = d.data;
if (d.__d3plusShape__ || d.__d3plus__) {
while (d && (d.__d3plusShape__ || d.__d3plus__)) {
i = d.i;
d = d.data;
}
} else i = that._data.indexOf(d);
var group = !that._active || typeof that._active !== "function" || !that._active(d, i) ? parent : that._activeGroup.node();
if (group !== this.parentNode) {
group.appendChild(this);
if (this.className.baseVal.includes("d3plus-Shape")) {
if (parent === group) _select(this).call(that._applyStyle.bind(that));else _select(this).call(that._updateStyle.bind(that, _select(this), that._activeStyle));
}
}
});
// this._renderImage();
// this._renderLabels();
this._group.selectAll("g.d3plus-".concat(this._name, "-shape, g.d3plus-").concat(this._name, "-image, g.d3plus-").concat(this._name, "-text")).attr("opacity", this._hover ? this._hoverOpacity : this._active ? this._activeOpacity : 1);
}
/**
@memberof Shape
@desc Modifies existing shapes to show hover status.
@private
*/
}, {
key: "_renderHover",
value: function _renderHover() {
var that = this;
this._group.selectAll("g.d3plus-".concat(this._name, "-shape, g.d3plus-").concat(this._name, "-image, g.d3plus-").concat(this._name, "-text, g.d3plus-").concat(this._name, "-hover")).selectAll(".d3plus-Shape, .d3plus-Image, .d3plus-textBox").each(function (d, i) {
if (!d) d = {};
if (!d.parentNode) d.parentNode = this.parentNode;
var parent = d.parentNode;
if (_select(this).classed("d3plus-textBox")) d = d.data;
if (d.__d3plusShape__ || d.__d3plus__) {
while (d && (d.__d3plusShape__ || d.__d3plus__)) {
i = d.i;
d = d.data;
}
} else i = that._data.indexOf(d);
var group = !that._hover || typeof that._hover !== "function" || !that._hover(d, i) ? parent : that._hoverGroup.node();
if (group !== this.parentNode) group.appendChild(this);
if (this.className.baseVal.includes("d3plus-Shape")) {
if (parent === group) _select(this).call(that._applyStyle.bind(that));else _select(this).call(that._updateStyle.bind(that, _select(this), that._hoverStyle));
}
});
// this._renderImage();
// this._renderLabels();
this._group.selectAll("g.d3plus-".concat(this._name, "-shape, g.d3plus-").concat(this._name, "-image, g.d3plus-").concat(this._name, "-text")).attr("opacity", this._hover ? this._hoverOpacity : this._active ? this._activeOpacity : 1);
}
/**
@memberof Shape
@desc Adds background image to each shape group.
@private
*/
}, {
key: "_renderImage",
value: function _renderImage() {
var _this6 = this;
var imageData = [];
this._update.merge(this._enter).data().forEach(function (datum, i) {
var aes = _this6._aes(datum, i);
if (aes.r || aes.width && aes.height) {
var d = datum;
if (datum.nested && datum.key && datum.values) {
d = datum.values[0];
i = _this6._data.indexOf(d);
}
var height = aes.r ? aes.r * 2 : aes.height,
url = _this6._backgroundImage(d, i),
width = aes.r ? aes.r * 2 : aes.width;
if (url) {
var x = d.__d3plusShape__ ? d.translate ? d.translate[0] : _this6._x(d.data, d.i) : _this6._x(d, i),
y = d.__d3plusShape__ ? d.translate ? d.translate[1] : _this6._y(d.data, d.i) : _this6._y(d, i);
if (aes.x) x += aes.x;
if (aes.y) y += aes.y;
if (d.__d3plusShape__) {
d = d.data;
i = d.i;
}
imageData.push({
__d3plus__: true,
data: d,
height: height,
i: i,
id: _this6._id(d, i),
url: url,
width: width,
x: x + -width / 2,
y: y + -height / 2
});
}
}
});
this._backgroundImageClass.data(imageData).duration(this._duration).opacity(this._nestWrapper(this._opacity)).pointerEvents("none").select(elem("g.d3plus-".concat(this._name, "-image"), {
parent: this._group,
update: {
opacity: this._active ? this._activeOpacity : 1
}
}).node()).render();
}
/**
@memberof Shape
@desc Adds labels to each shape group.
@private
*/
}, {
key: "_renderLabels",
value: function _renderLabels() {
var _this7 = this;
var labelData = [];
this._update.merge(this._enter).data().forEach(function (datum, i) {
var d = datum;
if (datum.nested && datum.key && datum.values) {
d = datum.values[0];
i = _this7._data.indexOf(d);
}
var labels = _this7._label(d, i);
if (_this7._labelBounds && labels !== false && labels !== undefined && labels !== null) {
var bounds = _this7._labelBounds.bind(_this7)(d, i, _this7._aes(datum, i));
if (bounds) {
if (labels.constructor !== Array) labels = [labels];
var x = d.__d3plusShape__ ? d.translate ? d.translate[0] : _this7._x(d.data, d.i) : _this7._x(d, i),
y = d.__d3plusShape__ ? d.translate ? d.translate[1] : _this7._y(d.data, d.i) : _this7._y(d, i);
if (d.__d3plusShape__) {
d = d.data;
i = d.i;
}
for (var l = 0; l < labels.length; l++) {
var b = bounds.constructor === Array ? bounds[l] : Object.assign({}, bounds);
var rotate = _this7._rotate(d, i);
var r = d.labelConfig && d.labelConfig.rotate ? d.labelConfig.rotate : bounds.angle !== undefined ? bounds.angle : 0;
r += rotate;
var rotateAnchor = rotate !== 0 ? [b.x * -1 || 0, b.y * -1 || 0] : [b.width / 2, b.height / 2];
labelData.push({
__d3plus__: true,
data: d,
height: b.height,
l: l,
id: "".concat(_this7._id(d, i), "_").concat(l),
r: r,
rotateAnchor: rotateAnchor,
text: labels[l],
width: b.width,
x: x + b.x,
y: y + b.y
});
}
}
}
});
this._labelClass.data(labelData).duration(this._duration).fontOpacity(this._nestWrapper(this._opacity)).pointerEvents("none").rotate(function (d) {
return d.__d3plus__ ? d.r : d.data.r;
}).rotateAnchor(function (d) {
return d.__d3plus__ ? d.rotateAnchor : d.data.rotateAnchor;
}).select(elem("g.d3plus-".concat(this._name, "-text"), {
parent: this._group,
update: {
opacity: this._active ? this._activeOpacity : 1
}
}).node()).config(configPrep.bind(this)(this._labelConfig)).render();
}
/**
@memberof Shape
@desc Renders the current Shape to the page. If a *callback* is specified, it will be called once the shapes are done drawing.
@param {Function} [*callback*]
@chainable
*/
}, {
key: "render",
value: function render(callback) {
var _this8 = this;
if (this._select === void 0) {
this.select(_select("body").append("svg").style("width", "".concat(window.innerWidth, "px")).style("height", "".concat(window.innerHeight, "px")).style("display", "block").node());
}
this._transition = transition(this._uuid).duration(this._duration);
var data = this._data,
key = this._id;
if (this._dataFilter) {
data = this._dataFilter(data);
if (data.key) key = data.key;
}
if (this._sort) {
data = data.sort(function (a, b) {
while (a.__d3plusShape__ || a.__d3plus__) a = a.data;
while (b.__d3plusShape__ || b.__d3plus__) b = b.data;
return _this8._sort(a, b);
});
}
var textureSet = unique(data.map(this._getTextureKey.bind(this))).filter(Boolean);
var existingTextureDefs = Object.keys(this._textureDefs);
existingTextureDefs.forEach(function (key) {
if (!textureSet.includes(key)) {
_select(_this8._select.select("pattern#".concat(_this8._textureDefs[key].id())).node().parentNode).remove();
delete _this8._textureDefs[key];
}
});
textureSet.forEach(function (key) {
if (!existingTextureDefs.includes(key)) {
var config = JSON.parse(key);
var textureClass = config.texture;
delete config.texture;
var t = textures[textureClass]();
var _loop2 = function _loop2(k) {
if ({}.hasOwnProperty.call(t, k) && k in t) {
if (k === "d") t[k](function () {
return config[k];
});else config[k] instanceof Array ? t[k].apply(null, config[k]) : t[k](config[k]);
}
};
for (var k in config) {
_loop2(k);
}
_this8._select.call(t);
_this8._textureDefs[key] = t;
}
});
selectAll("g.d3plus-".concat(this._name, "-hover > *, g.d3plus-").concat(this._name, "-active > *")).each(function (d) {
if (d && d.parentNode) d.parentNode.appendChild(this);else this.parentNode.removeChild(this);
});
// Makes the update state of the group selection accessible.
this._group = elem("g.d3plus-".concat(this._name, "-group"), {
parent: this._select
});
var update = this._update = elem("g.d3plus-".concat(this._name, "-shape"), {
parent: this._group,
update: {
opacity: this._active ? this._activeOpacity : 1
}
}).selectAll(".d3plus-".concat(this._name)).data(data, key);
// Orders and transforms the updating Shapes.
update.order();
if (this._duration) {
update.transition(this._transition).call(this._applyTransform.bind(this));
} else {
update.call(this._applyTransform.bind(this));
}
// Makes the enter state of the group selection accessible.
var enter = this._enter = update.enter().append(this._tagName).attr("class", function (d, i) {
return "d3plus-Shape d3plus-".concat(_this8._name, " d3plus-id-").concat(strip(_this8._nestWrapper(_this8._id)(d, i)));
}).call(this._applyTransform.bind(this)).attr("aria-label", this._ariaLabel).attr("role", this._role).attr("opacity", this._nestWrapper(this._opacity));
var enterUpdate = enter.merge(update);
var enterUpdateRender = enterUpdate.attr("shape-rendering", this._nestWrapper(this._shapeRendering));
if (this._duration) {
enterUpdateRender = enterUpdateRender.attr("pointer-events", "none").transition(this._transition).transition().delay(100).attr("pointer-events", this._pointerEvents);
}
enterUpdateRender.attr("opacity", this._nestWrapper(this._opacity));
// Makes the exit state of the group selection accessible.
var exit = this._exit = update.exit();
if (this._duration) exit.transition().delay(this._duration).remove();else exit.remove();
this._renderImage();
this._renderLabels();
this._hoverGroup = elem("g.d3plus-".concat(this._name, "-hover"), {
parent: this._group
});
this._activeGroup = elem("g.d3plus-".concat(this._name, "-active"), {
parent: this._group
});
var hitAreas = this._group.selectAll(".d3plus-HitArea").data(this._hitArea && Object.keys(this._on).length ? data : [], key);
hitAreas.order().call(this._applyTransform.bind(this));
var isLine = this._name === "Line";
if (isLine) {
var curve = this._curve.bind(this)(this.config());
isLine && this._path.curve(paths["curve".concat(curve.charAt(0).toUpperCase()).concat(curve.slice(1))]).defined(this._defined).x(this._x).y(this._y);
}
var hitEnter = hitAreas.enter().append(isLine ? "path" : "rect").attr("class", function (d, i) {
return "d3plus-HitArea d3plus-id-".concat(strip(_this8._nestWrapper(_this8._id)(d, i)));
}).attr("fill", "black").attr("stroke", "black").attr("pointer-events", "painted").attr("opacity", 0).call(this._applyTransform.bind(this));
var that = this;
var hitUpdates = hitAreas.merge(hitEnter).each(function (d) {
var i = that._data.indexOf(d);
var h = that._hitArea(d, i, that._aes(d, i));
return h && !(that._name === "Line" && parseFloat(that._strokeWidth(d, i)) > 10) ? _select(this).call(attrize, h) : _select(this).remove();
});
hitAreas.exit().remove();
this._applyEvents(this._hitArea ? hitUpdates : enterUpdate);
setTimeout(function () {
if (_this8._active) _this8._renderActive();else if (_this8._hover) _this8._renderHover();
if (callback) callback();
}, this._duration + 100);
return this;
}
/**
@memberof Shape
@desc If *value* is specified, sets the highlight accessor to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "active",
value: function active(_) {
if (!arguments.length || _ === undefined) return this._active;
this._active = _;
if (this._group) {
// this._renderImage();
// this._renderLabels();
this._renderActive();
}
return this;
}
/**
@memberof Shape
@desc When shapes are active, this is the opacity of any shape that is not active.
@param {Number} *value* = 0.25
@chainable
*/
}, {
key: "activeOpacity",
value: function activeOpacity(_) {
return arguments.length ? (this._activeOpacity = _, this) : this._activeOpacity;
}
/**
@memberof Shape
@desc The style to apply to active shapes.
@param {Object} *value*
@chainable
*/
}, {
key: "activeStyle",
value: function activeStyle(_) {
return arguments.length ? (this._activeStyle = assign({}, this._activeStyle, _), this) : this._activeStyle;
}
/**
@memberof Shape
@desc If *value* is specified, sets the aria-label attribute to the specified function or string and returns the current class instance.
@param {Function|String} *value*
@chainable
*/
}, {
key: "ariaLabel",
value: function ariaLabel(_) {
return _ !== undefined ? (this._ariaLabel = typeof _ === "function" ? _ : constant(_), this) : this._ariaLabel;
}
/**
@memberof Shape
@desc If *value* is specified, sets the background-image accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = false]
@chainable
*/
}, {
key: "backgroundImage",
value: function backgroundImage(_) {
return arguments.length ? (this._backgroundImage = typeof _ === "function" ? _ : constant(_), this) : this._backgroundImage;
}
/**
@memberof Shape
@desc If *data* is specified, sets the data array to the specified array and returns the current class instance. If *data* is not specified, returns the current data array. A shape will be drawn for each object in the array.
@param {Array} [*data* = []]
@chainable
*/
}, {
key: "data",
value: function data(_) {
return arguments.length ? (this._data = _, this) : this._data;
}
/**
@memberof Shape
@desc Determines if either the X or Y position is discrete along a Line, which helps in determining the nearest data point on a line for a hit area event.
@param {String} *value*
@chainable
*/
}, {
key: "discrete",
value: function discrete(_) {
return arguments.length ? (this._discrete = _, this) : this._discrete;
}
/**
@memberof Shape
@desc If *ms* is specified, sets the animation duration to the specified number and returns the current class instance. If *ms* is not specified, returns the current animation duration.
@param {Number} [*ms* = 600]
@chainable
*/
}, {
key: "duration",
value: function duration(_) {
return arguments.length ? (this._duration = _, this) : this._duration;
}
/**
@memberof Shape
@desc If *value* is specified, sets the fill accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = "black"]
@chainable
*/
}, {
key: "fill",
value: function fill(_) {
return arguments.length ? (this._fill = typeof _ === "function" ? _ : constant(_), this) : this._fill;
}
/**
@memberof Shape
@desc Defines the "fill-opacity" attribute for the shapes.
@param {Function|Number} [*value* = 1]
@chainable
*/
}, {
key: "fillOpacity",
value: function fillOpacity(_) {
return arguments.length ? (this._fillOpacity = typeof _ === "function" ? _ : constant(_), this) : this._fillOpacity;
}
/**
@memberof Shape
@desc If *value* is specified, sets the highlight accessor to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "hover",
value: function hover(_) {
if (!arguments.length || _ === void 0) return this._hover;
this._hover = _;
if (this._group) {
// this._renderImage();
// this._renderLabels();
this._renderHover();
}
return this;
}
/**
@memberof Shape
@desc The style to apply to hovered shapes.
@param {Object} *value*
@chainable
*/
}, {
key: "hoverStyle",
value: function hoverStyle(_) {
return arguments.length ? (this._hoverStyle = assign({}, this._hoverStyle, _), this) : this._hoverStyle;
}
/**
@memberof Shape
@desc If *value* is specified, sets the hover opacity to the specified function and returns the current class instance.
@param {Number} [*value* = 0.5]
@chainable
*/
}, {
key: "hoverOpacity",
value: function hoverOpacity(_) {
return arguments.length ? (this._hoverOpacity = _, this) : this._hoverOpacity;
}
/**
@memberof Shape
@desc If *bounds* is specified, sets the mouse hit area to the specified function and returns the current class instance. If *bounds* is not specified, returns the current mouse hit area accessor.
@param {Function} [*bounds*] The given function is passed the data point, index, and internally defined properties of the shape and should return an object containing the following values: `width`, `height`, `x`, `y`.
@chainable
@example
function(d, i, shape) {
return {
"width": shape.width,
"height": shape.height,
"x": -shape.width / 2,
"y": -shape.height / 2
};
}
*/
}, {
key: "hitArea",
value: function hitArea(_) {
return arguments.length ? (this._hitArea = typeof _ === "function" ? _ : constant(_), this) : this._hitArea;
}
/**
@memberof Shape
@desc If *value* is specified, sets the id accessor to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "id",
value: function id(_) {
return arguments.length ? (this._id = _, this) : this._id;
}
/**
@memberof Shape
@desc If *value* is specified, sets the label accessor to the specified function or string and returns the current class instance.
@param {Function|String|Array} [*value*]
@chainable
*/
}, {
key: "label",
value: function label(_) {
return arguments.length ? (this._label = typeof _ === "function" ? _ : constant(_), this) : this._label;
}
/**
@memberof Shape
@desc If *bounds* is specified, sets the label bounds to the specified function and returns the current class instance. If *bounds* is not specified, returns the current inner bounds accessor.
@param {Function} [*bounds*] The given function is passed the data point, index, and internally defined properties of the shape and should return an object containing the following values: `width`, `height`, `x`, `y`. If an array is returned from the function, each value will be used in conjunction with each label.
@chainable
@example
function(d, i, shape) {
return {
"width": shape.width,
"height": shape.height,
"x": -shape.width / 2,
"y": -shape.height / 2
};
}
*/
}, {
key: "labelBounds",
value: function labelBounds(_) {
return arguments.length ? (this._labelBounds = typeof _ === "function" ? _ : constant(_), this) : this._labelBounds;
}
/**
@memberof Shape
@desc A pass-through to the config method of the TextBox class used to create a shape's labels.
@param {Object} [*value*]
@chainable
*/
}, {
key: "labelConfig",
value: function labelConfig(_) {
return arguments.length ? (this._labelConfig = assign(this._labelConfig, _), this) : this._labelConfig;
}
/**
@memberof Shape
@desc If *value* is specified, sets the opacity accessor to the specified function or number and returns the current class instance.
@param {Number} [*value* = 1]
@chainable
*/
}, {
key: "opacity",
value: function opacity(_) {
return arguments.length ? (this._opacity = typeof _ === "function" ? _ : constant(_), this) : this._opacity;
}
/**
@memberof Shape
@desc If *value* is specified, sets the pointerEvents accessor to the specified function or string and returns the current class instance.
@param {String} [*value*]
@chainable
*/
}, {
key: "pointerEvents",
value: function pointerEvents(_) {
return arguments.length ? (this._pointerEvents = typeof _ === "function" ? _ : constant(_), this) : this._pointerEvents;
}
/**
@memberof Shape
@desc If *value* is specified, sets the role attribute to the specified function or string and returns the current class instance.
@param {Function|String} *value*
@chainable
*/
}, {
key: "role",
value: function role(_) {
return _ !== undefined ? (this._role = typeof _ === "function" ? _ : constant(_), this) : this._role;
}
/**
@memberof Shape
@desc If *value* is specified, sets the rotate accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value* = 0]
@chainable
*/
}, {
key: "rotate",
value: function rotate(_) {
return arguments.length ? (this._rotate = typeof _ === "function" ? _ : constant(_), this) : this._rotate;
}
/**
@memberof Shape
@desc Defines the "rx" attribute for the shapes.
@param {Function|Number} [*value* = 0]
@chainable
*/
}, {
key: "rx",
value: function rx(_) {
return arguments.length ? (this._rx = typeof _ === "function" ? _ : constant(_), this) : this._rx;
}
/**
@memberof Shape
@desc Defines the "rx" attribute for the shapes.
@param {Function|Number} [*value* = 0]
@chainable
*/
}, {
key: "ry",
value: function ry(_) {
return arguments.length ? (this._ry = typeof _ === "function" ? _ : constant(_), this) : this._ry;
}
/**
@memberof Shape
@desc If *value* is specified, sets the scale accessor to the specified function or string and returns the current class instance.
@param {Function|Number} [*value* = 1]
@chainable
*/
}, {
key: "scale",
value: function scale(_) {
return arguments.length ? (this._scale = typeof _ === "function" ? _ : constant(_), this) : this._scale;
}
/**
@memberof Shape
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element.
@param {String|HTMLElement} [*selector* = d3.select("body").append("svg")]
@chainable
*/
}, {
key: "select",
value: function select(_) {
return arguments.length ? (this._select = _select(_), this) : this._select;
}
/**
@memberof Shape
@desc If *value* is specified, sets the shape-rendering accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = "geometricPrecision"]
@chainable
@example
function(d) {
return d.x;
}
*/
}, {
key: "shapeRendering",
value: function shapeRendering(_) {
return arguments.length ? (this._shapeRendering = typeof _ === "function" ? _ : constant(_), this) : this._shapeRendering;
}
/**
@memberof Shape
@desc If *value* is specified, sets the sort comparator to the specified function and returns the current class instance.
@param {false|Function} [*value* = []]
@chainable
*/
}, {
key: "sort",
value: function sort(_) {
return arguments.length ? (this._sort = _, this) : this._sort;
}
/**
@memberof Shape
@desc If *value* is specified, sets the stroke accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = "black"]
@chainable
*/
}, {
key: "stroke",
value: function stroke(_) {
return arguments.length ? (this._stroke = typeof _ === "function" ? _ : constant(_), this) : this._stroke;
}
/**
@memberof Shape
@desc Defines the "stroke-dasharray" attribute for the shapes.
@param {Function|String} [*value* = "1"]
@chainable
*/
}, {
key: "strokeDasharray",
value: function strokeDasharray(_) {
return arguments.length ? (this._strokeDasharray = typeof _ === "function" ? _ : constant(_), this) : this._strokeDasharray;
}
/**
@memberof Shape
@desc Defines the "stroke-linecap" attribute for the shapes. Accepted values are `"butt"`, `"round"`, and `"square"`.
@param {Function|String} [*value* = "butt"]
@chainable
*/
}, {
key: "strokeLinecap",
value: function strokeLinecap(_) {
return arguments.length ? (this._strokeLinecap = typeof _ === "function" ? _ : constant(_), this) : this._strokeLinecap;
}
/**
@memberof Shape
@desc Defines the "stroke-opacity" attribute for the shapes.
@param {Function|Number} [*value* = 1]
@chainable
*/
}, {
key: "strokeOpacity",
value: function strokeOpacity(_) {
return arguments.length ? (this._strokeOpacity = typeof _ === "function" ? _ : constant(_), this) : this._strokeOpacity;
}
/**
@memberof Shape
@desc If *value* is specified, sets the stroke-width accessor to the specified function or string and returns the current class instance.
@param {Function|Number} [*value* = 0]
@chainable
*/
}, {
key: "strokeWidth",
value: function strokeWidth(_) {
return arguments.length ? (this._strokeWidth = typeof _ === "function" ? _ : constant(_), this) : this._strokeWidth;
}
/**
@memberof Shape
@desc If *value* is specified, sets the text-anchor accessor to the specified function or string and returns the current class instance.
@param {Function|String|Array} [*value* = "start"]
@chainable
*/
}, {
key: "textAnchor",
value: function textAnchor(_) {
return arguments.length ? (this._textAnchor = typeof _ === "function" ? _ : constant(_), this) : this._textAnchor;
}
/**
@memberof Shape
@desc Defines the texture used inside of each shape. This uses the [textures.js](https://riccardoscalco.it/textures/) package, and expects either a simple string (`"lines"` or `"circles"`) or a more complex Object containing the various properties of the texture (ie. `{texture: "lines", orientation: "3/8", stroke: "darkorange"}`). If multiple textures are necessary, provide an accsesor Function that returns the correct String/Object for each given data point and index.
@param {String|Object|Function} [*value*]
@chainable
*/
}, {
key: "texture",
value: function texture(_) {
return arguments.length ? (this._texture = typeof _ === "function" ? _ : constant(_), this) : this._texture;
}
/**
@memberof Shape
@desc A series of global texture methods to be used for all textures (ie. `{stroke: "darkorange", strokeWidth: 2}`).
@param {Object} [*value*]
@chainable
*/
}, {
key: "textureDefault",
value: function textureDefault(_) {
return arguments.length ? (this._textureDefault = assign(this._textureDefault, _), this) : this._textureDefault;
}
/**
@memberof Shape
@desc If *value* is specified, sets the vector-effect accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = "non-scaling-stroke"]
@chainable
*/
}, {
key: "vectorEffect",
value: function vectorEffect(_) {
return arguments.length ? (this._vectorEffect = typeof _ === "function" ? _ : constant(_), this) : this._vectorEffect;
}
/**
@memberof Shape
@desc If *value* is specified, sets the vertical alignment accessor to the specified function or string and returns the current class instance.
@param {Function|String|Array} [*value* = "start"]
@chainable
*/
}, {
key: "verticalAlign",
value: function verticalAlign(_) {
return arguments.length ? (this._verticalAlign = typeof _ === "function" ? _ : constant(_), this) : this._verticalAlign;
}
/**
@memberof Shape
@desc If *value* is specified, sets the x accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.x;
}
*/
}, {
key: "x",
value: function x(_) {
return arguments.length ? (this._x = typeof _ === "function" ? _ : constant(_), this) : this._x;
}
/**
@memberof Shape
@desc If *value* is specified, sets the y accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.y;
}
*/
}, {
key: "y",
value: function y(_) {
return arguments.length ? (this._y = typeof _ === "function" ? _ : constant(_), this) : this._y;
}
}]);
return Shape;
}(BaseClass);
export { Shape as default };