提交 a0797daf 编写于 作者: P pah100

tree map

上级 ac7ef3e2
define(function (require) {
var zrUtil = require('zrender/core/util');
var echarts = require('../echarts');
require('./treemap/TreemapSeries');
require('./treemap/TreemapView');
echarts.registerVisualCoding('chart', require('./treemap/treemapVisual'));
echarts.registerLayout(require('./treemap/TreemapLayout'), true);
});
\ No newline at end of file
define(function (require) {
var mathMax = Math.max;
var mathMin = Math.min;
var mathRound = Math.round;
var parsePercent = require('../../util/number').parsePercent;
var retrieveValue = require('../../util/model').retrieveValue;
var TreemapLayout = function () {
// FIXME
// 如果看效果不需要stick,则改成function形式的layout。
};
TreemapLayout.prototype = {
constructor: TreemapLayout,
/**
* @override
*/
update: function (ecModel, api, event) {
var ecWidth = api.getWidth();
var ecHeight = api.getHeight();
// Layout result in each node:
// {x, y, width, height, area, borderWidth}
ecModel.eachSeriesByType('treemap', function (seriesModel) {
var options = {
squareRatio: seriesModel.get('squareRatio'),
sort: seriesModel.get('sort')
};
var size = seriesModel.get('size') || []; // Compatible with ec2.
options.rootWidth = parsePercent(
retrieveValue(seriesModel.get('width'), size[0]),
ecWidth
);
options.rootHeight = parsePercent(
retrieveValue(seriesModel.get('height'), size[1]),
ecHeight
);
this.squarify(seriesModel.getViewRoot(), options);
}, this);
},
/**
* Layout treemap with squarify algorithm.
* @see https://graphics.ethz.ch/teaching/scivis_common/Literature/squarifiedTreeMaps.pdf
* @see https://github.com/mbostock/d3/blob/master/src/layout/treemap.js
*
* @protected
* @param {module:echarts/data/Tree~TreeNode} node
* @param {Object} options
* @param {number} [options.rootWidth]
* @param {number} [options.rootHeight]
* @param {number} [options.squareRatio]
*/
squarify: function (node, options) {
var width;
var height;
if (options.notRoot) {
var thisLayout = node.getLayout();
width = thisLayout.width;
height = thisLayout.height;
}
else {
width = options.rootWidth;
height = options.rootHeight;
node.setLayout({
x: 0, y: 0, width: width, height: height,
area: width * height
}, true);
}
var itemModel = node.getItemModel();
// Considering border and gap
// ????? borderWidth gapwidth在每个层级中定义。
var borderWidth = itemModel.get('itemStyle.normal.borderWidth');
var halfGapWidth = itemModel.get('itemStyle.normal.gapWidth') / 2;
var layoutOffset = borderWidth - halfGapWidth;
width -= 2 * layoutOffset;
height -= 2 * layoutOffset;
node.setLayout({borderWidth: borderWidth}, true);
var viewChildren = initChildren(node, width, height, itemModel, options);
if (!viewChildren.length) {
return;
}
var rect = {x: layoutOffset, y: layoutOffset, width: width, height: height};
var rowFixedLength = mathMin(width, height);
var best = Infinity; // the best row score so far
var remaining = viewChildren.slice();
var remainingLen;
var row = [];
row.area = 0;
while ((remainingLen = remaining.length) > 0) {
var child = remaining[remainingLen - 1];
row.push(child);
row.area += child.getLayout().area;
var score = worst(row, rowFixedLength, options.squareRatio);
// continue with this orientation
if (score <= best) {
remaining.pop();
best = score;
}
// abort, and try a different orientation
else {
row.area -= row.pop().getLayout().area;
position(row, rowFixedLength, rect, halfGapWidth, false);
rowFixedLength = mathMin(rect.width, rect.height);
row.length = row.area = 0;
best = Infinity;
}
}
if (row.length) {
position(row, rowFixedLength, rect, halfGapWidth, true);
}
options.notRoot = true;
for (var i = 0, len = viewChildren.length; i < len; i++) {
// The object "options" can be reused when tail recursion.
this.squarify(viewChildren[i], options);
}
}
};
/**
* Set area to each child.
*/
function initChildren(node, width, height, itemModel, options) {
var viewChildren = node.children || [];
// Sort children, order by desc.
viewChildren = viewChildren.slice();
if (options.sort) {
viewChildren.sort(function (a, b) {
// If 'asc', sort by desc, because layout is performed from tail to head.
return options.sort === 'asc'
? b.getValue() - a.getValue() : a.getValue() - b.getValue();
});
}
var sum = 0;
for (var i = 0, len = viewChildren.length; i < len; i++) {
sum += viewChildren[i].getValue();
}
var totalArea = width * height;
// Filter by thredshold.
for (var i = viewChildren.length - 1; i >= 0; i--) {
var value = viewChildren[i].getValue();
if (value / sum * totalArea < itemModel.get('itemStyle.normal.visibleMin')) {
viewChildren.slice(i, 1);
sum -= value;
}
else {
break;
}
}
// Set area to each child.
for (var i = 0, len = viewChildren.length; i < len; i++) {
var area = viewChildren[i].getValue() / sum * totalArea;
viewChildren[i].setLayout({area: area}, true);
}
node.viewChildren = viewChildren;
return viewChildren;
}
/**
* Computes the score for the specified row,
* as the worst aspect ratio.
*/
function worst(row, rowFixedLength, ratio) {
var areaMax = 0;
var areaMin = Infinity;
for (var i = 0, area, len = row.length; i < len; i++) {
if (area = row[i].getLayout().area) {
area < areaMin && (areaMin = area);
area > areaMax && (areaMax = area);
}
}
var squareArea = row.area * row.area;
var f = rowFixedLength * rowFixedLength * ratio;
return squareArea
? mathMax(
(f * areaMax) / squareArea,
squareArea / (f * areaMin)
)
: Infinity;
}
/**
* Positions the specified row of nodes. Modifies `rect`.
*/
function position(row, rowFixedLength, rect, halfGapWidth, flush) {
// When rowFixedLength === rect.width,
// it is horizontal subdivision,
// rowFixedLength is the width of the subdivision,
// rowOtherLength is the height of the subdivision,
// and nodes will be positioned from left to right.
// wh[idx0WhenH] means: when horizontal,
// wh[idx0WhenH] => wh[0] => 'width'.
// xy[idx1WhenH] => xy[1] => 'y'.
var idx0WhenH = rowFixedLength === rect.width ? 0 : 1;
var idx1WhenH = 1 - idx0WhenH;
var xy = ['x', 'y'];
var wh = ['width', 'height'];
var last = rect[xy[idx0WhenH]];
var rowOtherLength = rowFixedLength
? mathRound(row.area / rowFixedLength) : 0;
if (flush || rowOtherLength > rect[wh[idx1WhenH]]) {
rowOtherLength = rect[wh[idx1WhenH]]; // over+underflow
}
for (var i = 0, rowLen = row.length; i < rowLen; i++) {
var node = row[i];
var nodeLayout = {};
var step = rowOtherLength
? mathRound(node.getLayout().area / rowOtherLength) : 0;
nodeLayout[xy[idx1WhenH]] = rect[xy[idx1WhenH]] + halfGapWidth;
nodeLayout[xy[idx0WhenH]] = last + halfGapWidth;
nodeLayout[wh[idx1WhenH]] = rowOtherLength - 2 * halfGapWidth;
var remain = rect[xy[idx0WhenH]] + rect[wh[idx0WhenH]] - last;
var modWH = (i === rowLen - 1 || remain < step) ? remain : step;
nodeLayout[wh[idx0WhenH]] = modWH - 2 * halfGapWidth;
last += modWH;
node.setLayout(nodeLayout, true);
}
rect[xy[idx1WhenH]] += rowOtherLength;
rect[wh[idx1WhenH]] -= rowOtherLength;
}
return TreemapLayout;
});
\ No newline at end of file
define(function(require) {
var SeriesModel = require('../../model/Series');
var Tree = require('../../data/Tree');
var zrUtil = require('zrender/core/util');
return SeriesModel.extend({
type: 'series.treemap',
dependencies: ['grid', 'polar'],
defaultOption: {
calculable: false,
clickable: true,
// center: ['50%', '50%'], // not supported in ec3.
size: ['80%', '80%'], // deprecated, compatible with ec2.
x: 'center',
y: 'middle',
x2: null,
y2: null,
width: '80%',
height: '80%',
sort: 'desc', // Can be null or 'asc' or 'desc'
clipWindow: 'origin', // 缩放时窗口大小。'origin' or 'fullscreen'
squareRatio: 0.5 * (1 + Math.sqrt(5)), // golden ratio
root: '',
colorDimension: 'value', // 默认第一个维度。
breadcrumb: {
show: true,
itemStyle: {
normal: {
textStyle: {}
},
emphasis: {
textStyle: {}
}
}
},
label: {
normal: {
show: true,
x: 5,
y: 12,
textStyle: {
align: 'left',
color: '#000',
fontFamily: 'Arial',
fontSize: 13,
fontStyle: 'normal',
fontWeight: 'normal'
}
}
},
itemStyle: {
normal: {
color: null, // 各异 可以为数组,表示同一level的color 选取列表。
colorA: null, // 默认不设置 可以为数组,表示同一level的color alpha 选取范围。
colorS: null, // 默认不设置 可以为数组,表示同一level的color alpha 选取范围。
colorMapping: 'byIndex', // 'byIndex' or 'byValue'
borderWidth: 0,
borderColor: 'rgba(0,0,0,0)',
gapWidth: 0,
gapColor: 'rgba(0,0,0,0)' // 和borderColor恒相同。
},
emphasis: {}
},
visibleMin: 5, // Less than this threshold, node will not be rendered.
levels: [] // Each item: {
// visibleMin, itemStyle, colorDimension
// }
},
/**
* @override
*/
getInitialData: function (option, ecModel) {
var data = option.data;
data = data || [];
completeTreeValue(data);
return Tree.createTree(data, this).list;
},
/**
* @public
*/
getViewRoot: function () {
var optionRoot = this.option.root;
var treeRoot = this.getData().tree.root;
return optionRoot && treeRoot.getNodeByName(optionRoot) || treeRoot;
}
});
/**
* @param {Array.<Object>} data
* @return {number} Sum value of all children.
*/
function completeTreeValue(data) {
// Postorder travel tree.
// If value of none-leaf node is not set,
// calculate it by suming up the value of all children.
var sum = 0;
zrUtil.each(data, function (dataItem) {
var itemValue = dataItem.value;
var children = dataItem.children;
if (children && (itemValue == null || isNaN(itemValue))) {
itemValue = completeTreeValue(children);
}
// Value should not less than 0.
if (itemValue < 0) {
itemValue = 0;
}
dataItem.value = itemValue;
sum += itemValue;
});
return sum;
}
});
\ No newline at end of file
define(function(require) {
var zrUtil = require('zrender/core/util');
var graphic = require('../../util/graphic');
var layout = require('../../util/layout');
var Group = graphic.Group;
var Rect = graphic.Rect;
return require('../../echarts').extendChartView({
type: 'treemap',
/**
* @override
*/
init: function () {
},
/**
* @override
*/
render: function (seriesModel, ecModel, api) {
var contentGroup = new Group();
this._renderNodes(seriesModel.getViewRoot(), contentGroup);
this.group.add(contentGroup);
layout.positionGroup(
contentGroup,
{
x: seriesModel.get('x'),
y: seriesModel.get('y'),
x2: seriesModel.get('x2'),
y2: seriesModel.get('y2')
},
{
width: api.getWidth(),
height: api.getHeight()
}
);
},
/**
* @private
*/
_renderNodes: function (node, parentGroup) {
var layout = node.getLayout();
var thisWidth = layout.width;
var thisHeight = layout.height;
var viewChildren = node.viewChildren;
var group = new Group();
group.position = [layout.x, layout.y];
// Background
var itemModel = node.getItemModel();
// FIXME
// levels configuration ?????
var borderColor = itemModel.get('itemStyle.normal.borderColor')
|| itemModel.get('itemStyle.normal.gapColor');
group.add(new Rect({
shape: {x: 0, y: 0, width: thisWidth, height: thisHeight},
style: {fill: borderColor}
}));
// No children, render content.
if (!viewChildren || !viewChildren.length) {
var borderWidth = layout.borderWidth;
group.add(new Rect({
shape: {
x: borderWidth,
y: borderWidth,
width: thisWidth - 2 * borderWidth,
height: thisHeight - 2 * borderWidth
},
style: {
fill: node.getVisual('color', true)
}
// ?????????? text
}));
}
// Render children recursively.
else {
zrUtil.each(viewChildren, function (child) {
this._renderNodes(child, group);
}, this);
}
parentGroup.add(group);
},
/**
* @override
*/
remove: function () {
// var group = this.group;
// group.remove(this._polyline);
// group.remove(this._polygon);
// this._dataSymbol.remove(true);
}
});
});
\ No newline at end of file
define(function (require) {
var VisualMapping = require('../../visual/VisualMapping');
var zrColor = require('zrender/tool/color');
var zrUtil = require('zrender/core/util');
var isArray = zrUtil.isArray;
var each = zrUtil.each;
var VISUAL_LIST = ['color', 'colorA', 'colorS'];
return function (ecModel) {
var globalColorList = ecModel.get('color');
ecModel.eachSeriesByType('treemap', function (seriesModel) {
var rootVisual = {};
each(VISUAL_LIST, function (name) {
var visual = seriesModel.get('itemStyle.normal.' + name);
rootVisual[name] = isArray(visual) ? null : visual;
});
!rootVisual.color && (rootVisual.color = globalColorList);
travelTree(seriesModel.getViewRoot(), rootVisual, seriesModel);
});
};
function travelTree(node, designatedVisual, seriesModel) {
var itemModel = node.getItemModel();
var visuals = buildVisuals(node, itemModel, designatedVisual, seriesModel);
var viewChildren = node.viewChildren;
if (!viewChildren || !viewChildren.length) {
// Apply visual to this node.
node.setVisual('color', calculateColor(visuals, node));
}
else {
var mappingWrap = buildVisualMapping(visuals, itemModel, viewChildren);
// Designate visual to children.
zrUtil.each(viewChildren, function (child, index) {
var childVisual = mapVisual(visuals, child, index, itemModel, mappingWrap);
travelTree(child, childVisual, seriesModel);
});
}
}
function buildVisuals(node, itemModel, designatedVisual, seriesModel) {
var visuals = zrUtil.extend({}, designatedVisual);
zrUtil.each(VISUAL_LIST, function (visualName) {
// Priority: thisNode > thisLevel > parentNodeDesignated
var path = 'itemStyle.normal.' + visualName;
var visualValue = itemModel.get(path, true); // Ignore parent
if (visualValue == null) {
visualValue = retrieve(path, seriesModel.option.levels[node.depth]);
}
if (visualValue == null) {
visualValue = designatedVisual[visualName];
}
if (visualValue != null) {
visuals[visualName] = visualValue;
}
});
return visuals;
}
function calculateColor(visuals) {
var color = getValueVisualDefine(visuals, 'color');
if (color) {
var colorA = getValueVisualDefine(visuals, 'colorA');
var colorS = getValueVisualDefine(visuals, 'colorS');
if (colorS) {
color = zrColor.modifyHSL(color, null, null, colorS);
}
if (colorA) {
color = zrColor.modifyAlpha(color, colorA);
}
return color;
}
}
function buildVisualMapping(visuals, itemModel, viewChildren) {
if (!viewChildren || !viewChildren.length) {
return;
}
var mappingVisualName = getRangeVisualName(visuals, 'color')
|| (
visuals.color != null
&& (
getRangeVisualName(visuals, 'colorA')
|| getRangeVisualName(visuals, 'colorS')
)
);
if (!mappingVisualName) {
return;
}
var mappingType = mappingVisualName === 'color'
? (
itemModel.get('itemStyle.normal.colorMapping') === 'byValue'
? 'color' : 'colorByIndex'
)
: mappingVisualName;
var dataExtent = mappingType === 'colorByIndex'
? null
: calculateDataExtent(itemModel, viewChildren);
return {
mapping: new VisualMapping({
type: mappingType,
dataExtent: dataExtent,
dataNormalizer: 'linear',
visual: visuals[mappingVisualName]
}),
visualName: mappingVisualName
};
}
function calculateDataExtent(itemModel, viewChildren) {
var dimension = itemModel.get('colorDimension');
// The same as area dimension.
if (dimension === 'value') {
return [
viewChildren[viewChildren.length - 1].getValue(),
viewChildren[0].getValue()
];
}
// Other dimension.
else {
var dataExtent = [Infinity, -Infinity];
each(viewChildren, function (child) {
var value = child.getValue(dimension);
value < dataExtent[0] && (dataExtent[0] = value);
value > dataExtent[1] && (dataExtent[1] = value);
});
}
}
function mapVisual(visuals, child, index, itemModel, mappingWrap) {
var childVisuals = zrUtil.extend({}, visuals);
if (mappingWrap) {
var mapping = mappingWrap.mapping;
var value = mapping.type === 'colorByIndex'
? index : child.getValue(itemModel.get('colorDimension'));
childVisuals[mappingWrap.visualName] = mapping.mapValueToVisual(value);
}
return childVisuals;
}
function getValueVisualDefine(visuals, name) {
var value = visuals[name];
if (value != null && !isArray(value)) {
return value;
}
}
function getRangeVisualName(visuals, name) {
var value = visuals[name];
if (value != null && isArray(value)) {
return name;
}
}
// FIXME
// 这段代码是否和model中的复用?
function retrieve(path, base) {
path = path.split('.');
var obj = base;
for (var i = 0; i < path.length; i++) {
obj = obj && obj[path[i]];
if (obj == null) {
break;
}
}
return obj;
}
});
\ No newline at end of file
......@@ -290,7 +290,7 @@ define(function(require) {
var mappingOption = {
type: visualType,
dataExtent: dataExtent,
data: visualData
visual: visualData
};
fillVisualOption && fillVisualOption.call(this, mappingOption, state);
mappings[visualType] = new VisualMapping(mappingOption);
......
......@@ -6,7 +6,7 @@
*/
define(function(require) {
var zrUtil = require('zrender/tool/util');
var zrUtil = require('zrender/core/util');
var Model = require('../model/Model');
var List = require('./List');
var arraySlice = Array.prototype.slice;
......@@ -59,6 +59,12 @@ define(function(require) {
*/
this.children = [];
/**
* @type {Array.<module:echarts/data/Tree~TreeNode>}
* @pubilc
*/
this.viewChildren = [];
/**
* @type {moduel:echarts/data/Tree}
* @readOnly
......@@ -143,10 +149,11 @@ define(function(require) {
},
/**
* @param {string=} dimension Default 'value'. can be 'a', 'b', 'c', 'd', 'e'.
* @return {number} Value.
*/
getValue: function () {
return this.hostTree.list.get('value', this.dataIndex);
getValue: function (dimension) {
return this.hostTree.list.get(dimension || 'value', this.dataIndex);
},
/**
......@@ -162,6 +169,31 @@ define(function(require) {
*/
getLayout: function () {
return this.hostTree.list.getItemLayout(this.dataIndex);
},
/**
* @return {module:echarts/model/Model}
*/
getItemModel: function () {
return this.hostTree.list.getItemModel(this.dataIndex);
},
/**
* @example
* setItemVisual(0, 'color', color);
* setItemVisual(0, {
* 'color': color
* });
*/
setVisual: function (key, value) {
return this.hostTree.list.setItemVisual(this.dataIndex, key, value);
},
/**
* @public
*/
getVisual: function (key, ignoreParent) {
return this.hostTree.list.getItemVisual(this.dataIndex, key, ignoreParent);
}
});
......@@ -175,7 +207,7 @@ define(function(require) {
* @type {module:echarts/data/Tree~TreeNode}
* @readOnly
*/
this.root = new TreeNode(name);
this.root = new TreeNode(name, null, this);
/**
* @type {module:echarts/data/List}
......@@ -240,74 +272,89 @@ define(function(require) {
for (var i = 0, len = list.count(); i < len; i++) {
nodes[list.getRawIndex(i)].dataIndex = i;
}
},
}
};
/**
* data format:
* [
* {
* name: ...
* value: ...
* children: [
* {
* name: ...
* value: ...
* children: ...
* },
* ...
* ]
* },
* ...
* ]
*
* @param {Array.<Object>} data
* @param {module:echarts/model/Model} hostModel
* @return module:echarts/data/Tree
*/
createTree: function (data, hostModel) {
var listData = [];
/**
* data format:
* [
* {
* name: ...
* value: ...
* children: [
* {
* name: ...
* value: ...
* children: ...
* },
* ...
* ]
* },
* ...
* ]
*
* @static
* @param {Array.<Object>} data
* @param {module:echarts/model/Model} hostModel
* @return module:echarts/data/Tree
*/
Tree.createTree = function (data, hostModel) {
var listData = [];
var tree = new Tree();
var rootNode = tree.root;
var dataIndex = 0;
var tree = new Tree();
var rootNode = tree.root;
function buildHierarchy(dataNode, parentNode) {
var node = new TreeNode(dataNode.name, dataIndex, tree);
parentNode.add(node);
function buildHierarchy(dataNode, parentNode) {
listData.push(dataNode);
listData[dataIndex] = dataNode;
var node = new TreeNode(dataNode.name, listData.length - 1, tree);
parentNode.add(node);
var children = dataNode.children;
if (children) {
for (var i = 0; i < children.length; i++) {
buildHierarchy(children[i], node);
}
var children = dataNode.children;
if (children) {
for (var i = 0; i < children.length; i++) {
buildHierarchy(children[i], node);
}
}
}
for (var i = 0; i < data.length; i++) {
buildHierarchy(data[i], rootNode);
}
for (var i = 0; i < data.length; i++) {
buildHierarchy(data[i], rootNode);
}
tree.root.updateDepthAndHeight(0);
tree.root.updateDepthAndHeight(0);
var list = new List(['value'], hostModel);
list.initData(listData);
var list = createList(listData, hostModel);
tree.list = list;
list.tree = tree;
tree.list = list;
proxyList(list, tree);
proxyList(list, tree);
return tree;
}
return tree;
};
function createList(listData, hostModel) {
var firstValue = listData[0] && listData[0].value;
var dimSize = zrUtil.isArray(firstValue) ? firstValue.length : 1;
// FIXME
// 和 createListFromArray中一样,怎么改好看点。
var dimensionNames = ['value', 'a', 'b', 'c', 'd', 'e', 'f'];
var list = new List(dimensionNames.slice(0, dimSize), hostModel);
list.initData(listData);
return list;
}
function proxyList(list, tree) {
zrUtil.each(listProxyMethods, function (method, methodName) {
var originMethod = list[methodName];
list[methodName] = zrUtil.curry(method, originMethod, tree);
});
// Among list and its clones, only one can be active in echarts process.
// So a tree instance can be share by list and its clone.
list.tree = tree;
return list;
}
......
......@@ -18,7 +18,7 @@ define(function (require) {
* @param {Array.<Array>=} [option.intervalVisual=] [value1, value2, ...],
* specific visual of some interval,
* available when dataNormalizer is 'piecewise'
* @param {Array} [option.data=] Visual data.
* @param {Array} [option.visual=] Visual data.
*/
var VisualMapping = function (option) {
......@@ -50,10 +50,6 @@ define(function (require) {
mapValueToVisual: null,
getData: function () {
return this.option.data;
},
_getIntervalVisual: function(normalized) {
var intervalVisuals = this.option.intervalVisuals;
return (intervalVisuals && intervalVisuals.length)
......@@ -71,7 +67,7 @@ define(function (require) {
},
mapValueToVisual: function (value) {
var optionData = this.option.data;
var optionData = this.option.visual;
if (zrUtil.isArray(value)) {
value = [
......@@ -92,6 +88,17 @@ define(function (require) {
}
},
colorByIndex: {
applyVisual: function (index, getter, setter) {
setter('color', this.mapValueToVisual(index));
},
mapValueToVisual: function (index) {
var visual = this.option.visual;
return visual[index % visual.length];
}
},
colorS: makePartialColorVisualHandler(function (color, value) {
return zrColor.modifyHSL(color, null, value);
}),
......@@ -119,7 +126,7 @@ define(function (require) {
return specifiedVisual != null
? specifiedVisual
: (arrayGetByNormalizedValue(this.option.data, normalized) || {});
: (arrayGetByNormalizedValue(this.option.visual, normalized) || {});
}
},
......@@ -134,7 +141,7 @@ define(function (require) {
return specifiedVisual != null
? specifiedVisual
: linearMap(normalized, [0, 1], this.option.data, true);
: linearMap(normalized, [0, 1], this.option.visual, true);
}
}
};
......@@ -155,7 +162,7 @@ define(function (require) {
return specifiedVisual != null
? specifiedVisual
: linearMap(normalized, [0, 1], this.option.data, true);
: linearMap(normalized, [0, 1], this.option.visual, true);
}
};
}
......
<html>
<head>
<meta charset="utf-8">
<script src="esl.js"></script>
<script src="config.js"></script>
</head>
<body>
<style>
html, body, #main {
width: 100%;
height: 100%;
}
</style>
<div id="main"></div>
<script>
require([
'echarts',
'echarts/chart/treemap',
], function (echarts) {
var chart = echarts.init(document.getElementById('main'), null, {
renderer: 'canvas'
});
chart.setOption({
series: [
{
name:'矩形树图',
type:'treemap',
label: {
show: true,
formatter: "{b}"
},
itemStyle: {
normal: {
borderWidth: 1,
borderColor: 'black'
},
emphasis: {
}
},
data:[
{
name: '三星',
value: 6
},
{
name: '小米',
value: 4
},
{
name: '苹果',
value: 4
},
{
name: '华为',
value: 2
},
{
name: '联想',
value: 2
},
{
name: '魅族',
value: 1
},
{
name: '中兴',
value: 1
}
]
}
]
});
});
</script>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册