diff --git a/components/u-charts.js b/components/u-charts.js index 1e9376c..0e714b5 100644 --- a/components/u-charts.js +++ b/components/u-charts.js @@ -4,27 +4,25 @@ * Copyright (C) 2018-2022 QIUN (R) 秋云 https://www.ucharts.cn All rights reserved. * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) * 复制使用请保留本段注释,感谢支持开源! - * + * * uCharts (R) 官方网站 * https://www.uCharts.cn - * + * * 开源地址: * https://gitee.com/uCharts/uCharts - * + * * uni-app插件市场地址: * http://ext.dcloud.net.cn/plugin?id=271 - * + * */ 'use strict'; var config = { - version: 'v2.4.3-20220505', + version: 'v2.5.0-20230101', yAxisWidth: 15, xAxisHeight: 22, - xAxisTextPadding: 3, padding: [10, 10, 10, 10], - pixelRatio: 1, rotate: false, fontSize: 13, fontColor: '#666666', @@ -35,10 +33,6 @@ var config = { pieChartTextPadding: 5, titleFontSize: 20, subtitleFontSize: 15, - toolTipPadding: 3, - toolTipBackground: '#000000', - toolTipOpacity: 0.7, - toolTipLineHeight: 20, radarLabelTextMargin: 13, }; @@ -53,7 +47,7 @@ var assign = function(target, ...varArgs) { function deepAssign(obj1, obj2) { for (let key in obj2) { obj1[key] = obj1[key] && obj1[key].toString() === "[object Object]" ? - deepAssign(obj1[key], obj2[key]) : obj1[key] = obj2[key]; + deepAssign(obj1[key], obj2[key]) : obj1[key] = obj2[key]; } return obj1; } @@ -224,7 +218,7 @@ function createCurveControlPoints(points, i) { function isNotMiddlePoint(points, i) { if (points[i - 1] && points[i + 1]) { return points[i].y >= Math.max(points[i - 1].y, points[i + 1].y) || points[i].y <= Math.min(points[i - 1].y, - points[i + 1].y); + points[i + 1].y); } else { return false; } @@ -232,7 +226,7 @@ function createCurveControlPoints(points, i) { function isNotMiddlePointX(points, i) { if (points[i - 1] && points[i + 1]) { return points[i].x >= Math.max(points[i - 1].x, points[i + 1].x) || points[i].x <= Math.min(points[i - 1].x, - points[i + 1].x); + points[i + 1].x); } else { return false; } @@ -435,84 +429,40 @@ function getDataRange(minData, maxData) { function measureText(text, fontSize, context) { var width = 0; - // text = String(text); + text = String(text); // #ifdef MP-ALIPAY || MP-BAIDU || APP-NVUE context = false; // #endif - if (context !== false && context !== undefined && context.setFontSize && context.measureText) { - context.setFontSize(fontSize); - if(text instanceof Array) { - let max = 0 - text.map(n=>{ - let len = getLen(n) - if(max eachSpacing) { - result.angle = 45 * Math.PI / 180; - result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle); - } if (opts.xAxis.disabled === true) { result.xAxisHeight = 0; } @@ -1341,22 +1290,19 @@ function getPieDataPoints(series, radius) { return series; } -function getFunnelDataPoints(series, radius, type, eachSpacing) { +function getFunnelDataPoints(series, radius, option, eachSpacing) { var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; - series = series.sort(function(a, b) { - return parseInt(b.data) - parseInt(a.data); - }); for (let i = 0; i < series.length; i++) { - if(type == 'funnel'){ + if(option.type == 'funnel'){ series[i].radius = series[i].data / series[0].data * radius * process; }else{ series[i].radius = (eachSpacing * (series.length - i)) / (eachSpacing * series.length) * radius * process; } series[i]._proportion_ = series[i].data / series[0].data; } - if(type !== 'pyramid'){ - series.reverse(); - } + // if(option.type !== 'pyramid'){ + // series.reverse(); + // } return series; } @@ -1410,13 +1356,24 @@ function getArcbarDataPoints(series, arcbarOption) { if (arcbarOption.type == 'circle') { totalAngle = 2; } else { - if (arcbarOption.endAngle < arcbarOption.startAngle) { - totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle; - } else { - totalAngle = arcbarOption.startAngle - arcbarOption.endAngle; + if(arcbarOption.direction == 'ccw'){ + if (arcbarOption.startAngle < arcbarOption.endAngle) { + totalAngle = 2 + arcbarOption.startAngle - arcbarOption.endAngle; + } else { + totalAngle = arcbarOption.startAngle - arcbarOption.endAngle; + } + }else{ + if (arcbarOption.endAngle < arcbarOption.startAngle) { + totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle; + } else { + totalAngle = arcbarOption.startAngle - arcbarOption.endAngle; + } } } item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle; + if(arcbarOption.direction == 'ccw'){ + item._proportion_ = arcbarOption.startAngle - totalAngle * item.data * process ; + } if (item._proportion_ >= 2) { item._proportion_ = item._proportion_ % 2; } @@ -1451,7 +1408,12 @@ function getGaugeArcbarDataPoints(series, arcbarOption) { } function getGaugeAxisPoints(categories, startAngle, endAngle) { - let totalAngle = startAngle - endAngle + 1; + let totalAngle; + if (endAngle < startAngle) { + totalAngle = 2 + endAngle - startAngle; + } else { + totalAngle = startAngle - endAngle; + } let tempStartAngle = startAngle; for (let i = 0; i < categories.length; i++) { categories[i].value = categories[i].value === null ? 0 : categories[i].value; @@ -1480,7 +1442,12 @@ function getGaugeDataPoints(series, categories, gaugeOption) { } else { item.color = gaugeOption.pointer.color; } - let totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1; + let totalAngle; + if (gaugeOption.endAngle < gaugeOption.startAngle) { + totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle; + } else { + totalAngle = gaugeOption.startAngle - gaugeOption.endAngle; + } item._endAngle_ = totalAngle * item.data + gaugeOption.startAngle; item._oldAngle_ = gaugeOption.oldAngle; if (gaugeOption.oldAngle < gaugeOption.endAngle) { @@ -1717,8 +1684,91 @@ function getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, return points; } -function getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption) { - var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1; +function getLineDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, lineOption, process){ + var process = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 1; + var boundaryGap = opts.xAxis.boundaryGap; + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + var validWidth = opts.width - opts.area[1] - opts.area[3]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + if(lineOption.animation == 'vertical'){ + point.x = xAxisPoints[index]; + var value = item; + if (typeof item === 'object' && item !== null) { + if (item.constructor.toString().indexOf('Array') > -1) { + let xranges, xminRange, xmaxRange; + xranges = [].concat(opts.chartData.xAxisData.ranges); + xminRange = xranges.shift(); + xmaxRange = xranges.pop(); + value = item[1]; + point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange); + } else { + value = item.value; + } + } + if (boundaryGap == 'center') { + point.x += eachSpacing / 2; + } + var height = validHeight * (value - minRange) / (maxRange - minRange); + height *= process; + point.y = opts.height - height - opts.area[2]; + points.push(point); + }else{ + point.x = xAxisPoints[0] + eachSpacing * index * process; + var value = item; + if (boundaryGap == 'center') { + point.x += eachSpacing / 2; + } + var height = validHeight * (value - minRange) / (maxRange - minRange); + point.y = opts.height - height - opts.area[2]; + points.push(point); + } + } + }); + return points; +} + +function getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, zeroPoints, process){ + var process = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 1; + var points = []; + var validHeight = opts.height - opts.area[0] - opts.area[2]; + var validWidth = opts.width - opts.area[1] - opts.area[3]; + data.forEach(function(item, index) { + if (item === null) { + points.push(null); + } else { + var point = {}; + point.color = item.color; + point.x = xAxisPoints[index]; + var value = item; + if (typeof item === 'object' && item !== null) { + if (item.constructor.toString().indexOf('Array') > -1) { + let xranges, xminRange, xmaxRange; + xranges = [].concat(opts.chartData.xAxisData.ranges); + xminRange = xranges.shift(); + xmaxRange = xranges.pop(); + value = item[1]; + point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange); + } else { + value = item.value; + } + } + point.x += eachSpacing / 2; + var height = validHeight * (value * process - minRange) / (maxRange - minRange); + point.y = opts.height - height - opts.area[2]; + points.push(point); + } + }); + return points; +} + +function getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints) { + var process = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 1; var points = []; var validHeight = opts.height - opts.area[0] - opts.area[2]; var validWidth = opts.width - opts.area[1] - opts.area[3]; @@ -1732,8 +1782,7 @@ function getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing point.x = xAxisPoints[index]; point.x += eachSpacing / 2; var value = item.data; - var height = validHeight * (value - minRange) / (maxRange - minRange); - height *= process; + var height = validHeight * (value * process - minRange) / (maxRange - minRange); point.y = opts.height - height - opts.area[2]; point.value = value; point.width = mountWidth; @@ -1792,6 +1841,9 @@ function getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, var height0 = validHeight * (value0 - minRange) / (maxRange - minRange); } else { var value = item; + if (typeof item === 'object' && item !== null) { + value = item.value; + } var height = validHeight * (value - minRange) / (maxRange - minRange); var height0 = 0; } @@ -1827,6 +1879,9 @@ function getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacin var height0 = validHeight * (value0 - minRange) / (maxRange - minRange); } else { var value = item; + if (typeof item === 'object' && item !== null) { + value = item.value; + } var height = validHeight * (value - minRange) / (maxRange - minRange); var height0 = 0; } @@ -1888,8 +1943,6 @@ function getYAxisTextList(series, opts, config, stack, yData) { maxData = Math.max.apply(this, sorted); } if (minData === maxData) { - // var rangeSpan = maxData || 10; - // maxData += rangeSpan; if(maxData == 0){ maxData = 10; }else{ @@ -1899,8 +1952,8 @@ function getYAxisTextList(series, opts, config, stack, yData) { var dataRange = getDataRange(minData, maxData); var minRange = (yData.min === undefined || yData.min === null) ? dataRange.minRange : yData.min; var maxRange = (yData.max === undefined || yData.max === null) ? dataRange.maxRange : yData.max; - var range = []; var eachRange = (maxRange - minRange) / opts.yAxis.splitNumber; + var range = []; for (var i = 0; i <= opts.yAxis.splitNumber; i++) { range.push(minRange + eachRange * i); } @@ -1942,7 +1995,7 @@ function calYAxisData(series, opts, config, context) { rangesArr[i] = yData.categories; }else{ if(!yData.formatter){ - yData.formatter = (val,index,opts) => {return val.toFixed(yData.tofix) + (yData.unit || '')}; + yData.formatter = (val,index,opts) => {return util.toFixed(val, yData.tofix || 0) + (yData.unit || '')}; } rangesArr[i] = getYAxisTextList(newSeries[i], opts, config, columnstyle.type, yData, i); } @@ -2023,10 +2076,10 @@ function calTooltipYAxisData(point, series, opts, config, eachSpacing) { let minAxis = opts.area[0]; let items = []; for (let i = 0; i < ranges.length; i++) { - let maxVal = ranges[i].shift(); - let minVal = ranges[i].pop(); + let maxVal = Math.max.apply(this, ranges[i]); + let minVal = Math.min.apply(this, ranges[i]); let item = maxVal - (maxVal - minVal) * (point - minAxis) / spacingValid; - item = opts.yAxis.data[i].formatter ? opts.yAxis.data[i].formatter(item) : item.toFixed(0); + item = opts.yAxis.data && opts.yAxis.data[i].formatter ? opts.yAxis.data[i].formatter(item, i, opts) : item.toFixed(0); items.push(String(item)) } return items; @@ -2101,7 +2154,66 @@ function drawPointShape(points, color, shape, context, opts) { context.lineTo(item.x, item.y - 4.5); } }); + } else if (shape === 'none') { + return; + } + context.closePath(); + context.fill(); + context.stroke(); +} + +function drawActivePoint(points, color, shape, context, opts, option, seriesIndex) { + if(!opts.tooltip){ + return + } + if(opts.tooltip.group.length>0 && opts.tooltip.group.includes(seriesIndex) == false){ + return + } + var pointIndex = typeof opts.tooltip.index === 'number' ? opts.tooltip.index : opts.tooltip.index[opts.tooltip.group.indexOf(seriesIndex)]; + context.beginPath(); + if (option.activeType == 'hollow') { + context.setStrokeStyle(color); + context.setFillStyle(opts.background); + context.setLineWidth(2 * opts.pix); + } else { + context.setStrokeStyle("#ffffff"); + context.setFillStyle(color); + context.setLineWidth(1 * opts.pix); + } + if (shape === 'diamond') { + points.forEach(function(item, index) { + if (item !== null && pointIndex == index ) { + context.moveTo(item.x, item.y - 4.5); + context.lineTo(item.x - 4.5, item.y); + context.lineTo(item.x, item.y + 4.5); + context.lineTo(item.x + 4.5, item.y); + context.lineTo(item.x, item.y - 4.5); + } + }); + } else if (shape === 'circle') { + points.forEach(function(item, index) { + if (item !== null && pointIndex == index) { + context.moveTo(item.x + 2.5 * opts.pix, item.y); + context.arc(item.x, item.y, 3 * opts.pix, 0, 2 * Math.PI, false); + } + }); + } else if (shape === 'square') { + points.forEach(function(item, index) { + if (item !== null && pointIndex == index) { + context.moveTo(item.x - 3.5, item.y - 3.5); + context.rect(item.x - 3.5, item.y - 3.5, 7, 7); + } + }); } else if (shape === 'triangle') { + points.forEach(function(item, index) { + if (item !== null && pointIndex == index) { + context.moveTo(item.x, item.y - 4.5); + context.lineTo(item.x - 4.5, item.y + 4.5); + context.lineTo(item.x + 4.5, item.y + 4.5); + context.lineTo(item.x, item.y - 4.5); + } + }); + } else if (shape === 'none') { return; } context.closePath(); @@ -2177,10 +2289,74 @@ function drawPointText(points, series, config, context, opts) { }); } -function drawMountPointText(points, series, config, context, opts) { +function drawColumePointText(points, series, config, context, opts) { // 绘制数据文案 var data = series.data; var textOffset = series.textOffset ? series.textOffset : 0; + var Position = opts.extra.column.labelPosition; + points.forEach(function(item, index) { + if (item !== null) { + context.beginPath(); + var fontSize = series.textSize ? series.textSize * opts.pix : config.fontSize; + context.setFontSize(fontSize); + context.setFillStyle(series.textColor || opts.fontColor); + var value = data[index] + if (typeof data[index] === 'object' && data[index] !== null) { + if (data[index].constructor.toString().indexOf('Array')>-1) { + value = data[index][1]; + } else { + value = data[index].value + } + } + var formatVal = series.formatter ? series.formatter(value,index,series,opts) : value; + context.setTextAlign('center'); + var startY = item.y - 4 * opts.pix + textOffset * opts.pix; + if(item.y > series.zeroPoints){ + startY = item.y + textOffset * opts.pix + fontSize; + } + if(Position == 'insideTop'){ + startY = item.y + fontSize + textOffset * opts.pix; + if(item.y > series.zeroPoints){ + startY = item.y - textOffset * opts.pix - 4 * opts.pix; + } + } + if(Position == 'center'){ + startY = item.y + textOffset * opts.pix + (opts.height - opts.area[2] - item.y + fontSize)/2; + if(series.zeroPoints < opts.height - opts.area[2]){ + startY = item.y + textOffset * opts.pix + (series.zeroPoints - item.y + fontSize)/2; + } + if(item.y > series.zeroPoints){ + startY = item.y - textOffset * opts.pix - (item.y - series.zeroPoints - fontSize)/2; + } + if(opts.extra.column.type == 'stack'){ + startY = item.y + textOffset * opts.pix + (item.y0 - item.y + fontSize)/2; + } + } + if(Position == 'bottom'){ + startY = opts.height - opts.area[2] + textOffset * opts.pix - 4 * opts.pix; + if(series.zeroPoints < opts.height - opts.area[2]){ + startY = series.zeroPoints + textOffset * opts.pix - 4 * opts.pix; + } + if(item.y > series.zeroPoints){ + startY = series.zeroPoints - textOffset * opts.pix + fontSize + 2 * opts.pix; + } + if(opts.extra.column.type == 'stack'){ + startY = item.y0 + textOffset * opts.pix - 4 * opts.pix; + } + } + context.fillText(String(formatVal), item.x, startY); + context.closePath(); + context.stroke(); + context.setTextAlign('left'); + } + }); +} + +function drawMountPointText(points, series, config, context, opts, zeroPoints) { + // 绘制数据文案 + var data = series.data; + var textOffset = series.textOffset ? series.textOffset : 0; + var Position = opts.extra.mount.labelPosition; points.forEach(function(item, index) { if (item !== null) { context.beginPath(); @@ -2190,7 +2366,11 @@ function drawMountPointText(points, series, config, context, opts) { var value = item.value var formatVal = series[index].formatter ? series[index].formatter(value,index,series,opts) : value; context.setTextAlign('center'); - context.fillText(String(formatVal), item.x, item.y - 4 + textOffset * opts.pix); + var startY = item.y - 4 * opts.pix + textOffset * opts.pix; + if(item.y > zeroPoints){ + startY = item.y + textOffset * opts.pix + fontSize; + } + context.fillText(String(formatVal), item.x, startY); context.closePath(); context.stroke(); context.setTextAlign('left'); @@ -2224,7 +2404,12 @@ function drawBarPointText(points, series, config, context, opts) { function drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context) { radius -= gaugeOption.width / 2 + gaugeOption.labelOffset * opts.pix; radius = radius < 10 ? 10 : radius; - let totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1; + let totalAngle; + if (gaugeOption.endAngle < gaugeOption.startAngle) { + totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle; + } else { + totalAngle = gaugeOption.startAngle - gaugeOption.endAngle; + } let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber; let totalNumber = gaugeOption.endNumber - gaugeOption.startNumber; let splitNumber = totalNumber / gaugeOption.splitLine.splitNumber; @@ -2269,24 +2454,26 @@ function drawRadarLabel(angleList, radius, centerPosition, opts, config, context context.closePath(); context.fill(); } - var pos = { - x: (radius + config.radarLabelTextMargin * opts.pix) * Math.cos(angle), - y: (radius + config.radarLabelTextMargin * opts.pix) * Math.sin(angle) - }; - var posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition); - var startX = posRelativeCanvas.x; - var startY = posRelativeCanvas.y; - if (util.approximatelyEqual(pos.x, 0)) { - startX -= measureText(opts.categories[index] || '', config.fontSize, context) / 2; - } else if (pos.x < 0) { - startX -= measureText(opts.categories[index] || '', config.fontSize, context); + if(radarOption.labelShow === true){ + var pos = { + x: (radius + config.radarLabelTextMargin * opts.pix) * Math.cos(angle), + y: (radius + config.radarLabelTextMargin * opts.pix) * Math.sin(angle) + }; + var posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition); + var startX = posRelativeCanvas.x; + var startY = posRelativeCanvas.y; + if (util.approximatelyEqual(pos.x, 0)) { + startX -= measureText(opts.categories[index] || '', config.fontSize, context) / 2; + } else if (pos.x < 0) { + startX -= measureText(opts.categories[index] || '', config.fontSize, context); + } + context.beginPath(); + context.setFontSize(config.fontSize); + context.setFillStyle(radarOption.labelColor || opts.fontColor); + context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2); + context.closePath(); + context.stroke(); } - context.beginPath(); - context.setFontSize(config.fontSize); - context.setFillStyle(radarOption.labelColor || opts.fontColor); - context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2); - context.closePath(); - context.stroke(); }); } @@ -2314,7 +2501,6 @@ function drawPieText(series, opts, config, context, radius, center) { labelShow: item.labelShow }; }); - for (let i = 0; i < seriesConvert.length; i++) { let item = seriesConvert[i]; // line end @@ -2329,8 +2515,8 @@ function drawPieText(series, opts, config, context, radius, center) { let textWidth = measureText(item.text, item.textSize * opts.pix || config.fontSize, context); let startY = orginY3; if (lastTextObject && util.isSameXCoordinateArea(lastTextObject.start, { - x: orginX3 - })) { + x: orginX3 + })) { if (orginX3 > 0) { startY = Math.min(orginY3, lastTextObject.start.y); } else if (orginX1 < 0) { @@ -2397,16 +2583,7 @@ function drawPieText(series, opts, config, context, radius, center) { context.beginPath(); context.setFontSize(item.textSize * opts.pix || config.fontSize); context.setFillStyle(item.textColor || opts.fontColor); - if(item.text instanceof Array) { - item.text.map((n,i)=>{ - let y = textPosition.y + 3 +(i*(item.textSize || config.fontSize)) - context.fillText(n, textStartX, y); - }) - }else{ - - context.fillText(item.text, textStartX, textPosition.y + 3); - } - // context.fillText(item.text, textStartX, textPosition.y + 3); + context.fillText(item.text, textStartX, textPosition.y + 3); context.closePath(); context.stroke(); context.closePath(); @@ -2434,19 +2611,19 @@ function drawToolTipSplitLine(offsetX, opts, config, context) { context.setFontSize(config.fontSize); let textWidth = measureText(labelText, config.fontSize, context); let textX = offsetX - 0.5 * textWidth; - let textY = endY; + let textY = endY + 2 * opts.pix; context.beginPath(); context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity)); context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground); context.setLineWidth(1 * opts.pix); - context.rect(textX - config.toolTipPadding, textY, textWidth + 2 * config.toolTipPadding, config.fontSize + 2 * config.toolTipPadding); + context.rect(textX - toolTipOption.boxPadding * opts.pix, textY, textWidth + 2 * toolTipOption.boxPadding * opts.pix, config.fontSize + 2 * toolTipOption.boxPadding * opts.pix); context.closePath(); context.stroke(); context.fill(); context.beginPath(); context.setFontSize(config.fontSize); context.setFillStyle(toolTipOption.labelFontColor || opts.fontColor); - context.fillText(String(labelText), textX, textY + config.toolTipPadding + config.fontSize); + context.fillText(String(labelText), textX, textY + toolTipOption.boxPadding * opts.pix + config.fontSize); context.closePath(); context.stroke(); } @@ -2465,6 +2642,8 @@ function drawMarkLine(opts, config, context) { let item = assign({}, { lineColor: '#DE4A42', showLabel: false, + labelFontSize: 13, + labelPadding: 6, labelFontColor: '#666666', labelBgColor: '#DFE8FF', labelBgOpacity: 0.8, @@ -2483,28 +2662,29 @@ function drawMarkLine(opts, config, context) { context.stroke(); context.setLineDash([]); if (item.showLabel) { + let fontSize = item.labelFontSize * opts.pix; let labelText = item.labelText ? item.labelText : item.value; - context.setFontSize(config.fontSize); - let textWidth = measureText(labelText, config.fontSize, context); - let bgWidth = textWidth + config.toolTipPadding * 2; + context.setFontSize(fontSize); + let textWidth = measureText(labelText, fontSize, context); + let bgWidth = textWidth + item.labelPadding * opts.pix * 2; let bgStartX = item.labelAlign == 'left' ? opts.area[3] - bgWidth : opts.width - opts.area[1]; bgStartX += item.labelOffsetX; - let bgStartY = item.y - 0.5 * config.fontSize - config.toolTipPadding; + let bgStartY = item.y - 0.5 * fontSize - item.labelPadding * opts.pix; bgStartY += item.labelOffsetY; - let textX = bgStartX + config.toolTipPadding; + let textX = bgStartX + item.labelPadding * opts.pix; let textY = item.y; context.setFillStyle(hexToRgb(item.labelBgColor, item.labelBgOpacity)); context.setStrokeStyle(item.labelBgColor); context.setLineWidth(1 * opts.pix); context.beginPath(); - context.rect(bgStartX, bgStartY, bgWidth, config.fontSize + 2 * config.toolTipPadding); + context.rect(bgStartX, bgStartY, bgWidth, fontSize + 2 * item.labelPadding * opts.pix); context.closePath(); context.stroke(); context.fill(); - context.setFontSize(config.fontSize); + context.setFontSize(fontSize); context.setTextAlign('left'); context.setFillStyle(item.labelFontColor); - context.fillText(String(labelText), textX, bgStartY + config.fontSize + config.toolTipPadding/2); + context.fillText(String(labelText), textX, bgStartY + fontSize + item.labelPadding * opts.pix/2); context.stroke(); context.setTextAlign('left'); } @@ -2529,20 +2709,21 @@ function drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoin context.stroke(); context.setLineDash([]); if (toolTipOption.yAxisLabel) { + let boxPadding = toolTipOption.boxPadding * opts.pix; let labelText = calTooltipYAxisData(opts.tooltip.offset.y, opts.series, opts, config, eachSpacing); let widthArr = opts.chartData.yAxisData.yAxisWidth; let tStartLeft = opts.area[3]; let tStartRight = opts.width - opts.area[1]; for (let i = 0; i < labelText.length; i++) { - context.setFontSize(config.fontSize); - let textWidth = measureText(labelText[i], config.fontSize, context); + context.setFontSize(toolTipOption.fontSize * opts.pix); + let textWidth = measureText(labelText[i], toolTipOption.fontSize * opts.pix, context); let bgStartX, bgEndX, bgWidth; if (widthArr[i].position == 'left') { - bgStartX = tStartLeft - widthArr[i].width; - bgEndX = Math.max(bgStartX, bgStartX + textWidth + config.toolTipPadding * 2); + bgStartX = tStartLeft - (textWidth + boxPadding * 2) - 2 * opts.pix; + bgEndX = Math.max(bgStartX, bgStartX + textWidth + boxPadding * 2); } else { - bgStartX = tStartRight; - bgEndX = Math.max(bgStartX + widthArr[i].width, bgStartX + textWidth + config.toolTipPadding * 2); + bgStartX = tStartRight + 2 * opts.pix; + bgEndX = Math.max(bgStartX + widthArr[i].width, bgStartX + textWidth + boxPadding * 2); } bgWidth = bgEndX - bgStartX; let textX = bgStartX + (bgWidth - textWidth) / 2; @@ -2551,8 +2732,7 @@ function drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoin context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity)); context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground); context.setLineWidth(1 * opts.pix); - context.rect(bgStartX, textY - 0.5 * config.fontSize - config.toolTipPadding, bgWidth, config.fontSize + 2 * - config.toolTipPadding); + context.rect(bgStartX, textY - 0.5 * config.fontSize - boxPadding, bgWidth, config.fontSize + 2 * boxPadding); context.closePath(); context.stroke(); context.fill(); @@ -2615,14 +2795,26 @@ function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxis borderWidth: 0, borderRadius: 0, borderOpacity: 0.7, + boxPadding: 3, fontColor: '#FFFFFF', + fontSize: 13, + lineHeight: 20, + legendShow: true, + legendShape: 'auto', splitLine: true, }, opts.extra.tooltip); if(toolTipOption.showCategory==true && opts.categories){ textList.unshift({text:opts.categories[opts.tooltip.index],color:null}) } - var legendWidth = 4 * opts.pix; + var fontSize = toolTipOption.fontSize * opts.pix; + var lineHeight = toolTipOption.lineHeight * opts.pix; + var boxPadding = toolTipOption.boxPadding * opts.pix; + var legendWidth = fontSize; var legendMarginRight = 5 * opts.pix; + if(toolTipOption.legendShow == false){ + legendWidth = 0; + legendMarginRight = 0; + } var arrowWidth = toolTipOption.showArrow ? 8 * opts.pix : 0; var isOverRightBorder = false; if (opts.type == 'line' || opts.type == 'mount' || opts.type == 'area' || opts.type == 'candle' || opts.type == 'mix') { @@ -2636,10 +2828,10 @@ function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxis }, offset); offset.y -= 8 * opts.pix; var textWidth = textList.map(function(item) { - return measureText(item.text, config.fontSize, context); + return measureText(item.text, fontSize, context); }); - var toolTipWidth = legendWidth + legendMarginRight + 4 * config.toolTipPadding + Math.max.apply(null, textWidth); - var toolTipHeight = 2 * config.toolTipPadding + textList.length * config.toolTipLineHeight; + var toolTipWidth = legendWidth + legendMarginRight + 4 * boxPadding + Math.max.apply(null, textWidth); + var toolTipHeight = 2 * boxPadding + textList.length * lineHeight; if (toolTipOption.showBox == false) { return } @@ -2652,18 +2844,25 @@ function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxis } // draw background rect context.beginPath(); - context.setFillStyle(hexToRgb(toolTipOption.bgColor || config.toolTipBackground, toolTipOption.bgOpacity || config.toolTipOpacity)); + context.setFillStyle(hexToRgb(toolTipOption.bgColor, toolTipOption.bgOpacity)); context.setLineWidth(toolTipOption.borderWidth * opts.pix); context.setStrokeStyle(hexToRgb(toolTipOption.borderColor, toolTipOption.borderOpacity)); var radius = toolTipOption.borderRadius; if (isOverRightBorder) { + // 增加左侧仍然超出的判断 + if(toolTipWidth + arrowWidth > opts.width){ + offset.x = opts.width + Math.abs(opts._scrollDistance_ || 0) + arrowWidth + (toolTipWidth - opts.width) + } + if(toolTipWidth > offset.x){ + offset.x = opts.width + Math.abs(opts._scrollDistance_ || 0) + arrowWidth + (toolTipWidth - opts.width) + } if (toolTipOption.showArrow) { context.moveTo(offset.x, offset.y + 10 * opts.pix); context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pix + 5 * opts.pix); } context.arc(offset.x - arrowWidth - radius, offset.y + toolTipHeight - radius, radius, 0, Math.PI / 2, false); context.arc(offset.x - arrowWidth - Math.round(toolTipWidth) + radius, offset.y + toolTipHeight - radius, radius, - Math.PI / 2, Math.PI, false); + Math.PI / 2, Math.PI, false); context.arc(offset.x - arrowWidth - Math.round(toolTipWidth) + radius, offset.y + radius, radius, -Math.PI, -Math.PI / 2, false); context.arc(offset.x - arrowWidth - radius, offset.y + radius, radius, -Math.PI / 2, 0, false); if (toolTipOption.showArrow) { @@ -2677,9 +2876,9 @@ function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxis } context.arc(offset.x + arrowWidth + radius, offset.y + radius, radius, -Math.PI, -Math.PI / 2, false); context.arc(offset.x + arrowWidth + Math.round(toolTipWidth) - radius, offset.y + radius, radius, -Math.PI / 2, 0, - false); + false); context.arc(offset.x + arrowWidth + Math.round(toolTipWidth) - radius, offset.y + toolTipHeight - radius, radius, 0, - Math.PI / 2, false); + Math.PI / 2, false); context.arc(offset.x + arrowWidth + radius, offset.y + toolTipHeight - radius, radius, Math.PI / 2, Math.PI, false); if (toolTipOption.showArrow) { context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pix + 5 * opts.pix); @@ -2692,30 +2891,68 @@ function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxis context.stroke(); } // draw legend - textList.forEach(function(item, index) { - if (item.color !== null) { - context.beginPath(); - context.setFillStyle(item.color); - var startX = offset.x + arrowWidth + 2 * config.toolTipPadding; - var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index + config.toolTipPadding + 1; - if (isOverRightBorder) { - startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding; + if(toolTipOption.legendShow){ + textList.forEach(function(item, index) { + if (item.color !== null) { + context.beginPath(); + context.setFillStyle(item.color); + var startX = offset.x + arrowWidth + 2 * boxPadding; + var startY = offset.y + (lineHeight - fontSize) / 2 + lineHeight * index + boxPadding + 1; + if (isOverRightBorder) { + startX = offset.x - toolTipWidth - arrowWidth + 2 * boxPadding; + } + switch (item.legendShape) { + case 'line': + context.moveTo(startX, startY + 0.5 * legendWidth - 2 * opts.pix); + context.fillRect(startX, startY + 0.5 * legendWidth - 2 * opts.pix, legendWidth, 4 * opts.pix); + break; + case 'triangle': + context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix); + context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix); + context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix); + context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix); + break; + case 'diamond': + context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix); + context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * legendWidth); + context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix); + context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * legendWidth); + context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix); + break; + case 'circle': + context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth); + context.arc(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth, 5 * opts.pix, 0, 2 * Math.PI); + break; + case 'rect': + context.moveTo(startX, startY + 0.5 * legendWidth - 5 * opts.pix); + context.fillRect(startX, startY + 0.5 * legendWidth - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix); + break; + case 'square': + context.moveTo(startX + 2 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix); + context.fillRect(startX + 2 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix, 10 * opts.pix, 10 * opts.pix); + break; + default: + context.moveTo(startX, startY + 0.5 * legendWidth - 5 * opts.pix); + context.fillRect(startX, startY + 0.5 * legendWidth - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix); + } + context.closePath(); + context.fill(); } - context.fillRect(startX, startY, legendWidth, config.fontSize); - context.closePath(); - } - }); + }); + } + // draw text list textList.forEach(function(item, index) { - var startX = offset.x + arrowWidth + 2 * config.toolTipPadding + legendWidth + legendMarginRight; + var startX = offset.x + arrowWidth + 2 * boxPadding + legendWidth + legendMarginRight; if (isOverRightBorder) { - startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding + +legendWidth + legendMarginRight; + startX = offset.x - toolTipWidth - arrowWidth + 2 * boxPadding + legendWidth + legendMarginRight; } - var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index + config.toolTipPadding; + var startY = offset.y + lineHeight * index + (lineHeight - fontSize)/2 - 1 + boxPadding + fontSize; context.beginPath(); - context.setFontSize(config.fontSize); + context.setFontSize(fontSize); + context.setTextBaseline('normal'); context.setFillStyle(toolTipOption.fontColor); - context.fillText(item.text, startX, startY + config.fontSize); + context.fillText(item.text, startX, startY); context.closePath(); context.stroke(); }); @@ -2724,8 +2961,8 @@ function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxis function drawColumnDataPoints(series, opts, config, context) { let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; let xAxisData = opts.chartData.xAxisData, - xAxisPoints = xAxisData.xAxisPoints, - eachSpacing = xAxisData.eachSpacing; + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; let columnOption = assign({}, { type: 'group', width: eachSpacing / 2, @@ -2738,6 +2975,7 @@ function drawColumnDataPoints(series, opts, config, context) { linearOpacity: 1, customColor: [], colorStop: 0, + labelPosition: 'outside' }, opts.extra.column); let calPoints = []; context.save(); @@ -2757,10 +2995,16 @@ function drawColumnDataPoints(series, opts, config, context) { ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); minRange = ranges.pop(); maxRange = ranges.shift(); + + // 计算0轴坐标 + let spacingValid = opts.height - opts.area[0] - opts.area[2]; + let zeroHeight = spacingValid * (0 - minRange) / (maxRange - minRange); + let zeroPoints = opts.height - Math.round(zeroHeight) - opts.area[2]; + eachSeries.zeroPoints = zeroPoints; var data = eachSeries.data; switch (columnOption.type) { case 'group': - var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + var points = getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, zeroPoints, process); var tooltipPoints = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process); calPoints.push(tooltipPoints); points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts); @@ -2774,7 +3018,7 @@ function drawColumnDataPoints(series, opts, config, context) { var fillColor = item.color || eachSeries.color var strokeColor = item.color || eachSeries.color if (columnOption.linearType !== 'none') { - var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]); + var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints); //透明渐变 if (columnOption.linearType == 'opacity') { grd.addColorStop(0, hexToRgb(fillColor, columnOption.linearOpacity)); @@ -2789,12 +3033,15 @@ function drawColumnDataPoints(series, opts, config, context) { // 圆角边框 if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) { const left = startX; - const top = item.y; + const top = item.y > zeroPoints ? zeroPoints : item.y; const width = item.width; - const height = opts.height - opts.area[2] - item.y; + const height = Math.abs(zeroPoints - item.y); if (columnOption.barBorderCircle) { columnOption.barBorderRadius = [width / 2, width / 2, 0, 0]; } + if(item.y > zeroPoints){ + columnOption.barBorderRadius = [0, 0,width / 2, width / 2]; + } let [r0, r1, r2, r3] = columnOption.barBorderRadius; let minRadius = Math.min(width/2,height/2); r0 = r0 > minRadius ? minRadius : r0; @@ -2812,8 +3059,8 @@ function drawColumnDataPoints(series, opts, config, context) { } else { context.moveTo(startX, item.y); context.lineTo(startX + item.width, item.y); - context.lineTo(startX + item.width, opts.height - opts.area[2]); - context.lineTo(startX, opts.height - opts.area[2]); + context.lineTo(startX + item.width, zeroPoints); + context.lineTo(startX, zeroPoints); context.lineTo(startX, item.y); context.setLineWidth(1) context.setStrokeStyle(strokeColor); @@ -2854,59 +3101,59 @@ function drawColumnDataPoints(series, opts, config, context) { var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); calPoints.push(points); points = fixColumeMeterData(points, eachSpacing, series.length, seriesIndex, config, opts, columnOption.meterBorder); - for (let i = 0; i < points.length; i++) { - let item = points[i]; - if (item !== null && i > leftNum && i < rightNum) { - //画背景颜色 - context.beginPath(); - if (seriesIndex == 0 && columnOption.meterBorder > 0) { - context.setStrokeStyle(eachSeries.color); - context.setLineWidth(columnOption.meterBorder * opts.pix); - } - if(seriesIndex == 0){ - context.setFillStyle(columnOption.meterFillColor); - }else{ - context.setFillStyle(item.color || eachSeries.color); - } - var startX = item.x - item.width / 2; - var height = opts.height - item.y - opts.area[2]; - if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) { - const left = startX; - const top = item.y; - const width = item.width; - const height = opts.height - opts.area[2] - item.y; - if (columnOption.barBorderCircle) { - columnOption.barBorderRadius = [width / 2, width / 2, 0, 0]; - } - let [r0, r1, r2, r3] = columnOption.barBorderRadius; - let minRadius = Math.min(width/2,height/2); - r0 = r0 > minRadius ? minRadius : r0; - r1 = r1 > minRadius ? minRadius : r1; - r2 = r2 > minRadius ? minRadius : r2; - r3 = r3 > minRadius ? minRadius : r3; - r0 = r0 < 0 ? 0 : r0; - r1 = r1 < 0 ? 0 : r1; - r2 = r2 < 0 ? 0 : r2; - r3 = r3 < 0 ? 0 : r3; - context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2); - context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0); - context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2); - context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI); - context.fill(); - }else{ - context.moveTo(startX, item.y); - context.lineTo(startX + item.width, item.y); - context.lineTo(startX + item.width, opts.height - opts.area[2]); - context.lineTo(startX, opts.height - opts.area[2]); - context.lineTo(startX, item.y); - context.fill(); - } - if (seriesIndex == 0 && columnOption.meterBorder > 0) { - context.closePath(); - context.stroke(); + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + //画背景颜色 + context.beginPath(); + if (seriesIndex == 0 && columnOption.meterBorder > 0) { + context.setStrokeStyle(eachSeries.color); + context.setLineWidth(columnOption.meterBorder * opts.pix); + } + if(seriesIndex == 0){ + context.setFillStyle(columnOption.meterFillColor); + }else{ + context.setFillStyle(item.color || eachSeries.color); + } + var startX = item.x - item.width / 2; + var height = opts.height - item.y - opts.area[2]; + if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) { + const left = startX; + const top = item.y; + const width = item.width; + const height = zeroPoints - item.y; + if (columnOption.barBorderCircle) { + columnOption.barBorderRadius = [width / 2, width / 2, 0, 0]; } + let [r0, r1, r2, r3] = columnOption.barBorderRadius; + let minRadius = Math.min(width/2,height/2); + r0 = r0 > minRadius ? minRadius : r0; + r1 = r1 > minRadius ? minRadius : r1; + r2 = r2 > minRadius ? minRadius : r2; + r3 = r3 > minRadius ? minRadius : r3; + r0 = r0 < 0 ? 0 : r0; + r1 = r1 < 0 ? 0 : r1; + r2 = r2 < 0 ? 0 : r2; + r3 = r3 < 0 ? 0 : r3; + context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2); + context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0); + context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2); + context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI); + context.fill(); + }else{ + context.moveTo(startX, item.y); + context.lineTo(startX + item.width, item.y); + context.lineTo(startX + item.width, zeroPoints); + context.lineTo(startX, zeroPoints); + context.lineTo(startX, item.y); + context.fill(); + } + if (seriesIndex == 0 && columnOption.meterBorder > 0) { + context.closePath(); + context.stroke(); } } + } break; } }); @@ -2920,17 +3167,17 @@ function drawColumnDataPoints(series, opts, config, context) { var data = eachSeries.data; switch (columnOption.type) { case 'group': - var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + var points = getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts); - drawPointText(points, eachSeries, config, context, opts); + drawColumePointText(points, eachSeries, config, context, opts); break; case 'stack': var points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process); - drawPointText(points, eachSeries, config, context, opts); + drawColumePointText(points, eachSeries, config, context, opts); break; case 'meter': var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); - drawPointText(points, eachSeries, config, context, opts); + drawColumePointText(points, eachSeries, config, context, opts); break; } }); @@ -2946,8 +3193,8 @@ function drawColumnDataPoints(series, opts, config, context) { function drawMountDataPoints(series, opts, config, context) { let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; let xAxisData = opts.chartData.xAxisData, - xAxisPoints = xAxisData.xAxisPoints, - eachSpacing = xAxisData.eachSpacing; + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; let mountOption = assign({}, { type: 'mount', widthRatio: 1, @@ -2971,189 +3218,198 @@ function drawMountDataPoints(series, opts, config, context) { rightNum = leftNum + opts.xAxis.itemCount + 4; } mountOption.customColor = fillCustomColor(mountOption.linearType, mountOption.customColor, series, config); - let ranges, minRange, maxRange; - ranges = [].concat(opts.chartData.yAxisData.ranges[0]); - minRange = ranges.pop(); - maxRange = ranges.shift(); - var points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, process); - switch (mountOption.type) { - case 'bar': - for (let i = 0; i < points.length; i++) { - let item = points[i]; - if (item !== null && i > leftNum && i < rightNum) { - var startX = item.x - eachSpacing*mountOption.widthRatio/2; - var height = opts.height - item.y - opts.area[2]; - context.beginPath(); - var fillColor = item.color || series[i].color - var strokeColor = item.color || series[i].color - if (mountOption.linearType !== 'none') { - var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]); - //透明渐变 - if (mountOption.linearType == 'opacity') { - grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); - grd.addColorStop(1, hexToRgb(fillColor, 1)); - } else { - grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); - grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); - grd.addColorStop(1, hexToRgb(fillColor, 1)); - } - fillColor = grd - } - // 圆角边框 - if ((mountOption.barBorderRadius && mountOption.barBorderRadius.length === 4) || mountOption.barBorderCircle === true) { - const left = startX; - const top = item.y; - const width = item.width; - const height = opts.height - opts.area[2] - item.y - mountOption.borderWidth * opts.pix / 2; - if (mountOption.barBorderCircle) { - mountOption.barBorderRadius = [width / 2, width / 2, 0, 0]; - } - let [r0, r1, r2, r3] = mountOption.barBorderRadius; - let minRadius = Math.min(width/2,height/2); - r0 = r0 > minRadius ? minRadius : r0; - r1 = r1 > minRadius ? minRadius : r1; - r2 = r2 > minRadius ? minRadius : r2; - r3 = r3 > minRadius ? minRadius : r3; - r0 = r0 < 0 ? 0 : r0; - r1 = r1 < 0 ? 0 : r1; - r2 = r2 < 0 ? 0 : r2; - r3 = r3 < 0 ? 0 : r3; - context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2); - context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0); - context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2); - context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI); + let ranges, minRange, maxRange; + ranges = [].concat(opts.chartData.yAxisData.ranges[0]); + minRange = ranges.pop(); + maxRange = ranges.shift(); + + // 计算0轴坐标 + let spacingValid = opts.height - opts.area[0] - opts.area[2]; + let zeroHeight = spacingValid * (0 - minRange) / (maxRange - minRange); + let zeroPoints = opts.height - Math.round(zeroHeight) - opts.area[2]; + + var points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints, process); + switch (mountOption.type) { + case 'bar': + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + var startX = item.x - eachSpacing*mountOption.widthRatio/2; + var height = opts.height - item.y - opts.area[2]; + context.beginPath(); + var fillColor = item.color || series[i].color + var strokeColor = item.color || series[i].color + if (mountOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints); + //透明渐变 + if (mountOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); } else { - context.moveTo(startX, item.y); - context.lineTo(startX + item.width, item.y); - context.lineTo(startX + item.width, opts.height - opts.area[2]); - context.lineTo(startX, opts.height - opts.area[2]); - context.lineTo(startX, item.y); + grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); + grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); } - context.setStrokeStyle(strokeColor); - context.setFillStyle(fillColor); - if(mountOption.borderWidth > 0){ - context.setLineWidth(mountOption.borderWidth * opts.pix); - context.closePath(); - context.stroke(); - } - context.fill(); + fillColor = grd } - }; - break; - case 'triangle': - for (let i = 0; i < points.length; i++) { - let item = points[i]; - if (item !== null && i > leftNum && i < rightNum) { - var startX = item.x - eachSpacing*mountOption.widthRatio/2; - var height = opts.height - item.y - opts.area[2]; - context.beginPath(); - var fillColor = item.color || series[i].color - var strokeColor = item.color || series[i].color - if (mountOption.linearType !== 'none') { - var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]); - //透明渐变 - if (mountOption.linearType == 'opacity') { - grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); - grd.addColorStop(1, hexToRgb(fillColor, 1)); - } else { - grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); - grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); - grd.addColorStop(1, hexToRgb(fillColor, 1)); - } - fillColor = grd + // 圆角边框 + if ((mountOption.barBorderRadius && mountOption.barBorderRadius.length === 4) || mountOption.barBorderCircle === true) { + const left = startX; + const top = item.y > zeroPoints ? zeroPoints : item.y; + const width = item.width; + const height = Math.abs(zeroPoints - item.y); + if (mountOption.barBorderCircle) { + mountOption.barBorderRadius = [width / 2, width / 2, 0, 0]; } - context.moveTo(startX, opts.height - opts.area[2]); - context.lineTo(item.x, item.y); - context.lineTo(startX + item.width, opts.height - opts.area[2]); - context.setStrokeStyle(strokeColor); - context.setFillStyle(fillColor); - if(mountOption.borderWidth > 0){ - context.setLineWidth(mountOption.borderWidth * opts.pix); - context.stroke(); + if(item.y > zeroPoints){ + mountOption.barBorderRadius = [0, 0,width / 2, width / 2]; } - context.fill(); + let [r0, r1, r2, r3] = mountOption.barBorderRadius; + let minRadius = Math.min(width/2,height/2); + r0 = r0 > minRadius ? minRadius : r0; + r1 = r1 > minRadius ? minRadius : r1; + r2 = r2 > minRadius ? minRadius : r2; + r3 = r3 > minRadius ? minRadius : r3; + r0 = r0 < 0 ? 0 : r0; + r1 = r1 < 0 ? 0 : r1; + r2 = r2 < 0 ? 0 : r2; + r3 = r3 < 0 ? 0 : r3; + context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2); + context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0); + context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2); + context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI); + } else { + context.moveTo(startX, item.y); + context.lineTo(startX + item.width, item.y); + context.lineTo(startX + item.width, zeroPoints); + context.lineTo(startX, zeroPoints); + context.lineTo(startX, item.y); } - }; - break; - case 'mount': - for (let i = 0; i < points.length; i++) { - let item = points[i]; - if (item !== null && i > leftNum && i < rightNum) { - var startX = item.x - eachSpacing*mountOption.widthRatio/2; - var height = opts.height - item.y - opts.area[2]; - context.beginPath(); - var fillColor = item.color || series[i].color - var strokeColor = item.color || series[i].color - if (mountOption.linearType !== 'none') { - var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]); - //透明渐变 - if (mountOption.linearType == 'opacity') { - grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); - grd.addColorStop(1, hexToRgb(fillColor, 1)); - } else { - grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); - grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); - grd.addColorStop(1, hexToRgb(fillColor, 1)); - } - fillColor = grd - } - context.moveTo(startX, opts.height - opts.area[2]); - context.bezierCurveTo(item.x - item.width/4, opts.height - opts.area[2], item.x - item.width/4, item.y, item.x, item.y); - context.bezierCurveTo(item.x + item.width/4, item.y, item.x + item.width/4, opts.height - opts.area[2], startX + item.width, opts.height - opts.area[2]); - context.setStrokeStyle(strokeColor); - context.setFillStyle(fillColor); - if(mountOption.borderWidth > 0){ - context.setLineWidth(mountOption.borderWidth * opts.pix); - context.stroke(); - } - context.fill(); + context.setStrokeStyle(strokeColor); + context.setFillStyle(fillColor); + if(mountOption.borderWidth > 0){ + context.setLineWidth(mountOption.borderWidth * opts.pix); + context.closePath(); + context.stroke(); } - }; - break; - case 'sharp': - for (let i = 0; i < points.length; i++) { - let item = points[i]; - if (item !== null && i > leftNum && i < rightNum) { - var startX = item.x - eachSpacing*mountOption.widthRatio/2; - var height = opts.height - item.y - opts.area[2]; - context.beginPath(); - var fillColor = item.color || series[i].color - var strokeColor = item.color || series[i].color - if (mountOption.linearType !== 'none') { - var grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]); - //透明渐变 - if (mountOption.linearType == 'opacity') { - grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); - grd.addColorStop(1, hexToRgb(fillColor, 1)); - } else { - grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); - grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); - grd.addColorStop(1, hexToRgb(fillColor, 1)); - } - fillColor = grd + context.fill(); + } + }; + break; + case 'triangle': + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + var startX = item.x - eachSpacing*mountOption.widthRatio/2; + var height = opts.height - item.y - opts.area[2]; + context.beginPath(); + var fillColor = item.color || series[i].color + var strokeColor = item.color || series[i].color + if (mountOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints); + //透明渐变 + if (mountOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } else { + grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); + grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); } - context.moveTo(startX, opts.height - opts.area[2]); - context.quadraticCurveTo(item.x - 0, opts.height - opts.area[2] - height/4, item.x, item.y); - context.quadraticCurveTo(item.x + 0, opts.height - opts.area[2] - height/4, startX + item.width, opts.height - opts.area[2]) - context.setStrokeStyle(strokeColor); - context.setFillStyle(fillColor); - if(mountOption.borderWidth > 0){ - context.setLineWidth(mountOption.borderWidth * opts.pix); - context.stroke(); - } - context.fill(); + fillColor = grd } - }; - break; - } + context.moveTo(startX, zeroPoints); + context.lineTo(item.x, item.y); + context.lineTo(startX + item.width, zeroPoints); + context.setStrokeStyle(strokeColor); + context.setFillStyle(fillColor); + if(mountOption.borderWidth > 0){ + context.setLineWidth(mountOption.borderWidth * opts.pix); + context.stroke(); + } + context.fill(); + } + }; + break; + case 'mount': + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + var startX = item.x - eachSpacing*mountOption.widthRatio/2; + var height = opts.height - item.y - opts.area[2]; + context.beginPath(); + var fillColor = item.color || series[i].color + var strokeColor = item.color || series[i].color + if (mountOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints); + //透明渐变 + if (mountOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } else { + grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); + grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } + fillColor = grd + } + context.moveTo(startX, zeroPoints); + context.bezierCurveTo(item.x - item.width/4, zeroPoints, item.x - item.width/4, item.y, item.x, item.y); + context.bezierCurveTo(item.x + item.width/4, item.y, item.x + item.width/4, zeroPoints, startX + item.width, zeroPoints); + context.setStrokeStyle(strokeColor); + context.setFillStyle(fillColor); + if(mountOption.borderWidth > 0){ + context.setLineWidth(mountOption.borderWidth * opts.pix); + context.stroke(); + } + context.fill(); + } + }; + break; + case 'sharp': + for (let i = 0; i < points.length; i++) { + let item = points[i]; + if (item !== null && i > leftNum && i < rightNum) { + var startX = item.x - eachSpacing*mountOption.widthRatio/2; + var height = opts.height - item.y - opts.area[2]; + context.beginPath(); + var fillColor = item.color || series[i].color + var strokeColor = item.color || series[i].color + if (mountOption.linearType !== 'none') { + var grd = context.createLinearGradient(startX, item.y, startX, zeroPoints); + //透明渐变 + if (mountOption.linearType == 'opacity') { + grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } else { + grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity)); + grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity)); + grd.addColorStop(1, hexToRgb(fillColor, 1)); + } + fillColor = grd + } + context.moveTo(startX, zeroPoints); + context.quadraticCurveTo(item.x - 0, zeroPoints - height/4, item.x, item.y); + context.quadraticCurveTo(item.x + 0, zeroPoints - height/4, startX + item.width, zeroPoints) + context.setStrokeStyle(strokeColor); + context.setFillStyle(fillColor); + if(mountOption.borderWidth > 0){ + context.setLineWidth(mountOption.borderWidth * opts.pix); + context.stroke(); + } + context.fill(); + } + }; + break; + } if (opts.dataLabel !== false && process === 1) { let ranges, minRange, maxRange; ranges = [].concat(opts.chartData.yAxisData.ranges[0]); minRange = ranges.pop(); maxRange = ranges.shift(); - var points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, process); - drawMountPointText(points, series, config, context, opts); + var points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints, process); + drawMountPointText(points, series, config, context, opts, zeroPoints); } context.restore(); return { @@ -3246,7 +3502,7 @@ function drawBarDataPoints(series, opts, config, context) { r1 = r1 < 0 ? 0 : r1; r2 = r2 < 0 ? 0 : r2; r3 = r3 < 0 ? 0 : r3; - + context.arc(left + r3, top + r3, r3, -Math.PI, -Math.PI / 2); context.arc(item.x - r0, top + r0, r0, -Math.PI / 2, 0); context.arc(item.x - r1, top + width - r1, r1, 0, Math.PI / 2); @@ -3336,8 +3592,8 @@ function drawCandleDataPoints(series, seriesMA, opts, config, context) { }, candleOption.average); opts.extra.candle = candleOption; let xAxisData = opts.chartData.xAxisData, - xAxisPoints = xAxisData.xAxisPoints, - eachSpacing = xAxisData.eachSpacing; + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; let calPoints = []; context.save(); let leftNum = -2; @@ -3381,7 +3637,7 @@ function drawCandleDataPoints(series, seriesMA, opts, config, context) { if (j > 0 && item.x > leftSpace && item.x < rightSpace) { var ctrlPoint = createCurveControlPoints(points, j - 1); context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, - item.y); + item.y); } } context.moveTo(points[0].x, points[0].y); @@ -3458,11 +3714,12 @@ function drawAreaDataPoints(series, opts, config, context) { opacity: 0.2, addLine: false, width: 2, - gradient: false + gradient: false, + activeType: 'none' }, opts.extra.area); let xAxisData = opts.chartData.xAxisData, - xAxisPoints = xAxisData.xAxisPoints, - eachSpacing = xAxisData.eachSpacing; + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; let endY = opts.height - opts.area[2]; let calPoints = []; context.save(); @@ -3513,7 +3770,7 @@ function drawAreaDataPoints(series, opts, config, context) { context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y); } }; - } + } if (areaOption.type === 'straight') { for (let j = 0; j < points.length; j++) { let item = points[j]; @@ -3545,10 +3802,10 @@ function drawAreaDataPoints(series, opts, config, context) { } else { let item = points[0]; context.moveTo(item.x - eachSpacing / 2, item.y); - context.lineTo(item.x + eachSpacing / 2, item.y); - context.lineTo(item.x + eachSpacing / 2, endY); - context.lineTo(item.x - eachSpacing / 2, endY); - context.moveTo(item.x - eachSpacing / 2, item.y); + // context.lineTo(item.x + eachSpacing / 2, item.y); + // context.lineTo(item.x + eachSpacing / 2, endY); + // context.lineTo(item.x - eachSpacing / 2, endY); + // context.moveTo(item.x - eachSpacing / 2, item.y); } context.closePath(); context.fill(); @@ -3564,7 +3821,7 @@ function drawAreaDataPoints(series, opts, config, context) { context.setLineWidth(areaOption.width * opts.pix); if (points.length === 1) { context.moveTo(points[0].x, points[0].y); - context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + // context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); } else { context.moveTo(points[0].x, points[0].y); let startPoint = 0; @@ -3616,6 +3873,7 @@ function drawAreaDataPoints(series, opts, config, context) { if (opts.dataPointShape !== false) { drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts); } + drawActivePoint(points, eachSeries.color, eachSeries.pointShape, context, opts, areaOption,seriesIndex); }); if (opts.dataLabel !== false && process === 1) { @@ -3643,8 +3901,8 @@ function drawScatterDataPoints(series, opts, config, context) { type: 'circle' }, opts.extra.scatter); let xAxisData = opts.chartData.xAxisData, - xAxisPoints = xAxisData.xAxisPoints, - eachSpacing = xAxisData.eachSpacing; + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; var calPoints = []; context.save(); let leftSpace = 0; @@ -3732,8 +3990,8 @@ function drawBubbleDataPoints(series, opts, config, context) { border:2 }, opts.extra.bubble); let xAxisData = opts.chartData.xAxisData, - xAxisPoints = xAxisData.xAxisPoints, - eachSpacing = xAxisData.eachSpacing; + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; var calPoints = []; context.save(); let leftSpace = 0; @@ -3761,13 +4019,13 @@ function drawBubbleDataPoints(series, opts, config, context) { context.closePath(); context.fill(); context.stroke(); - + if (opts.dataLabel !== false && process === 1) { points.forEach(function(item, index) { context.beginPath(); - var fontSize = series.textSize * opts.pix || config.fontSize; + var fontSize = eachSeries.textSize * opts.pix || config.fontSize; context.setFontSize(fontSize); - context.setFillStyle(series.textColor || "#FFFFFF"); + context.setFillStyle(eachSeries.textColor || "#FFFFFF"); context.setTextAlign('center'); context.fillText(String(item.t), item.x, item.y + fontSize/2); context.closePath(); @@ -3788,12 +4046,16 @@ function drawLineDataPoints(series, opts, config, context) { var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; var lineOption = assign({}, { type: 'straight', - width: 2 + width: 2, + activeType: 'none', + linearType: 'none', + onShadow: false, + animation: 'vertical', }, opts.extra.line); lineOption.width *= opts.pix; let xAxisData = opts.chartData.xAxisData, - xAxisPoints = xAxisData.xAxisPoints, - eachSpacing = xAxisData.eachSpacing; + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; var calPoints = []; context.save(); let leftSpace = 0; @@ -3804,12 +4066,18 @@ function drawLineDataPoints(series, opts, config, context) { rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing; } series.forEach(function(eachSeries, seriesIndex) { + // 这段很神奇的代码用于解决ios16的setStrokeStyle失效的bug + context.beginPath(); + context.setStrokeStyle(eachSeries.color); + context.moveTo(-10000, -10000); + context.lineTo(-10001, -10001); + context.stroke(); let ranges, minRange, maxRange; ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]); minRange = ranges.pop(); maxRange = ranges.shift(); var data = eachSeries.data; - var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process); + var points = getLineDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, lineOption, process); calPoints.push(points); var splitPointList = splitPoints(points,eachSeries); if (eachSeries.lineType == 'dash') { @@ -3818,12 +4086,25 @@ function drawLineDataPoints(series, opts, config, context) { context.setLineDash([dashLength, dashLength]); } context.beginPath(); - context.setStrokeStyle(eachSeries.color); + var strokeColor = eachSeries.color; + if (lineOption.linearType !== 'none' && eachSeries.linearColor && eachSeries.linearColor.length > 0) { + var grd = context.createLinearGradient(opts.chartData.xAxisData.startX, opts.height/2, opts.chartData.xAxisData.endX, opts.height/2); + for (var i = 0; i < eachSeries.linearColor.length; i++) { + grd.addColorStop(eachSeries.linearColor[i][0], hexToRgb(eachSeries.linearColor[i][1], 1)); + } + strokeColor = grd + } + context.setStrokeStyle(strokeColor); + if (lineOption.onShadow == true && eachSeries.setShadow && eachSeries.setShadow.length > 0) { + context.setShadow(eachSeries.setShadow[0], eachSeries.setShadow[1], eachSeries.setShadow[2], eachSeries.setShadow[3]); + }else{ + context.setShadow(0, 0, 0, 'rgba(0,0,0,0)'); + } context.setLineWidth(lineOption.width); splitPointList.forEach(function(points, index) { if (points.length === 1) { context.moveTo(points[0].x, points[0].y); - context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + // context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); } else { context.moveTo(points[0].x, points[0].y); let startPoint = 0; @@ -3873,6 +4154,7 @@ function drawLineDataPoints(series, opts, config, context) { if (opts.dataPointShape !== false) { drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts); } + drawActivePoint(points, eachSeries.color, eachSeries.pointShape, context, opts, lineOption); }); if (opts.dataLabel !== false && process === 1) { series.forEach(function(eachSeries, seriesIndex) { @@ -3896,8 +4178,8 @@ function drawLineDataPoints(series, opts, config, context) { function drawMixDataPoints(series, opts, config, context) { let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1; let xAxisData = opts.chartData.xAxisData, - xAxisPoints = xAxisData.xAxisPoints, - eachSpacing = xAxisData.eachSpacing; + xAxisPoints = xAxisData.xAxisPoints, + eachSpacing = xAxisData.eachSpacing; let columnOption = assign({}, { width: eachSpacing / 2, barBorderCircle: false, @@ -3912,6 +4194,9 @@ function drawMixDataPoints(series, opts, config, context) { opacity: 0.2, gradient: false }, opts.extra.mix.area); + let lineOption = assign({}, { + width: 2 + }, opts.extra.mix.line); let endY = opts.height - opts.area[2]; let calPoints = []; var columnIndex = 0; @@ -4058,10 +4343,10 @@ function drawMixDataPoints(series, opts, config, context) { } else { let item = points[0]; context.moveTo(item.x - eachSpacing / 2, item.y); - context.lineTo(item.x + eachSpacing / 2, item.y); - context.lineTo(item.x + eachSpacing / 2, endY); - context.lineTo(item.x - eachSpacing / 2, endY); - context.moveTo(item.x - eachSpacing / 2, item.y); + // context.lineTo(item.x + eachSpacing / 2, item.y); + // context.lineTo(item.x + eachSpacing / 2, endY); + // context.lineTo(item.x - eachSpacing / 2, endY); + // context.moveTo(item.x - eachSpacing / 2, item.y); } context.closePath(); context.fill(); @@ -4078,10 +4363,10 @@ function drawMixDataPoints(series, opts, config, context) { } context.beginPath(); context.setStrokeStyle(eachSeries.color); - context.setLineWidth(2 * opts.pix); + context.setLineWidth(lineOption.width * opts.pix); if (points.length === 1) { context.moveTo(points[0].x, points[0].y); - context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); + // context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI); } else { context.moveTo(points[0].x, points[0].y); let startPoint = 0; @@ -4095,7 +4380,7 @@ function drawMixDataPoints(series, opts, config, context) { if (j > 0 && item.x > leftSpace && item.x < rightSpace) { var ctrlPoint = createCurveControlPoints(points, j - 1); context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, - item.x, item.y); + item.x, item.y); } } } else { @@ -4170,10 +4455,10 @@ function drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoi function drawXAxis(categories, opts, config, context) { let xAxisData = opts.chartData.xAxisData, - xAxisPoints = xAxisData.xAxisPoints, - startX = xAxisData.startX, - endX = xAxisData.endX, - eachSpacing = xAxisData.eachSpacing; + xAxisPoints = xAxisData.xAxisPoints, + startX = xAxisData.startX, + endX = xAxisData.endX, + eachSpacing = xAxisData.eachSpacing; var boundaryGap = 'center'; if (opts.type == 'bar' || opts.type == 'line' || opts.type == 'area'|| opts.type == 'scatter' || opts.type == 'bubble') { boundaryGap = opts.xAxis.boundaryGap; @@ -4291,47 +4576,68 @@ function drawXAxis(categories, opts, config, context) { if (opts.xAxis.scrollShow) { scrollHeight = 6 * opts.pix; } - context.beginPath(); - context.setFontSize(xAxisFontSize); - context.setFillStyle(opts.xAxis.fontColor || opts.fontColor); - context.fillText(String(xitem), xAxisPoints[index] + offset, startY + xAxisFontSize + (config.xAxisHeight - scrollHeight - xAxisFontSize) / 2); - context.closePath(); - context.stroke(); + // 如果在主视图区域内 + var _scrollDistance_ = opts._scrollDistance_ || 0; + var truePoints = boundaryGap == 'center' ? xAxisPoints[index] + eachSpacing / 2 : xAxisPoints[index]; + if((truePoints - Math.abs(_scrollDistance_)) >= (opts.area[3] - 1) && (truePoints - Math.abs(_scrollDistance_)) <= (opts.width - opts.area[1] + 1)){ + context.beginPath(); + context.setFontSize(xAxisFontSize); + context.setFillStyle(opts.xAxis.fontColor || opts.fontColor); + context.fillText(String(xitem), xAxisPoints[index] + offset, startY + opts.xAxis.marginTop * opts.pix + (opts.xAxis.lineHeight - opts.xAxis.fontSize) * opts.pix / 2 + opts.xAxis.fontSize * opts.pix); + context.closePath(); + context.stroke(); + } }); } else { newCategories.forEach(function(item, index) { var xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item) : item; - context.save(); - context.beginPath(); - context.setFontSize(xAxisFontSize); - context.setFillStyle(opts.xAxis.fontColor || opts.fontColor); - var textWidth = measureText(String(xitem), xAxisFontSize, context); - var offsetX = xAxisPoints[index]; - if (boundaryGap == 'center') { - offsetX = xAxisPoints[index] + eachSpacing / 2; + // 如果在主视图区域内 + var _scrollDistance_ = opts._scrollDistance_ || 0; + var truePoints = boundaryGap == 'center' ? xAxisPoints[index] + eachSpacing / 2 : xAxisPoints[index]; + if((truePoints - Math.abs(_scrollDistance_)) >= (opts.area[3] - 1) && (truePoints - Math.abs(_scrollDistance_)) <= (opts.width - opts.area[1] + 1)){ + context.save(); + context.beginPath(); + context.setFontSize(xAxisFontSize); + context.setFillStyle(opts.xAxis.fontColor || opts.fontColor); + var textWidth = measureText(String(xitem), xAxisFontSize, context); + var offsetX = xAxisPoints[index]; + if (boundaryGap == 'center') { + offsetX = xAxisPoints[index] + eachSpacing / 2; + } + var scrollHeight = 0; + if (opts.xAxis.scrollShow) { + scrollHeight = 6 * opts.pix; + } + var offsetY = startY + opts.xAxis.marginTop * opts.pix + xAxisFontSize - xAxisFontSize * Math.abs(Math.sin(config._xAxisTextAngle_)); + if(opts.xAxis.rotateAngle < 0){ + offsetX -= xAxisFontSize / 2; + textWidth = 0; + }else{ + offsetX += xAxisFontSize / 2; + textWidth = -textWidth; + } + context.translate(offsetX, offsetY); + context.rotate(-1 * config._xAxisTextAngle_); + context.fillText(String(xitem), textWidth , 0 ); + context.closePath(); + context.stroke(); + context.restore(); } - var scrollHeight = 0; - if (opts.xAxis.scrollShow) { - scrollHeight = 6 * opts.pix; - } - var offsetY = startY + 6 * opts.pix + xAxisFontSize - xAxisFontSize * Math.abs(Math.sin(config._xAxisTextAngle_)); - if(opts.xAxis.rotateAngle < 0){ - offsetX -= xAxisFontSize / 2; - textWidth = 0; - }else{ - offsetX += xAxisFontSize / 2; - textWidth = -textWidth; - } - context.translate(offsetX, offsetY); - context.rotate(-1 * config._xAxisTextAngle_); - context.fillText(String(xitem), textWidth , 0 ); - context.closePath(); - context.stroke(); - context.restore(); }); } } context.restore(); + + //画X轴标题 + if (opts.xAxis.title) { + context.beginPath(); + context.setFontSize(opts.xAxis.titleFontSize * opts.pix); + context.setFillStyle(opts.xAxis.titleFontColor); + context.fillText(String(opts.xAxis.title), opts.width - opts.area[1] + opts.xAxis.titleOffsetX * opts.pix,opts.height - opts.area[2] + opts.xAxis.marginTop * opts.pix + (opts.xAxis.lineHeight - opts.xAxis.titleFontSize) * opts.pix / 2 + (opts.xAxis.titleFontSize + opts.xAxis.titleOffsetY) * opts.pix); + context.closePath(); + context.stroke(); + } + //绘制X轴轴线 if (opts.xAxis.axisLine) { context.beginPath(); @@ -4351,11 +4657,11 @@ function drawYAxisGrid(categories, opts, config, context) { let eachSpacing = spacingValid / opts.yAxis.splitNumber; let startX = opts.area[3]; let xAxisPoints = opts.chartData.xAxisData.xAxisPoints, - xAxiseachSpacing = opts.chartData.xAxisData.eachSpacing; + xAxiseachSpacing = opts.chartData.xAxisData.eachSpacing; let TotalWidth = xAxiseachSpacing * (xAxisPoints.length - 1); if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1 ){ if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2 - TotalWidth += (opts.extra.mount.widthRatio - 1)*xAxiseachSpacing; + TotalWidth += (opts.extra.mount.widthRatio - 1) * xAxiseachSpacing; } let endX = startX + TotalWidth; let points = []; @@ -4394,25 +4700,18 @@ function drawYAxis(series, opts, config, context) { var startX = opts.area[3]; var endX = opts.width - opts.area[1]; var endY = opts.height - opts.area[2]; - var fillEndY = endY + config.xAxisHeight; - if (opts.xAxis.scrollShow) { - fillEndY -= 3 * opts.pix; - } - if (opts.xAxis.rotateLabel) { - fillEndY = opts.height - opts.area[2] + opts.fontSize * opts.pix / 2; - } // set YAxis background context.beginPath(); context.setFillStyle(opts.background); if (opts.enableScroll == true && opts.xAxis.scrollPosition && opts.xAxis.scrollPosition !== 'left') { - context.fillRect(0, 0, startX, fillEndY); + context.fillRect(0, 0, startX, endY + 2 * opts.pix); } if (opts.enableScroll == true && opts.xAxis.scrollPosition && opts.xAxis.scrollPosition !== 'right') { - context.fillRect(endX, 0, opts.width, fillEndY); + context.fillRect(endX, 0, opts.width, endY + 2 * opts.pix); } context.closePath(); context.stroke(); - + let tStartLeft = opts.area[3]; let tStartRight = opts.width - opts.area[1]; let tStartCenter = opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2; @@ -4594,12 +4893,12 @@ function drawLegend(series, opts, config, context, chartData) { switch (opts.legend.float) { case 'left': startX = legendArea.start.x + padding; - break; + break; case 'right': startX = legendArea.start.x + legendArea.width - width; - break; + break; default: - startX = legendArea.start.x + (legendArea.width - width) / 2; + startX = legendArea.start.x + (legendArea.width - width) / 2; } startY = legendArea.start.y + padding + listIndex * lineHeight; } else { @@ -4803,6 +5102,9 @@ function drawRoseDataPoints(series, opts, config, context) { var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding); radius = radius < 10 ? 10 : radius; var minRadius = roseOption.minRadius || radius * 0.5; + if(radius < minRadius){ + radius = minRadius + 10; + } series = getRoseDataPoints(series, roseOption.type, minRadius, radius, process); var activeRadius = roseOption.activeRadius * opts.pix; roseOption.customColor = fillCustomColor(roseOption.linearType, roseOption.customColor, series, config); @@ -4863,6 +5165,7 @@ function drawArcbarDataPoints(series, opts, config, context) { startAngle: 0.75, endAngle: 0.25, type: 'default', + direction: 'cw', lineCap: 'round', width: 12 , gap: 2 , @@ -4892,7 +5195,7 @@ function drawArcbarDataPoints(series, opts, config, context) { } radius = radius < 10 ? 10 : radius; arcbarOption.customColor = fillCustomColor(arcbarOption.linearType, arcbarOption.customColor, series, config); - + for (let i = 0; i < series.length; i++) { let eachSeries = series[i]; //背景颜色 @@ -4901,9 +5204,9 @@ function drawArcbarDataPoints(series, opts, config, context) { context.setLineCap(arcbarOption.lineCap); context.beginPath(); if (arcbarOption.type == 'default') { - context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, arcbarOption.endAngle * Math.PI, false); + context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, arcbarOption.endAngle * Math.PI, arcbarOption.direction == 'ccw'); } else { - context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, 0, 2 * Math.PI, false); + context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, 0, 2 * Math.PI, arcbarOption.direction == 'ccw'); } context.stroke(); //进度条 @@ -4918,7 +5221,7 @@ function drawArcbarDataPoints(series, opts, config, context) { context.setStrokeStyle(fillColor); context.setLineCap(arcbarOption.lineCap); context.beginPath(); - context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, eachSeries._proportion_ * Math.PI, false); + context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, eachSeries._proportion_ * Math.PI, arcbarOption.direction == 'ccw'); context.stroke(); } drawRingTitle(opts, config, context, centerPosition); @@ -4988,7 +5291,11 @@ function drawGaugeDataPoints(categories, series, opts, config, context) { context.arc(centerPosition.x, centerPosition.y, innerRadius, gaugeOption.startAngle * Math.PI, gaugeOption.endAngle * Math.PI, false); context.stroke(); //## 第二步画刻度线 - totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1; + if (gaugeOption.endAngle < gaugeOption.startAngle) { + totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle; + } else { + totalAngle = gaugeOption.startAngle - gaugeOption.endAngle; + } let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber; let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber; let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius; @@ -5060,7 +5367,11 @@ function drawGaugeDataPoints(categories, series, opts, config, context) { } context.save(); //画刻度线 - totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1; + if (gaugeOption.endAngle < gaugeOption.startAngle) { + totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle; + } else { + totalAngle = gaugeOption.startAngle - gaugeOption.endAngle; + } let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber; let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber; let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius; @@ -5140,6 +5451,7 @@ function drawRadarDataPoints(series, opts, config, context) { gridEval:1, axisLabel:false, axisLabelTofix:0, + labelShow:true, labelColor:'#666666', labelPointShow:false, labelPointRadius:3, @@ -5161,6 +5473,7 @@ function drawRadarDataPoints(series, opts, config, context) { var radius = Math.min(xr - (getMaxTextListLength(opts.categories, config.fontSize, context) + config.radarLabelTextMargin), yr - config.radarLabelTextMargin); radius -= config.radarLabelTextMargin * opts.pix; radius = radius < 10 ? 10 : radius; + radius = radarOption.radius ? radarOption.radius : radius; // 画分割线 context.beginPath(); context.setLineWidth(1 * opts.pix); @@ -5174,7 +5487,7 @@ function drawRadarDataPoints(series, opts, config, context) { }); context.stroke(); context.closePath(); - + // 画背景网格 var _loop = function _loop(i) { var startPos = {}; @@ -5184,7 +5497,7 @@ function drawRadarDataPoints(series, opts, config, context) { if (radarOption.gridType == 'radar') { coordinateAngle.forEach(function(angle, index) { var pos = convertCoordinateOrigin(radius / radarOption.gridCount * i * Math.cos(angle), radius / - radarOption.gridCount * i * Math.sin(angle), centerPosition); + radarOption.gridCount * i * Math.sin(angle), centerPosition); if (index === 0) { startPos = pos; context.moveTo(pos.x, pos.y); @@ -5210,7 +5523,7 @@ function drawRadarDataPoints(series, opts, config, context) { context.beginPath(); context.setLineWidth(radarOption.borderWidth * opts.pix); context.setStrokeStyle(eachSeries.color); - + var fillcolor = hexToRgb(eachSeries.color, radarOption.opacity); if (radarOption.linearType == 'custom') { var grd; @@ -5223,7 +5536,7 @@ function drawRadarDataPoints(series, opts, config, context) { grd.addColorStop(1, hexToRgb(eachSeries.color, radarOption.opacity)) fillcolor = grd } - + context.setFillStyle(fillcolor); eachSeries.data.forEach(function(item, index) { if (index === 0) { @@ -5259,10 +5572,10 @@ function drawRadarDataPoints(series, opts, config, context) { context.fillText(String(label), centerPosition.x + 3 * opts.pix, centerPosition.y - i * stepLength + fontSize / 2); } } - + // draw label text drawRadarLabel(coordinateAngle, radius, centerPosition, opts, config, context); - + // draw dataLabel if (opts.dataLabel !== false && process === 1) { radarDataPoints.forEach(function(eachSeries, seriesIndex) { @@ -5297,7 +5610,7 @@ function drawRadarDataPoints(series, opts, config, context) { }); context.setTextAlign('left'); } - + return { center: centerPosition, radius: radius, @@ -5429,6 +5742,7 @@ function drawMapDataPoints(series, opts, config, context) { border: true, mercator: false, borderWidth: 1, + active:true, borderColor: '#666666', fillOpacity: 0.6, activeBorderColor: '#f04864', @@ -5455,8 +5769,8 @@ function drawMapDataPoints(series, opts, config, context) { context.beginPath(); context.setLineWidth(mapOption.borderWidth * opts.pix); context.setStrokeStyle(mapOption.borderColor); - context.setFillStyle(hexToRgb(series[i].color, mapOption.fillOpacity)); - if (opts.tooltip) { + context.setFillStyle(hexToRgb(series[i].color, series[i].fillOpacity||mapOption.fillOpacity)); + if (mapOption.active == true && opts.tooltip) { if (opts.tooltip.index == i) { context.setStrokeStyle(mapOption.activeBorderColor); context.setFillStyle(hexToRgb(mapOption.activeFillColor, mapOption.activeFillOpacity)); @@ -5498,10 +5812,14 @@ function drawMapDataPoints(series, opts, config, context) { } point = coordinateToPoint(centerPoint[1], centerPoint[0], bounds, scale, xoffset, yoffset); let fontSize = data[i].textSize * opts.pix || config.fontSize; + let fontColor = data[i].textColor || opts.fontColor; + if(mapOption.active && mapOption.activeTextColor && opts.tooltip && opts.tooltip.index == i){ + fontColor = mapOption.activeTextColor; + } let text = data[i].properties.name; context.beginPath(); context.setFontSize(fontSize) - context.setFillStyle(data[i].textColor || opts.fontColor) + context.setFillStyle(fontColor) context.fillText(text, point.x - measureText(text, fontSize, context) / 2, point.y + fontSize / 2); context.closePath(); context.stroke(); @@ -5566,7 +5884,7 @@ function getWordCloudPoint(opts, type, context) { x = normalInt(-opts.width / 2, opts.width / 2, 5) - tWidth / 2; y = normalInt(-opts.height / 2, opts.height / 2, 5) + tHeight / 2; area = [x - 5 + opts.width / 2, y - 5 - tHeight + opts.height / 2, x + tWidth + 5 + opts.width / 2, y + 5 + - opts.height / 2 + opts.height / 2 ]; let isCollision = collisionNew(area, points, opts.width, opts.height); if (!isCollision) break; @@ -5579,14 +5897,14 @@ function getWordCloudPoint(opts, type, context) { } break; case 'vertical': - function Spin() { - //获取均匀随机值,是否旋转,旋转的概率为(1-0.5) - if (Math.random() > 0.7) { - return true; - } else { - return false - }; + function Spin() { + //获取均匀随机值,是否旋转,旋转的概率为(1-0.5) + if (Math.random() > 0.7) { + return true; + } else { + return false }; + }; for (let i = 0; i < points.length; i++) { let text = points[i].name; let tHeight = points[i].textSize * opts.pix; @@ -5697,6 +6015,7 @@ function drawFunnelDataPoints(series, opts, config, context) { borderWidth: 2, borderColor: '#FFFFFF', fillOpacity: 1, + minSize: 0, labelAlign: 'right', linearType: 'none', customColor: [], @@ -5708,42 +6027,42 @@ function drawFunnelDataPoints(series, opts, config, context) { }; let activeWidth = funnelOption.activeWidth * opts.pix; let radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - activeWidth, (opts.height - opts.area[0] - opts.area[2]) / 2 - activeWidth); - series = getFunnelDataPoints(series, radius, funnelOption.type, eachSpacing, process); + let seriesNew = getFunnelDataPoints(series, radius, funnelOption, eachSpacing, process); context.save(); context.translate(centerPosition.x, centerPosition.y); funnelOption.customColor = fillCustomColor(funnelOption.linearType, funnelOption.customColor, series, config); if(funnelOption.type == 'pyramid'){ - for (let i = 0; i < series.length; i++) { - if (i == series.length -1) { + for (let i = 0; i < seriesNew.length; i++) { + if (i == seriesNew.length -1) { if (opts.tooltip) { if (opts.tooltip.index == i) { context.beginPath(); - context.setFillStyle(hexToRgb(series[i].color, funnelOption.activeOpacity)); + context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity)); context.moveTo(-activeWidth, -eachSpacing); - context.lineTo(-series[i].radius - activeWidth, 0); - context.lineTo(series[i].radius + activeWidth, 0); + context.lineTo(-seriesNew[i].radius - activeWidth, 0); + context.lineTo(seriesNew[i].radius + activeWidth, 0); context.lineTo(activeWidth, -eachSpacing); context.lineTo(-activeWidth, -eachSpacing); context.closePath(); context.fill(); } } - series[i].funnelArea = [centerPosition.x - series[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + series[i].radius, centerPosition.y - eachSpacing * i]; + seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * i]; context.beginPath(); context.setLineWidth(funnelOption.borderWidth * opts.pix); context.setStrokeStyle(funnelOption.borderColor); - var fillColor = hexToRgb(series[i].color, funnelOption.fillOpacity); + var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity); if (funnelOption.linearType == 'custom') { - var grd = context.createLinearGradient(series[i].radius, -eachSpacing, -series[i].radius, -eachSpacing); - grd.addColorStop(0, hexToRgb(series[i].color, funnelOption.fillOpacity)); - grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[series[i].linearIndex], funnelOption.fillOpacity)); - grd.addColorStop(1, hexToRgb(series[i].color, funnelOption.fillOpacity)); + var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing); + grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity)); + grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); fillColor = grd } context.setFillStyle(fillColor); context.moveTo(0, -eachSpacing); - context.lineTo(-series[i].radius, 0); - context.lineTo(series[i].radius, 0); + context.lineTo(-seriesNew[i].radius, 0); + context.lineTo(seriesNew[i].radius, 0); context.lineTo(0, -eachSpacing); context.closePath(); context.fill(); @@ -5754,35 +6073,35 @@ function drawFunnelDataPoints(series, opts, config, context) { if (opts.tooltip) { if (opts.tooltip.index == i) { context.beginPath(); - context.setFillStyle(hexToRgb(series[i].color, funnelOption.activeOpacity)); + context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity)); context.moveTo(0, 0); - context.lineTo(-series[i].radius - activeWidth, 0); - context.lineTo(-series[i + 1].radius - activeWidth, -eachSpacing); - context.lineTo(series[i + 1].radius + activeWidth, -eachSpacing); - context.lineTo(series[i].radius + activeWidth, 0); + context.lineTo(-seriesNew[i].radius - activeWidth, 0); + context.lineTo(-seriesNew[i + 1].radius - activeWidth, -eachSpacing); + context.lineTo(seriesNew[i + 1].radius + activeWidth, -eachSpacing); + context.lineTo(seriesNew[i].radius + activeWidth, 0); context.lineTo(0, 0); context.closePath(); context.fill(); } } - series[i].funnelArea = [centerPosition.x - series[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + series[i].radius, centerPosition.y - eachSpacing * i]; + seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * i]; context.beginPath(); context.setLineWidth(funnelOption.borderWidth * opts.pix); context.setStrokeStyle(funnelOption.borderColor); - var fillColor = hexToRgb(series[i].color, funnelOption.fillOpacity); + var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity); if (funnelOption.linearType == 'custom') { - var grd = context.createLinearGradient(series[i].radius, -eachSpacing, -series[i].radius, -eachSpacing); - grd.addColorStop(0, hexToRgb(series[i].color, funnelOption.fillOpacity)); - grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[series[i].linearIndex], funnelOption.fillOpacity)); - grd.addColorStop(1, hexToRgb(series[i].color, funnelOption.fillOpacity)); + var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing); + grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity)); + grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); fillColor = grd } context.setFillStyle(fillColor); context.moveTo(0, 0); - context.lineTo(-series[i].radius, 0); - context.lineTo(-series[i + 1].radius, -eachSpacing); - context.lineTo(series[i + 1].radius, -eachSpacing); - context.lineTo(series[i].radius, 0); + context.lineTo(-seriesNew[i].radius, 0); + context.lineTo(-seriesNew[i + 1].radius, -eachSpacing); + context.lineTo(seriesNew[i + 1].radius, -eachSpacing); + context.lineTo(seriesNew[i].radius, 0); context.lineTo(0, 0); context.closePath(); context.fill(); @@ -5793,37 +6112,40 @@ function drawFunnelDataPoints(series, opts, config, context) { context.translate(0, -eachSpacing) } }else{ - for (let i = 0; i < series.length; i++) { - if (i == 0) { + context.translate(0, - (seriesNew.length - 1) * eachSpacing); + for (let i = 0; i < seriesNew.length; i++) { + if (i == seriesNew.length - 1) { if (opts.tooltip) { if (opts.tooltip.index == i) { context.beginPath(); - context.setFillStyle(hexToRgb(series[i].color, funnelOption.activeOpacity)); - context.moveTo(-activeWidth, 0); - context.lineTo(-series[i].radius - activeWidth, -eachSpacing); - context.lineTo(series[i].radius + activeWidth, -eachSpacing); - context.lineTo(activeWidth, 0); - context.lineTo(-activeWidth, 0); + context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity)); + context.moveTo(-activeWidth - funnelOption.minSize/2, 0); + context.lineTo(-seriesNew[i].radius - activeWidth, -eachSpacing); + context.lineTo(seriesNew[i].radius + activeWidth, -eachSpacing); + context.lineTo(activeWidth + funnelOption.minSize/2, 0); + context.lineTo(-activeWidth - funnelOption.minSize/2, 0); context.closePath(); context.fill(); } } - series[i].funnelArea = [centerPosition.x - series[i].radius, centerPosition.y - eachSpacing, centerPosition.x + series[i].radius, centerPosition.y]; + seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing, centerPosition.x + seriesNew[i].radius, centerPosition.y ]; context.beginPath(); context.setLineWidth(funnelOption.borderWidth * opts.pix); context.setStrokeStyle(funnelOption.borderColor); - var fillColor = hexToRgb(series[i].color, funnelOption.fillOpacity); + var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity); if (funnelOption.linearType == 'custom') { - var grd = context.createLinearGradient(series[i].radius, -eachSpacing, -series[i].radius, -eachSpacing); - grd.addColorStop(0, hexToRgb(series[i].color, funnelOption.fillOpacity)); - grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[series[i].linearIndex], funnelOption.fillOpacity)); - grd.addColorStop(1, hexToRgb(series[i].color, funnelOption.fillOpacity)); + var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing); + grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity)); + grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); fillColor = grd } context.setFillStyle(fillColor); context.moveTo(0, 0); - context.lineTo(-series[i].radius, -eachSpacing); - context.lineTo(series[i].radius, -eachSpacing); + context.lineTo(-funnelOption.minSize/2, 0); + context.lineTo(-seriesNew[i].radius, -eachSpacing); + context.lineTo(seriesNew[i].radius, -eachSpacing); + context.lineTo(funnelOption.minSize/2, 0); context.lineTo(0, 0); context.closePath(); context.fill(); @@ -5834,35 +6156,35 @@ function drawFunnelDataPoints(series, opts, config, context) { if (opts.tooltip) { if (opts.tooltip.index == i) { context.beginPath(); - context.setFillStyle(hexToRgb(series[i].color, funnelOption.activeOpacity)); + context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity)); context.moveTo(0, 0); - context.lineTo(-series[i - 1].radius - activeWidth, 0); - context.lineTo(-series[i].radius - activeWidth, -eachSpacing); - context.lineTo(series[i].radius + activeWidth, -eachSpacing); - context.lineTo(series[i - 1].radius + activeWidth, 0); + context.lineTo(-seriesNew[i + 1].radius - activeWidth, 0); + context.lineTo(-seriesNew[i].radius - activeWidth, -eachSpacing); + context.lineTo(seriesNew[i].radius + activeWidth, -eachSpacing); + context.lineTo(seriesNew[i + 1].radius + activeWidth, 0); context.lineTo(0, 0); context.closePath(); context.fill(); } } - series[i].funnelArea = [centerPosition.x - series[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + series[i].radius, centerPosition.y - eachSpacing * i]; + seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (seriesNew.length - i), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * (seriesNew.length - i - 1)]; context.beginPath(); context.setLineWidth(funnelOption.borderWidth * opts.pix); context.setStrokeStyle(funnelOption.borderColor); - var fillColor = hexToRgb(series[i].color, funnelOption.fillOpacity); + var fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity); if (funnelOption.linearType == 'custom') { - var grd = context.createLinearGradient(series[i].radius, -eachSpacing, -series[i].radius, -eachSpacing); - grd.addColorStop(0, hexToRgb(series[i].color, funnelOption.fillOpacity)); - grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[series[i].linearIndex], funnelOption.fillOpacity)); - grd.addColorStop(1, hexToRgb(series[i].color, funnelOption.fillOpacity)); + var grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing); + grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); + grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity)); + grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity)); fillColor = grd } context.setFillStyle(fillColor); context.moveTo(0, 0); - context.lineTo(-series[i - 1].radius, 0); - context.lineTo(-series[i].radius, -eachSpacing); - context.lineTo(series[i].radius, -eachSpacing); - context.lineTo(series[i - 1].radius, 0); + context.lineTo(-seriesNew[i + 1].radius, 0); + context.lineTo(-seriesNew[i].radius, -eachSpacing); + context.lineTo(seriesNew[i].radius, -eachSpacing); + context.lineTo(seriesNew[i + 1].radius, 0); context.lineTo(0, 0); context.closePath(); context.fill(); @@ -5870,18 +6192,21 @@ function drawFunnelDataPoints(series, opts, config, context) { context.stroke(); } } - context.translate(0, -eachSpacing) + context.translate(0, eachSpacing) } } - + context.restore(); if (opts.dataLabel !== false && process === 1) { - drawFunnelText(series, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition); + drawFunnelText(seriesNew, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition); + } + if (process === 1) { + drawFunnelCenterText(seriesNew, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition); } return { center: centerPosition, radius: radius, - series: series + series: seriesNew }; } @@ -5895,18 +6220,10 @@ function drawFunnelText(series, opts, context, eachSpacing, labelAlign, activeWi let text = item.formatter ? item.formatter(item,i,series,opts) : util.toFixed(item._proportion_ * 100) + '%'; text = item.labelText ? item.labelText : text; if (labelAlign == 'right') { - if(opts.extra.funnel.type === 'pyramid'){ - if (i == series.length -1) { - startX = (item.funnelArea[2] + centerPosition.x) / 2; - } else { - startX = (item.funnelArea[2] + series[i + 1].funnelArea[2]) / 2; - } - }else{ - if (i == 0) { - startX = (item.funnelArea[2] + centerPosition.x) / 2; - } else { - startX = (item.funnelArea[2] + series[i - 1].funnelArea[2]) / 2; - } + if (i == series.length -1) { + startX = (item.funnelArea[2] + centerPosition.x) / 2; + } else { + startX = (item.funnelArea[2] + series[i + 1].funnelArea[2]) / 2; } endX = startX + activeWidth * 2; startY = item.funnelArea[1] + eachSpacing / 2; @@ -5931,19 +6248,12 @@ function drawFunnelText(series, opts, context, eachSpacing, labelAlign, activeWi context.closePath(); context.stroke(); context.closePath(); - } else { - if(opts.extra.funnel.type === 'pyramid'){ - if (i == series.length -1) { - startX = (item.funnelArea[0] + centerPosition.x) / 2; - } else { - startX = (item.funnelArea[0] + series[i + 1].funnelArea[0]) / 2; - } - }else{ - if (i == 0) { - startX = (item.funnelArea[0] + centerPosition.x) / 2; - } else { - startX = (item.funnelArea[0] + series[i - 1].funnelArea[0]) / 2; - } + } + if (labelAlign == 'left') { + if (i == series.length -1) { + startX = (item.funnelArea[0] + centerPosition.x) / 2; + } else { + startX = (item.funnelArea[0] + series[i + 1].funnelArea[0]) / 2; } endX = startX - activeWidth * 2; startY = item.funnelArea[1] + eachSpacing / 2; @@ -5969,12 +6279,32 @@ function drawFunnelText(series, opts, context, eachSpacing, labelAlign, activeWi context.stroke(); context.closePath(); } + } +} +function drawFunnelCenterText(series, opts, context, eachSpacing, labelAlign, activeWidth, centerPosition) { + for (let i = 0; i < series.length; i++) { + let item = series[i]; + let startY, fontSize; + if (item.centerText) { + startY = item.funnelArea[1] + eachSpacing / 2; + fontSize = item.centerTextSize * opts.pix || opts.fontSize * opts.pix; + context.beginPath(); + context.setFontSize(fontSize); + context.setFillStyle(item.centerTextColor || "#FFFFFF"); + context.fillText(item.centerText, centerPosition.x - measureText(item.centerText, fontSize, context) / 2, startY + fontSize / 2 - 2); + context.closePath(); + context.stroke(); + context.closePath(); + } } } function drawCanvas(opts, context) { + context.save(); + context.translate(0, 0.5); + context.restore(); context.draw(); } @@ -6091,8 +6421,8 @@ function drawCharts(type, opts, config, context) { } //通过计算三大区域:图例、X轴、Y轴的大小,确定绘图区域 var _calLegendData = calLegendData(seriesMA, opts, config, opts.chartData, context), - legendHeight = _calLegendData.area.wholeHeight, - legendWidth = _calLegendData.area.wholeWidth; + legendHeight = _calLegendData.area.wholeHeight, + legendWidth = _calLegendData.area.wholeWidth; switch (opts.legend.position) { case 'top': @@ -6110,10 +6440,10 @@ function drawCharts(type, opts, config, context) { } let _calYAxisData = {}, - yAxisWidth = 0; + yAxisWidth = 0; if (opts.type === 'line' || opts.type === 'column'|| opts.type === 'mount' || opts.type === 'area' || opts.type === 'mix' || opts.type === 'candle' || opts.type === 'scatter' || opts.type === 'bubble' || opts.type === 'bar') { - _calYAxisData = calYAxisData(series, opts, config, context); - yAxisWidth = _calYAxisData.yAxisWidth; + _calYAxisData = calYAxisData(series, opts, config, context); + yAxisWidth = _calYAxisData.yAxisWidth; //如果显示Y轴标题 if (opts.yAxis.showTitle) { let maxTitleHeight = 0; @@ -6123,7 +6453,7 @@ function drawCharts(type, opts, config, context) { opts.area[0] += maxTitleHeight; } let rightIndex = 0, - leftIndex = 0; + leftIndex = 0; //计算主绘图区域左右位置 for (let i = 0; i < yAxisWidth.length; i++) { if (yAxisWidth[i].position == 'left') { @@ -6150,8 +6480,8 @@ function drawCharts(type, opts, config, context) { if (opts.categories && opts.categories.length && opts.type !== 'radar' && opts.type !== 'gauge' && opts.type !== 'bar') { opts.chartData.xAxisData = getXAxisPoints(opts.categories, opts, config); let _calCategoriesData = calCategoriesData(opts.categories, opts, config, opts.chartData.xAxisData.eachSpacing, context), - xAxisHeight = _calCategoriesData.xAxisHeight, - angle = _calCategoriesData.angle; + xAxisHeight = _calCategoriesData.xAxisHeight, + angle = _calCategoriesData.angle; config.xAxisHeight = xAxisHeight; config._xAxisTextAngle_ = angle; opts.area[2] += xAxisHeight; @@ -6161,8 +6491,8 @@ function drawCharts(type, opts, config, context) { opts.chartData.xAxisData = calXAxisData(series, opts, config, context); categories = opts.chartData.xAxisData.rangesFormat; let _calCategoriesData = calCategoriesData(categories, opts, config, opts.chartData.xAxisData.eachSpacing, context), - xAxisHeight = _calCategoriesData.xAxisHeight, - angle = _calCategoriesData.angle; + xAxisHeight = _calCategoriesData.xAxisHeight, + angle = _calCategoriesData.angle; config.xAxisHeight = xAxisHeight; config._xAxisTextAngle_ = angle; opts.area[2] += xAxisHeight; @@ -6177,10 +6507,10 @@ function drawCharts(type, opts, config, context) { //计算右对齐偏移距离 if (opts.enableScroll && opts.xAxis.scrollAlign == 'right' && opts._scrollDistance_ === undefined) { let offsetLeft = 0, - xAxisPoints = opts.chartData.xAxisData.xAxisPoints, - startX = opts.chartData.xAxisData.startX, - endX = opts.chartData.xAxisData.endX, - eachSpacing = opts.chartData.xAxisData.eachSpacing; + xAxisPoints = opts.chartData.xAxisData.xAxisPoints, + startX = opts.chartData.xAxisData.startX, + endX = opts.chartData.xAxisData.endX, + eachSpacing = opts.chartData.xAxisData.eachSpacing; let totalWidth = eachSpacing * (xAxisPoints.length - 1); let screenWidth = endX - startX; offsetLeft = screenWidth - totalWidth; @@ -6194,7 +6524,7 @@ function drawCharts(type, opts, config, context) { if (type === 'pie' || type === 'ring' || type === 'rose') { config._pieTextMaxLength_ = opts.dataLabel === false ? 0 : getPieTextMaxLength(seriesMA, config, context, opts); } - + switch (type) { case 'word': this.animationInstance = new Animation({ @@ -6216,6 +6546,9 @@ function drawCharts(type, opts, config, context) { case 'map': context.clearRect(0, 0, opts.width, opts.height); drawMapDataPoints(series, opts, config, context); + setTimeout(()=>{ + this.uevent.trigger('renderComplete'); + },50) break; case 'funnel': this.animationInstance = new Animation({ @@ -6248,9 +6581,9 @@ function drawCharts(type, opts, config, context) { drawYAxisGrid(categories, opts, config, context); drawXAxis(categories, opts, config, context); var _drawLineDataPoints = drawLineDataPoints(series, opts, config, context, process), - xAxisPoints = _drawLineDataPoints.xAxisPoints, - calPoints = _drawLineDataPoints.calPoints, - eachSpacing = _drawLineDataPoints.eachSpacing; + xAxisPoints = _drawLineDataPoints.xAxisPoints, + calPoints = _drawLineDataPoints.calPoints, + eachSpacing = _drawLineDataPoints.eachSpacing; opts.chartData.xAxisPoints = xAxisPoints; opts.chartData.calPoints = calPoints; opts.chartData.eachSpacing = eachSpacing; @@ -6279,9 +6612,9 @@ function drawCharts(type, opts, config, context) { drawYAxisGrid(categories, opts, config, context); drawXAxis(categories, opts, config, context); var _drawScatterDataPoints = drawScatterDataPoints(series, opts, config, context, process), - xAxisPoints = _drawScatterDataPoints.xAxisPoints, - calPoints = _drawScatterDataPoints.calPoints, - eachSpacing = _drawScatterDataPoints.eachSpacing; + xAxisPoints = _drawScatterDataPoints.xAxisPoints, + calPoints = _drawScatterDataPoints.calPoints, + eachSpacing = _drawScatterDataPoints.eachSpacing; opts.chartData.xAxisPoints = xAxisPoints; opts.chartData.calPoints = calPoints; opts.chartData.eachSpacing = eachSpacing; @@ -6310,9 +6643,9 @@ function drawCharts(type, opts, config, context) { drawYAxisGrid(categories, opts, config, context); drawXAxis(categories, opts, config, context); var _drawBubbleDataPoints = drawBubbleDataPoints(series, opts, config, context, process), - xAxisPoints = _drawBubbleDataPoints.xAxisPoints, - calPoints = _drawBubbleDataPoints.calPoints, - eachSpacing = _drawBubbleDataPoints.eachSpacing; + xAxisPoints = _drawBubbleDataPoints.xAxisPoints, + calPoints = _drawBubbleDataPoints.calPoints, + eachSpacing = _drawBubbleDataPoints.eachSpacing; opts.chartData.xAxisPoints = xAxisPoints; opts.chartData.calPoints = calPoints; opts.chartData.eachSpacing = eachSpacing; @@ -6341,9 +6674,9 @@ function drawCharts(type, opts, config, context) { drawYAxisGrid(categories, opts, config, context); drawXAxis(categories, opts, config, context); var _drawMixDataPoints = drawMixDataPoints(series, opts, config, context, process), - xAxisPoints = _drawMixDataPoints.xAxisPoints, - calPoints = _drawMixDataPoints.calPoints, - eachSpacing = _drawMixDataPoints.eachSpacing; + xAxisPoints = _drawMixDataPoints.xAxisPoints, + calPoints = _drawMixDataPoints.calPoints, + eachSpacing = _drawMixDataPoints.eachSpacing; opts.chartData.xAxisPoints = xAxisPoints; opts.chartData.calPoints = calPoints; opts.chartData.eachSpacing = eachSpacing; @@ -6372,9 +6705,9 @@ function drawCharts(type, opts, config, context) { drawYAxisGrid(categories, opts, config, context); drawXAxis(categories, opts, config, context); var _drawColumnDataPoints = drawColumnDataPoints(series, opts, config, context, process), - xAxisPoints = _drawColumnDataPoints.xAxisPoints, - calPoints = _drawColumnDataPoints.calPoints, - eachSpacing = _drawColumnDataPoints.eachSpacing; + xAxisPoints = _drawColumnDataPoints.xAxisPoints, + calPoints = _drawColumnDataPoints.calPoints, + eachSpacing = _drawColumnDataPoints.eachSpacing; opts.chartData.xAxisPoints = xAxisPoints; opts.chartData.calPoints = calPoints; opts.chartData.eachSpacing = eachSpacing; @@ -6403,9 +6736,9 @@ function drawCharts(type, opts, config, context) { drawYAxisGrid(categories, opts, config, context); drawXAxis(categories, opts, config, context); var _drawMountDataPoints = drawMountDataPoints(series, opts, config, context, process), - xAxisPoints = _drawMountDataPoints.xAxisPoints, - calPoints = _drawMountDataPoints.calPoints, - eachSpacing = _drawMountDataPoints.eachSpacing; + xAxisPoints = _drawMountDataPoints.xAxisPoints, + calPoints = _drawMountDataPoints.calPoints, + eachSpacing = _drawMountDataPoints.eachSpacing; opts.chartData.xAxisPoints = xAxisPoints; opts.chartData.calPoints = calPoints; opts.chartData.eachSpacing = eachSpacing; @@ -6433,9 +6766,9 @@ function drawCharts(type, opts, config, context) { } drawXAxis(categories, opts, config, context); var _drawBarDataPoints = drawBarDataPoints(series, opts, config, context, process), - yAxisPoints = _drawBarDataPoints.yAxisPoints, - calPoints = _drawBarDataPoints.calPoints, - eachSpacing = _drawBarDataPoints.eachSpacing; + yAxisPoints = _drawBarDataPoints.yAxisPoints, + calPoints = _drawBarDataPoints.calPoints, + eachSpacing = _drawBarDataPoints.eachSpacing; opts.chartData.yAxisPoints = yAxisPoints; opts.chartData.xAxisPoints = opts.chartData.xAxisData.xAxisPoints; opts.chartData.calPoints = calPoints; @@ -6465,9 +6798,9 @@ function drawCharts(type, opts, config, context) { drawYAxisGrid(categories, opts, config, context); drawXAxis(categories, opts, config, context); var _drawAreaDataPoints = drawAreaDataPoints(series, opts, config, context, process), - xAxisPoints = _drawAreaDataPoints.xAxisPoints, - calPoints = _drawAreaDataPoints.calPoints, - eachSpacing = _drawAreaDataPoints.eachSpacing; + xAxisPoints = _drawAreaDataPoints.xAxisPoints, + calPoints = _drawAreaDataPoints.calPoints, + eachSpacing = _drawAreaDataPoints.eachSpacing; opts.chartData.xAxisPoints = xAxisPoints; opts.chartData.calPoints = calPoints; opts.chartData.eachSpacing = eachSpacing; @@ -6606,9 +6939,9 @@ function drawCharts(type, opts, config, context) { drawYAxisGrid(categories, opts, config, context); drawXAxis(categories, opts, config, context); var _drawCandleDataPoints = drawCandleDataPoints(series, seriesMA, opts, config, context, process), - xAxisPoints = _drawCandleDataPoints.xAxisPoints, - calPoints = _drawCandleDataPoints.calPoints, - eachSpacing = _drawCandleDataPoints.eachSpacing; + xAxisPoints = _drawCandleDataPoints.xAxisPoints, + calPoints = _drawCandleDataPoints.calPoints, + eachSpacing = _drawCandleDataPoints.eachSpacing; opts.chartData.xAxisPoints = xAxisPoints; opts.chartData.calPoints = calPoints; opts.chartData.eachSpacing = eachSpacing; @@ -6656,7 +6989,7 @@ uChartsEvent.prototype.trigger = function() { try { listener.apply(null, params); } catch (e) { - //console.log('[uCharts] '+e); + //console.log('[uCharts] '+e); } }); } @@ -6677,6 +7010,7 @@ var uCharts = function uCharts(opts) { showTitle: false, disabled: false, disableGrid: false, + gridSet: 'number', splitNumber: 5, gridType: 'solid', dashLength: 4 * opts.pix, @@ -6691,12 +7025,20 @@ var uCharts = function uCharts(opts) { disableGrid: false, splitNumber: 5, calibration:false, + fontColor: '#666666', + fontSize: 13, + lineHeight: 20, + marginTop: 0, gridType: 'solid', dashLength: 4, scrollAlign: 'left', boundaryGap: 'center', axisLine: true, - axisLineColor: '#cccccc' + axisLineColor: '#cccccc', + titleFontSize: 13, + titleOffsetY: 0, + titleOffsetX: 0, + titleFontColor: '#666666' }, opts.xAxis); opts.xAxis.scrollPosition = opts.xAxis.scrollAlign; opts.legend = assign({}, { @@ -6715,12 +7057,16 @@ var uCharts = function uCharts(opts) { formatter: {}, hiddenColor: '#CECECE' }, opts.legend); - opts.extra = assign({}, opts.extra); + opts.extra = assign({ + tooltip:{ + legendShape: 'auto' + } + }, opts.extra); opts.rotate = opts.rotate ? true : false; opts.animation = opts.animation ? true : false; opts.rotate = opts.rotate ? true : false; opts.canvas2d = opts.canvas2d ? true : false; - + let config$$1 = assign({}, config); config$$1.color = opts.color ? opts.color : config$$1.color; if (opts.type == 'pie') { @@ -6746,15 +7092,9 @@ var uCharts = function uCharts(opts) { //适配高分屏 opts.padding = opts.padding ? opts.padding : config$$1.padding; config$$1.yAxisWidth = config.yAxisWidth * opts.pix; - config$$1.xAxisHeight = config.xAxisHeight * opts.pix; - if (opts.enableScroll && opts.xAxis.scrollShow) { - config$$1.xAxisHeight += 6 * opts.pix; - } config$$1.fontSize = opts.fontSize * opts.pix; config$$1.titleFontSize = config.titleFontSize * opts.pix; config$$1.subtitleFontSize = config.subtitleFontSize * opts.pix; - config$$1.toolTipPadding = config.toolTipPadding * opts.pix; - config$$1.toolTipLineHeight = config.toolTipLineHeight * opts.pix; if(!opts.context){ throw new Error('[uCharts] 未获取到context!注意:v2.0版本后,需要自行获取canvas的绘图上下文并传入opts.context!'); } @@ -6778,6 +7118,15 @@ var uCharts = function uCharts(opts) { this.context.setTextAlign = function(e) { return this.textAlign = e; } + this.context.setTextBaseline = function(e) { + return this.textBaseline = e; + } + this.context.setShadow = function(offsetX,offsetY,blur,color) { + this.shadowColor = color; + this.shadowOffsetX = offsetX; + this.shadowOffsetY = offsetY; + this.shadowBlur = blur; + } this.context.draw = function() {} } //兼容NVUEsetLineDash @@ -6820,9 +7169,9 @@ uCharts.prototype.updateData = function() { this.config.yAxisWidth = yAxisWidth; let offsetLeft = 0; let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config), xAxisPoints = _getXAxisPoints0.xAxisPoints, - startX = _getXAxisPoints0.startX, - endX = _getXAxisPoints0.endX, - eachSpacing = _getXAxisPoints0.eachSpacing; + startX = _getXAxisPoints0.startX, + endX = _getXAxisPoints0.endX, + eachSpacing = _getXAxisPoints0.eachSpacing; let totalWidth = eachSpacing * (xAxisPoints.length - 1); let screenWidth = endX - startX; offsetLeft = screenWidth - totalWidth; @@ -6850,14 +7199,14 @@ uCharts.prototype.zoom = function() { this.opts.xAxis.itemCount = val.itemCount; //重新计算x轴偏移距离 let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config, this.context), - yAxisWidth = _calYAxisData.yAxisWidth; + yAxisWidth = _calYAxisData.yAxisWidth; this.config.yAxisWidth = yAxisWidth; let offsetLeft = 0; let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config), - xAxisPoints = _getXAxisPoints0.xAxisPoints, - startX = _getXAxisPoints0.startX, - endX = _getXAxisPoints0.endX, - eachSpacing = _getXAxisPoints0.eachSpacing; + xAxisPoints = _getXAxisPoints0.xAxisPoints, + startX = _getXAxisPoints0.startX, + endX = _getXAxisPoints0.endX, + eachSpacing = _getXAxisPoints0.eachSpacing; let centerLeft = eachSpacing * centerPoint; let screenWidth = endX - startX; let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1); @@ -6892,7 +7241,7 @@ uCharts.prototype.dobuleZoom = function(e) { tcs[i].x = tcs[i].x ? tcs[i].x : tcs[i].clientX; tcs[i].y = tcs[i].y ? tcs[i].y : tcs[i].clientY; } - const ntcs = [getTouches(tcs[0], this.opts, e),getTouches(tcs[1], this.opts, e)]; + const ntcs = [getTouches(tcs[0], this.opts, e),getTouches(tcs[1], this.opts, e)]; const xlength = Math.abs(ntcs[0].x - ntcs[1].x); // 记录初始的两指之间的数据 if(!this.scrollOption.moveCount){ @@ -6910,7 +7259,7 @@ uCharts.prototype.dobuleZoom = function(e) { this.scrollOption.moveCurrent2 = Math.max(moveCurrent1, moveCurrent2); return; } - + let currentEachSpacing = xlength / this.scrollOption.moveCount; let itemCount = (this.opts.width - this.opts.area[1] - this.opts.area[3]) / currentEachSpacing; itemCount = itemCount <= 2 ? 2 : itemCount; @@ -6920,10 +7269,10 @@ uCharts.prototype.dobuleZoom = function(e) { // 重新计算滚动条偏移距离 let offsetLeft = 0; let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config), - xAxisPoints = _getXAxisPoints0.xAxisPoints, - startX = _getXAxisPoints0.startX, - endX = _getXAxisPoints0.endX, - eachSpacing = _getXAxisPoints0.eachSpacing; + xAxisPoints = _getXAxisPoints0.xAxisPoints, + startX = _getXAxisPoints0.startX, + endX = _getXAxisPoints0.endX, + eachSpacing = _getXAxisPoints0.eachSpacing; let currentLeft = eachSpacing * this.scrollOption.moveCurrent1; let screenWidth = endX - startX; let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1); @@ -7074,14 +7423,15 @@ uCharts.prototype.showToolTip = function(e) { var seriesData = getSeriesDataItem(this.opts.series, index, current.group); if (seriesData.length !== 0) { var _getToolTipData = getToolTipData(seriesData, this.opts, index, current.group, this.opts.categories, option), - textList = _getToolTipData.textList, - offset = _getToolTipData.offset; + textList = _getToolTipData.textList, + offset = _getToolTipData.offset; offset.y = _touches$.y; opts.tooltip = { textList: option.textList !== undefined ? option.textList : textList, offset: option.offset !== undefined ? option.offset : offset, option: option, - index: index + index: index, + group: current.group }; } } @@ -7094,7 +7444,8 @@ uCharts.prototype.showToolTip = function(e) { var seriesData = assign({}, opts._series_[index]); var textList = [{ text: option.formatter ? option.formatter(seriesData, undefined, index, opts) : seriesData.name + ': ' + seriesData.data, - color: seriesData.color + color: seriesData.color, + legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape }]; var offset = { x: opts.chartData.calPoints[index].x, @@ -7107,7 +7458,7 @@ uCharts.prototype.showToolTip = function(e) { index: index }; } - + drawCharts.call(this, opts.type, opts, this.config, this.context); } if (this.opts.type === 'bar') { @@ -7117,8 +7468,8 @@ uCharts.prototype.showToolTip = function(e) { var seriesData = getSeriesDataItem(this.opts.series, index, current.group); if (seriesData.length !== 0) { var _getToolTipData = getToolTipData(seriesData, this.opts, index, current.group, this.opts.categories, option), - textList = _getToolTipData.textList, - offset = _getToolTipData.offset; + textList = _getToolTipData.textList, + offset = _getToolTipData.offset; offset.x = _touches$.x; opts.tooltip = { textList: option.textList !== undefined ? option.textList : textList, @@ -7142,8 +7493,8 @@ uCharts.prototype.showToolTip = function(e) { var seriesData = getSeriesDataItem(this.opts.series, index); if (seriesData.length !== 0) { var _getMixToolTipData = getMixToolTipData(seriesData, this.opts, index, this.opts.categories, option), - textList = _getMixToolTipData.textList, - offset = _getMixToolTipData.offset; + textList = _getMixToolTipData.textList, + offset = _getMixToolTipData.offset; offset.y = _touches$.y; opts.tooltip = { textList: option.textList ? option.textList : textList, @@ -7167,8 +7518,8 @@ uCharts.prototype.showToolTip = function(e) { var seriesData = getSeriesDataItem(this.opts.series, index); if (seriesData.length !== 0) { var _getToolTipData = getCandleToolTipData(this.opts.series[0].data, seriesData, this.opts, index, this.opts.categories, this.opts.extra.candle, option), - textList = _getToolTipData.textList, - offset = _getToolTipData.offset; + textList = _getToolTipData.textList, + offset = _getToolTipData.offset; offset.y = _touches$.y; opts.tooltip = { textList: option.textList ? option.textList : textList, @@ -7187,7 +7538,8 @@ uCharts.prototype.showToolTip = function(e) { var seriesData = assign({}, opts._series_[index]); var textList = [{ text: option.formatter ? option.formatter(seriesData, undefined, index, opts) : seriesData.name + ': ' + seriesData.data, - color: seriesData.color + color: seriesData.color, + legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape }]; var offset = { x: _touches$.x, @@ -7210,7 +7562,8 @@ uCharts.prototype.showToolTip = function(e) { seriesData.name = seriesData.properties.name var textList = [{ text: option.formatter ? option.formatter(seriesData, undefined, index, this.opts) : seriesData.name, - color: seriesData.color + color: seriesData.color, + legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape }]; var offset = { x: _touches$.x, @@ -7233,7 +7586,8 @@ uCharts.prototype.showToolTip = function(e) { var seriesData = assign({}, this.opts.series[index]); var textList = [{ text: option.formatter ? option.formatter(seriesData, undefined, index, this.opts) : seriesData.name, - color: seriesData.color + color: seriesData.color, + legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape }]; var offset = { x: _touches$.x, @@ -7258,7 +7612,8 @@ uCharts.prototype.showToolTip = function(e) { var textList = seriesData.map((item) => { return { text: option.formatter ? option.formatter(item, this.opts.categories[index], index, this.opts) : item.name + ': ' + item.data, - color: item.color + color: item.color, + legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? item.legendShape : this.opts.extra.tooltip.legendShape }; }); var offset = { @@ -7331,7 +7686,7 @@ uCharts.prototype.scroll = function(e) { _scrollDistance_: currentOffset + _distance, animation: false }); - this.opts = opts; + this.opts = opts; drawCharts.call(this, opts.type, opts, this.config, this.context); return currentOffset + _distance; } @@ -7340,8 +7695,8 @@ uCharts.prototype.scroll = function(e) { uCharts.prototype.scrollEnd = function(e) { if (this.opts.enableScroll === true) { var _scrollOption = this.scrollOption, - currentOffset = _scrollOption.currentOffset, - distance = _scrollOption.distance; + currentOffset = _scrollOption.currentOffset, + distance = _scrollOption.distance; this.scrollOption.currentOffset = currentOffset + distance; this.scrollOption.distance = 0; this.scrollOption.moveCount = 0; diff --git a/package-lock.json b/package-lock.json index 55880c8..c968fc6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "wechat_ahyd (2)", + "name": "ahyd_DIB", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/pages/commercialBI/carPortrait.vue b/pages/commercialBI/carPortrait.vue index dc61a36..fd5db57 100644 --- a/pages/commercialBI/carPortrait.vue +++ b/pages/commercialBI/carPortrait.vue @@ -32,135 +32,222 @@
分析 - 新桥服务区入区车辆主要来自杭州市, 入车新桥服务区入区车辆主要来自杭州市, 入车入车新桥服务区入区车辆主要来自杭州市入车新桥服务区入区车辆主要来自杭州市 + 新桥服务区入区车辆主要来自杭州市, 入车车辆主要是普通车型(30-60万)
-
+

入区车流分析

-
-
- -
-
-
+ + +
+
+ + {{item.name}} + +

车辆归属地

+ + +
+
+

车辆类型占比与停留时间

+ + +
+
+

车辆价值与停留时间分析

+ + +
+
+

入区率占比

+ +
@@ -175,11 +262,16 @@ export default { background: linear-gradient(180deg, #A1B9E8 0%, #F0F5FF 100%); position: relative; .headerTop{ - width: calc(100% - 32px); + width: 100vw; position: fixed; top: 0; + left: 0; + z-index: 9999999999999; + background: linear-gradient(180deg, #A2B9E8 0%, #B2C6ED 100%); .box{ + padding: 0 16px; position: absolute; + box-sizing: border-box; width: 100%; display: flex; justify-content: space-between; @@ -356,7 +448,33 @@ export default { width: 100%; box-sizing: border-box; padding: 28px 16px 0; - .carAnalyse{ + .chartsItem{ + .tab{ + width: 100%; + height: 38px; + background: #F2F1F1; + border-radius: 4px; + box-sizing: border-box; + padding:4px; + display: flex; + align-items: center; + margin-bottom: 12px; + .tabItem{ + display: flex; + justify-content: center; + align-items: center; + width: calc(100% / 3); + height: 30px; + border-radius: 4px; + font-size: 14px; + font-family: PingFangSC-Regular, PingFang SC; + font-weight: 400; + color: #160002; + } + .tabItemActive{ + background: #FFFFFF; + } + } .title{ font-size: 34rpx; font-family: PingFangSC-Semibold, PingFang SC; @@ -364,24 +482,13 @@ export default { color: #160002; line-height: 48rpx; } - .content{ - width: 100%; - height: 188px; - display: flex; - .item{ - width: 50%; - height: 100%; - box-sizing: border-box; - display: flex; - justify-content: center; - align-items: center; - .carNum{ - width: 100%; - height: 100%; - } - } + .homePlace{ + } } + .chartsItem:last-child{ + padding-bottom: 32px; + } } } \ No newline at end of file diff --git a/pages/commercialBI/components/analyse.vue b/pages/commercialBI/components/analyse.vue new file mode 100644 index 0000000..74b79f6 --- /dev/null +++ b/pages/commercialBI/components/analyse.vue @@ -0,0 +1,56 @@ + + + + + \ No newline at end of file diff --git a/pages/commercialBI/components/car/carTypeTime.vue b/pages/commercialBI/components/car/carTypeTime.vue new file mode 100644 index 0000000..033f133 --- /dev/null +++ b/pages/commercialBI/components/car/carTypeTime.vue @@ -0,0 +1,137 @@ + + + + + \ No newline at end of file diff --git a/pages/commercialBI/components/car/entryZone.vue b/pages/commercialBI/components/car/entryZone.vue new file mode 100644 index 0000000..940ff03 --- /dev/null +++ b/pages/commercialBI/components/car/entryZone.vue @@ -0,0 +1,200 @@ + + + + + \ No newline at end of file diff --git a/pages/commercialBI/components/car/homePlace.vue b/pages/commercialBI/components/car/homePlace.vue new file mode 100644 index 0000000..97d5aae --- /dev/null +++ b/pages/commercialBI/components/car/homePlace.vue @@ -0,0 +1,189 @@ + + + + + \ No newline at end of file diff --git a/pages/commercialBI/components/car/percentEntry.vue b/pages/commercialBI/components/car/percentEntry.vue new file mode 100644 index 0000000..0294d98 --- /dev/null +++ b/pages/commercialBI/components/car/percentEntry.vue @@ -0,0 +1,181 @@ + + + + + \ No newline at end of file diff --git a/pages/commercialBI/components/car/timeAnalysis.vue b/pages/commercialBI/components/car/timeAnalysis.vue new file mode 100644 index 0000000..5bd2516 --- /dev/null +++ b/pages/commercialBI/components/car/timeAnalysis.vue @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/pages/commercialBI/components/模板.vue b/pages/commercialBI/components/模板.vue new file mode 100644 index 0000000..4d5383f --- /dev/null +++ b/pages/commercialBI/components/模板.vue @@ -0,0 +1,95 @@ + + + + + \ No newline at end of file diff --git a/pages/index/index.vue b/pages/index/index.vue index 0387d91..d4cdd35 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -16,17 +16,17 @@ - -

对客营收

+ +

对客营收

门店上传: {{showTableData.Revenue_Upload?showTableData.Revenue_Upload:'-'}}/{{allShopCount?allShopCount:'-'}}
- +

{{showTableData.CashPay || '0.00'}}

- + {{showTableData.compared?showTableData.compared + '%':'-' + '%'}} (相比昨日) @@ -247,8 +247,11 @@

- -

{{monthAdd?monthAdd + '%':'-'}}

+ 比计划: + + +

{{monthAdd?monthAdd + '%':'-'}}

+
@@ -286,8 +289,11 @@

- -

{{yearAdd?yearAdd + '%':''}}

+ 比计划: +
+ +

{{yearAdd?yearAdd + '%':''}}

+
@@ -553,8 +559,8 @@ export default { let oneDay = 100/day // 到了当天的应该有的百分比 let thisDayShould= oneDay*nowDay - this.monthAdd = (((this.plan.percentageMonth - thisDayShould)/thisDayShould)*100).toFixed(2) - this.yearAdd = (((res.Result_Data.RevenueYear_Amount - res.Result_Data.RevenueYear_PlanAmount)/res.Result_Data.RevenueYear_PlanAmount)*100).toFixed(2) + this.monthAdd = (this.plan.percentageMonth - thisDayShould).toFixed(2) + this.yearAdd = (((res.Result_Data.RevenueYear_Amount - res.Result_Data.RevenueYear_PlanAmount)/res.Result_Data.BudgetYear_Amount)*100).toFixed(2) //处理数据 this.plan.RevenueMonth_Amount = this.$util.fmoney(res.Result_Data.RevenueMonth_Amount) this.plan.BudgetMonth_Amount = this.$util.fmoney(res.Result_Data.BudgetMonth_Amount) @@ -883,7 +889,7 @@ export default { console.log('处理数据的方法') // 由于页面大部分的内容采用渲染的格式 这样的方法是最快的对原数据进行赋值 对照data里面的几个主要的数组看就能看明白 // 门店上传的前后数字计算来决定样式 - if(this.showTableData.Revenue_Upload > this.allShopCount){ + if(this.showTableData.Revenue_Upload >= this.allShopCount){ this.isBig = false }else{ this.isBig = true @@ -1549,18 +1555,34 @@ $iphoneHeight: env(safe-area-inset-bottom); } } .right{ + flex: 1; display: flex; + justify-content: flex-end; align-items: center; - .addIcon { - width: 16px; - height: 16px; - margin-right: 2px; + .comparePlan{ + font-size: 24rpx; + font-family: PingFangSC-Regular, PingFang SC; + font-weight: 400; + color: #a69e9f; + line-height: 36rpx; + white-space: nowrap; } - .text{ - font-size: 16px; - font-family: DINAlternate-Bold, DINAlternate; - color: #150002; - line-height: 40rpx; + .box2{ + display: flex; + align-items: center; + .text{ + font-size: 14px; + font-family: DINAlternate-Bold, DINAlternate; + color: #150002; + font-weight: bold; + + line-height: 40rpx; + } + .addIcon { + width: 16px; + height: 16px; + margin-right: 2px; + } } } }