UNPKG

d3plus-shape

Version:

Fancy SVG shapes for visualizations

261 lines (236 loc) 9.3 kB
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; } import { select as _select } from "d3-selection"; import { transition } from "d3-transition"; import { accessor, constant } from "d3plus-common"; /** @class Image @desc Creates SVG images based on an array of data. @example <caption>a sample row of data</caption> var data = {"url": "file.png", "width": "100", "height": "50"}; @example <caption>passed to the generator</caption> new Image().data([data]).render(); @example <caption>creates the following</caption> <image class="d3plus-Image" opacity="1" href="file.png" width="100" height="50" x="0" y="0"></image> @example <caption>this is shorthand for the following</caption> image().data([data])(); @example <caption>which also allows a post-draw callback function</caption> image().data([data])(function() { alert("draw complete!"); }) */ var Image = /*#__PURE__*/ function () { /** @memberof Image @desc Invoked when creating a new class instance, and sets any default parameters. @private */ function Image() { _classCallCheck(this, Image); this._duration = 600; this._height = accessor("height"); this._id = accessor("id"); this._pointerEvents = constant("auto"); this._select; this._url = accessor("url"); this._width = accessor("width"); this._x = accessor("x", 0); this._y = accessor("y", 0); } /** @memberof Image @desc Renders the current Image to the page. If a *callback* is specified, it will be called once the images are done drawing. @param {Function} [*callback*] @chainable */ _createClass(Image, [{ key: "render", value: function render(callback) { var _this = 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()); var images = this._select.selectAll(".d3plus-Image").data(this._data, this._id); var enter = images.enter().append("image").attr("class", "d3plus-Image").attr("opacity", 0).attr("width", 0).attr("height", 0).attr("x", function (d, i) { return _this._x(d, i) + _this._width(d, i) / 2; }).attr("y", function (d, i) { return _this._y(d, i) + _this._height(d, i) / 2; }); var t = transition().duration(this._duration), that = this, update = enter.merge(images); update.attr("xlink:href", this._url).style("pointer-events", this._pointerEvents).transition(t).attr("opacity", 1).attr("width", function (d, i) { return _this._width(d, i); }).attr("height", function (d, i) { return _this._height(d, i); }).attr("x", function (d, i) { return _this._x(d, i); }).attr("y", function (d, i) { return _this._y(d, i); }).each(function (d, i) { var image = _select(this), link = that._url(d, i); var fullAddress = link.indexOf("http://") === 0 || link.indexOf("https://") === 0; if (!fullAddress || link.indexOf(window.location.hostname) === 0) { var img = new Image(); img.src = link; img.crossOrigin = "Anonymous"; img.onload = function () { var canvas = document.createElement("canvas"); canvas.width = this.width; canvas.height = this.height; var context = canvas.getContext("2d"); context.drawImage(this, 0, 0); image.attr("xlink:href", canvas.toDataURL("image/png")); }; } }); images.exit().transition(t).attr("width", function (d, i) { return _this._width(d, i); }).attr("height", function (d, i) { return _this._height(d, i); }).attr("x", function (d, i) { return _this._x(d, i); }).attr("y", function (d, i) { return _this._y(d, i); }).attr("opacity", 0).remove(); if (callback) setTimeout(callback, this._duration + 100); return this; } /** @memberof Image @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. An <image> tag 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 Image @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 Image @desc If *value* is specified, sets the height accessor to the specified function or number and returns the current class instance. @param {Function|Number} [*value*] @chainable @example function(d) { return d.height; } */ }, { key: "height", value: function height(_) { return arguments.length ? (this._height = typeof _ === "function" ? _ : constant(_), this) : this._height; } /** @memberof Image @desc If *value* is specified, sets the id accessor to the specified function and returns the current class instance. @param {Function} [*value*] @chainable @example function(d) { return d.id; } */ }, { key: "id", value: function id(_) { return arguments.length ? (this._id = _, this) : this._id; } /** @memberof Image @desc If *value* is specified, sets the pointer-events accessor to the specified function or string and returns the current class instance. @param {Function|String} [*value* = "auto"] @chainable */ }, { key: "pointerEvents", value: function pointerEvents(_) { return arguments.length ? (this._pointerEvents = typeof _ === "function" ? _ : constant(_), this) : this._pointerEvents; } /** @memberof Image @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 Image @desc If *value* is specified, sets the URL accessor to the specified function and returns the current class instance. @param {Function} [*value*] @chainable @example function(d) { return d.url; } */ }, { key: "url", value: function url(_) { return arguments.length ? (this._url = _, this) : this._url; } /** @memberof Image @desc If *value* is specified, sets the width accessor to the specified function or number and returns the current class instance. @param {Function|Number} [*value*] @chainable @example function(d) { return d.width; } */ }, { key: "width", value: function width(_) { return arguments.length ? (this._width = typeof _ === "function" ? _ : constant(_), this) : this._width; } /** @memberof Image @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 || 0; } */ }, { key: "x", value: function x(_) { return arguments.length ? (this._x = typeof _ === "function" ? _ : constant(_), this) : this._x; } /** @memberof Image @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 || 0; } */ }, { key: "y", value: function y(_) { return arguments.length ? (this._y = typeof _ === "function" ? _ : constant(_), this) : this._y; } }]); return Image; }(); export { Image as default };