Есть ли функция в реакции-визу для масштабирования каждой серии строк в ее диапазоне%, при этом для минимального домена установлено значение 0, а для максимального значения - 100?

У меня есть 9 различных серий линий, нарисованных на графике реакции. Значения этих рядов строк различаются. Наименьший диапазон — от 0 до 4, самый большой — от 0 до 12000 (изображение 1). Когда я рисую все эти серии линий, большинство из них располагаются внизу графика, будучи недостаточно читаемыми.

диаграмма реакции и отображения, показывающая текущий диапазон 0–2000

Я пытался использовать yDomain={[0, 100]}. Однако то, что я вижу сейчас, заключается в том, что максимальное значение графика в конечном итоге равно 100, а все остальные серии строк со значениями выше 100 не видны (они рисуются над тем, что мы можем видеть).

график реакции, показывающий диапазон, установленный yDomain на 0-100, и отсутствие других рядов строк в результате

Вот пример кода, если это поможет:

            <FlexibleWidthXYPlot
              onMouseLeave={() => this.setState({crosshairValues: []})}
              height={250}
              color="blue"
              size="12"
              xType="time"
              yDomain={[0, 100]}
              >
              <VerticalGridLines />
              <HorizontalGridLines />
              <XAxis 
                tickFormat={function tickFormat(d){
                  const date = new Date(d)
                  return date.toISOString().substr(11, 8)
                }}
                tickLabelAngle={45}
                margin={{bottom: 100}}
                padding={{left: 100}}
              />
              <YAxis />
              <LineSeries
                onNearestX={(value, {index}) =>
                  this.setState({crosshairValues: gasDataFiltered.map(d => d[index])}
                )}
                data={gasDataFiltered[0]}
                color="#27AE60" 
                opacity={battVoltShow === true ? 1 : 0.15}
              />
              <LineSeries
                data={gasDataFiltered[1]}
                color="#2A80B9" 
                opacity={fuelInjShow === true ? 1 : 0.15}
              />
              <LineSeries
                data={gasDataFiltered[2]}
                color="#8E44AD" 
                opacity={gasInjShow === true ? 1 : 0.15}
              />
              <LineSeries
                data={gasDataFiltered[3]}
                color="#560E0D" 
                opacity={gasLvlShow === true ? 1 : 0.15}
              />
              <LineSeries
                data={gasDataFiltered[4]}
                color="#F39C13" 
                opacity={gasPressShow === true ? 1 : 0.15}
              />
              <LineSeries
                data={gasDataFiltered[5]}
                color="#E91F62" 
                opacity={gasTempShow === true ? 1 : 0.15}
              />
              <LineSeries
                data={gasDataFiltered[6]}
                color="#20E3D1" 
                opacity={mapShow === true ? 1 : 0.15}
              />
              <LineSeries
                data={gasDataFiltered[7]}
                color="#246A80"
                opacity={reducerTempShow === true ? 1 : 0.15} 
              />
              <LineSeries
                data={gasDataFiltered[8]}
                color="#FF81C3" 
                opacity={rpmShow === true ? 1 : 0.15}
              />
              <Crosshair values={crosshairValues}>
                <div className='oscilloscope-tooltip'>
                  <ul>
                    <li><span className='oscilloscope-color oscilloscope-color--green'></span>{t('oscilloscope.battVolt')}: {crosshairValues[0] !== undefined && crosshairValues[0].y}</li>
                    <li><span className='oscilloscope-color oscilloscope-color--blue'></span>{t('oscilloscope.fuelInj')}: {crosshairValues[1] !== undefined && crosshairValues[1].y}</li>
                    <li><span className='oscilloscope-color oscilloscope-color--purple'></span>{t('oscilloscope.gasInj')}: {crosshairValues[2] !== undefined && crosshairValues[2].y}</li>
                    <li><span className='oscilloscope-color oscilloscope-color--dark'></span>{t('oscilloscope.gasLvl')}: {crosshairValues[3] !== undefined && crosshairValues[3].y}</li>
                    <li><span className='oscilloscope-color oscilloscope-color--orange'></span>{t('oscilloscope.gasPress')}: {crosshairValues[4] !== undefined && crosshairValues[4].y}</li>
                    <li><span className='oscilloscope-color oscilloscope-color--red'></span>{t('oscilloscope.gasTemp')}: {crosshairValues[5] !== undefined && crosshairValues[5].y}</li>
                    <li><span className='oscilloscope-color oscilloscope-color--light'></span>{t('oscilloscope.map')}: {crosshairValues[6] !== undefined && crosshairValues[6].y}</li>
                    <li><span className='oscilloscope-color oscilloscope-color--navy'></span>{t('oscilloscope.reducerTemp')}: {crosshairValues[7] !== undefined && crosshairValues[7].y}</li>
                    <li><span className='oscilloscope-color oscilloscope-color--pink'></span>{t('oscilloscope.rpm')}: {crosshairValues[8] !== undefined && crosshairValues[8].y}</li>
                  </ul>
                </div>
              </Crosshair>
            </FlexibleWidthXYPlot>

Я хотел бы, чтобы каждая серия строк воспринималась в диапазоне от 0 до 100% без изменения фактических значений. Мне нужно, чтобы эти значения по-прежнему отображались, поскольку я использую перекрестие, чтобы показать их.


person xyz83242    schedule 03.09.2019    source источник


Ответы (1)


Вот пример того, как я масштабировал два графика (один в миллионах, второй в %) для одновременного отображения на одном графике.

export const getBound = (arr, key, max = true) => {
  if (!Array.isArray(arr)) {
    return false
  }
  // `${key}0` is a check for graphs that has y0 and x0 values, for example Bar Charts
  const key0 = `${key}0`
  let result = max ? 0 : Number(arr[0][key])
  arr.forEach(item => {
    if (max) {
      if (Number(item[key]) > result || (item[key0] && Number(item[key0]) > result)) {
        result = item[key0] ? (Number(item[key]) > Number(item[key0])
          ? Number(item[key]) : Number(item[key0])) : Number(item[key])
      }
    } else {
      if (Number(item[key]) < result || (item[key0] && Number(item[key0]) < result)) {
        result = item[key0] ? (Number(item[key]) < Number(item[key0])
          ? Number(item[key]) : Number(item[key0])) : Number(item[key])
      }
    }
  })
  return result
}


export const getScaleValues = (arr1, arr2, roundTicksTo = 5) => {
  const arr1AbsMax = Math.abs(getBound(arr1, 'y')) > Math.abs(getBound(arr1, 'y', false))
    ? Math.abs(getBound(arr1, 'y')) : Math.abs(getBound(arr1, 'y', false))

  const arr2AbsMax = Math.abs(getBound(arr2, 'y')) > Math.abs(getBound(arr2, 'y', false))
    ? Math.abs(getBound(arr2, 'y')) : Math.abs(getBound(arr2, 'y', false))

  const coef = arr1AbsMax / arr2AbsMax

  const scaled = arr2.map(item => {
    return Object.assign({}, item, {
      y: item.y * coef,
    })
  })

  const ticksFormat = (v) => formatPercentageTicks(v, coef, roundTicksTo)

  return {
    coef: coef,
    scaled: scaled,
    ticksFormat: ticksFormat,
  }
}

export const formatPercentageTicks = (value, coef, roundTo = 1) => {
  return `${round(value / (coef), roundTo)} %`
}

export const round = (num, roundTo) => {
  return num % roundTo < (Math.ceil(roundTo / 2))
    ? (num % roundTo === 0 ? num : Math.floor(num / roundTo) * roundTo) : Math.ceil(num / roundTo) * roundTo
}

Если у вас 9 строк, вы можете взять 1 по умолчанию и масштабировать 8 других в % от значения по умолчанию. Кроме того, ось Y по умолчанию будет отображать числа, и вы можете добавить дополнительную ось Y для % с правой стороны:

<YAxis orientation={'right'} tickFormat={v => scaledObj.ticksFormat(v)} />
person Pavlo Zabaikin    schedule 21.11.2019