屏幕适配
大屏成像原理几乎都是投屏,也就是把电脑屏幕通过有线信号投放到大屏上,电脑上呈现什么内容,大屏上就会呈现什么内容,所以电脑屏幕横向和纵向上都不能出现滚条。在网上看了一些适配方案,最后参考了大屏数据可视化——屏幕适配方案(多分辨率下),用CSS3的scale,将容器设置为设计稿宽高,如3840*2160,动态根据浏览器视口的宽高进行缩放,从而实现容器始终铺满浏览器视口,而不出现滚动条。
容器组件的结构:
<template>
<div class="bsd-frame" :style="{'background': bgColor}" ref="bsdFrame">
<slot></slot>
</div>
</template>
第一步、获取容器实际宽高,通常是设计稿宽高,或者电脑屏幕的宽高。
setSize () {
this.frameWidth = this.width || screen.width
this.frameHeight = this.height || screen.height
const frame = this.$refs.bsdFrame //为容器根元素设置宽高
frame.style.width = this.frameWidth + 'px'
frame.style.height = this.frameHeight + 'px'
}
第二步、根据浏览器视口的的宽高,为容器设置缩放比例。
setScale () {
const bodyWidth = document.body.clientWidth //前提是html,body的height: 100%; width: 100%
const bodyHeight = document.body.clientHeight
const scaleX = bodyWidth / this.frameWidth
const scaleY = bodyHeight / this.frameHeight
this.$refs.bsdFrame.style.transform = `scale(${scaleX},${scaleY})`
}
第三部、监听resize事件,每次触发resize事件时,重新计算容器缩放比例。
mounted () {
this.setSize()
this.setScale()
window.addEventListener('resize', this.setScale)
},
destroyed () {
window.removeEventListener('resize', this.setScale)
}
echarts开发图表
主要用了柱状图、折线图、饼图等基础图表,以及地图。这部分主要的工作就是对着echarts配置项调整图标配置。 echarts.apache.org/zh/option.h…
echarts5对按需引入作了调整。将渲染器、组件和图表从echarts核心分离开来,根据需要进行引用,之前默认包含canvas和svg渲染器,现在可以根据需要选择canvas渲染器或是svg渲染器。组件和图表的按需引入方式和之前也不一样。比如要画一个带标题的折线图,就像下面这样引入TitleComponent、LineChart。
import * as echarts from 'echarts/core';
import { TitleComponent } from 'echarts/components';
import { LineChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
echarts.use(
[TitleComponent, LineChart, CanvasRenderer]
);
使用:
var dom = document.getElementById('main');
var myChart = echarts.init(dom); //初始化
var option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}]
};
option && myChart.setOption(option); // 设置选项
要在一个dom中绘制图表,首先是echarts.init(dom)
初始化一个echarts实例,然后为这个实例设置选项myChart.setOption(option)
,就可以完成图表的绘制了。可以参考官网的案例,echarts案例 。
当数据发生改变,要重新绘制,就再次调用myChart.setOption(newOption)
。
项目中很多地方都要用到echarts,之前用的vue-echarts组件库
是基于echarts4的,所以就简易地基于echarts5封装了一个组件,可以根据传入的option初始化图表,当option发生改变,重新渲染图表。
<template>
<div class="echarts"></div>
</template>
<script>
import * as echarts from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
echarts.use([CanvasRenderer])
export default {
name: 'vue-echarts',
props: {
options: {
type: Object,
required: true
}
},
watch: {
options (newValue, oldValue) {
if (this.chart && newValue) { //没有设置deep:true,所以当数据改变时,要改变option指针,才能触发该方法。
this.chart.setOption(newValue)
}
}
},
methods: {
init (opt) {
if (!this.chart) {
this.chart = echarts.init(this.$el)
}
this.chart.setOption(this.options)
}
},
mounted () {
this.init()
}
}
</script>
<style lang="scss" scoped>
.echarts {
width: 100%;
height: 100%;
}
</style>
使用:
<vue-echarts :options="chartOption" />
computed: {
chartOption () {
const categorySales = this.$store.state.categorySales
categoryOpt.series[0].data = categorySales
return Object.assign({}, categoryOpt)
}
}
滚动播放
滚动播放用的是transition,改变最上面一行的高度height,
transition: height 0.3s linear;
当最上面一行隐藏后,将它的数据从数组头部移到尾部。实现循环滚动。
//this.rowHeight为计算出的每一行的高度,这里是将所有行高都还原成初始值,len是数组长度
this.rowHeights = new Array(len).fill(this.rowHeight)
//将最上面一行的高度设为0
this.rowHeights.splice(0, 1, 0)
//将数组头部的数据移到尾部, this.currentIndex为移动指针,初始值为0
const temp = this.rowsx.slice(this.currentIndex)
temp.push(...this.rowsx.slice(0, this.currentIndex))
this.rowsData = temp
this.currentIndex += 1
<div v-for="(item, index) in rowsData" :key = "item.index"></div>
地图开发
echarts.registerMapapi支持自定义地理坐标系,如echarts.registerMap('china', map)
,第一个参数是自定义的地图名称,第二参数是GeoJson格式的数据,长下面这样:
GeoJson格式的数据可以在这个网站输入地名获取。
datav.aliyun.com/tools/atlas…
自定义地理坐标系的使用:
- 直接画地图,用于
type: 'map'
的图表类型
series: [
{
name: '产品流向分布',
type: 'map',
map: 'china',
zoom: 1.6,
center: [104.114129, 36.050339],
itemStyle: {
borderColor: 'blue',
borderWidth: 2
}
}
]
再加上视觉映射组件
visualMap
, 就可以实现热力分布地图。
visualMap: {
show: false,
min: 0,
max: 10000,
seriesIndex: [0],
inRange: {
color: ['#a7d5f2', '#3f95ff', '#5470c6']
}
},
series: [
{
name: '产品流向分布',
type: 'map',
map: 'china',
zoom: 1.6,
center: [104.114129, 36.050339],
itemStyle: {
borderColor: 'blue',
borderWidth: 2
}
}
]
- 作为坐标系,在坐标系上绘制散点图,线集等。
geo: {
map: 'china', //自定义的地图名称
zoom: 1.6,
center: [104.114129, 36.050339],
itemStyle: {
borderColor: 'blue',
borderWidth: 2
}
},
series: [
{
type: 'effectScatter',
coordinateSystem: 'geo', //指定geo坐标系
symbolSize: function (val) {
return val[2] / 200
},
rippleEffect: {
brushType: 'stroke'
},
label: {
show: true,
position: ['20', '0'],
formatter: '{b}',
fontSize: 16
},
itemStyle: {
color: 'yellow'
}
}]
自定义地理坐标系的使用是很常见的,省市区域的一些统计情况都可以用上述的方法进行实现。
数据
项目用的是模拟数据,用vuex进行数据的管理通信。更新方式采用定时轮询。
//Home.vue
created () {
this.$store.dispatch('updateAll')
setInterval(() => { // 模拟定时轮询
this.$store.dispatch('updateAll')
}, 5 * 60 * 1000)
}
在actions中模拟请求数据。
actions: {
updateAll (context) {
setTimeout(() => { // 模拟成功请求接口数据
// 接口返回,数据变化,更新状态
//context.commit('updateOverall', data)
...
}, 1000)
}
},
在组件的computed中处理使用数据:
computed: {
chartOption () {
const categorySales = this.$store.state.categorySales
categoryOpt.series[0].data = categorySales
return Object.assign({}, categoryOpt)
}
}