UNPKG

@huangjs888/d3-chart

Version:

Implement some charts based on d3 library.

919 lines (917 loc) 39.6 kB
"use strict"; var _WeakMap = require("@babel/runtime-corejs3/core-js/weak-map"); var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs3/core-js/object/get-own-property-descriptor"); var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = generateHeatMap; var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/objectWithoutPropertiesLoose")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/assertThisInitialized")); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/inheritsLoose")); var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/extends")); var _findIndex = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/instance/find-index")); var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/instance/map")); var _slice = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/instance/slice")); var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/instance/concat")); var d3 = _interopRequireWildcard(require("d3")); var _BaseChart = _interopRequireDefault(require("../BaseChart")); var _LineGraph = _interopRequireDefault(require("../LineGraph")); var util = _interopRequireWildcard(require("../util")); var _excluded = ["data", "tooltip", "legend", "scale"], _excluded2 = ["heat"], _excluded3 = ["width", "height", "padding"], _excluded4 = ["heat"], _excluded5 = ["z"], _excluded6 = ["z"]; // @ts-nocheck /* * @Author: Huangjs * @Date: 2021-12-07 15:02:48 * @LastEditors: Huangjs * @LastEditTime: 2023-10-24 14:21:19 * @Description: 按需生成HeatMap构造器 */ function _getRequireWildcardCache(nodeInterop) { if (typeof _WeakMap !== "function") return null; var cacheBabelInterop = new _WeakMap(); var cacheNodeInterop = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && _Object$getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? _Object$getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } var iconSize = 18; var prefixSIFormat = d3.format('~s'); // 折半查找指定像素val在数组arr的哪个像素范围内 var searchValIndex = function searchValIndex(val, arr) { var n1 = 0; var n2 = arr.length; var c = 0; var binSize = n2 > 1 ? (arr[n2 - 1] - arr[0]) / (n2 - 1) : 1; var n; var test; if (binSize >= 0) { test = function test(a, b) { return a <= b; }; } else { test = function test(a, b) { return a > b; }; } // don't trust floating point equality - fraction of bin size to call var v = val + binSize * 1e-9 * (binSize >= 0 ? 1 : -1); // c is just to avoid infinite loops if there's an error while (n1 < n2 && c < 100) { c += 1; n = Math.floor((n1 + n2) / 2); if (test(arr[n], v)) n1 = n + 1;else n2 = n; } if (c > 90) window.console.log('Long binary search...'); return Math.min(Math.max(n1 - 1, 0), arr.length - 1); }; // 计算两值之间任意值占比以及前后值 var computeFactor = function computeFactor(val, val0, val1, bin0, bin1) { var factor = (val - val0) / (val1 - val0) || 0; if (factor <= 0) { return { factor: 0, bin0: bin0, bin1: bin0 }; } if (factor > 0.5) { return { factor: 1 - factor, bin0: bin1, bin1: bin0 }; } return { factor: factor, bin0: bin0, bin1: bin1 }; }; // 计算每个像素对应值的插值计算比例 var getInterpFactor = function getInterpFactor(pixel, valPixs) { var index0 = searchValIndex(pixel, valPixs); var index1 = index0 + 1; return computeFactor(pixel, valPixs[index0], valPixs[index1], index0, index1); }; // 根据四个点计算中间点的平均值 var matrixAverage = function matrixAverage(xFactor, val00, val01, yFactor, val10, val11) { var val = 0; if (val00 !== undefined) { var dx = val01 - val00 || 0; var dy = val10 - val00 || 0; var dxy = 0; if (val01 === undefined) { if (val11 === undefined) dxy = 0;else if (val10 === undefined) dxy = 2 * (val11 - val00);else dxy = (2 * val11 - val10 - val00) * 2 / 3; } else if (val11 === undefined) { if (val10 === undefined) dxy = 0;else dxy = (2 * val00 - val01 - val10) * 2 / 3; } else if (val10 === undefined) dxy = (2 * val11 - val01 - val00) * 2 / 3;else dxy = val11 + val00 - val01 - val10; val = val00 + (xFactor || 0) * dx + (yFactor || 0) * (dy + (xFactor || 0) * dxy); } return val; }; // 将给定值数组中的值映射到给定长度的每一个像素点上 // 若值数组长度比像素点多,则会均匀抽稀映射 // 若值数组长度比像素点少,则会平滑插值映射 var valueForPixel = function valueForPixel(value, pixel, reverse) { var valPixs = []; var len = value.length; var minVal = value[0]; var maxVal = value[len - 1]; for (var i = 0; i < len; i += 1) { valPixs[reverse ? len - 1 - i : i] = Math.round(Math.round(100 * pixel * ((value[i] - minVal) / (maxVal - minVal))) / 100); } return valPixs; }; // 矩阵插值上色(根据矩形四个点值,计算矩形内部所有像素点的值,并渲染颜色) var matrixInterp = function matrixInterp(_ref, _ref2, c) { var w = _ref.w, h = _ref.h, d = _ref.d; var x = _ref2.x, y = _ref2.y, z = _ref2.z; var _d$ = d[0], x0 = _d$[0], y0 = _d$[1], _d$2 = d[1], x1 = _d$2[0], y1 = _d$2[1]; var cw = x1 - x0; var ch = y1 - y0; var xValPixs = valueForPixel(x, w); var yValPixs = valueForPixel(y, h, true); var pixels; var index = 0; try { pixels = new Uint8Array(cw * ch * 4); } catch (e) { pixels = new Array(cw * ch * 4); } var xInterpArray = []; var _loop = function _loop() { var yInterp = getInterpFactor(j, yValPixs); var val0 = z[yInterp.bin0] || []; var val1 = z[yInterp.bin1] || []; // 获取y轴(横向)范围内无效索引集合 var yInvalidIndex = y.invalid || []; // 判断当前横向一整条像素的上bin0下bin1都是无效索引,则无效 var yInvalid = (0, _findIndex.default)(yInvalidIndex).call(yInvalidIndex, function (o) { return o === yInterp.bin0 || o === yInterp.bin1; }) !== -1; var _loop2 = function _loop2() { var rgba = { r: 0, g: 0, b: 0, opacity: 0 }; // 有效才计算颜色 if (!yInvalid) { var xInterp = xInterpArray[i]; if (!xInterp) { xInterp = getInterpFactor(i, xValPixs); xInterpArray[i] = xInterp; } // 获取x轴(竖向)范围内无效索引集合 var xInvalidIndex = x.invalid || []; // 判断当前像素点的左bin0右bin1都是无效索引,则无效 var xInvalid = (0, _findIndex.default)(xInvalidIndex).call(xInvalidIndex, function (o) { return o === xInterp.bin0 || o === xInterp.bin1; }) !== -1; // 有效才计算颜色 if (!xInvalid) { rgba = c(matrixAverage(xInterp.factor, val0[xInterp.bin0], val0[xInterp.bin1], yInterp.factor, val1[xInterp.bin0], val1[xInterp.bin1])); } } pixels[index] = rgba.r; pixels[index + 1] = rgba.g; pixels[index + 2] = rgba.b; pixels[index + 3] = rgba.opacity * 255; // 透明度0-1需要转换成0-255 index += 4; }; for (var i = x0; i < x1; i += 1) { _loop2(); } }; for (var j = y0; j < y1; j += 1) { _loop(); } return pixels; }; function drawend(zContext, _ref3) { var xScale = _ref3.xScale, yScale = _ref3.yScale; zContext.save(); // 先清空画布 zContext.clearRect(0, 0, this.width$, this.height$); if (this.showHeat$) { var zScale = this.zScale$; var viewRange = null; var _this$data$heat = this.data.heat, x = _this$data$heat.x, y = _this$data$heat.y, z = _this$data$heat.z; // 原始范围 // 根据xy轴的刻度变换函数分别计算出原始数据图的上下左右坐标位置 var xMinPx = xScale(x[0] || 0); var xMaxPx = xScale(x[x.length - 1] || 0); // 因为y坐标是反转的(domain和range大小反转对应) var yMinPx = yScale(y[y.length - 1] || 0); var yMaxPx = yScale(y[0] || 0); // 原始数据的实际宽高 var width = Math.round(xMaxPx - xMinPx); var height = Math.round(yMaxPx - yMinPx); // 如果实际的宽高小于或等于0则表示压根没有数据 if (width > 0 && height > 0) { // 画布范围 // 画布上下左右坐标位置,this.width$, this.height$是画布的宽高 var xcMinPx = 0; var xcMaxPx = this.width$ + xcMinPx; var ycMinPx = 0; var ycMaxPx = this.height$ + ycMinPx; // 真实渲染的数据,是原始数据的范围,配置中筛选的范围以及画布的范围最终确定 // 根据以上三个范围计算确定真正需要渲染的范围,要考虑此范围的两个问题: // 1,对于原始数据段转换的像素范围,应该选择哪一段像素去渲染? // 2,对于视图,这一段数据应该渲染在画布上哪一个范围(在画布内部的位置)? // 以下计算需要渲染的像素段在原始数据像素范围内(宽和高)起点和终点的索引 var xMin = Math.max(xcMinPx, xMinPx); // 取x最小范围中的最大值 var xMax = Math.min(xcMaxPx, xMaxPx); // 取x最大范围中的最小值 var yMin = Math.max(ycMinPx, yMinPx); // 取y最小范围中的最大值 var yMax = Math.min(ycMaxPx, yMaxPx); // 取y最大范围中的最小值 // 实际被裁减后的宽高(可能等于画布宽高,也可能小于,但是不会大于因为被裁掉了) var dataRange = [[Math.round(xMin - xMinPx), Math.round(yMin - yMinPx)], // 筛选后数据在原数据的起点index [Math.round(xMax - xMinPx), Math.round(yMax - yMinPx)] // 筛选后数据在原数据的终点index ]; var cWidth = dataRange[1][0] - dataRange[0][0]; var cHeight = dataRange[1][1] - dataRange[0][1]; // 如果裁剪后的宽高小于或等于0则表示没有可以渲染的数据了 if (cWidth > 0 && cHeight > 0) { // 计算出渲染图片的每个像素rgba值 var pixelData = matrixInterp({ w: width, h: height, d: dataRange }, { x: x, y: y, z: z }, function (v) { // 老版本d3得到的rgba是字符串,新版本d3是对象,这里做个兼容 var rgba = zScale(v); return typeof rgba === 'string' ? d3.color(rgba) : rgba; }); // 创建一个空的图片数据(使用裁剪后的宽高) var imageData = zContext.createImageData(cWidth, cHeight); // 将像素数据设置到图片数据内 try { imageData.data.set(pixelData); } catch (e) { var cdata = imageData.data; var len = cdata.length; for (var i = 0; i < len; i += 1) { cdata[i] = pixelData[i]; } } // 以下计在算在画布上需要渲染的范围起点和终点的位置(相对于画布) viewRange = [[xMin - xcMinPx, yMin - ycMinPx], [xMax - xcMinPx, yMax - ycMinPx]]; // 将计算好的数据放到画布 zContext.putImageData(imageData, Math.round(viewRange[0][0]), Math.round(viewRange[0][1])); var canvas = this.tempCanvas$.canvas; if (canvas) { // 存储渲染后的裁剪数据和图片数据 canvas.width = cWidth; canvas.height = cHeight; canvas.getContext('2d').putImageData(imageData, 0, 0); } } } this.tempCanvas$.range = !viewRange ? null : (0, _map.default)(viewRange).call(viewRange, function (r) { return (0, _map.default)(r).call(r, function (v, i) { return (i === 0 ? xScale : yScale).invert(v); }); }); } zContext.restore(); } function drawing(zContext, _ref4) { var xScale = _ref4.xScale, yScale = _ref4.yScale; if (this.showHeat$) { var lineMarkX = this.lineMark$[0]; if (lineMarkX.node()) { var xp = xScale(lineMarkX.datum()) || (!this.scale.x ? this.width$ : 0); lineMarkX.style('left', xp + "px").style('display', xp < 0 || xp >= this.width$ ? 'none' : 'block'); } var lineMarkY = this.lineMark$[1]; if (lineMarkY.node()) { var yp = yScale(lineMarkY.datum()) || (!this.scale.y ? 0 : this.height$); lineMarkY.style('top', yp + "px").style('display', yp < 0 || yp >= this.height$ ? 'none' : 'block'); } var _this$tempCanvas$ = this.tempCanvas$, canvas = _this$tempCanvas$.canvas, range = _this$tempCanvas$.range; if (range) { // 将上一次变换后的图,经过本次变换的变形重新绘制到画布上 var _range$map = (0, _map.default)(range).call(range, function (r) { return (0, _map.default)(r).call(r, function (v, i) { return (i === 0 ? xScale : yScale)(v); }); }), _range$map$ = _range$map[0], x0 = _range$map$[0], y0 = _range$map$[1], _range$map$2 = _range$map[1], x1 = _range$map$2[0], y1 = _range$map$2[1]; zContext.save(); zContext.clearRect(0, 0, this.width$, this.height$); zContext.drawImage(canvas, x0, y0, x1 - x0, y1 - y0); zContext.restore(); } } } function tipCompute(prevRes, point, scaleAxis) { var scaleOpt = this.scale; var _this$tooltip = this.tooltip, cross = _this$tooltip.cross, average = _this$tooltip.average; var _ref5 = cross === 'xy' ? this.getPointData(point, scaleAxis, average) : { point: point, value: [] }, newPoint = _ref5.point, value = _ref5.value; if (value.length > 0) { var _context, _context2; // 去掉第一个因为第一个是标题 var prevValue = (0, _slice.default)(_context = prevRes.data || []).call(_context, 1); var ndata = (0, _concat.default)(_context2 = []).call(_context2, (0, _map.default)(value).call(value, function (v, i) { var k = i === 0 ? 'x' : i === 1 ? 'y' : 'z'; return (0, _extends2.default)({}, scaleOpt[scaleAxis[k] ? k : "" + k + (k != 'z' ? '2' : '')], { value: v }); }), prevValue); var result = function result(selection) { selection.selectAll('div').data(ndata).join('div').attr('style', 'white-space: nowrap;').html(function (d, i) { return i === 0 ? "" + (d.label ? d.label + ": " : '') + d.format(d.value) + (d.unit || '') : (!d.color ? '' : "<span style=\"background: " + d.color + "; width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 8px;\"></span>") + "<span>" + (d.label ? d.label + ": " : '') + "</span><span style=\"display: inline-block; " + (!d.color ? '' : 'margin-left: 30px;') + "\">" + d.format(d.value) + (d.unit || '') + "</span>"; }); }; return { x0: newPoint[0], y0: newPoint[1], data: ndata, result: result }; } return (0, _extends2.default)({}, prevRes); } function updateScale() { if (this.scale.z) { var zFormat = this.scale.z.format || function (v) { return v; }; var _ref6 = this.scale.z.domain || [], opacity = _ref6[0], range = _ref6[1], domain = _ref6[2]; opacity = opacity || 1; range = range || ['#000', '#fff']; domain = domain || [0, 1]; this.zScale$.range((0, _map.default)(range).call(range, function (c) { return d3.color(c).copy({ opacity: opacity }); })).domain(domain).clamp(true); // 设置true可以卡住所给不在domain中的参数生成的数据仍然在range范围内 if (this.legend) { var linearGradient = this.rootSelection$.select('linearGradient'); var heatLegend = this.rootSelection$.select('.heatLegend'); var height = this.height$; var startDomain = domain[0]; var deltDomain = domain[domain.length - 1] - startDomain; var width = this.legend.width; linearGradient.selectAll('stop').data(domain).join('stop').attr('offset', function (v) { return 100 * (v - startDomain) / deltDomain + "%"; }).attr('stop-color', function (_, i) { return range[i]; }); heatLegend.selectAll('g').data(domain).join(function (enter) { var tick = enter.append('g').attr('class', 'tick').attr('transform', function (v) { return "translate(" + width + "," + height * (1 - (v - startDomain) / deltDomain) + ")"; }); tick.append('path').attr('d', 'M0,0 L4,4 L4,-4 Z'); tick.append('text').attr('x', 8).attr('dy', '0.32em').attr('text-anchor', 'start').text(function (v) { return zFormat(v); }); return tick; }, function (update) { update.attr('transform', function (v) { return "translate(" + width + "," + height * (1 - (v - startDomain) / deltDomain) + ")"; }); update.select('text').text(function (v) { return zFormat(v); }); return update; }); } } } function doubleClick(point, _ref7) { var xScale = _ref7.xScale, yScale = _ref7.yScale; var result = {}; if (this.showHeat$) { var heatData = this.data.heat; var x0 = point[0], y0 = point[1]; var _ref8 = [], xval = _ref8[0], yval = _ref8[1]; var lineMarkX = this.lineMark$[0]; if (lineMarkX.node()) { xval = Math.max(Math.min(+xScale.invert(x0), heatData.x[heatData.x.length - 1]), heatData.x[0]); x0 = xScale(xval); lineMarkX.style('left', x0 + "px").style('display', 'block'); } var lineMarkY = this.lineMark$[1]; if (lineMarkY.node()) { yval = Math.max(Math.min(+yScale.invert(y0), heatData.y[heatData.y.length - 1]), heatData.y[0]); y0 = yScale(yval); lineMarkY.style('top', y0 + "px").style('display', 'block'); } this.setLineMark([xval, yval], function (res) { result = res; }); } return result; } function generateHeatMap(superName) { var HeatMap = /*#__PURE__*/function (_ref9) { (0, _inheritsLoose2.default)(HeatMap, _ref9); function HeatMap() { var _this; var _ref10 = (arguments.length <= 0 ? undefined : arguments[0]) || {}, data = _ref10.data, tooltip = _ref10.tooltip, legend = _ref10.legend, scale = _ref10.scale, restOptions = (0, _objectWithoutPropertiesLoose2.default)(_ref10, _excluded); var _ref11 = data || {}, heat = _ref11.heat, restData = (0, _objectWithoutPropertiesLoose2.default)(_ref11, _excluded2); var rWidth = restOptions.rWidth; if (legend) { legend.show = !!legend.show; legend.left = util.isNumber(legend.left) ? legend.left : 0; legend.width = util.isNumber(legend.width) ? legend.width : 0; legend.right = util.isNumber(legend.right) ? legend.right : 0; if (legend.show) { rWidth = (util.isNumber(rWidth) ? rWidth : 0) + legend.left + legend.width + legend.right; } } _this = _ref9.call(this, (0, _extends2.default)({}, restOptions, { rWidth: rWidth, data: (0, _extends2.default)({ heat: !heat ? { x: [], y: [], z: [] } : { x: heat.x || [], y: heat.y || [], z: heat.z || [] } }, restData), tooltip: !tooltip ? false : (0, _extends2.default)({ cross: 'xy', select: '', average: true }, tooltip, { compute: function compute(res) { var _context3; for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } var result = tipCompute.call.apply(tipCompute, (0, _concat.default)(_context3 = [(0, _assertThisInitialized2.default)(_this), res]).call(_context3, args)); if (typeof tooltip.compute === 'function') { var _tooltip$compute, _context4; result = (_tooltip$compute = tooltip.compute).call.apply(_tooltip$compute, (0, _concat.default)(_context4 = [(0, _assertThisInitialized2.default)(_this), result]).call(_context4, args)); } return result; } }), scale: (0, _extends2.default)({ /* z: { type: 'linear', // 坐标类型 ticks: 5, // 坐标刻度数目 format: (v) => v, // 坐标值格式化函数 domain: [0, ['#fff', '#fff'], [0, 0]], // 值的色域范围和透明度 label: '', // 坐标名称 unit: '', // 坐标值单位 }, */ z: { format: prefixSIFormat } }, scale) })) || this; _this.legend = legend; _this.showHeat$ = true; var tempText = "" + (_this.scale.z.label || '') + (_this.scale.z.subLabel ? " ( " + _this.scale.z.subLabel + " )" : '') + (_this.scale.z.unit ? " ( " + _this.scale.z.unit + " )" : ''); var baselineDelt = _this.fontSize + 2; var heatLabel = _this.rootSelection$.select('g.group').append('g').attr('class', 'heatLabel').attr('fill', 'currentColor').attr('transform', "translate(" + (_this.scale.y ? 10 : _this.width$ - 10) + "," + (_this.scale.x ? baselineDelt - _this.padding[0] : _this.height$ + _this.padding[2] - iconSize + baselineDelt) + ")"); heatLabel.append('text').attr('dx', (_this.scale.y ? 1 : -1) * util.measureSvgText(tempText, _this.fontSize) / 2).text(tempText); if (_this.tooltip) { var select = _this.tooltip.select; (select || '').split('').forEach(function (key) { if (key) { _this.zoomSelection$.append('div').attr('class', key + "-linemark").style('background', '#fa9305').style('display', 'none').style('position', 'absolute').style('top', !_this.scale.y ? 0 : _this.height$ - 1).style('left', !_this.scale.x ? _this.width$ - 1 : 0).style('width', key === 'x' ? '1px' : '100%').style('height', key === 'x' ? '100%' : '1px'); } }); } var lineMark = [_this.zoomSelection$.select('.x-linemark'), _this.zoomSelection$.select('.y-linemark')]; _this.lineMark$ = lineMark; var zCanvasParent = _this.rootSelection$.insert('div', 'svg').style('position', 'absolute').style('width', _this.width$ + "px").style('height', _this.height$ + "px").style('top', _this.padding[0] + "px").style('left', _this.padding[3] + "px"); var zCanvas = zCanvasParent.append('canvas').style('width', '100%').style('height', '100%').attr('width', _this.width$).attr('height', _this.height$); if (legend) { var gradientId = util.guid('gradient'); _this.rootSelection$.select('svg').select('defs').append('linearGradient').attr('id', gradientId).attr('x1', '0%').attr('y1', '100%').attr('x2', '0%').attr('y2', '0%'); _this.rootSelection$.select('svg').select('.group').append('g').attr('class', 'heatLegend').style('display', legend.show ? 'block' : 'none').attr('fill', 'currentColor').attr('transform', "translate(" + (_this.width$ + _this.padding[1] + legend.left) + ",0)").append('rect').attr('x', 0).attr('y', 0).attr('width', legend.width).attr('height', _this.height$).attr('fill', "url(#" + gradientId + ")"); } var zContext = zCanvas.node().getContext('2d'); _this.zScale$ = d3.scaleLinear(); updateScale.call((0, _assertThisInitialized2.default)(_this)); _this.tempCanvas$ = { canvas: document.createElement('canvas'), range: null }; var dblclick$$ = _this.dblclick$; _this.dblclick$ = function (e) { var _context5; for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } dblclick$$.call.apply(dblclick$$, (0, _concat.default)(_context5 = [null, e]).call(_context5, args)); var _e$scaleAxis = e.scaleAxis, x = _e$scaleAxis.x, x2 = _e$scaleAxis.x2, y = _e$scaleAxis.y, y2 = _e$scaleAxis.y2; var xScale = (x || x2).scale; var yScale = (y || y2).scale; return doubleClick.call((0, _assertThisInitialized2.default)(_this), e.sourceEvent ? d3.pointer(e.sourceEvent) : [0, 0], { xScale: xScale, yScale: yScale }); }; var click$$ = _this.click$; _this.click$ = function (e) { var _context6; for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { args[_key3 - 1] = arguments[_key3]; } click$$.call.apply(click$$, (0, _concat.default)(_context6 = [null, e]).call(_context6, args)); lineMark.forEach(function (lm) { return lm.node() && lm.style('display', 'none'); }); }; var contextmenu$$ = _this.contextmenu$; _this.contextmenu$ = function (e) { var _context7; for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { args[_key4 - 1] = arguments[_key4]; } contextmenu$$.call.apply(contextmenu$$, (0, _concat.default)(_context7 = [null, e]).call(_context7, args)); lineMark.forEach(function (lm) { return lm.node() && lm.style('display', 'none'); }); }; var zoomstart$$ = _this.zoomstart$; _this.zoomstart$ = function (e) { var _context8; for (var _len5 = arguments.length, args = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { args[_key5 - 1] = arguments[_key5]; } zoomstart$$.call.apply(zoomstart$$, (0, _concat.default)(_context8 = [null, e]).call(_context8, args)); if (_this.debounceDrawend$) { // 每次开始前把上一次结束时需要调用的取消掉,防止调用两次有闪动 _this.debounceDrawend$.cancel(); } }; var zooming$$ = _this.zooming$; _this.zooming$ = function (e) { var _context9; for (var _len6 = arguments.length, args = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) { args[_key6 - 1] = arguments[_key6]; } zooming$$.call.apply(zooming$$, (0, _concat.default)(_context9 = [null, e]).call(_context9, args)); var _e$scaleAxis2 = e.scaleAxis, x = _e$scaleAxis2.x, x2 = _e$scaleAxis2.x2, y = _e$scaleAxis2.y, y2 = _e$scaleAxis2.y2; var xScale = (x || x2).scale; var yScale = (y || y2).scale; drawing.call((0, _assertThisInitialized2.default)(_this), zContext, { xScale: xScale, yScale: yScale }); }; var zoomend$$ = _this.zoomend$; _this.debounceDrawend$ = util.debounce(drawend, 300, { leading: false, trailing: true }); _this.zoomend$ = function (e) { var _context10; for (var _len7 = arguments.length, args = new Array(_len7 > 1 ? _len7 - 1 : 0), _key7 = 1; _key7 < _len7; _key7++) { args[_key7 - 1] = arguments[_key7]; } zoomend$$.call.apply(zoomend$$, (0, _concat.default)(_context10 = [null, e]).call(_context10, args)); var _e$scaleAxis3 = e.scaleAxis, x = _e$scaleAxis3.x, x2 = _e$scaleAxis3.x2, y = _e$scaleAxis3.y, y2 = _e$scaleAxis3.y2; var xScale = (x || x2).scale; var yScale = (y || y2).scale; _this.debounceDrawend$.call((0, _assertThisInitialized2.default)(_this), zContext, { xScale: xScale, yScale: yScale }); // 用户自己调用渲染的时候,可以在下一事件循环立即调用 if (!e.sourceEvent || e.sourceEvent.type === 'call') { util.delay(function () { _this.debounceDrawend$.flush(); }, 1); } }; var resize$$ = _this.resize$; _this.resize$ = function (e, _ref12) { var _context11; var width = _ref12.width, height = _ref12.height, padding = _ref12.padding, rest = (0, _objectWithoutPropertiesLoose2.default)(_ref12, _excluded3); for (var _len8 = arguments.length, args = new Array(_len8 > 2 ? _len8 - 2 : 0), _key8 = 2; _key8 < _len8; _key8++) { args[_key8 - 2] = arguments[_key8]; } resize$$.call.apply(resize$$, (0, _concat.default)(_context11 = [null, e, (0, _extends2.default)({ width: width, height: height, padding: padding }, rest)]).call(_context11, args)); zCanvasParent.style('width', width + "px").style('height', height + "px").style('top', padding[0] + "px").style('left', padding[3] + "px"); zCanvas.attr('width', width).attr('height', height); heatLabel.attr('transform', "translate(" + (_this.scale.y ? 10 : width - 10) + "," + (_this.scale.x ? baselineDelt - padding[0] : height + padding[2] - iconSize + baselineDelt) + ")"); if (legend) { var heatLegend = _this.rootSelection$.select('.heatLegend'); heatLegend.attr('transform', "translate(" + (width + padding[1] + legend.left) + ",0)"); heatLegend.select('rect').attr('height', height); var ticks = heatLegend.selectAll('.tick'); var domain = ticks.data(); var startDomain = domain[0]; var deltDomain = domain[domain.length - 1] - startDomain; ticks.attr('transform', function (v) { return "translate(" + legend.width + "," + height * (1 - (v - startDomain) / deltDomain) + ")"; }); } }; heatLabel.on('click', function () { if (_this.destroyed) return; _this.showHeat$ = !_this.showHeat$; lineMark.forEach(function (lm) { return lm.node() && lm.style('display', _this.showHeat$ ? 'block' : 'none'); }); heatLabel.attr('fill', !_this.showHeat$ ? '#aaa' : 'currentColor'); if (_this.rendered) { _this.render(); } }); return _this; } var _proto = HeatMap.prototype; _proto.getPointData = function getPointData(point, scaleAxis, avg) { var currentPoint = point; if (!Array.isArray(point)) { currentPoint = d3.pointer(point, this.zoomSelection$.node()); } var _currentPoint = currentPoint, x0 = _currentPoint[0], y0 = _currentPoint[1]; var data = this.data.heat; var value = []; if (this.showHeat$) { var xScale = (scaleAxis.x || scaleAxis.x2).scale; var yScale = (scaleAxis.y || scaleAxis.y2).scale; var xval = xScale.invert(x0); var yval = yScale.invert(y0); var zval = 0; var _util$findNearIndex = util.findNearIndex(+xval, data.x), xi0 = _util$findNearIndex[0], xi1 = _util$findNearIndex[1]; var _util$findNearIndex2 = util.findNearIndex(+yval, data.y), yi0 = _util$findNearIndex2[0], yi1 = _util$findNearIndex2[1]; // 确保point在图层内 if (xi0 >= 0 && xi1 >= 0 && yi0 >= 0 && yi1 >= 0) { var xval0 = +data.x[xi0]; var xval1 = +data.x[xi1]; var yval0 = +data.y[yi0]; var yval1 = +data.y[yi1]; if (xval0 === xval1 && yval0 === yval1) { // 正好移动到了xy交叉数据点上 zval = (data.z[yi0] || [])[xi0]; } else if (avg) { var xInterp = computeFactor(+xval, xval0, xval1, xi0, xi1); var yInterp = computeFactor(+yval, yval0, yval1, yi0, yi1); var val00 = (data.z[yInterp.bin0] || [])[xInterp.bin0]; var val01 = (data.z[yInterp.bin0] || [])[xInterp.bin1]; var val10 = (data.z[yInterp.bin1] || [])[xInterp.bin0]; var val11 = (data.z[yInterp.bin1] || [])[xInterp.bin1]; zval = matrixAverage(xInterp.factor, val00, val01, yInterp.factor, val10, val11); } else { var xi = Math.abs(xval - xval0) > Math.abs(xval - xval1) ? xi1 : xi0; var yi = Math.abs(yval - yval0) > Math.abs(yval - yval1) ? yi1 : yi0; xval = +data.x[xi]; yval = +data.y[yi]; zval = (data.z[yi] || [])[xi]; x0 = xScale(xval); y0 = yScale(yval); } value.push(xval, yval, zval); } } return { value: value, point: [x0, y0] }; }; _proto.getLineMark = function getLineMark() { var result = []; var lineMarkX = this.lineMark$[0]; if (lineMarkX.node()) { var xval = lineMarkX.datum(); result[0] = xval; } var lineMarkY = this.lineMark$[1]; if (lineMarkY.node()) { var yval = lineMarkY.datum(); result[1] = yval; } return result; }; _proto.setLineMark = function setLineMark(lm, cb) { var lineMark = lm || []; var average = this.tooltip.average; var heatData = this.data.heat; var xSelect = null; var ySelect = null; var lineMarkX = this.lineMark$[0]; if (lineMarkX.node()) { var xval = !lineMark[0] && lineMark[0] !== 0 ? heatData.x[0] : lineMark[0]; lineMarkX.datum(xval); var zval = []; // xval在数据范围之内才可计算出zval if (xval >= heatData.x[0] && xval <= heatData.x[heatData.x.length - 1]) { var _context12; var xi = util.findNearIndex(xval, heatData.x, !average); if (!average) xi = [xi, xi]; var xBin = 0; if (xi[0] !== xi[1]) xBin = (xval - heatData.x[xi[0]]) / (heatData.x[xi[1]] - heatData.x[xi[0]]); zval = (0, _map.default)(_context12 = heatData.z).call(_context12, function (v) { var vv = v || []; return xBin * ((vv[xi[1]] || 0) - (vv[xi[0]] || 0)) + (vv[xi[0]] || 0); }); } xSelect = { x: xval, y: heatData.y, z: zval }; } var lineMarkY = this.lineMark$[1]; if (lineMarkY.node()) { var yval = !lineMark[1] && lineMark[1] !== 0 ? heatData.y[0] : lineMark[1]; lineMarkY.datum(yval); var _zval = []; // yval在数据范围之内才可计算出zval if (yval >= heatData.y[0] && yval <= heatData.y[heatData.y.length - 1]) { var _context13; var yi = util.findNearIndex(yval, heatData.y, !average); if (!average) yi = [yi, yi]; var yBin = 0; if (yi[0] !== yi[1]) yBin = (yval - heatData.y[yi[0]]) / (heatData.y[yi[1]] - heatData.y[yi[0]]); _zval = (0, _map.default)(_context13 = heatData.z[yi[0]] || []).call(_context13, function (v0, i) { var v1 = (heatData.z[yi[1]] || [])[i] || 0; return yBin * (v1 - v0) + v0; }); } ySelect = { x: heatData.x, y: yval, z: _zval }; } if (typeof cb === 'function') { cb({ xSelect: xSelect, ySelect: ySelect }); } return this; }; _proto.setData = function setData(data, render, computeDomain) { if (!data) return this; var _ref13 = data || {}, heat = _ref13.heat, restData = (0, _objectWithoutPropertiesLoose2.default)(_ref13, _excluded4); _ref9.prototype.setData.call(this, (0, _extends2.default)({ heat: !heat ? { x: [], y: [], z: [] } : { x: heat.x || [], y: heat.y || [], z: heat.z || [] } }, restData), false, !heat ? computeDomain : function (_ref14, needDomain) { var heatData = _ref14.heat; var domains = {}; needDomain.forEach(function (key) { if (heatData[key] && heatData[key].length > 0) { var _context14; domains[key] = d3.extent((0, _concat.default)(_context14 = []).call(_context14, heatData[key])); } }); return domains; }); // 将linemark归位到起点 this.setLineMark(); if (render) { this.render(); } return this; }; _proto.setDomain = function setDomain(domain, render) { if (!domain) return this; var z = domain.z, rest = (0, _objectWithoutPropertiesLoose2.default)(domain, _excluded5); _ref9.prototype.setDomain.call(this, rest); if (z && this.scale.z) { this.scale.z.domain = z; updateScale.call(this); if (render) { this.render(); } } return this; }; _proto.setLabel = function setLabel(label, render) { if (!label) return this; var z = label.z, rest = (0, _objectWithoutPropertiesLoose2.default)(label, _excluded6); _ref9.prototype.setLabel.call(this, rest); if (z && this.scale.z) { this.scale.z.label = z.label; this.scale.z.subLabel = z.subLabel; this.scale.z.unit = z.unit; var tempText = "" + (this.scale.z.label || '') + (this.scale.z.subLabel ? " ( " + this.scale.z.subLabel + " )" : '') + (this.scale.z.unit ? " ( " + this.scale.z.unit + " )" : ''); this.rootSelection$.select('.heatLabel').select('text').attr('dx', (this.scale.y ? 1 : -1) * util.measureSvgText(tempText, this.fontSize) / 2).text(tempText); if (render) { this.render(); } } return this; }; _proto.downloadImage = function downloadImage() { var zCanvas = this.rootSelection$.select('canvas').node(); var svgDiv = this.rootSelection$.select('.actions'); var left = window.parseInt(svgDiv.style('left')); var top = window.parseInt(svgDiv.style('top')); _ref9.prototype.downloadImage.call(this, (this.scale.z || {}).label, { image: zCanvas, x: left, y: top }); }; _proto.destroy = function destroy() { if (this.debounceDrawend$) { this.debounceDrawend$.cancel(); this.debounceDrawend$ = null; } this.zScale$ = null; this.tempCanvas$ = null; this.click$ = null; this.dblclick$ = null; this.contextmenu$ = null; this.zoomstart$ = null; this.zooming$ = null; this.zoomend$ = null; this.resize$ = null; this.reset$ = null; this.canZoom$ = null; _ref9.prototype.destroy.call(this); return this; }; return HeatMap; }(superName === 'LineGraph' ? _LineGraph.default : _BaseChart.default); return HeatMap; }