Индивидуальная визуализация данных на большом экране

JavaScript

предисловие

В проекте реализовано: создание диаграмм, произвольное перетаскивание, изменение размера диаграммы, стиля (введите ввод и нажмите Enter), двойной щелчок для удаления, полноэкранный режим, настраиваемая визуализация данных на большом экране.

Адрес опыта проекта:Визуализация данных на большом экране

Адрес исходного кода проекта:исходный код

Стек технологий: react + antd + echarts + react-hooks + react-dnd

Предварительный просмотр проекта

выполнить

Создавайте диаграммы, реализуйте перетаскивание, полноэкранный режим, см. предыдущую статью:Создать диаграмму

Схема пакета

Вы можете обратиться к сообществу echarts:echarts

Здесь много больших парней, которые сделали много хороших чартов, блоггеры ленивы, и все они чарты от больших парней.

import ReactEcharts from 'echarts-for-react';

<ReactEcharts
    option={option}
    theme="Imooc"
    style={{ width: `${width}px`, height: `${height}px` }}
    ref={chartRef}
/>

пройти черезecharts-for-reactС опцией стиля диаграммы в сообществе мы можем легко инкапсулировать различные стили диаграмм. Блогеру потребовалось менее 20 минут, чтобы сделать вышеуказанные стили.

Измените стиль диаграммы для синхронного обновления представления.

Элемент на некоторое время застревает в обновлении синхронизации представления, сложность здесь заключается в том, чтобы заставить диаграмму повторно отображаться после того, как мы изменим состояние справа.

Я начал думать о том, чтобы использовать ререндер echarts самостоятельно. Позже нашелecharts-for-reactПредоставляет нам доступ к диаграмме и предоставляет API.

Через ref получаем предоставленную библиотекуgetEchartsInstanceметод, на нем есть все методы echarts, а ререндер чарта можно реализовать сбросом setOption.

Идеи реализации:

Когда мы нажимаем клавишу Enter (ввод) в состоянии обновления справа, чтобы вызвать отправку и изменить данные, соответствующие центру обработки данных, наш компонент диаграммы также будет отображаться, запускаяuseEffectПерехватите функцию для завершения синхронного обновления представления.

const chartRef = React.useRef()

React.useEffect(() => {
    chartRef.current.getEchartsInstance().setOption(option)
}, [option])

return (
    <div
        className={ClassNames({ 'active': active })}
        onDoubleClick={(e) => deleteChart(id)}
        onClick={(e) => selectChart(e, id)}
        ref={drag}
        style={{ ...style, left, top }}
    >
        <ReactEcharts
            option={option}
            theme="Imooc"
            style={{ width: `${width}px`, height: `${height}px` }}
            ref={chartRef}
        />
    </div>
)

Панель стиля диаграммы

Когда мы выбираем диаграмму, получаем параметр диаграммы, анализируем ее и преобразуем в соответствующий тег dom.

Основная проблема здесь в том, что option — это глубокая структура объекта, и нам нужно пройти слой за слоем, чтобы получить свойства объекта.

После долгих размышлений об этом я все еще не могу придумать хорошего решения. В конце концов, мы можем использовать только самый глупый метод, послойный анализ и оценку, и отфильтровывать данные, которые не могут быть отображены на боковой панели.

Такая реализация глупа:

<Menu
    className="tab-menu"
    theme="dark"
    mode="inline"
    openKeys={openKeys}
    onOpenChange={(v) => onOpenChange(v)}
    style={{ width: '100%', height: '100%' }}
>
    {
        Object.keys(view).map(v => {
            if (v === 'data' || v === 'series') {
                return null
            }
            return (
                <SubMenu
                    className="tab-submenu"
                    key={v}
                    title={
                        <span>
                            <span>{v}</span>
                        </span>
                    }
                >
                    {
                        Object.keys(view[v]).map(item => {
                            if (item === 'data' || item === 'series') {
                                return null
                            }
                            if (typeof view[v][item] === 'object') {
                                return (
                                    <SubMenu
                                        className="tab-subitemmenu"
                                        key={item}
                                        title={
                                            <span>
                                                <span>{item}</span>
                                            </span>
                                        }
                                    >
                                        {
                                            Object.keys(view[v][item]).map(subitem => {
                                                return (
                                                    <Menu.Item key={subitem} className="tab-submenuitem">
                                                        <span style={{ marginRight: '5px' }}>{subitem}</span>
                                                        <Input
                                                            onPressEnter={(e) => onPressEnter(e, subitem, item, v)}
                                                            className="submenuitem-input"
                                                            onChange={e => inputOnChange(e, subitem, item, v)}
                                                            value={view[v][subitem]}
                                                        />
                                                    </Menu.Item>
                                                )
                                            })
                                        }
                                    </SubMenu>
                                )

                            }
                            return (
                                <Menu.Item key={item} className="tab-menuitem">
                                    <span style={{ marginRight: '5px' }}>{item}</span>
                                    <Input
                                        onPressEnter={(e) => onPressEnter(e, item, v)}
                                        className="menuitem-input"
                                        onChange={e => inputOnChange(e, item, v)}
                                        value={view[v][item]}
                                    />
                                </Menu.Item>
                            )

                        })
                    }
                </SubMenu>
            )
        })
    }
</Menu>

выбранный стиль

Когда мы нажимаем на диаграмму, добавляем к ней класс: активный, щелкните в другом месте, чтобы удалить стиль.

Идеи:

Здесь я используюclassnamesплагин. Это позволяет нам:

className={ClassNames({ 'active': active })}

где active — логическое значение, если true, добавить активный стиль, если false, удалить активный стиль.

выполнить:

В состояние каждого графика добавляю активный элемент, по умолчанию false, при клике становится true, а остальные false.

Примечание: чтобы остановить пузырение.

case 'activeClass':                                 //给选中的图表添加选中的样式
    Object.keys(state).map(item => {
        if (item === id) {
            state[item].active = true
            return item
        }
        state[item].active = false
        return item
    })
    return { ...state }
...

const selectChart = (e, id) => {                               //设置选中图表, 并添加被选中的样式
    e.stopPropagation()
    setSelect(chartsObj[id])
    dispatch({ type: "activeClass", id })
}

При нажатии на область, не относящуюся к графику, диспетчер превращает все в false:


const cancelSelect = () => {                                //取消选中样式
    setSelect({})
    dispatch({ type: "activeClass" })
}

позже

Что делать дальше:

Самое главное — запустить данные, настроить источник данных, настроить сгенерированный большой экран и сохранить его на сервере.

Во-вторых, настроить стиль графика (в настоящее время эти пакеты в основном скопированы из Интернета, а некоторые подходящие графики будут разработаны позже)