This is an automated email from the ASF dual-hosted git repository. shenyi pushed a commit to branch feature/clip in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
commit 94dfc9284f12cba56b7524dcf60776d0c39dbe79 Author: pissang <bm2736...@gmail.com> AuthorDate: Tue Sep 17 16:22:33 2019 +0800 WIP(clip): support clip in lines series --- src/chart/helper/createClipPathFromCoordSys.js | 101 ++++++++++++++++++++ src/chart/line/LineView.js | 107 ++++++--------------- src/chart/lines/LinesView.js | 11 +++ src/coord/cartesian/Cartesian2D.js | 2 +- test/clip.html | 125 ++++++++++++++++++++++++- 5 files changed, 261 insertions(+), 85 deletions(-) diff --git a/src/chart/helper/createClipPathFromCoordSys.js b/src/chart/helper/createClipPathFromCoordSys.js new file mode 100644 index 0000000..9759ca2 --- /dev/null +++ b/src/chart/helper/createClipPathFromCoordSys.js @@ -0,0 +1,101 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +import * as graphic from '../../util/graphic'; +import {round} from '../../util/number'; + +function createGridClipPath(cartesian, hasAnimation, seriesModel) { + var rect = cartesian.getArea(); + var isHorizontal = cartesian.getBaseAxis().isHorizontal(); + + var x = rect.x; + var y = rect.y; + var width = rect.width; + var height = rect.height; + + var lineWidth = seriesModel.get('lineStyle.width') || 2; + // Expand the clip path a bit to avoid the border is clipped and looks thinner + x -= lineWidth / 2; + y -= lineWidth / 2; + width += lineWidth; + height += lineWidth; + + var clipPath = new graphic.Rect({ + shape: { + x: x, + y: y, + width: width, + height: height + } + }); + + if (hasAnimation) { + clipPath.shape[isHorizontal ? 'width' : 'height'] = 0; + graphic.initProps(clipPath, { + shape: { + width: width, + height: height + } + }, seriesModel); + } + + return clipPath; +} + +function createPolarClipPath(polar, hasAnimation, seriesModel) { + var sectorArea = polar.getArea(); + // Avoid float number rounding error for symbol on the edge of axis extent. + + var clipPath = new graphic.Sector({ + shape: { + cx: round(polar.cx, 1), + cy: round(polar.cy, 1), + r0: round(sectorArea.r0, 1), + r: round(sectorArea.r1, 1), + startAngle: sectorArea.startAngle, + endAngle: sectorArea.endAngle, + clockwise: sectorArea.clockwise + } + }); + + if (hasAnimation) { + clipPath.shape.endAngle = sectorArea.startAngle; + graphic.initProps(clipPath, { + shape: { + endAngle: sectorArea.endAngle + } + }, seriesModel); + } + + return clipPath; +} + +function createClipPath(coordSys, hasAnimation, seriesModel) { + if (!coordSys) { + return null; + } + else if (coordSys.type === 'polar') { + return createPolarClipPath(coordSys, hasAnimation, seriesModel); + } + else if (coordSys.type === 'cartesian2d') { + return createGridClipPath(coordSys, hasAnimation, seriesModel); + } + return null; +} + +export {createGridClipPath, createPolarClipPath, createClipPath}; \ No newline at end of file diff --git a/src/chart/line/LineView.js b/src/chart/line/LineView.js index de172c0..ea7fd3f 100644 --- a/src/chart/line/LineView.js +++ b/src/chart/line/LineView.js @@ -28,8 +28,8 @@ import * as graphic from '../../util/graphic'; import * as modelUtil from '../../util/model'; import {Polyline, Polygon} from './poly'; import ChartView from '../../view/Chart'; -import {round} from '../../util/number'; import {prepareDataCoordInfo, getStackedOnPoint} from './helper'; +import {createGridClipPath, createPolarClipPath} from '../helper/createClipPathFromCoordSys'; function isPointsSame(points1, points2) { if (points1.length !== points2.length) { @@ -68,83 +68,6 @@ function getStackedOnPoints(coordSys, data, dataCoordInfo) { return points; } -function createGridClipShape(cartesian, hasAnimation, seriesModel) { - var rect = cartesian.getArea(); - var isHorizontal = cartesian.getBaseAxis().isHorizontal(); - - var x = rect.x; - var y = rect.y; - var width = rect.width; - var height = rect.height; - - var lineWidth = seriesModel.get('lineStyle.width') || 2; - // Expand clip shape to avoid clipping when line value exceeds axis - var expandSize = seriesModel.get('clip') ? lineWidth / 2 : Math.max(width, height); - if (isHorizontal) { - y -= expandSize; - height += expandSize * 2; - } - else { - x -= expandSize; - width += expandSize * 2; - } - - var clipPath = new graphic.Rect({ - shape: { - x: x, - y: y, - width: width, - height: height - } - }); - - if (hasAnimation) { - clipPath.shape[isHorizontal ? 'width' : 'height'] = 0; - graphic.initProps(clipPath, { - shape: { - width: width, - height: height - } - }, seriesModel); - } - - return clipPath; -} - -function createPolarClipShape(polar, hasAnimation, seriesModel) { - var sectorArea = polar.getArea(); - // Avoid float number rounding error for symbol on the edge of axis extent. - - var clipPath = new graphic.Sector({ - shape: { - cx: round(polar.cx, 1), - cy: round(polar.cy, 1), - r0: round(sectorArea.r0, 1), - r: round(sectorArea.r1, 1), - startAngle: sectorArea.startAngle, - endAngle: sectorArea.endAngle, - clockwise: sectorArea.clockwise - } - }); - - if (hasAnimation) { - clipPath.shape.endAngle = sectorArea.startAngle; - graphic.initProps(clipPath, { - shape: { - endAngle: sectorArea.endAngle - } - }, seriesModel); - } - - return clipPath; -} - -function createClipShape(coordSys, hasAnimation, seriesModel) { - return coordSys.type === 'polar' - ? createPolarClipShape(coordSys, hasAnimation, seriesModel) - : createGridClipShape(coordSys, hasAnimation, seriesModel); -} - function turnPointsIntoStep(points, coordSys, stepTurnAt) { var baseAxis = coordSys.getBaseAxis(); var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1; @@ -341,6 +264,30 @@ function canShowAllSymbolForCategory(categoryAxis, data) { return true; } +function createLineClipPath(coordSys, hasAnimation, seriesModel) { + if (coordSys.type === 'cartesian2d') { + var isHorizontal = coordSys.getBaseAxis().isHorizontal(); + var clipPath = createGridClipPath(coordSys, hasAnimation, seriesModel); + // Expand clip shape to avoid clipping when line value exceeds axis + if (!seriesModel.get('clip')) { + var rectShape = clipPath.shape; + var expandSize = Math.max(rectShape.width, rectShape.height); + if (isHorizontal) { + rectShape.y -= expandSize; + rectShape.height += expandSize * 2; + } + else { + rectShape.x -= expandSize; + rectShape.width += expandSize * 2; + } + } + } + else { + return createPolarClipPath(coordSys, hasAnimation, seriesModel); + } + +} + export default ChartView.extend({ type: 'line', @@ -443,7 +390,7 @@ export default ChartView.extend({ coordSys, hasAnimation ); } - lineGroup.setClipPath(createClipShape(coordSys, true, seriesModel)); + lineGroup.setClipPath(createLineClipPath(coordSys, true, seriesModel)); } else { if (isAreaChart && !polygon) { @@ -460,7 +407,7 @@ export default ChartView.extend({ } // Update clipPath - lineGroup.setClipPath(createClipShape(coordSys, false, seriesModel)); + lineGroup.setClipPath(createLineClipPath(coordSys, false, seriesModel)); // Always update, or it is wrong in the case turning on legend // because points are not changed diff --git a/src/chart/lines/LinesView.js b/src/chart/lines/LinesView.js index e742d01..02b5c83 100644 --- a/src/chart/lines/LinesView.js +++ b/src/chart/lines/LinesView.js @@ -26,6 +26,7 @@ import Polyline from '../helper/Polyline'; import EffectPolyline from '../helper/EffectPolyline'; import LargeLineDraw from '../helper/LargeLineDraw'; import linesLayout from './linesLayout'; +import {createClipPath} from '../helper/createClipPathFromCoordSys'; export default echarts.extendChartView({ @@ -76,6 +77,16 @@ export default echarts.extendChartView({ lineDraw.updateData(data); + var clipPath = seriesModel.get('clip') && createClipPath( + seriesModel.coordinateSystem, false, seriesModel + ); + if (clipPath) { + this.group.setClipPath(clipPath); + } + else { + this.group.removeClipPath(); + } + this._lastZlevel = zlevel; this._finished = true; diff --git a/src/coord/cartesian/Cartesian2D.js b/src/coord/cartesian/Cartesian2D.js index 74eb442..511ddf1 100644 --- a/src/coord/cartesian/Cartesian2D.js +++ b/src/coord/cartesian/Cartesian2D.js @@ -159,7 +159,7 @@ Cartesian2D.prototype = { var width = Math.max(xExtent[0], xExtent[1]) - x; var height = Math.max(yExtent[0], yExtent[1]) - y; - let rect = new BoundingRect(x, y, width, height); + var rect = new BoundingRect(x, y, width, height); return rect; } diff --git a/test/clip.html b/test/clip.html index a0fb68b..9fcb0bb 100644 --- a/test/clip.html +++ b/test/clip.html @@ -48,12 +48,10 @@ under the License. <!-- <h1>Scatter Clip with Incremental Rendering</h1> <div class="chart" id="scatter-clip-incremental"></div> --> <div class="chart" id="large-scatter-clip"></div> - <div class="chart" id="scatter-clip-polar"></div> - - <h1>Lines</h1> <div class="chart" id="lines-clip"></div> - <h1>Bar</h1> <div class="chart" id="bar-clip"></div> + <div class="chart" id="custom-clip"></div> + <div class="chart" id="candlestick-clip"></div> <script> function makeToggleChartButtons(toggleClip) { @@ -239,5 +237,124 @@ under the License. }) </script> + <script> + require([ + 'echarts' + ], function (echarts) { + + var lineData = [] + + function getColor() { + //定义字符串变量colorValue存放可以构成十六进制颜色值的值 + var colorValue = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f"; + //以","为分隔符,将colorValue字符串分割为字符数组["0","1",...,"f"] + var colorArray = colorValue.split(","); + var color = "#";//定义一个存放十六进制颜色值的字符串变量,先将#存放进去 + //使用for循环语句生成剩余的六位十六进制值 + for (var i = 0; i < 6; i++) { + //colorArray[Math.floor(Math.random()*16)]随机取出 + // 由16个元素组成的colorArray的某一个值,然后将其加在color中, + //字符串相加后,得出的仍是字符串 + color += colorArray[Math.floor(Math.random() * 16)]; + } + return color; + } + + for (var i = 0; i < 20; ++i) { + var x = Math.floor(Math.random()*600+50) + var y = Math.floor(Math.random()*600+50) + var xSign = Math.floor(Math.random()*2+1) + var ySign = Math.floor(Math.random()*2+1) + //负数 + if (xSign === 1) { + x *= -1; + } + if (ySign === 1) { + y *= -1; + } + + var obj = { + name: "测试直线"+i+1, + coords: [ + [0, 0], + [x, y] + ], + label: { + show:false + }, + lineStyle: { + normal: { + color: getColor(), + width: 1 + } + } + }; + lineData.push(obj); + } + + option = { + animation: false, + title: { + text: '网络拓扑图' + }, + xAxis: { + type:'value', + min: -1000, + max: 1000, + splitLine:{ + lineStyle: { + width: 1 + } + } + }, + yAxis: { + type:'value', + min: -1000, + max: 1000, + splitLine:{ + lineStyle: { + width: 1 + } + } + }, + dataZoom: [{ + type: 'inside', + xAxisIndex: 0, + filterMode: 'filter' + }, + { + type: 'inside', + yAxisIndex: 0, + filterMode: 'weakFilter' + } + ], + series: [{ + type: 'lines', + name: '网络拓扑图', + coordinateSystem: 'cartesian2d', + lineStyle: { + normal: { + color: '#F00', + width: 1 + } + }, + label: { + fontSize: 15 + }, + symbol: ['none', 'arrow'], + // 数据 + data: lineData + }] + }; + + var chart = testHelper.create(echarts, 'lines-clip', { + title: 'Lines Clip,(case from #10748). Should not overflow after zoomed in', + option: option, + height: 400, + buttons: makeToggleChartButtons() + }); + }) + </script> + </body> </html> \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@echarts.apache.org For additional commands, e-mail: commits-h...@echarts.apache.org