UNPKG

d3plus-shape

Version:

Fancy SVG shapes for visualizations

1,088 lines (944 loc) 39.4 kB
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _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, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } 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 _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 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 } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } /** @external BaseClass @see https://github.com/d3plus/d3plus-common#BaseClass */ import { min } from "d3-array"; import { color } from "d3-color"; import { mouse, select as _select, selectAll } from "d3-selection"; import { transition } from "d3-transition"; import { accessor, assign, attrize, BaseClass, configPrep, constant, elem } from "d3plus-common"; import { colorContrast } from "d3plus-color"; import * as paths from "d3-shape"; import { strip, TextBox } from "d3plus-text"; import Image from "../Image"; import pointDistance from "../geom/pointDistance"; /** @class Shape @extends external:BaseClass @desc An abstracted class for generating shapes. */ var Shape = /*#__PURE__*/ function (_BaseClass) { _inherits(Shape, _BaseClass); /** @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 = _possibleConstructorReturn(this, _getPrototypeOf(Shape).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); }; _this._strokeDasharray = constant("0"); _this._strokeLinecap = constant("butt"); _this._strokeOpacity = constant(1); _this._strokeWidth = constant(0); _this._tagName = tagName; _this._textAnchor = constant("start"); _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 (d, i) { if (!_this2._on[events[e]]) return; if (d.i !== void 0) i = d.i; if (d.nested && d.values) { var cursor = mouse(_this2._select.node()), values = d.values.map(function (d) { return pointDistance(cursor, [_this2._x(d, i), _this2._y(d, i)]); }); d = d.values[values.indexOf(min(values))]; } _this2._on[events[e]].bind(_this2)(d, i); }); }; 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 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", styleLogic.bind(this._fill)).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 _this3 = this; elem.attr("transform", function (d, i) { return "\n translate(".concat(d.__d3plusShape__ ? d.translate ? d.translate : "".concat(_this3._x(d.data, d.i), ",").concat(_this3._y(d.data, d.i)) : "".concat(_this3._x(d, i), ",").concat(_this3._y(d, i)), ")\n scale(").concat(d.__d3plusShape__ ? d.scale || _this3._scale(d.data, d.i) : _this3._scale(d, i), ")\n rotate(").concat(d.__d3plusShape__ ? d.rotate ? d.rotate : _this3._rotate(d.data || d, d.i) : _this3._rotate(d.data || d, d.i), ")"); }); } /** @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 _this4 = this; var imageData = []; this._update.merge(this._enter).data().forEach(function (datum, i) { var aes = _this4._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 = _this4._data.indexOf(d); } var height = aes.r ? aes.r * 2 : aes.height, url = _this4._backgroundImage(d, i), width = aes.r ? aes.r * 2 : aes.width; if (url) { var x = d.__d3plusShape__ ? d.translate ? d.translate[0] : _this4._x(d.data, d.i) : _this4._x(d, i), y = d.__d3plusShape__ ? d.translate ? d.translate[1] : _this4._y(d.data, d.i) : _this4._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: _this4._id(d, i), url: url, width: width, x: x + -width / 2, y: y + -height / 2 }); } } }); this._backgroundImageClass.data(imageData).duration(this._duration).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 _this5 = 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 = _this5._data.indexOf(d); } var labels = _this5._label(d, i); if (_this5._labelBounds && labels !== false && labels !== undefined && labels !== null) { var bounds = _this5._labelBounds(d, i, _this5._aes(datum, i)); if (bounds) { if (labels.constructor !== Array) labels = [labels]; var x = d.__d3plusShape__ ? d.translate ? d.translate[0] : _this5._x(d.data, d.i) : _this5._x(d, i), y = d.__d3plusShape__ ? d.translate ? d.translate[1] : _this5._y(d.data, d.i) : _this5._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 = _this5._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(_this5._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).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 _this6 = 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().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 _this6._sort(a, b); }); } 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(_this6._name, " d3plus-id-").concat(strip(_this6._nestWrapper(_this6._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 ? data : [], key); hitAreas.order().call(this._applyTransform.bind(this)); var isLine = this._name === "Line"; isLine && this._path.curve(paths["curve".concat(this._curve.charAt(0).toUpperCase()).concat(this._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(_this6._nestWrapper(_this6._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 (_this6._active) _this6._renderActive();else if (_this6._hover) _this6._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 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 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 };