@minix-iot/ui
Version:
基于Vue的移动端轻量级UI组件库
278 lines (269 loc) • 8.88 kB
JavaScript
import F2 from "@antv/f2"
export function mixChart(){
return {
props:{
axis:{
type: Object,
},
geometry:{
type: Object,
required: true
},
data:{
type: Array | Object,
required: true
},
width:{
type: Number
},
height:{
type: Number
},
showTag:{
type: Boolean,
default: false
}
},
data(){
return {
chart:null
}
},
computed:{
isUsingYR(){
return Array.isArray(this.data[0])
}
},
watch:{
axis(){
this.repaint()
},
geometry(){
this.repaint()
},
showTag(){
this.repaint()
},
width(value){
this.chart.changeSize(value,null)
},
height(value){
this.chart.changeSize(null,value)
},
data(){
this.changeSource()
}
},
mounted(){
this.initChart()
this.renderCoord()
this.renderAxis()
this.renderScale()
this.renderTooltip()
this.renderLegend()
this.renderGuide()
this.renderSource()
this.renderGeometry()
this.chart.render()
this.useInteraction()
},
beforeDestory(){
this.chart.destory()
},
methods:{
initChart(){
this.chart = new F2.Chart({
el: this.getCanvas(),
width: this.width,
height: this.height,
pixelRatio: window.devicePixelRatio
})
},
renderCoord(){
},
renderAxis(){
this.chart.axis(this.getAxisOption())
},
renderScale(){
const {x,y,yr} = this.axis
x.scale && this.chart.scale(x.use, x.scale)
y.scale && this.chart.scale(y.use, y.scale)
yr && yr.scale && this.chart.scale(yr.use,yr.scale)
},
renderTooltip(){
this.chart.tooltip(this.getTooltipOption())
},
renderLegend(){
this.chart.legend({
align: 'center',
marker:{
radius:4
},
nameStyle:{
fill:'#8A8A8F',
fontSize: 12
},
valueStyle:{
fill:'#8A8A8F',
fontSize: 12
}
})
},
renderGuide(){
if(this.showTag){
const items = this.data.flat()
const {x,y,yr} = this.axis
const {classifyBy} = this.geometry
items.forEach(item=>{
const position = [item[x.use],item[y.use] ?? item[yr.use]]
const content = item[y.use] ?? item[yr.use]
this.chart.guide().text(this.getGuideTextOption(position,content))
})
}
},
renderSource(){
this.chart.source(this.data.flat())
},
renderGeometry(){
},
useInteraction(){
},
changeSource(){
this.chart.changeSource(this.data.flat())
},
repaint(){
this.chart.clear()
this.renderCoord()
this.renderAxis()
this.renderScale()
this.renderTooltip()
this.renderLegend()
this.renderGuide()
this.renderSource()
this.renderGeometry()
this.chart.repaint()
},
getCanvas(){
return this.$el
},
getAxisOption(transposed = false){
const option = {}
const {x,y,yr} = this.axis
if(x){
option[x.use] = transposed ? this.getAxisYOption(): this.getAxisXOption()
}
if(y){
option[y.use] = transposed ? this.getAxisXOption() : this.getAxisYOption()
}
if(yr){
option[yr.use] =this.getAxisYOption(option=>option.positon='right')
}
return option
},
getAxisXOption(configAxis = option=>option){
const option = {
label:{
fill:'#8A8A8F',
fontSize: 12,
}
}
configAxis(option)
return option
},
getAxisYOption(configAxis = option=>option){
const option = {
label:{
fill: '#C7C7CC',
fontSize: 10
},
grid:{
stroke:'#F2F2F2',
lineWidth:1,
lineDash:0
}
}
configAxis(option)
return option
},
getTooltipOption(showCrosshairs = false){
const option = {
showCrosshairs,
crosshairsStyle: {
stroke: '#C7C7CC',
lineWidth: 1,
lineDash: [3,1.2]
},
background:{
fill:'#FFFFFF',
radius: 15,
padding:[8,25],
shadowOffsetX:0,
shadowOffsetY:2,
shadowBlur:8,
shadowColor:'rgba(0,0,0,0.1)',
},
nameStyle:{
fill:'#666666',
fontSize: 13,
fontFamily:'PingFangSC-Medium',
fontWeight:500
},
valueStyle:{
fill:'#666666',
fontSize:13,
fontFamily:'PingFangSC-Medium',
fontWeight:500
}
}
if(this.geometry.classifyBy){
option.custom = true
// onchange
option.onChange = obj=>{
const legend = this.chart.get('legendController').legends.top?.[0];
if(!legend){
return
}
const tooltipItems = obj.items;
const legendItems = legend.items;
const map = {};
legendItems.forEach(function (item) {
map[item.name] = {...item};
});
tooltipItems.forEach(function (item) {
const name = item.name;
const value = item.value;
if (map[name]) {
map[name].value = value;
}
});
legend?.setItems(Object.values(map));
}
// onHide
option.onHide = ()=>{
const legend = this.chart.get('legendController').legends.top?.[0];
legend?.setItems(this.chart.getLegendItems().country);
}
}
return option
},
getGuideTextOption(position,content){
const option = {
position,
content,
style:{
fill:'#666666',
fontSize:9
},
offsetY:-8
}
return option
},
getLinearColor(color,angle=90){
if(Array.isArray(color)){
return color.map(x=>`l(${angle}) 0:${x}FF 1:${x}00`)
}
return `l(${angle}) 0:${color}FF 1:${color}00`
}
}
}
}