Решение для адаптации экрана для Echarts.
Добро пожаловать в колонкуКодовая книга энтропии и монад
В веб-разработке, особенно в SPA типа панели инструментов, часто требуется, чтобы каждый компонент мог масштабироваться и адаптироваться к различным разрешениям экрана.Одним из распространенных решений является использование единиц длины rem и em в CSS в сочетании с медиа-запросами.
В некоторых недавних требованиях к визуализации данных компонент диаграммы использует Echarts.Обнаружено, что, поскольку Echarts генерирует диаграммы на основе метода рисования Canvas, в элементах конфигурации все расстояния и размеры могут быть установлены только в пикселях, что делает экран адаптация очень неудобная, при смене разрешения не только размер шрифта и расстояние в диаграмме не гармонируют с общим интерфейсом, но и шрифты часто перекрываются.
Подумав об этом, каждый раз, когда перерисовки Echarts передаются в конфигурации через метод setOption в JavaScript, вы можете использовать объект окна, чтобы получить размер окна, динамически установить переменную, которая будет играть роль размера шрифта корневого элемента. , и имитируйте rem Effects с помощью медиа-запросов.
Сначала создайте файл конфигурации стиля для компонента или добавьте его в существующий файл конфигурации:
// styleProps.js
const viewPort = window.screen.width;
let rootFontSize = 100;
if (viewPort <= 1480) rootFontSize = 71;
if (viewPort >= 1481 && viewPort <= 1760) rootFontSize = 83;
if (viewPort >= 2241 && viewPort <= 3200) rootFontSize = 130;
if (viewPort >= 3201) rootFontSize = 200;
export default {
titleFontColor: 'rgba(255,255,255,0.97)',
bodyFontColor: 'rgba(255,255,255,0.91)',
titleFontSize: rootFontSize * 0.18,
bodyFontSize: rootFontSize * 0.16,
titleFontFamily: 'FangZhengZhengZhongHeiJT',
bodyFontFamily: 'FangZhengZhengXianHeiJT',
};
Для того, чтобы решить проблему минимального размера шрифта 12px под браузером Chrome, принято устанавливать font-size корневого элемента в 100px, а rootFontSize здесь тоже выставлен в 100.
Получите ширину экрана через переменную viewPort и адаптируйтесь к следующим общим разрешениям экрана в соответствии с интервалом:
1366*768
1600*900
1920*1080
2560*1400
3840*2160
Если вы выберете ширину, в основном полный экран, проекционный экран и другие ситуации не будут затронуты.Конечно, поскольку это приложение типа панели инструментов, оно не учитывает странные ситуации, такие как пользователь, вытягивающий маленькую форму.
Эта конфигурация styleProps.js «изоморфна» нашим настройкам в CSS всего приложения:
html{
font-size: 625%;
}
@media (max-width: 1480px) {
html{
font-size: 444%;
}
}
@media (min-width: 1481px) and (max-width: 1760px) {
html{
font-size: 521%;
}
}
@media (min-width: 2241px) and (max-width: 3200px) {
html{
font-size: 810%;
}
}
@media (min-width: 3201px) {
html{
font-size: 1250%;
}
}
body{
font-size: 0.2rem;
font-family: FangZhengZhengXianHeiJT;
color: rgba(255,255,255,0.91);
}
h1 {
font-size: 0.44rem;
font-family: FangZhengZhengZhongHeiJT;
color: rgba(255,255,255,0.97);
}
h2 {
font-size: 0.32rem;
font-family: FangZhengZhengZhongHeiJT;
color: rgba(255,255,255,0.97);
}
h3 {
font-size: 0.24rem;
font-family: FangZhengZhengZhongHeiJT;
color: rgba(255,255,255,0.97);
}
Затем просто оберните компонент для кривой и гистограмм:
import React from 'react';
import echarts from 'echarts';
import styleProps from '../styleProps';
export default class HArrayChart extends React.Component {
static defaultProps = {
title: '',
/**
* dataItem {
* data: [],
* type: '',
* name: '',
* axis: 'left' | 'right',
* }
*/
dataList: [],
/**
* {
* name: '',
* data: []
* }
*/
index: {},
/**
* ['发电量(kWh)','功率(kW)']
*/
axes: []
}
componentDidMount() {
this.chart = echarts.init(this.chart);
this.updateChart();
}
componentDidUpdate() {
this.updateChart();
}
updateChart = () => {
const getSerisOption = (type) => {
switch (type) {
case 'line':
return {
symbol: 'none'
};
default:
break;
}
return null;
};
this.chart.setOption({
title: {
text: this.props.title,
x: 'center',
textStyle: {
color: styleProps.titleFontColor,
fontFamily: styleProps.titleFontFamily,
fontSize: styleProps.titleFontSize
}
},
grid: {
top: (styleProps.bodyFontSize * 2.4) + styleProps.titleFontSize,
right: (styleProps.bodyFontSize * 3.8) + 8,
bottom: (styleProps.bodyFontSize * 4.2) + 8,
left: (styleProps.bodyFontSize * 3.8) + 8
},
yAxis: this.props.axes.map(name => ({
name,
nameGap: styleProps.bodyFontSize * 0.8,
type: 'value',
nameTextStyle: {
color: styleProps.bodyFontColor,
fontFamily: styleProps.bodyFontFamily,
fontSize: styleProps.bodyFontSize
},
axisLine: {
lineStyle: {
color: styleProps.bodyFontColor
}
},
axisLabel: {
color: styleProps.bodyFontColor,
fontFamily: styleProps.bodyFontFamily,
fontSize: styleProps.bodyFontSize
}
})),
legend: {
data: this.props.dataList.map(dataItem => dataItem.name),
icon: 'bar',
bottom: 0,
textStyle: {
color: styleProps.bodyFontColor,
fontFamily: styleProps.bodyFontFamily,
fontSize: styleProps.bodyFontSize
}
},
xAxis: {
data: this.props.index.data,
type: 'category',
name: this.props.index.name,
nameLocation: 'center',
nameGap: (styleProps.bodyFontSize * 1.2) + 8,
nameTextStyle: {
color: styleProps.bodyFontColor,
fontFamily: styleProps.bodyFontFamily,
fontSize: styleProps.bodyFontSize
},
axisLine: {
lineStyle: {
color: styleProps.bodyFontColor
}
},
axisLabel: {
color: styleProps.bodyFontColor,
fontFamily: styleProps.bodyFontFamily,
fontSize: styleProps.bodyFontSize
}
},
series: this.props.dataList.map(dataItem => ({
data: dataItem.data,
type: dataItem.type || 'line',
name: dataItem.name,
animation: false,
yAxisIndex: dataItem.axis === 'right' ? 1 : 0,
...getSerisOption(dataItem.type || 'line')
}))
});
}
render() {
return <div className={this.props.className} ref={(div) => { this.chart = div; }} />;
}
}
Предыдущий файл конфигурации styleProps.js импортируется через импорт, и соответствующие параметры будут рассчитаны до создания компонента, что достаточно для адаптации к разрешению экрана.Конечно, если вы хотите иметь возможность более динамичной настройки, вы Также можно установить вид наблюдения за состоянием.Ширина рта, параметр пересчитывается в каждом компонентеWillUpdate.
Для удобства пользователей, не знакомых с конфигурацией Echarts, этот компонент предоставляет только 4 параметра:
title: '',
dataList: [],
index: {},
axes: []
dataList может передавать несколько рядов данных через массив, каждый из которых может быть независимо настроен с типом кривой или столбца и связан с левой или правой осью координат.Длина каждого ряда данных должна соответствовать длине индекса абсцисса. Конечно, такая конфигурация делает степень свободы очень малой, и элемент конфигурации опции также может быть предоставлен пользователю для переопределения конфигурации по умолчанию.
Так как настройка размера шрифта в конфигурации styleProps.js "изоморфна" с нашей настройкой в CSS всего приложения, то через titleFontSize и bodyFontSize при изменении адаптивного соответствия разрешения экрана Echarts и в целом поведение интерфейса остается согласованы, а такие изменения, как размер шрифта и расстояние, координируются.
Расстояние между каждым элементом на диаграмме, такое как расстояние между легендой и осью x, расстояние между сеткой и четырьмя сторонами и т. д., также задается соотношением bodyFontSize, так что при изменении шрифтов на диаграмме они изменятся. не пересекаться друг с другом:
yAxis: this.props.axes.map(name => ({
nameGap: styleProps.bodyFontSize * 0.8,
})),
Так как в проекте используются styled-components, корневой элемент компонента должен быть передан в className={this.props.className} .
Когда используется последний компонент, это выглядит примерно так:
import styled from 'styled-components';
import { HArrayChart } from './hyphix';
const Chart = styled(HArrayChart)`
width: 5rem;
height: 3rem;
`;
const dataList = [
{
data: [2, 4, 5, 80, 22, 27, 39, 0, 12],
name: '今日功率',
},
{
data: [32, 33, 3, 8, 2, 27, 3, 3, 15],
name: '昨日功率',
type: 'bar'
},
{
data: [837, 3099, 122, 3999, 100, 299, 3987, 3298, 1500],
name: '昨日效率',
axis: 'right'
},
];
const index = { data: [1, 2, 3, 4, 5, 6, 7, 8, 9], name: '时间' };const Chart = styled(HArrayChart)`
width: 500px;
height: 300px;
`;
const dataList = [
{
data: [2, 4, 5, 80, 22, 27, 39, 0, 12],
name: '今日功率',
},
{
data: [32, 33, 3, 8, 2, 27, 3, 3, 15],
name: '昨日功率',
type: 'bar'
},
{
data: [837, 3099, 122, 3999, 100, 299, 3987, 3298, 1500],
name: '昨日效率',
axis: 'right'
},
];
const index = { data: [1, 2, 3, 4, 5, 6, 7, 8, 9], name: '时间' };
<Route path="/test" exact component={() => <Chart title={'今日发电功率曲线'} dataList={dataList} index={index} axes={['发电量(kWh)', '功率(kW)']} />} />
Поскольку нет красивых данных, изображение не будет отображаться.Компоненты - это только общая идея, а красивые детали необходимо улучшить.