| <!DOCTYPE html> | |
| <!-- | |
| 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. | |
| --> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <script src="https://d3js.org/d3.v4.min.js"></script> | |
| <script src="lib/simpleRequire.js"></script> | |
| <script src="lib/config.js"></script> | |
| <script src="lib/jquery.min.js"></script> | |
| <script src="lib/facePrint.js"></script> | |
| <script src="lib/testHelper.js"></script> | |
| <!-- <script src="ut/lib/canteen.js"></script> --> | |
| <link rel="stylesheet" href="lib/reset.css" /> | |
| </head> | |
| <body> | |
| <style> | |
| </style> | |
| <div id="main0"></div> | |
| <div id="main1"></div> | |
| <script> | |
| window.ANIMATION_DURATION_UPDATE = 1000; | |
| </script> | |
| <script> | |
| require([ | |
| 'echarts', | |
| // 'map/js/china', | |
| // './data/nutrients.json' | |
| ], function (echarts) { | |
| var option; | |
| var stratify = d3.stratify() | |
| .parentId(function(d) { | |
| return d.id.substring(0, d.id.lastIndexOf(".")); | |
| }); | |
| function toPlainTree(root) { | |
| return { | |
| children: root.children && root.children.map(child => toPlainTree(child)), | |
| value: root.value, | |
| name: root.id.split('.').pop(), | |
| id: root.id | |
| } | |
| } | |
| d3.csv("data/flare.csv", function(error, rawData) { | |
| if (error) throw error; | |
| var root = stratify(rawData) | |
| .sum(function(d) { | |
| return d.value; | |
| }) | |
| .sort(function(a, b) { | |
| return b.value - a.value; | |
| }); | |
| var maxDepth = 0; | |
| var seriesDataLinear = root.descendants().map(function (node) { | |
| maxDepth = Math.max(maxDepth, node.depth); | |
| return [ | |
| node.value, | |
| node.depth, | |
| node.id | |
| ]; | |
| }); | |
| function renderItem(params, api) { | |
| var context = params.context; | |
| if (!context.layout) { | |
| d3.pack() | |
| .size([api.getWidth() - 2, api.getHeight() - 2]) | |
| .padding(3)(root); | |
| context.nodes = {}; | |
| root.descendants().forEach(function (node, index) { | |
| context.nodes[node.id] = { | |
| index: index, | |
| node: node | |
| } | |
| }); | |
| } | |
| var nodePath = api.value(2); | |
| var node = context.nodes[nodePath].node; | |
| var isLeaf = !node.children || !node.children.length; | |
| var textFont = api.font({ | |
| fontSize: 12, | |
| fontFamily: 'Arial' | |
| }); | |
| var focus = new Uint32Array(node.descendants().map(function (node) { | |
| return context.nodes[node.id].index; | |
| })); | |
| var nodeName = isLeaf ? nodePath.slice(nodePath.lastIndexOf('.') + 1).split(/(?=[A-Z][^A-Z])/g).join('\n') : ''; | |
| var z2 = api.value(1) * 2; | |
| return { | |
| type: 'circle', | |
| focus: focus, | |
| shape: { | |
| cx: node.x, | |
| cy: node.y, | |
| r: node.r | |
| }, | |
| z2: z2, | |
| textContent: { | |
| type: 'text', | |
| style: { | |
| text: nodeName, | |
| width: node.r * 1.3, | |
| overflow: 'truncate', | |
| fontSize: node.r / 3 | |
| }, | |
| emphasis: { | |
| style: { | |
| overflow: null, | |
| fontSize: Math.max(node.r / 3, 12) | |
| } | |
| } | |
| }, | |
| textConfig: { | |
| position: 'inside' | |
| }, | |
| style: { | |
| fill: api.visual('color'), | |
| text: nodeName, | |
| font: textFont, | |
| }, | |
| emphasis: { | |
| style: { | |
| font: textFont, | |
| shadowBlur: 20, | |
| shadowOffsetX: 3, | |
| shadowOffsetY: 5, | |
| shadowColor: 'rgba(0,0,0,0.3)' | |
| } | |
| } | |
| }; | |
| } | |
| var circlePackingOption = { | |
| tooltip: {}, | |
| visualMap: { | |
| show: false, | |
| min: 0, | |
| max: maxDepth, | |
| dimension: 1, | |
| inRange: { | |
| color: ['#006edd', '#e0ffff'] | |
| } | |
| }, | |
| series: { | |
| type: 'custom', | |
| id: 'main', | |
| renderItem: renderItem, | |
| coordinateSystem: null, | |
| animationDurationUpdate: ANIMATION_DURATION_UPDATE, | |
| encode: { | |
| tooltip: 0, | |
| itemName: 2 | |
| }, | |
| universalTransition: { | |
| enabled: true | |
| }, | |
| data: seriesDataLinear | |
| } | |
| }; | |
| var treemapOption = { | |
| series: { | |
| type: 'treemap', | |
| id: 'main', | |
| data: toPlainTree(root).children, | |
| animationDurationUpdate: ANIMATION_DURATION_UPDATE, | |
| roam: false, | |
| label: { | |
| fontSize: 10 | |
| }, | |
| breadcrumb: { | |
| show: false | |
| }, | |
| universalTransition: { | |
| enabled: true | |
| }, | |
| itemStyle: { | |
| color: '#ddd', | |
| borderWidth: 2 | |
| } | |
| } | |
| } | |
| var sunburstOption = { | |
| series: { | |
| type: 'sunburst', | |
| id: 'main', | |
| data: toPlainTree(root).children, | |
| animationDurationUpdate: ANIMATION_DURATION_UPDATE, | |
| roam: false, | |
| radius: ['20%', '90%'], | |
| label: { | |
| show: false | |
| }, | |
| breadcrumb: { | |
| show: false | |
| }, | |
| universalTransition: { | |
| enabled: true | |
| }, | |
| itemStyle: { | |
| borderWidth: 1 | |
| } | |
| } | |
| } | |
| var chart = testHelper.create(echarts, 'main0', { | |
| title: [ | |
| 'Custom Series: Universal Transition betwee treemap and circle packing ' | |
| ], | |
| recordVideo: true, | |
| option: treemapOption, | |
| height: 500, | |
| buttons: [{ | |
| text: 'Custom Circle Packing', | |
| onclick: function () { | |
| chart.setOption(circlePackingOption, true); | |
| } | |
| }, { | |
| text: 'Treemap', | |
| onclick: function () { | |
| chart.setOption(treemapOption, true); | |
| } | |
| }, { | |
| text: 'Sunburst', | |
| onclick: function () { | |
| chart.setOption(sunburstOption, true); | |
| } | |
| }], | |
| }); | |
| }); | |
| }); | |
| </script> | |
| <script> | |
| require([ | |
| 'echarts' | |
| ], function (echarts) { | |
| var pieData = [ | |
| { value: 800, name: 'A' }, | |
| { value: 635, name: 'B' }, | |
| { value: 580, name: 'C' }, | |
| { value: 484, name: 'D' }, | |
| { value: 300, name: 'E' }, | |
| { value: 200, name: 'F' } | |
| ]; | |
| const defaultPalette = [ | |
| // '#51689b', '#ce5c5c', '#fbc357', '#8fbf8f', '#659d84', '#fb8e6a', '#c77288', '#786090', '#91c4c5', '#6890ba' | |
| '#5470c6', | |
| '#91cc75', | |
| '#fac858', | |
| '#ee6666', | |
| '#73c0de', | |
| '#3ba272', | |
| '#fc8452', | |
| '#9a60b4', | |
| '#ea7ccc' | |
| ]; | |
| const radius = ['30%', '80%']; | |
| var pieOption = { | |
| series: [{ | |
| type: 'pie', | |
| center: ['50%', '50%'], | |
| radius: radius, | |
| label: { | |
| show: false | |
| }, | |
| itemStyle: { | |
| borderRadius: 0 | |
| }, | |
| universalTransition: { | |
| enabled: true, | |
| seriesKey: 'first' | |
| }, | |
| animationDurationUpdate: 1000, | |
| data: pieData | |
| }] | |
| }; | |
| var parliamentOption = (function () { | |
| const sum = pieData.reduce((sum, cur) => { | |
| return sum + cur.value; | |
| }, 0); | |
| const angles = []; | |
| const startAngle = -Math.PI / 2; | |
| let curAngle = startAngle; | |
| pieData.forEach(item => { | |
| angles.push(curAngle); | |
| curAngle += (item.value / sum) * Math.PI * 2; | |
| }); | |
| angles.push(startAngle + Math.PI * 2); | |
| function parliamentLayout(startAngle, endAngle, totalAngle, r0, r1, size) { | |
| const rowsCount = Math.ceil((r1 - r0) / size); | |
| const points = []; | |
| let r = r0; | |
| for (let i = 0; i < rowsCount; i++) { | |
| // Recalculate size | |
| const totalRingSeatsNumber = Math.round((totalAngle * r) / size); | |
| const newSize = (totalAngle * r) / totalRingSeatsNumber; | |
| for ( | |
| let k = Math.floor((startAngle * r) / newSize) * newSize; | |
| k < Math.floor((endAngle * r) / newSize) * newSize - 1e-6; | |
| k += newSize | |
| ) { | |
| const angle = k / r; | |
| const x = Math.cos(angle) * r; | |
| const y = Math.sin(angle) * r; | |
| points.push([x, y]); | |
| } | |
| r += size; | |
| } | |
| return points; | |
| } | |
| return { | |
| series: { | |
| type: 'custom', | |
| data: pieData, | |
| coordinateSystem: undefined, | |
| universalTransition: { | |
| enabled: true, | |
| seriesKey: 'first' | |
| }, | |
| animationDurationUpdate: 1000, | |
| renderItem(params, api) { | |
| const idx = params.dataIndex; | |
| const viewSize = Math.min(api.getWidth(), api.getHeight()); | |
| const r0 = ((parseFloat(radius[0]) / 100) * viewSize) / 2; | |
| const r1 = ((parseFloat(radius[1]) / 100) * viewSize) / 2; | |
| const cx = api.getWidth() * 0.5; | |
| const cy = api.getHeight() * 0.5; | |
| const size = 15; | |
| const points = parliamentLayout( | |
| angles[idx], | |
| angles[idx + 1], | |
| Math.PI * 2, | |
| r0, | |
| r1, | |
| size + 3 | |
| ); | |
| return { | |
| type: 'group', | |
| children: points.map(pt => { | |
| return { | |
| type: 'circle', | |
| autoBatch: true, | |
| shape: { | |
| cx: cx + pt[0], | |
| cy: cy + pt[1], | |
| r: size / 2 | |
| }, | |
| style: { | |
| fill: defaultPalette[idx % defaultPalette.length] | |
| } | |
| }; | |
| }) | |
| }; | |
| } | |
| } | |
| }; | |
| })(); | |
| var chart = testHelper.create(echarts, 'main1', { | |
| title: [ | |
| 'Parliament and pie chart.' | |
| ], | |
| recordVideo: true, | |
| option: pieOption, | |
| height: 500, | |
| buttons: [{ | |
| text: 'Parliament chart', | |
| onclick: function () { | |
| chart.setOption(parliamentOption, true); | |
| } | |
| }, { | |
| text: 'Pie chart', | |
| onclick: function () { | |
| chart.setOption(pieOption, true); | |
| } | |
| }], | |
| }); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |