提交 d0636bbf 编写于 作者: B break60 提交者: qiaozhanwei

Replace ans charts with source code (#1144)

* Dependency workflow add dependency correction value

* Download workflow instance map width adjustment and change "desc" field to "description"

* The third-party library that builds the dependency is recommended to be placed in 'devDependencies'

* Tree chart and Gantt chart style modification

* The workflow instance can be deleted only when its status is success, failure, stop and pause.

* change desc to description

* Maximum width of tooltip is set to 500px, note the copyright number of login page

* Delete copyright number

* No tenant in the list of selected tenants the default is default, and the status not shown in the repair page

* repair

* Repair security center module prompt

* Remove blank character during verification

* Remove blank character during verification

* Non admin users cannot create users, tenants, alarm groups, queues and worker groups

* Remove CI windows detection

* The value of loadaverage should be two decimal places

* Add license

* delete docs

* update package.json

* delete LICENSE

* Display icon when there is no data in process definition

* Worker group add IP format verification

* Modify MySQL page of monitoring center

* DB page rename and background color modification

* IO build replace with source code

* Replace ans charts with source code
上级 2902c2e0
......@@ -24,7 +24,7 @@ import router from './router'
import store from './store'
import i18n from '@/module/i18n'
import { sync } from 'vuex-router-sync'
import Chart from '~/@analysys/ana-charts'
import Chart from '@/module/ana-charts'
import '@/module/filter/formatDate'
import themeData from '@/module/echarts/themeData.json'
import Permissions from '@/module/permissions'
......
......@@ -30,7 +30,7 @@
import _ from 'lodash'
import { mapActions } from 'vuex'
import { simple } from './chartConfig'
import Chart from '~/@analysys/ana-charts'
import Chart from '@/module/ana-charts'
import mNoData from '@/module/components/noData/noData'
export default {
......
......@@ -30,7 +30,7 @@
import _ from 'lodash'
import { mapActions } from 'vuex'
import { bar } from './chartConfig'
import Chart from '~/@analysys/ana-charts'
import Chart from '@/module/ana-charts'
import mNoData from '@/module/components/noData/noData'
export default {
name: 'define-user-count',
......
......@@ -48,7 +48,7 @@
import _ from 'lodash'
import { mapActions } from 'vuex'
import { pie } from './chartConfig'
import Chart from '~/@analysys/ana-charts'
import Chart from '@/module/ana-charts'
import mNoData from '@/module/components/noData/noData'
import { stateType } from '@/conf/home/pages/projects/pages/_source/instanceConditions/common'
export default {
......
......@@ -48,7 +48,7 @@
import _ from 'lodash'
import { mapActions } from 'vuex'
import { pie } from './chartConfig'
import Chart from '~/@analysys/ana-charts'
import Chart from '@/module/ana-charts'
import mNoData from '@/module/components/noData/noData'
export default {
name: 'queue-count',
......
......@@ -52,7 +52,7 @@
import _ from 'lodash'
import { mapActions } from 'vuex'
import { pie } from './chartConfig'
import Chart from '~/@analysys/ana-charts'
import Chart from '@/module/ana-charts'
import mNoData from '@/module/components/noData/noData'
import { stateType } from '@/conf/home/pages/projects/pages/_source/instanceConditions/common'
......
/**
* 根据参数找到容器并初始化图表,然后返回一个或者一组图表实例
* @param {*} Target 图表组件类
* @param {*} el 选择器或者 DOM 对象
* @param {*} data 数据源
* @param {*} options 可选项
*/
export const init = (Target, el, data, options) => {
const list = getChartContainers(el)
const settings = Object.assign({}, { data }, options)
const charts = list.map(element => {
return new Target(element, settings)
})
return charts.length === 1 ? charts[0] : charts
}
/**
* 统一图表容器为 DOM 元素数组
* @param {*} el 选择器或者 DOM 对象
*/
function getChartContainers (el) {
// 未传参数,直接返回
if (!el) {
return
}
if (typeof el === 'string') {
if (el.startsWith('#')) {
el = document.getElementById(el.slice(1))
} else if (el.startsWith('.')) {
el = document.getElementsByClassName(el.slice(1))
} else {
return
}
}
if (!el) {
throw new Error('找不到对应的dom对象!')
}
let list
if (HTMLElement.prototype.isPrototypeOf(el)) {
list = new Array(el)
} else {
list = Array.from(el)
}
if (!list) {
throw new Error('未找到对应的dom对象!')
}
return list
}
/**
* 检测在指定对象中是否存在指定的属性名
* @param {Object} model 待检测模型
* @param {...any} params 待检测属性名
*/
export const checkKeyInModel = (model, ...params) => {
for (const key of params) {
if (!model.hasOwnProperty(key)) {
throw new Error('数据格式错误!未找到指定属性:' + key)
}
}
}
/*
* 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 echarts from 'echarts'
import Line from './packages/line'
import Bar from './packages/bar'
import Pie from './packages/pie'
import Radar from './packages/radar'
import Funnel from './packages/funnel'
import Scatter from './packages/scatter'
import { checkKeyInModel, init } from './common'
const components = {
Line,
Bar,
Pie,
Radar,
Funnel,
Scatter
}
const Chart = {
// 默认配置
settings: {},
/**
* 配置全局属性
* @param {Object} options 全局配置项
*/
config (options) {
const { theme } = options
// 注册主题
if (theme) {
checkKeyInModel(theme, 'name', 'data')
echarts.registerTheme(theme.name, theme.data)
if (theme.default) {
Chart.settings.defaultTheme = theme.name
}
}
}
}
// 注入不同组件对应方法
for (const key in components) {
if (components.hasOwnProperty(key)) {
Chart[key.toLowerCase()] = (el, data, options) => {
return init(components[key], el, data, options)
}
}
}
export {
Line,
Bar,
Pie,
Radar,
Funnel,
Scatter
}
export default Chart
if (typeof window !== 'undefined') {
window.Chart = Chart
}
/*
* 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 Base from '../base'
import { checkKeyInModel, init } from '../../common'
const TYPE = 'bar'
/**
* 柱状图
*/
export default class Bar extends Base {
/**
* 单独导出时调用的初始化方法
* @param {*} el 选择器或者 DOM 对象
* @param {*} data 数据源
* @param {*} options 可选项
*/
static init (el, data, options) {
return init(Bar, el, data, options)
}
/**
* 将用户配置转换为符合 ECharts API 格式的配置格式
*/
transform () {
const { data = [] } = this.settings
if (data.length === 0) {
throw new Error('数据源为空!')
}
if (Object.keys(data[0]).length > 2) {
return this.setMultipleBars()
} else {
this.simple = true
return this.setSingleBar()
}
}
/**
* 单条柱
*/
setSingleBar () {
const {
// 数据
data = [],
// 属性字典
keyMap = {
xAxisKey: 'key',
dataKey: 'value'
},
// 图表标题
title = '单条柱状图'
} = this.settings
// x 轴对应属性名,数据值对应的属性名
const { xAxisKey, dataKey } = keyMap
checkKeyInModel(data[0], xAxisKey, dataKey)
const series = [{
type: TYPE,
data: []
}]
const xAxis = {
type: 'category',
data: []
}
for (let i = 0; i < data.length; i++) {
xAxis.data.push(data[i][xAxisKey])
series[0].data.push(data[i][dataKey])
}
return { title, xAxis, series }
}
/**
* 多条柱
*/
setMultipleBars () {
const {
// 数据
data = [],
// 属性字典
keyMap = {
xAxisKey: 'key',
legendKey: 'typeName',
dataKey: 'value'
},
// 图表标题
title = '多条柱状图',
// 折柱混合时,指定的折线数据索引
lineTypes
} = this.settings
// x 轴对应属性名,图例对应的属性名,数据值对应的属性名
const { xAxisKey, legendKey, dataKey } = keyMap
// 是否使用时间轴数据
const timeline = Object.keys(data[0]).length === 4
const timelineKey = keyMap.timelineKey || 'timeline'
if (timeline) {
checkKeyInModel(data[0], xAxisKey, legendKey, dataKey, timelineKey)
} else {
checkKeyInModel(data[0], xAxisKey, legendKey, dataKey)
}
// 规范折柱混合索引
let lineTypeList = []
if (lineTypes) {
if (!Array.isArray(lineTypes)) {
lineTypeList = [lineTypes]
} else {
lineTypeList = lineTypes
}
}
// 时间轴默认配置
const timelineOptions = {
timeline: {
axisType: 'category',
autoPlay: true,
playInterval: 1000,
data: []
},
options: []
}
// 初始值
const legendData = []
const series = []
const xAxis = {
type: 'category',
data: []
}
for (let i = 0; i < data.length; i++) {
const legendItem = data[i][legendKey]
const xAxisItem = data[i][xAxisKey]
const dataItem = data[i][dataKey]
// 图例
if (!legendData.includes(legendItem)) {
legendData.push(legendItem)
}
// x 轴
if (!xAxis.data.includes(xAxisItem)) {
xAxis.data.push(xAxisItem)
}
// 时间轴
if (timeline) {
const timelineItem = data[i][timelineKey]
// 设置时间轴 label
if (!timelineOptions.timeline.data.includes(timelineItem)) {
timelineOptions.timeline.data.push(timelineItem)
}
// 通用的系列配置
if (!series.some(s => s.name === legendItem)) {
let seriesType = TYPE
if (lineTypeList.length !== 0 && lineTypeList.includes(legendItem)) {
seriesType = 'line'
}
series.push({
name: legendItem,
type: seriesType
})
}
// 系列数据
let targetOptions = timelineOptions.options.find(o => o._helpName === timelineItem)
if (!targetOptions) {
// 初始化 option
targetOptions = {
_helpName: timelineItem,
title: { text: title.replace('$timeline', timelineItem) },
series: []
}
timelineOptions.options.push(targetOptions)
}
let targetSeries = targetOptions.series.find(d => d._helpName === legendItem)
if (!targetSeries) {
// 初始化系列数据
targetSeries = {
_helpName: legendItem,
data: []
}
targetOptions.series.push(targetSeries)
}
targetSeries.data.push(dataItem)
} else {
// 非时间轴数据处理
let targetSeries = series.find(s => s.name === legendItem)
if (!targetSeries) {
let seriesType = TYPE
if (lineTypeList.length !== 0 && lineTypeList.includes(legendItem)) {
seriesType = 'line'
}
targetSeries = {
name: legendItem,
type: seriesType,
data: []
}
series.push(targetSeries)
}
targetSeries.data.push(dataItem)
}
}
if (timeline) {
return { title, xAxis, series, legendData, timelineOptions }
}
return { title, xAxis, series, legendData }
}
/**
* 绘制图表
*/
apply () {
const { title, xAxis, series, legendData, timelineOptions } = this.options
const {
// 是否为横向图
reverseAxis = false,
// 自定义 y 轴
yAxis,
// 是否为堆叠图
stack = false,
// 注入配置到 series
insertSeries
} = this.settings
const valueAxis = { type: 'value' }
let yAxisModel = reverseAxis ? xAxis : valueAxis
let xAxisModel = reverseAxis ? valueAxis : xAxis
// 使用自定义 y 轴覆盖
if (yAxis) {
yAxisModel = yAxis
}
// 设置堆叠图
if (stack) {
series.forEach(set => {
set.stack = '总量'
set.label = {
normal: {
show: true,
position: reverseAxis ? 'insideRight' : 'insideTop'
}
}
})
}
let _series = series
if (insertSeries && insertSeries.length && series.length) {
_series = this.injectDataIntoSeries(insertSeries, _series)
}
// 时间轴
if (timelineOptions) {
let opts = {
baseOption: {
timeline: timelineOptions.timeline,
tooltip: {
trigger: 'axis'
},
grid: {
top: 80,
bottom: 100,
containLabel: true
},
legend: {
x: 'right',
data: legendData
},
xAxis: xAxisModel,
yAxis: yAxisModel,
series: _series
},
options: timelineOptions.options
}
this.echart.setOption(opts, true)
this.echart.clear()
this.echart.setOption(opts, true)
} else {
// 简单图表标题为空时,图表垂直居中
const top = !title && this.simple ? '3%' : 60
let opts = {
title: {
text: title
},
tooltip: {
trigger: 'axis'
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top,
containLabel: true
},
legend: {
data: legendData
},
xAxis: xAxisModel,
yAxis: yAxisModel,
series: _series
}
this.echart.setOption(opts, true)
this.echart.clear()
this.echart.setOption(opts, true)
}
}
}
/*
* 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 echarts from 'echarts'
import Chart from '../index'
export default class Base {
constructor (element, settings) {
this.settings = settings
const options = this.transform()
if (options) {
this.options = options
if (settings.theme) {
// 使用已经注册的自定义主题
this.echart = echarts.init(element, settings.theme)
} else if (Chart.settings.defaultTheme) {
// 使用全局配置的主题
this.echart = echarts.init(element, Chart.settings.defaultTheme)
} else {
this.echart = echarts.init(element)
}
// 响应窗口 resize 事件
window.addEventListener('resize', () => this.echart.resize())
this.apply()
}
}
/**
* 刷新数据
* @param {*} data 图表数据
*/
setData (data) {
if (data && data.length !== 0) {
this.settings.data = data
this.options = this.transform()
this.apply()
}
}
injectDataIntoSeries (data, series) {
data.forEach(o => {
if (o.index === 'all') {
delete o.index
series = series.map(item => {
return Object.assign({}, item, o)
})
} else if (o.index === 'start') {
delete o.index
series[0] = Object.assign({}, series[0], o)
} else if (o.index === 'end') {
delete o.index
series[series.length - 1] = Object.assign({}, series[series.length - 1], o)
} else if (Array.isArray(o.index)) {
for (const i of o.index) {
if (series[i]) {
series[i] = Object.assign({}, series[i], o)
}
}
}
})
return series
}
}
/*
* 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 Base from '../base'
import { checkKeyInModel, init } from '../../common'
const TYPE = 'funnel'
/**
* 漏斗图
*/
export default class Funnel extends Base {
/**
* 单独导出时调用的初始化方法
* @param {*} el 选择器或者 DOM 对象
* @param {*} data 数据源
* @param {*} options 可选项
*/
static init (el, data, options) {
return init(Funnel, el, data, options)
}
/**
* 将用户配置转换为符合 ECharts API 格式的配置格式
*/
transform () {
const {
// 数据
data = [],
// 标题
title = '漏斗图',
// 属性字典
keyMap = {
textKey: 'key',
dataKey: 'value'
}
} = this.settings
if (data.length === 0) {
throw new Error('数据源为空!')
}
// 文本对应属性名,数据值对应的属性名
const { textKey, dataKey } = keyMap
checkKeyInModel(data[0], textKey, dataKey)
const legendData = []
const series = [{
type: TYPE,
left: '10%',
top: 60,
bottom: 60,
width: '80%',
min: 0,
max: 100,
minSize: '0%',
maxSize: '100%',
sort: 'descending',
gap: 2,
label: {
normal: {
show: true,
position: 'inside'
},
emphasis: {
textStyle: {
fontSize: 20
}
}
},
labelLine: {
normal: {
length: 10,
lineStyle: {
width: 1,
type: 'solid'
}
}
},
itemStyle: {
normal: {
borderColor: '#fff',
borderWidth: 1
}
},
data: []
}]
// 填充数据
for (let i = 0; i < data.length; i++) {
const element = data[i]
const { [dataKey]: value, [textKey]: name, ...other } = element
const item = {
value,
name,
...other,
_raw: element
}
series[0].data.push(item)
}
return { title, series, legendData }
}
/**
* 绘制图表
*/
apply () {
let { title, series, legendData } = this.options
// 注入配置到series
let { insertSeries } = this.settings
let _series = series
if (insertSeries && insertSeries.length && series.length) {
_series = this.injectDataIntoSeries(insertSeries, _series)
}
this.echart.setOption({
title: {
text: title
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}%'
},
legend: {
data: legendData
},
series: _series
}, true)
}
}
/*
* 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 Base from '../base'
import { checkKeyInModel, init } from '../../common'
const TYPE = 'line'
/**
* 折线图
*/
export default class Line extends Base {
/**
* 单独导出时调用的初始化方法
* @param {*} el 选择器或者 DOM 对象
* @param {*} data 数据源
* @param {*} options 可选项
*/
static init (el, data, options) {
return init(Line, el, data, options)
}
/**
* 将用户配置转换为符合 ECharts API 格式的配置格式
*/
transform () {
const { data = [] } = this.settings
if (data.length === 0) {
throw new Error('数据源为空!')
}
if (Object.keys(data[0]).length > 2) {
return this.setMultipleLines()
} else {
this.simple = true
return this.setSingleLine()
}
}
/**
* 单条折线
*/
setSingleLine () {
const {
// 数据
data = [],
// 属性字典
keyMap = {
xAxisKey: 'key',
dataKey: 'value'
},
// 图表标题
title = '单条折线图'
} = this.settings
// x 轴对应属性名,数据值对应的属性名
const { xAxisKey, dataKey } = keyMap
checkKeyInModel(data[0], xAxisKey, dataKey)
const series = [{
type: TYPE,
data: []
}]
const xAxis = {
type: 'category',
data: []
}
for (let i = 0; i < data.length; i++) {
xAxis.data.push(data[i][xAxisKey])
series[0].data.push(data[i][dataKey])
}
return { title, xAxis, series }
}
/**
* 多条折线
*/
setMultipleLines () {
const {
// 数据
data = [],
// 属性字典
keyMap = {
xAxisKey: 'key',
legendKey: 'typeName',
dataKey: 'value'
},
// 图表标题
title = '多条折线图'
} = this.settings
// x 轴对应属性名,图例对应的属性名,数据值对应的属性名
const { xAxisKey, legendKey, dataKey } = keyMap
checkKeyInModel(data[0], xAxisKey, legendKey, dataKey)
const legendData = []
const series = []
const xAxis = {
type: 'category',
data: []
}
for (let i = 0; i < data.length; i++) {
const legendItem = data[i][legendKey]
const xAxisItem = data[i][xAxisKey]
const dataItem = data[i][dataKey]
// 图例
if (!legendData.includes(legendItem)) {
legendData.push(legendItem)
}
// x 轴
if (!xAxis.data.includes(xAxisItem)) {
xAxis.data.push(xAxisItem)
}
// 系列
let targetSeries = series.find(s => s.name === legendItem)
if (!targetSeries) {
targetSeries = {
name: legendItem,
type: TYPE,
data: []
}
series.push(targetSeries)
}
targetSeries.data.push(dataItem)
}
return { title, xAxis, series, legendData }
}
/**
* 绘制图表
*/
apply () {
const { title, xAxis, series, legendData = [] } = this.options
const {
// 是否为横向图
reverseAxis = false,
// 自定义 y 轴
yAxis,
// 注入配置到 series
insertSeries
} = this.settings
const valueAxis = { type: 'value' }
let yAxisModel = reverseAxis ? xAxis : valueAxis
let xAxisModel = reverseAxis ? valueAxis : xAxis
// 使用自定义 y 轴覆盖
if (yAxis) {
yAxisModel = yAxis
}
// 简单图表标题为空时,图表垂直居中
const top = !title && this.simple ? '3%' : 60
let _series = series
if (insertSeries && insertSeries.length && series.length) {
_series = this.injectDataIntoSeries(insertSeries, _series)
}
let opts = {
title: {
text: title
},
tooltip: {
trigger: 'axis'
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top,
containLabel: true
},
legend: {
data: legendData
},
xAxis: xAxisModel,
yAxis: yAxisModel,
series: _series
}
this.echart.setOption(opts, true)
this.echart.clear()
this.echart.setOption(opts, true)
}
}
/*
* 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 Base from '../base'
import { checkKeyInModel, init } from '../../common'
const TYPE = 'pie'
/**
* 饼图
*/
export default class Pie extends Base {
/**
* 单独导出时调用的初始化方法
* @param {*} el 选择器或者 DOM 对象
* @param {*} data 数据源
* @param {*} options 可选项
*/
static init (el, data, options) {
return init(Pie, el, data, options)
}
/**
* 将用户配置转换为符合 ECharts API 格式的配置格式
*/
transform () {
const {
// 数据
data = [],
// 标题
title = '饼图',
// 是否环形图
ring = false,
// 属性字典
keyMap = {
textKey: 'key',
dataKey: 'value'
}
} = this.settings
if (data.length === 0) {
throw new Error('数据源为空!')
}
// 文本对应属性名,数据值对应的属性名
const { textKey, dataKey } = keyMap
checkKeyInModel(data[0], textKey, dataKey)
const legendData = []
let radius = ring ? ['50%', '70%'] : '60%'
let center = title ? ['50%', '60%'] : ['50%', '50%']
const series = [{
radius: radius,
center: center,
type: TYPE,
data: []
}]
// 填充数据
for (let i = 0; i < data.length; i++) {
const element = data[i]
const { [dataKey]: value, [textKey]: name, ...other } = element
const item = {
value,
name,
...other,
_raw: element
}
series[0].data.push(item)
}
return { title, series, legendData }
}
/**
* 绘制图表
*/
apply () {
let { title, series, legendData } = this.options
// 注入配置到series
let { insertSeries } = this.settings
let _series = series
if (insertSeries && insertSeries.length && series.length) {
_series = this.injectDataIntoSeries(insertSeries, _series)
}
let opts = {
title: {
text: title,
x: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 'left',
data: legendData
},
series: _series
}
this.echart.setOption(opts, true)
this.echart.clear()
this.echart.setOption(opts, true)
}
}
/*
* 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 Base from '../base'
import { checkKeyInModel, init } from '../../common'
const TYPE = 'radar'
/**
* 雷达图
*/
export default class Radar extends Base {
/**
* 单独导出时调用的初始化方法
* @param {*} el 选择器或者 DOM 对象
* @param {*} data 数据源
* @param {*} options 可选项
*/
static init (el, data, options) {
return init(Radar, el, data, options)
}
/**
* 将用户配置转换为符合 ECharts API 格式的配置格式
*/
transform () {
const {
// 数据
data = [],
// 图表标题
title = '雷达图',
// 属性字典
keyMap = {
textKey: 'key',
legendKey: 'typeName',
dataKey: 'value'
}
} = this.settings
if (data.length === 0) {
throw new Error('数据源为空!')
}
// 文本对应属性名,图例对应的属性名,数据值对应的属性名
const { textKey, legendKey, dataKey } = keyMap
checkKeyInModel(data[0], textKey, legendKey, dataKey)
const legendData = []
const seriesData = []
const indicator = []
// 设置图例并初始化数据系列
for (let i = 0; i < data.length; i++) {
const legendItem = data[i][legendKey]
const textItem = data[i][textKey]
const dataItem = data[i][dataKey]
// 图例
if (!legendData.includes(legendItem)) {
legendData.push(legendItem)
}
// 系列
let targetSeries = seriesData.find(s => s.name === legendItem)
if (!targetSeries) {
targetSeries = {
name: legendItem,
value: [],
_raw: []
}
seriesData.push(targetSeries)
}
targetSeries.value.push(dataItem)
targetSeries._raw.push(data[i])
// 指标
let targetIndicator = indicator.find(i => i.name === textItem)
if (!targetIndicator) {
indicator.push({ name: textItem })
}
}
return { title, seriesData, legendData, indicator }
}
/**
* 绘制图表
*/
apply () {
const { title, seriesData, legendData = [], indicator } = this.options
this.echart.setOption({
title: {
text: title
},
tooltip: {},
legend: {
data: legendData
},
radar: {
name: {
textStyle: {
color: '#fff',
backgroundColor: '#999',
borderRadius: 3,
padding: [3, 5]
}
},
indicator
},
series: [{
type: TYPE,
data: seriesData
}]
}, true)
}
}
/*
* 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 Base from '../base'
import { checkKeyInModel, init } from '../../common'
const TYPE = 'scatter'
/**
* 气泡图
*/
export default class Scatter extends Base {
/**
* 单独导出时调用的初始化方法
* @param {*} el 选择器或者 DOM 对象
* @param {*} data 数据源
* @param {*} options 可选项
*/
static init (el, data, options) {
return init(Scatter, el, data, options)
}
/**
* 将用户配置转换为符合 ECharts API 格式的配置格式
*/
transform () {
const {
// 数据
data = [],
// 图表标题
title = '气泡图',
// 属性字典
keyMap = {
xKey: 'x',
yKey: 'y',
sizeKey: 'size',
textKey: 'text',
legendKey: 'typeName'
}
} = this.settings
if (data.length === 0) {
throw new Error('数据源为空!')
}
const legendData = []
const series = []
const { xKey, yKey, sizeKey, textKey, legendKey } = keyMap
checkKeyInModel(data[0], xKey, yKey, sizeKey, textKey, legendKey)
for (let i = 0; i < data.length; i++) {
const {
[legendKey]: legendItem,
[xKey]: xValue,
[yKey]: yValue,
[sizeKey]: sizeValue,
[textKey]: textValue,
...other
} = data[i]
// 图例
if (!legendData.includes(legendItem)) {
legendData.push(legendItem)
}
// 系列
let targetSeries = series.find(s => s.name === legendItem)
if (!targetSeries) {
targetSeries = {
type: TYPE,
name: legendItem,
data: [],
symbolSize: function (data) {
return Math.sqrt(data[2])
},
label: {
emphasis: {
show: true,
formatter: function (param) {
return param.data[3]
},
position: 'top'
}
}
}
series.push(targetSeries)
}
targetSeries.data.push({
value: [
xValue,
yValue,
sizeValue,
textValue
],
...other,
_raw: data[i]
})
}
return { title, series, legendData }
}
/**
* 绘制图表
*/
apply () {
const { title, series, legendData = [] } = this.options
let {
// 自定义 x 轴
xAxis,
// 自定义 y 轴
yAxis,
// 注入配置到 series
insertSeries
} = this.settings
let _series = series
if (insertSeries && insertSeries.length && series.length) {
_series = this.injectDataIntoSeries(insertSeries, _series)
}
this.echart.setOption({
title: {
text: title
},
legend: {
right: 10,
data: legendData
},
xAxis: xAxis || {},
yAxis: yAxis || {},
series: _series
}, true)
}
}
# ana-charts
echarts 扩展
## 安装
```
npm i @analysys/ana-charts
```
## 特性
- 统一的数据结构
- 支持 ECharts 原生操作
## 快速开始
### 全量导入
```html
<template>
<div>
<div id="chart" style="height:500px"></div>
</div>
</template>
<script>
import Chart from '@analysys/ana-charts'
export default {
mounted () {
Chart.line('#chart', [
{ key: 'Monday', value: 1 },
{ key: 'Tuesday', value: 2 },
{ key: 'Wednesday', value: 3 }
])
}
}
</script>
```
### 按需导入
```html
<template>
<div>
<div id="chart" style="height:500px"></div>
</div>
</template>
<script>
import { Line } from '@analysys/ana-charts'
export default {
mounted () {
Line.init('#chart', [
{ key: 'Monday', value: 1 },
{ key: 'Tuesday', value: 2 },
{ key: 'Wednesday', value: 3 }
])
}
}
</script>
```
## APIs
### 一般用法
``` js
const myChart = Chart.line(el, data, options)
// const myChart = Chart.bar(el, data, options)
// const myChart = Chart.pie(el, data, options)
// const myChart = Chart.radar(el, data, options)
// const myChart = Chart.funnel(el, data, options)
// const myChart = Chart.scatter(el, data, options)
// 刷新数据
myChart.setData(data)
```
### 注入属性
``` js
// 以 line 折线图为例,bar、funnel、pie、scatter 均可使用
Chart.line(el, data, {
insertSeries: [
{
// index 可选 `all`,`start`,`end`,也可指定需要被注入的索引数组,如 [0, 2, 4]
index: 'all',
// 以下属性会被注入到指定的序列中
areaStyle: {}
}
]
})
```
### ECharts 对象
> 初始化图表后返回的对象上保存了 ECharts 对象的引用,可以通过该属性来设置图表配置和监听事件
``` js
const myChart = Chart.line(el, data, options)
// 设置可配置项
myChart.echart.setOption({
// 与 ECharts 参考文档用法一致
})
```
### 折线图
#### 基本用法
``` js
Chart.line('#chart', [
{ key: 'Monday', value: 1 },
{ key: 'Tuesday', value: 2 },
{ key: 'Wednesday', value: 3 },
...
])
```
#### 多条折线图
``` js
Chart.line('#chart', [
{ typeName: 'apple', key: 'Monday', value: 1 },
{ typeName: 'apple', key: 'Tuesday', value: 2 },
{ typeName: 'apple', key: 'Wednesday', value: 3 },
{ typeName: 'pear', key: 'Monday', value: 11 },
{ typeName: 'pear', key: 'Tuesday', value: 21 },
{ typeName: 'pear', key: 'Wednesday', value: 31 },
{ typeName: 'banana', key: 'Monday', value: 31 },
{ typeName: 'banana', key: 'Tuesday', value: 32 },
{ typeName: 'banana', key: 'Wednesday', value: 33 },
...
])
```
#### options 可配置参数
| 属性 | 说明 | required | 类型 | 默认值 |
| :----| :------| :--------| :---:| :------|
| title | 图表标题 | - | String | '单条折线图' 或 '多条折线图' |
| keyMap | 数据列表的属性字典 | - | Object | 详见后续属性 |
| keyMap.xAxisKey | x 轴对应的属性名称 | - | String | 'key' |
| keyMap.dataKey | 数据值对应的属性名称 | - | String | 'value' |
| keyMap.legendKey | 图例对应的属性名称 | - | String | 'typeName' |
| reverseAxis | 是否为横向图 | - | Boolean | false |
### 柱状图
#### 基本用法
``` js
Chart.bar('#chart', [
{ key: 'Monday', value: 1 },
{ key: 'Tuesday', value: 2 },
{ key: 'Wednesday', value: 3 },
...
])
```
#### 多条柱状图
``` js
Chart.bar('#chart', [
{ typeName: 'apple', key: 'Monday', value: 1 },
{ typeName: 'apple', key: 'Tuesday', value: 2 },
{ typeName: 'apple', key: 'Wednesday', value: 3 },
{ typeName: 'pear', key: 'Monday', value: 11 },
{ typeName: 'pear', key: 'Tuesday', value: 21 },
{ typeName: 'pear', key: 'Wednesday', value: 31 },
{ typeName: 'banana', key: 'Monday', value: 31 },
{ typeName: 'banana', key: 'Tuesday', value: 32 },
{ typeName: 'banana', key: 'Wednesday', value: 33 },
...
])
```
#### 折柱混合图
``` js
Chart.bar('#chart', [
{ typeName: 'apple', key: 'Monday', value: 1 },
{ typeName: 'apple', key: 'Tuesday', value: 2 },
{ typeName: 'apple', key: 'Wednesday', value: 3 },
{ typeName: 'pear', key: 'Monday', value: 11 },
{ typeName: 'pear', key: 'Tuesday', value: 21 },
{ typeName: 'pear', key: 'Wednesday', value: 31 },
{ typeName: 'banana', key: 'Monday', value: 31 },
{ typeName: 'banana', key: 'Tuesday', value: 32 },
{ typeName: 'banana', key: 'Wednesday', value: 33 },
...
], {
lineTypes: ['banana']
})
```
#### 时间轴柱状图
``` js
Chart.bar('#chart', [
{ timeline: 2015, typeName: 'apple', key: 'Monday', value: 1 },
{ timeline: 2015, typeName: 'apple', key: 'Tuesday', value: 2 },
{ timeline: 2015, typeName: 'apple', key: 'Wednesday', value: 3 },
{ timeline: 2015, typeName: 'pear', key: 'Monday', value: 11 },
{ timeline: 2015, typeName: 'pear', key: 'Tuesday', value: 21 },
{ timeline: 2015, typeName: 'pear', key: 'Wednesday', value: 31 },
{ timeline: 2015, typeName: 'banana', key: 'Monday', value: 31 },
{ timeline: 2015, typeName: 'banana', key: 'Tuesday', value: 32 },
{ timeline: 2015, typeName: 'banana', key: 'Wednesday', value: 33 },
{ timeline: 2016, typeName: 'apple', key: 'Monday', value: 1 },
{ timeline: 2016, typeName: 'apple', key: 'Tuesday', value: 2 },
{ timeline: 2016, typeName: 'apple', key: 'Wednesday', value: 3 },
{ timeline: 2016, typeName: 'pear', key: 'Monday', value: 11 },
{ timeline: 2016, typeName: 'pear', key: 'Tuesday', value: 21 },
{ timeline: 2016, typeName: 'pear', key: 'Wednesday', value: 31 },
{ timeline: 2016, typeName: 'banana', key: 'Monday', value: 31 },
{ timeline: 2016, typeName: 'banana', key: 'Tuesday', value: 32 },
{ timeline: 2016, typeName: 'banana', key: 'Wednesday', value: 33 },
...
], {
// 可以使用 $timeline 进行占位,该字符串将替换为 timeline 属性的值
title: '$timeline时间轴柱状图'
})
```
#### options 可配置参数
| 属性 | 说明 | required | 类型 | 默认值 |
| :----| :------| :--------| :---:| :------|
| title | 图表标题 | - | String | '单条柱状图' 或 '多条柱状图' |
| keyMap | 数据列表的属性字典 | - | Object | 详见后续属性 |
| keyMap.xAxisKey | x 轴对应的属性名称 | - | String | 'key' |
| keyMap.dataKey | 数据值对应的属性名称 | - | String | 'value' |
| keyMap.legendKey | 图例对应的属性名称 | - | String | 'typeName' |
| keyMap.timelineKey | 时间轴对应的属性名称 | - | String | 'timeline' |
| reverseAxis | 是否为横向图 | - | Boolean | false |
| stack | 是否为堆叠图 | - | Boolean | false |
| lineTypes | 折柱混合图中折线数据对应的图例名称数组 | - | Array | - |
| yAxis | 自定义的 y 轴,请参考 echarts 配置 | - | Object | - |
### 饼状图
#### 基本用法
``` js
Chart.pie('#chart', [
{ key: 'Monday', value: 1 },
{ key: 'Tuesday', value: 2 },
{ key: 'Wednesday', value: 3 },
...
])
```
#### 环形图
``` js
Chart.pie('#chart', [
{ key: 'Monday', value: 1 },
{ key: 'Tuesday', value: 2 },
{ key: 'Wednesday', value: 3 },
...
], {
ring: true
})
```
#### options 可配置参数
| 属性 | 说明 | required | 类型 | 默认值 |
| :----| :------| :--------| :---:| :------|
| title | 图表标题 | - | String | '饼图' |
| keyMap | 数据列表的属性字典 | - | Object | 详见后续属性 |
| keyMap.textKey | 文本对应的属性名称 | - | String | 'key' |
| keyMap.dataKey | 数据值对应的属性名称 | - | String | 'value' |
| ring | 是否环形图 | - | Boolean | false |
### 雷达图
#### 基本用法
``` js
Chart.radar('#chart', [
{ typeName: 'apple', key: 'Monday', value: 1 },
{ typeName: 'apple', key: 'Tuesday', value: 2 },
{ typeName: 'apple', key: 'Wednesday', value: 3 },
{ typeName: 'pear', key: 'Monday', value: 11 },
{ typeName: 'pear', key: 'Tuesday', value: 21 },
{ typeName: 'pear', key: 'Wednesday', value: 31 },
{ typeName: 'banana', key: 'Monday', value: 31 },
{ typeName: 'banana', key: 'Tuesday', value: 32 },
{ typeName: 'banana', key: 'Wednesday', value: 33 },
...
])
```
#### options 可配置参数
| 属性 | 说明 | required | 类型 | 默认值 |
| :----| :------| :--------| :---:| :------|
| title | 图表标题 | - | String | '雷达图' |
| keyMap | 数据列表的属性字典 | - | Object | 详见后续属性 |
| keyMap.textKey | 指标对应的属性名称 | - | String | 'key' |
| keyMap.dataKey | 数据值对应的属性名称 | - | String | 'value' |
| keyMap.legendKey | 图例对应的属性名称 | - | String | 'typeName' |
### 漏斗图
#### 基本用法
``` js
Chart.funnel('#chart', [
{ key: 'Monday', value: 1 },
{ key: 'Tuesday', value: 2 },
{ key: 'Wednesday', value: 3 },
...
])
```
#### options 可配置参数
| 属性 | 说明 | required | 类型 | 默认值 |
| :----| :------| :--------| :---:| :------|
| title | 图表标题 | - | String | '漏斗图' |
| keyMap | 数据列表的属性字典 | - | Object | 详见后续属性 |
| keyMap.textKey | 文本对应的属性名称 | - | String | 'key' |
| keyMap.dataKey | 数据值对应的属性名称 | - | String | 'value' |
### 气泡图
#### 基本用法
``` js
Chart.scatter('#chart', [
{ typeName: 'apple', text: 'Monday', x: 1, y: 1, size: 1 },
{ typeName: 'apple', text: 'Tuesday', x: 2, y: 2, size: 2 },
{ typeName: 'apple', text: 'Wednesday', x: 3, y: 3, size: 3 },
{ typeName: 'pear', text: 'Monday', x: 11, y: 11, size: 11 },
{ typeName: 'pear', text: 'Tuesday', x: 21, y: 21, size: 21 },
{ typeName: 'pear', text: 'Wednesday', x: 31, y: 31, size: 31 },
{ typeName: 'banana', text: 'Monday', x: 31, y: 31, size: 31 },
{ typeName: 'banana', text: 'Tuesday', x: 32, y: 32, size: 32 },
{ typeName: 'banana', text: 'Wednesday', x: 33, y: 33, size: 33 },
...
])
```
#### options 可配置参数
| 属性 | 说明 | required | 类型 | 默认值 |
| :----| :------| :--------| :---:| :------|
| title | 图表标题 | - | String | '气泡图' |
| keyMap | 数据列表的属性字典 | - | Object | 详见后续属性 |
| keyMap.xKey | x 坐标对应的属性名称 | - | String | 'x' |
| keyMap.yKey | y 坐标对应的属性名称 | - | String | 'y' |
| keyMap.sizeKey | 气泡大小对应的属性名称 | - | String | 'size' |
| keyMap.textKey | 气泡文本对应的属性名称 | - | String | 'text' |
| keyMap.legendKey | 图例对应的属性名称 | - | String | 'typeName' |
### 全局配置
#### 主题
注册并按需使用
``` js
import themeData from './theme.json'
// 注册主题
Chart.config({
theme: {
name: 'themeName',
data: themeData
}
})
// 使用主题
Chart.line('#chart', data, { theme: 'themeName' })
```
注册并全局使用
``` js
import themeData from './theme.json'
// 注册为默认主题后,所有的图表均使用该主题,不需要特别指定
Chart.config({
theme: {
name: 'themeName',
data: themeData,
default: true
}
})
```
### 实例 API
| 方法 | 说明 | 参数 | 参数类型 | 返回值 |
| :----| :------| :--------| :---:| :------|
| setData | 重新设置数据 | data | Array | - |
## License
[MIT](http://opensource.org/licenses/MIT)
/**
* webpack config
*
* author: liuxin(liuxin@analysys.com.cn)
*/
const path = require('path')
const glob = require('globby')
const isProduction = process.env.NODE_ENV !== 'development'
const resolve = dir => path.join(__dirname, '..', dir)
const assetsDir = resolve('src')
const distDir = resolve('dist')
const baseConfig = {
entry: {
'index': glob.sync(['index.js'], { cwd: assetsDir })
},
output: {
path: distDir
},
module: {
rules: [
{
test: /\.js$/,
exclude: file => (
/node_modules/.test(file) &&
!/\.vue\.js/.test(file)
),
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
cacheIdentifier: true
}
}
]
}
]
},
resolve: {
modules: [
resolve('node_modules'),
resolve('src')
],
extensions: ['.js', '.json', '.vue', '.scss']
},
externals: {
'vue': 'Vue',
'echarts': 'echarts'
}
}
module.exports = {
isProduction,
assetsDir,
distDir,
baseConfig
}
/**
* webpack config for production
*
* author: liuxin(liuxin@analysys.com.cn)
*/
const webpack = require('webpack')
const merge = require('webpack-merge')
const { baseConfig } = require('./config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const config = merge.smart(baseConfig, {
devtool: 'source-map',
output: {
filename: '[name].js',
libraryTarget: 'umd',
umdNamedDefine: false
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
hotReload: false
}
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
use: [
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: (loader) => [
require('autoprefixer')({
'browsers': ['ie > 8', 'last 2 version', 'safari >= 9']
}),
require('cssnano')
]
}
}
],
fallback: ['vue-style-loader']
})
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
use: [
'css-loader',
'sass-loader',
{
loader: 'postcss-loader',
options: {
plugins: (loader) => [
require('autoprefixer')({
'browsers': ['ie > 8', 'last 2 version', 'safari >= 9']
}),
require('cssnano')
]
}
}
],
fallback: ['vue-style-loader']
})
}
]
},
plugins: [
new VueLoaderPlugin(),
new ExtractTextPlugin({ filename: '[name].css', allChunks: true }),
new webpack.optimize.OccurrenceOrderPlugin(),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano'),
cssProcessorOptions: { discardComments: { removeAll: true } },
canPrint: true
}),
new UglifyJSPlugin({
parallel: true,
sourceMap: true,
uglifyOptions: {
compress: {
drop_console: true,
drop_debugger: true
},
comments: function (n, c) {
/*! IMPORTANT: Please preserve 3rd-party library license info, inspired from @allex/amd-build-worker/config/util.js */
var text = c.value, type = c.type
if (type === 'comment2') {
return /^!|@preserve|@license|@cc_on|MIT/i.test(text)
}
}
}
})
]
})
module.exports = config
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("echarts"));else if("function"==typeof define&&define.amd)define(["echarts"],t);else{var n="object"==typeof exports?t(require("echarts")):t(e.echarts);for(var i in n)("object"==typeof exports?exports:e)[i]=n[i]}}("undefined"!=typeof self?self:this,function(e){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:i})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=4)}([function(e,t,n){"use strict";t.__esModule=!0;t.init=function(e,t,n,i){var r=function(e){if(!e)return;if("string"==typeof e)if(e.startsWith("#"))e=document.getElementById(e.slice(1));else{if(!e.startsWith("."))return;e=document.getElementsByClassName(e.slice(1))}if(!e)throw new Error("找不到对应的dom对象!");var t=void 0;t=HTMLElement.prototype.isPrototypeOf(e)?new Array(e):Array.from(e);if(!t)throw new Error("未找到对应的dom对象!");return t}(t),a=Object.assign({},{data:n},i),o=r.map(function(t){return new e(t,a)});return 1===o.length?o[0]:o};t.checkKeyInModel=function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),i=1;i<t;i++)n[i-1]=arguments[i];var r=n,a=Array.isArray(r),o=0;for(r=a?r:r[Symbol.iterator]();;){var s;if(a){if(o>=r.length)break;s=r[o++]}else{if((o=r.next()).done)break;s=o.value}var l=s;if(!e.hasOwnProperty(l))throw new Error("数据格式错误!未找到指定属性:"+l)}}},function(e,t,n){"use strict";t.__esModule=!0;var i=a(n(3)),r=a(n(2));function a(e){return e&&e.__esModule?e:{default:e}}var o=function(){function e(t,n){var a=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.settings=n;var o=this.transform();o&&(this.options=o,n.theme?this.echart=i.default.init(t,n.theme):r.default.settings.defaultTheme?this.echart=i.default.init(t,r.default.settings.defaultTheme):this.echart=i.default.init(t),window.addEventListener("resize",function(){return a.echart.resize()}),this.apply())}return e.prototype.setData=function(e){e&&0!==e.length&&(this.settings.data=e,this.options=this.transform(),this.apply())},e.prototype.injectDataIntoSeries=function(e,t){return e.forEach(function(e){if("all"===e.index)delete e.index,t=t.map(function(t){return Object.assign({},t,e)});else if("start"===e.index)delete e.index,t[0]=Object.assign({},t[0],e);else if("end"===e.index)delete e.index,t[t.length-1]=Object.assign({},t[t.length-1],e);else if(Array.isArray(e.index)){var n=e.index,i=Array.isArray(n),r=0;for(n=i?n:n[Symbol.iterator]();;){var a;if(i){if(r>=n.length)break;a=n[r++]}else{if((r=n.next()).done)break;a=r.value}var o=a;t[o]&&(t[o]=Object.assign({},t[o],e))}}}),t},e}();t.default=o},function(e,t,n){"use strict";t.__esModule=!0,t.Scatter=t.Funnel=t.Radar=t.Pie=t.Bar=t.Line=void 0;var i=c(n(3)),r=c(n(5)),a=c(n(6)),o=c(n(7)),s=c(n(8)),l=c(n(9)),u=c(n(10)),f=n(0);function c(e){return e&&e.__esModule?e:{default:e}}var p={Line:r.default,Bar:a.default,Pie:o.default,Radar:s.default,Funnel:l.default,Scatter:u.default},d={settings:{},config:function(e){var t=e.theme;t&&((0,f.checkKeyInModel)(t,"name","data"),i.default.registerTheme(t.name,t.data),t.default&&(d.settings.defaultTheme=t.name))}},h=function(e){p.hasOwnProperty(e)&&(d[e.toLowerCase()]=function(t,n,i){return(0,f.init)(p[e],t,n,i)})};for(var y in p)h(y);t.Line=r.default,t.Bar=a.default,t.Pie=o.default,t.Radar=s.default,t.Funnel=l.default,t.Scatter=u.default,t.default=d,"undefined"!=typeof window&&(window.Chart=d)},function(t,n){t.exports=e},function(e,t,n){e.exports=n(2)},function(e,t,n){"use strict";t.__esModule=!0;var i,r=n(1),a=(i=r)&&i.__esModule?i:{default:i},o=n(0);var s=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,e.apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.init=function(e,n,i){return(0,o.init)(t,e,n,i)},t.prototype.transform=function(){var e=this.settings.data,t=void 0===e?[]:e;if(0===t.length)throw new Error("数据源为空!");return Object.keys(t[0]).length>2?this.setMultipleLines():(this.simple=!0,this.setSingleLine())},t.prototype.setSingleLine=function(){var e=this.settings,t=e.data,n=void 0===t?[]:t,i=e.keyMap,r=void 0===i?{xAxisKey:"key",dataKey:"value"}:i,a=e.title,s=void 0===a?"单条折线图":a,l=r.xAxisKey,u=r.dataKey;(0,o.checkKeyInModel)(n[0],l,u);for(var f=[{type:"line",data:[]}],c={type:"category",data:[]},p=0;p<n.length;p++)c.data.push(n[p][l]),f[0].data.push(n[p][u]);return{title:s,xAxis:c,series:f}},t.prototype.setMultipleLines=function(){var e=this.settings,t=e.data,n=void 0===t?[]:t,i=e.keyMap,r=void 0===i?{xAxisKey:"key",legendKey:"typeName",dataKey:"value"}:i,a=e.title,s=void 0===a?"多条折线图":a,l=r.xAxisKey,u=r.legendKey,f=r.dataKey;(0,o.checkKeyInModel)(n[0],l,u,f);for(var c=[],p=[],d={type:"category",data:[]},h=function(e){var t=n[e][u],i=n[e][l],r=n[e][f];c.includes(t)||c.push(t),d.data.includes(i)||d.data.push(i);var a=p.find(function(e){return e.name===t});a||(a={name:t,type:"line",data:[]},p.push(a)),a.data.push(r)},y=0;y<n.length;y++)h(y);return{title:s,xAxis:d,series:p,legendData:c}},t.prototype.apply=function(){var e=this.options,t=e.title,n=e.xAxis,i=e.series,r=e.legendData,a=void 0===r?[]:r,o=this.settings.reverseAxis,s=void 0!==o&&o,l={type:"value"},u=s?n:l,f=s?l:n,c=!t&&this.simple?"3%":60,p=this.settings.insertSeries,d=i;p&&p.length&&i.length&&(d=this.injectDataIntoSeries(p,d)),this.echart.setOption({title:{text:t},tooltip:{trigger:"axis"},grid:{left:"3%",right:"4%",bottom:"3%",top:c,containLabel:!0},legend:{data:a},xAxis:f,yAxis:u,series:d},!0)},t}(a.default);t.default=s},function(e,t,n){"use strict";t.__esModule=!0;var i,r=n(1),a=(i=r)&&i.__esModule?i:{default:i},o=n(0);var s=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,e.apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.init=function(e,n,i){return(0,o.init)(t,e,n,i)},t.prototype.transform=function(){var e=this.settings.data,t=void 0===e?[]:e;if(0===t.length)throw new Error("数据源为空!");return Object.keys(t[0]).length>2?this.setMultipleBars():(this.simple=!0,this.setSingleBar())},t.prototype.setSingleBar=function(){var e=this.settings,t=e.data,n=void 0===t?[]:t,i=e.keyMap,r=void 0===i?{xAxisKey:"key",dataKey:"value"}:i,a=e.title,s=void 0===a?"单条柱状图":a,l=r.xAxisKey,u=r.dataKey;(0,o.checkKeyInModel)(n[0],l,u);for(var f=[{type:"bar",data:[]}],c={type:"category",data:[]},p=0;p<n.length;p++)c.data.push(n[p][l]),f[0].data.push(n[p][u]);return{title:s,xAxis:c,series:f}},t.prototype.setMultipleBars=function(){var e=this.settings,t=e.data,n=void 0===t?[]:t,i=e.keyMap,r=void 0===i?{xAxisKey:"key",legendKey:"typeName",dataKey:"value"}:i,a=e.title,s=void 0===a?"多条柱状图":a,l=e.lineTypes,u=r.xAxisKey,f=r.legendKey,c=r.dataKey,p=4===Object.keys(n[0]).length,d=r.timelineKey||"timeline";p?(0,o.checkKeyInModel)(n[0],u,f,c,d):(0,o.checkKeyInModel)(n[0],u,f,c);var h=[];l&&(h=Array.isArray(l)?l:[l]);for(var y={timeline:{axisType:"category",autoPlay:!0,playInterval:1e3,data:[]},options:[]},v=[],g=[],b={type:"category",data:[]},m=function(e){var t=n[e][f],i=n[e][u],r=n[e][c];if(v.includes(t)||v.push(t),b.data.includes(i)||b.data.push(i),p){var a=n[e][d];if(y.timeline.data.includes(a)||y.timeline.data.push(a),!g.some(function(e){return e.name===t})){var o="bar";0!==h.length&&h.includes(t)&&(o="line"),g.push({name:t,type:o})}var l=y.options.find(function(e){return e._helpName===a});l||(l={_helpName:a,title:{text:s.replace("$timeline",a)},series:[]},y.options.push(l));var m=l.series.find(function(e){return e._helpName===t});m||(m={_helpName:t,data:[]},l.series.push(m)),m.data.push(r)}else{var x=g.find(function(e){return e.name===t});if(!x){var w="bar";0!==h.length&&h.includes(t)&&(w="line"),x={name:t,type:w,data:[]},g.push(x)}x.data.push(r)}},x=0;x<n.length;x++)m(x);return p?{title:s,xAxis:b,series:g,legendData:v,timelineOptions:y}:{title:s,xAxis:b,series:g,legendData:v}},t.prototype.apply=function(){var e=this.options,t=e.title,n=e.xAxis,i=e.series,r=e.legendData,a=e.timelineOptions,o=this.settings,s=o.reverseAxis,l=void 0!==s&&s,u=o.yAxis,f=o.stack,c={type:"value"},p=l?n:c,d=l?c:n;u&&(p=u),void 0!==f&&f&&i.forEach(function(e){e.stack="总量",e.label={normal:{show:!0,position:l?"insideRight":"insideTop"}}});var h=this.settings.insertSeries,y=i;if(h&&h.length&&i.length&&(y=this.injectDataIntoSeries(h,y)),a)this.echart.setOption({baseOption:{timeline:a.timeline,tooltip:{trigger:"axis"},grid:{top:80,bottom:100,containLabel:!0},legend:{x:"right",data:r},xAxis:d,yAxis:p,series:y},options:a.options},!0);else{var v=!t&&this.simple?"3%":60;this.echart.setOption({title:{text:t},tooltip:{trigger:"axis"},grid:{left:"3%",right:"4%",bottom:"3%",top:v,containLabel:!0},legend:{data:r},xAxis:d,yAxis:p,series:y},!0)}},t}(a.default);t.default=s},function(e,t,n){"use strict";t.__esModule=!0;var i,r=n(1),a=(i=r)&&i.__esModule?i:{default:i},o=n(0);function s(e,t){var n={};for(var i in e)t.indexOf(i)>=0||Object.prototype.hasOwnProperty.call(e,i)&&(n[i]=e[i]);return n}var l=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,e.apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.init=function(e,n,i){return(0,o.init)(t,e,n,i)},t.prototype.transform=function(){var e=this.settings,t=e.data,n=void 0===t?[]:t,i=e.title,r=void 0===i?"饼图":i,a=e.ring,l=void 0!==a&&a,u=e.keyMap,f=void 0===u?{textKey:"key",dataKey:"value"}:u;if(0===n.length)throw new Error("数据源为空!");var c=f.textKey,p=f.dataKey;(0,o.checkKeyInModel)(n[0],c,p);for(var d=[{radius:l?["50%","70%"]:"60%",center:r?["50%","60%"]:["50%","50%"],type:"pie",data:[]}],h=0;h<n.length;h++){var y=n[h],v=y[p],g=y[c],b=s(y,[p,c]),m=Object.assign({value:v,name:g},b,{_raw:y});d[0].data.push(m)}return{title:r,series:d,legendData:[]}},t.prototype.apply=function(){var e=this.options,t=e.title,n=e.series,i=e.legendData,r=this.settings.insertSeries,a=n;r&&r.length&&n.length&&(a=this.injectDataIntoSeries(r,a)),this.echart.setOption({title:{text:t,x:"center"},tooltip:{trigger:"item",formatter:"{b} : {c} ({d}%)"},legend:{orient:"vertical",left:"left",data:i},series:a},!0)},t}(a.default);t.default=l},function(e,t,n){"use strict";t.__esModule=!0;var i,r=n(1),a=(i=r)&&i.__esModule?i:{default:i},o=n(0);var s=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,e.apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.init=function(e,n,i){return(0,o.init)(t,e,n,i)},t.prototype.transform=function(){var e=this.settings,t=e.data,n=void 0===t?[]:t,i=e.title,r=void 0===i?"雷达图":i,a=e.keyMap,s=void 0===a?{textKey:"key",legendKey:"typeName",dataKey:"value"}:a;if(0===n.length)throw new Error("数据源为空!");var l=s.textKey,u=s.legendKey,f=s.dataKey;(0,o.checkKeyInModel)(n[0],l,u,f);for(var c=[],p=[],d=[],h=function(e){var t=n[e][u],i=n[e][l],r=n[e][f];c.includes(t)||c.push(t);var a=p.find(function(e){return e.name===t});a||(a={name:t,value:[],_raw:[]},p.push(a)),a.value.push(r),a._raw.push(n[e]),d.find(function(e){return e.name===i})||d.push({name:i})},y=0;y<n.length;y++)h(y);return{title:r,seriesData:p,legendData:c,indicator:d}},t.prototype.apply=function(){var e=this.options,t=e.title,n=e.seriesData,i=e.legendData,r=void 0===i?[]:i,a=e.indicator;this.echart.setOption({title:{text:t},tooltip:{},legend:{data:r},radar:{name:{textStyle:{color:"#fff",backgroundColor:"#999",borderRadius:3,padding:[3,5]}},indicator:a},series:[{type:"radar",data:n}]},!0)},t}(a.default);t.default=s},function(e,t,n){"use strict";t.__esModule=!0;var i,r=n(1),a=(i=r)&&i.__esModule?i:{default:i},o=n(0);function s(e,t){var n={};for(var i in e)t.indexOf(i)>=0||Object.prototype.hasOwnProperty.call(e,i)&&(n[i]=e[i]);return n}var l=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,e.apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.init=function(e,n,i){return(0,o.init)(t,e,n,i)},t.prototype.transform=function(){var e=this.settings,t=e.data,n=void 0===t?[]:t,i=e.title,r=void 0===i?"漏斗图":i,a=e.keyMap,l=void 0===a?{textKey:"key",dataKey:"value"}:a;if(0===n.length)throw new Error("数据源为空!");var u=l.textKey,f=l.dataKey;(0,o.checkKeyInModel)(n[0],u,f);for(var c=[{type:"funnel",left:"10%",top:60,bottom:60,width:"80%",min:0,max:100,minSize:"0%",maxSize:"100%",sort:"descending",gap:2,label:{normal:{show:!0,position:"inside"},emphasis:{textStyle:{fontSize:20}}},labelLine:{normal:{length:10,lineStyle:{width:1,type:"solid"}}},itemStyle:{normal:{borderColor:"#fff",borderWidth:1}},data:[]}],p=0;p<n.length;p++){var d=n[p],h=d[f],y=d[u],v=s(d,[f,u]),g=Object.assign({value:h,name:y},v,{_raw:d});c[0].data.push(g)}return{title:r,series:c,legendData:[]}},t.prototype.apply=function(){var e=this.options,t=e.title,n=e.series,i=e.legendData,r=this.settings.insertSeries,a=n;r&&r.length&&n.length&&(a=this.injectDataIntoSeries(r,a)),this.echart.setOption({title:{text:t},tooltip:{trigger:"item",formatter:"{a} <br/>{b} : {c}%"},legend:{data:i},series:a},!0)},t}(a.default);t.default=l},function(e,t,n){"use strict";t.__esModule=!0;var i,r=n(1),a=(i=r)&&i.__esModule?i:{default:i},o=n(0);var s=function(e){function t(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,e.apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.init=function(e,n,i){return(0,o.init)(t,e,n,i)},t.prototype.transform=function(){var e=this.settings,t=e.data,n=void 0===t?[]:t,i=e.title,r=void 0===i?"气泡图":i,a=e.keyMap,s=void 0===a?{xKey:"x",yKey:"y",sizeKey:"size",textKey:"text",legendKey:"typeName"}:a;if(0===n.length)throw new Error("数据源为空!");var l=[],u=[],f=s.xKey,c=s.yKey,p=s.sizeKey,d=s.textKey,h=s.legendKey;(0,o.checkKeyInModel)(n[0],f,c,p,d,h);for(var y=function(e){var t=n[e],i=t[h],r=t[f],a=t[c],o=t[p],s=t[d],y=function(e,t){var n={};for(var i in e)t.indexOf(i)>=0||Object.prototype.hasOwnProperty.call(e,i)&&(n[i]=e[i]);return n}(t,[h,f,c,p,d]);l.includes(i)||l.push(i);var v=u.find(function(e){return e.name===i});v||(v={type:"scatter",name:i,data:[],symbolSize:function(e){return Math.sqrt(e[2])},label:{emphasis:{show:!0,formatter:function(e){return e.data[3]},position:"top"}}},u.push(v)),v.data.push(Object.assign({value:[r,a,o,s]},y,{_raw:n[e]}))},v=0;v<n.length;v++)y(v);return{title:r,series:u,legendData:l}},t.prototype.apply=function(){var e=this.options,t=e.title,n=e.series,i=e.legendData,r=void 0===i?[]:i,a=this.settings.insertSeries,o=n;a&&a.length&&n.length&&(o=this.injectDataIntoSeries(a,o)),this.echart.setOption({title:{text:t},legend:{right:10,data:r},xAxis:{},yAxis:{},series:o},!0)},t}(a.default);t.default=s}])});
//# sourceMappingURL=index.js.map
\ No newline at end of file
<template>
<div class="app-container">
<div class="left">
<ul class="sidebar">
<li v-for="(link, i) in links" :key="i">
<router-link :to="link.url">{{link.name}}</router-link>
<ul class="sub" v-if="link.subs">
<li v-for="(sub, j) in link.subs" :key="j">
<router-link :to="sub.url">{{sub.name}}</router-link>
</li>
</ul>
</li>
</ul>
</div>
<div class="right">
<router-view />
</div>
</div>
</template>
<script>
import './styles/main.scss'
export default {
name: 'App',
data () {
return {
links: [
{
name: '折线图',
url: '/line',
subs: [
{ name: '单条折线图', url: '/line#simple' },
{ name: '多条折线图', url: '/line#multiple' },
{ name: '横向折线图', url: '/line#reverse' }
]
},
{
name: '柱状图',
url: '/bar',
subs: [
{ name: '单条柱状图', url: '/bar#simple' },
{ name: '多条柱状图', url: '/bar#multiple' },
{ name: '横向柱状图', url: '/bar#reverse' },
{ name: '折柱混合图', url: '/bar#mixin' },
{ name: '堆叠柱状图', url: '/bar#stack' },
{ name: '时间轴柱状图', url: '/bar#timeline' }
]
},
{
name: '饼状图',
url: '/pie',
subs: [
{ name: '简单饼状图', url: '/pie#simple' },
{ name: '环形图', url: '/pie#ring' }
]
},
{
name: '雷达图',
url: '/radar',
subs: [
{ name: '简单雷达图', url: '/radar#simple' }
]
},
{
name: '漏斗图',
url: '/funnel',
subs: [
{ name: '简单漏斗图', url: '/funnel#simple' }
]
},
{
name: '气泡图',
url: '/scatter',
subs: [
{ name: '气泡图', url: '/scatter#simple' }
]
}
]
}
}
}
</script>
<style lang="scss">
</style>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name=viewport content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1">
<title>demo</title>
</head>
<body>
<div id="app"></div>
<script src="./index.js"></script>
</body>
</html>
import Vue from 'vue'
import router from './router'
import App from './app.vue'
new Vue({
el: '#app',
router,
render: h => h(App),
mounted () {
if (this.$route.path === '/') {
this.$router.push('/line')
}
}
})
export const getTimelineList = () => {
const list = []
for (let i = 2008; i < 2018; i++) {
let index = 0
for (const key of keys) {
for (const day of days) {
list.push({
timeline: i,
typeName: key,
key: day,
value: Math.floor(Math.random() * 100 + (index + 1) * 100)
})
index++
}
}
}
return list
}
export const getSimpleList = () => {
const list = []
for (const key of keys) {
list.push({
key: key,
value: Math.floor(Math.random() * 100)
})
}
return list
}
export const getMultipleList = (scatter = false) => {
const list = []
let index = 0
for (const key of keys) {
for (const day of days) {
if (scatter) {
list.push({
typeName: key,
text: day,
x: Math.floor(Math.random() * 100 + (index + 1) * 100),
y: Math.floor(Math.random() * 100 + (index + 1) * 100),
size: Math.floor(Math.random() * 1000)
})
} else {
list.push({
typeName: key,
key: day,
value: Math.floor(Math.random() * 100 + (index + 1) * 100)
})
}
}
index++
}
return list
}
const keys = ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
const days = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
{
"color": [
"#fc97af",
"#87f7cf",
"#f7f494",
"#72ccff",
"#f7c5a0",
"#d4a4eb",
"#d2f5a6",
"#76f2f2"
],
"backgroundColor": "rgba(41,52,65,1)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#ffffff"
},
"subtextStyle": {
"color": "#dddddd"
}
},
"line": {
"itemStyle": {
"normal": {
"borderWidth": "4"
}
},
"lineStyle": {
"normal": {
"width": "3"
}
},
"symbolSize": "0",
"symbol": "circle",
"smooth": true
},
"radar": {
"itemStyle": {
"normal": {
"borderWidth": "4"
}
},
"lineStyle": {
"normal": {
"width": "3"
}
},
"symbolSize": "0",
"symbol": "circle",
"smooth": true
},
"bar": {
"itemStyle": {
"normal": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
},
"emphasis": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
}
},
"pie": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"scatter": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"boxplot": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"parallel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"sankey": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"funnel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"gauge": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"candlestick": {
"itemStyle": {
"normal": {
"color": "#fc97af",
"color0": "transparent",
"borderColor": "#fc97af",
"borderColor0": "#87f7cf",
"borderWidth": "2"
}
}
},
"graph": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"lineStyle": {
"normal": {
"width": "1",
"color": "#ffffff"
}
},
"symbolSize": "0",
"symbol": "circle",
"smooth": true,
"color": [
"#fc97af",
"#87f7cf",
"#f7f494",
"#72ccff",
"#f7c5a0",
"#d4a4eb",
"#d2f5a6",
"#76f2f2"
],
"label": {
"normal": {
"textStyle": {
"color": "#293441"
}
}
}
},
"map": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#999999",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(255,178,72,1)",
"borderColor": "#eb8146",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#893448"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(137,52,72)"
}
}
}
},
"geo": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#999999",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(255,178,72,1)",
"borderColor": "#eb8146",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#893448"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(137,52,72)"
}
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#aaaaaa"
}
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#e6e6e6"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#aaaaaa"
}
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#e6e6e6"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#aaaaaa"
}
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#e6e6e6"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#666666"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#aaaaaa"
}
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#e6e6e6"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"toolbox": {
"iconStyle": {
"normal": {
"borderColor": "#999999"
},
"emphasis": {
"borderColor": "#666666"
}
}
},
"legend": {
"textStyle": {
"color": "#999999"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#cccccc",
"width": 1
},
"crossStyle": {
"color": "#cccccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#87f7cf",
"width": 1
},
"itemStyle": {
"normal": {
"color": "#87f7cf",
"borderWidth": 1
},
"emphasis": {
"color": "#f7f494"
}
},
"controlStyle": {
"normal": {
"color": "#87f7cf",
"borderColor": "#87f7cf",
"borderWidth": 0.5
},
"emphasis": {
"color": "#87f7cf",
"borderColor": "#87f7cf",
"borderWidth": 0.5
}
},
"checkpointStyle": {
"color": "#fc97af",
"borderColor": "rgba(252,151,175,0.3)"
},
"label": {
"normal": {
"textStyle": {
"color": "#87f7cf"
}
},
"emphasis": {
"textStyle": {
"color": "#87f7cf"
}
}
}
},
"visualMap": {
"color": [
"#fc97af",
"#87f7cf"
]
},
"dataZoom": {
"backgroundColor": "rgba(255,255,255,0)",
"dataBackgroundColor": "rgba(114,204,255,1)",
"fillerColor": "rgba(114,204,255,0.2)",
"handleColor": "#72ccff",
"handleSize": "100%",
"textStyle": {
"color": "#333333"
}
},
"markPoint": {
"label": {
"normal": {
"textStyle": {
"color": "#293441"
}
},
"emphasis": {
"textStyle": {
"color": "#293441"
}
}
}
}
}
<template>
<div>
<h1>柱状图示例</h1>
<h2 id="simple">单条柱状图</h2>
<div id="simpleChart" class="chart-container" ></div>
<h2 id="multiple">多条柱状图</h2>
<div id="multipleChart" class="chart-container" ></div>
<h2 id="reverse">横向柱状图</h2>
<div id="reverseChart" class="chart-container tall" ></div>
<h2 id="mixin">折柱混合图</h2>
<div id="mixinChart" class="chart-container tall" ></div>
<h2 id="stack">堆叠柱状图</h2>
<div id="stackChart" class="chart-container tall" ></div>
<h2 id="timeline">时间轴柱状图</h2>
<div id="timelineChart" class="chart-container tall" ></div>
</div>
</template>
<script>
import Chart from '../../src/index'
import { getSimpleList, getMultipleList, getTimelineList } from '../mock/data.js'
import theme from '../mock/theme.json'
export default {
name: 'barCharts',
mounted () {
// 注册主题
Chart.config({
theme: {
name: 'test',
data: theme,
default: true
}
})
Chart.bar('#simpleChart', getSimpleList())
Chart.bar('#multipleChart', getMultipleList(), { theme: 'none' })
Chart.bar('#reverseChart', getMultipleList(), { reverseAxis: true })
Chart.bar('#mixinChart', getMultipleList(), {
lineTypes: ['直接访问', '搜索引擎'],
title: '',
yAxis: [
{
type: 'value',
name: '数值'
},
{
type: 'value',
name: '温度',
min: 0,
max: 25,
interval: 5,
axisLabel: {
formatter: '{value} °C'
}
}
]
})
Chart.bar('#stackChart', getMultipleList(), {
title: '',
stack: true
})
Chart.bar('#timelineChart', getTimelineList(), {
type: 'bar',
title: '$timeline时间轴柱状图'
})
}
}
</script>
<style lang="scss">
</style>
<template>
<div>
<h1>漏斗图示例</h1>
<h2 id="simple">简单漏斗图</h2>
<div id="simpleChart" class="chart-container tall" ></div>
</div>
</template>
<script>
import Chart from '../../src/index'
import { getSimpleList } from '../mock/data.js'
export default {
name: 'funnelCharts',
mounted () {
Chart.funnel('#simpleChart', getSimpleList())
}
}
</script>
<style lang="scss">
</style>
<template>
<div>
<h1>折线图示例</h1>
<h2 id="simple">单条折线图</h2>
<div id="simpleChart" class="chart-container" ></div>
<h2 id="multiple">多条折线图</h2>
<div id="multipleChart" class="chart-container" ></div>
<h2 id="reverse">横向折线图</h2>
<div id="reverseChart" class="chart-container tall" ></div>
</div>
</template>
<script>
import { Line } from '../../src/index'
import { getSimpleList, getMultipleList } from '../mock/data.js'
export default {
name: 'lineCharts',
mounted () {
Line.init('#simpleChart', getSimpleList())
Line.init('#multipleChart', getMultipleList())
Line.init('#reverseChart', getMultipleList(), { reverseAxis: true })
}
}
</script>
<style lang="scss">
</style>
<template>
<div>
<h1>饼状图示例</h1>
<h2 id="simple">简单饼状图</h2>
<div id="simpleChart" class="chart-container" ></div>
<h2 id="ring">环形图</h2>
<div id="ringChart" class="chart-container" ></div>
</div>
</template>
<script>
import Chart from '../../src/index'
import { getSimpleList } from '../mock/data.js'
export default {
name: 'pieCharts',
mounted () {
Chart.pie('#simpleChart', getSimpleList())
Chart.pie('#ringChart', getSimpleList(), {
title: '环形图',
ring: true
})
}
}
</script>
<style lang="scss">
</style>
<template>
<div>
<h1>雷达图示例</h1>
<h2 id="simple">简单雷达图</h2>
<div id="simpleChart" class="chart-container tall" ></div>
</div>
</template>
<script>
import Chart from '../../src/index'
import { getMultipleList } from '../mock/data.js'
export default {
name: 'radarCharts',
mounted () {
Chart.radar('#simpleChart', getMultipleList())
}
}
</script>
<style lang="scss">
</style>
<template>
<div>
<h1>气泡图示例</h1>
<h2 id="simple">气泡图</h2>
<div id="simpleChart" class="chart-container tall" ></div>
</div>
</template>
<script>
import Chart from '../../src/index'
import { getMultipleList } from '../mock/data.js'
export default {
name: 'scatterCharts',
mounted () {
Chart.scatter('#simpleChart', getMultipleList(true))
}
}
</script>
<style lang="scss">
</style>
import Vue from 'vue'
import Router from 'vue-router'
import Line from '../packages/line'
import Bar from '../packages/bar'
import Pie from '../packages/pie'
import Radar from '../packages/radar'
import Funnel from '../packages/funnel'
import Scatter from '../packages/scatter'
Vue.use(Router)
const router = new Router({
mode: 'history',
routes: [
{
path: '/line',
component: Line
},
{
path: '/bar',
component: Bar
},
{
path: '/pie',
component: Pie
},
{
path: '/radar',
component: Radar
},
{
path: '/funnel',
component: Funnel
},
{
path: '/scatter',
component: Scatter
}
]
})
router.afterEach((to, from) => {
if (to.hash) {
const target = document.querySelector(to.hash)
if (target) {
window.scrollTo(0, target.offsetTop)
}
} else {
window.scrollTo(0, 0)
}
})
export default router
$leftWidth: 200px;
$leftPaddingX: 30px;
body {
margin: 0;
padding: 0;
}
.app-container {
.left {
position: fixed;
left: 0;
top: 0;
display: flex;
flex-direction: column;
width: $leftWidth;
min-height: 500px;
padding: 20px $leftPaddingX;
.sidebar {
padding: 0;
list-style-type: none;
a {
display: block;
text-decoration: none;
color: #35495e;
padding: 5px 10px;
border-radius: 4px;
letter-spacing: .25px;
}
.router-link-active {
color: #fff;
background-color: #41b883;
}
.router-link-active + .sub {
display: block;
}
li {
font-size: 16px;
.sub {
display: none;
padding-left: 20px;
list-style-type: none;
li {
font-size: 14px;
}
.router-link-active {
color: #41b883;
background: #fff;
}
}
}
}
}
.right {
margin-left: $leftWidth + $leftPaddingX * 2;
border-left: 1px solid #c6c6c6;
h1 {
margin: 0;
padding: 30px;
text-align: center;
}
h2 {
margin: 0;
padding: 20px;
text-align: center;
}
.chart-container {
width: 80%;
height: 300px;
margin: auto;
padding-bottom: 50px;
}
.tall {
height: 600px;
}
}
}
{
"name": "@analysys/ana-charts",
"version": "1.0.4",
"main": "dist/index.js",
"repository": "git@git.analysys.cn:fss-modules/echarts-tooltip.git",
"author": "liuxin <liuxin@analysys.com.cn>",
"license": "MIT",
"scripts": {
"dev": "npm run clean && parcel ./example/index.html -p 3000",
"build": "npm run clean && cross-env NODE_ENV=production webpack --config ./build/webpack.config.prod.js",
"lint": "standard \"**/*.{js,vue}\"",
"lint:fix": "standard \"**/*.{js,vue}\" --fix",
"prepublishOnly": "npm run build",
"clean": "rimraf dist",
"start": "npm run dev",
"test": "npm run lint"
},
"dependencies": {
"echarts": "^4.1.0"
},
"devDependencies": {
"@fedor/standard": "^1.0.3",
"@vue/component-compiler-utils": "^2.2.0",
"autoprefixer": "^9.1.3",
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.6",
"babel-loader": "^7.1.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.7.0",
"cross-env": "^5.2.0",
"css-loader": "^0.28.8",
"cssnano": "^4.1.0",
"extract-text-webpack-plugin": "^3.0.2",
"ghooks": "^2.0.4",
"node-sass": "^4.9.3",
"optimize-css-assets-webpack-plugin": "3.2.0",
"postcss-loader": "^3.0.0",
"rimraf": "^2.6.2",
"sass-loader": "^7.1.0",
"uglifyjs-webpack-plugin": "^1.2.7",
"vue": "^2.5.17",
"vue-hot-reload-api": "^2.3.0",
"vue-loader": "^15.4.1",
"vue-router": "^3.0.1",
"vue-style-loader": "^4.1.1",
"vue-template-compiler": "^2.5.17",
"webpack": "^3.12.0",
"webpack-merge": "^4.1.4"
},
"standard": {
"parser": "babel-eslint",
"ignore": [
"src/font/*",
"dist/**",
"test/coverage/**",
"karma.conf.js",
"postcss.config.js"
]
},
"config": {
"ghooks": {
"pre-commit": "npm run lint"
}
}
}
module.exports = {
plugins: [
require('autoprefixer')({
browsers: ["ie > 8", "last 2 version", "safari >= 9"]
})
]
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册