具有线系列图的虚拟测量装置

Virtual measurement device with line series chart

我正在使用 LightningChart JS 并且想实现一个虚拟测量设备,我可以在其中单击 A 点然后拖动到 B 点并获得 A 点和 B 点的 x,y 值。

就我对事件处理程序的调查而言,它们只是 return 一个鼠标事件,根据屏幕位置具有开始和停止位置。如果我错了,请纠正我。还请建议一种有效的方法来做到这一点。 提前致谢。

鼠标事件return鼠标坐标与普通JS鼠标事件在同一坐标space。要在系列坐标 space 中获取点击位置,需要执行几个步骤。

首先需要将鼠标坐标转换为引擎坐标space。引擎坐标space是canvas区域,0,0在canvas的左下角。这可以用 chart.engine.clientLocation2Engine(ev.clientX,ev.clientY) 来完成。这 return 使用图表引擎比例在引擎坐标 space 中的事件坐标。

这需要转换为系列坐标。这可以通过 translatePoint 方法来完成。 translatePoint 可用于在两种不同尺度之间转换点数。 LightningChart JS 中的刻度基本上是坐标 space.

const m = chart.engine.clientLocation2Engine(ev.clientX, ev.clientY)
const translated = translatePoint(m, chart.engine.scale, lineSeries.scale)

现在 translated 变量包含系列坐标 space 中的点击位置。

查看下面的完整代码片段,您可以在其中拖动系列区域,当拖动停止时,标记将放置在拖动的开始和结束位置。

const {
    lightningChart,
    SolidLine,
    SolidFill,
    ColorRGBA,
    AxisTickStrategies,
    UIOrigins,
    DataPatterns,
    translatePoint,
    ColorHEX
} = lcjs

const chart = lightningChart().ChartXY()

const diesel = [
    { x: 0, y: 1.52 },
    { x: 1, y: 1.52 },
    { x: 2, y: 1.52 },
    { x: 3, y: 1.58 },
    { x: 4, y: 2.00 },
    { x: 5, y: 2.00 },
    { x: 6, y: 2.00 },
    { x: 7, y: 2.00 },
    { x: 8, y: 2.26 },
    { x: 9, y: 1.90 },
    { x: 10, y: 1.90 },
    { x: 11, y: 1.90 },
    { x: 12, y: 1.90 },
    { x: 13, y: 1.60 },
    { x: 14, y: 1.60 },
    { x: 15, y: 1.60 },
    { x: 16, y: 1.00 },
    { x: 17, y: 1.00 },
    { x: 18, y: 1.00 },
    { x: 19, y: 1.74 },
    { x: 20, y: 1.47 },
    { x: 21, y: 1.47 },
    { x: 22, y: 1.47 },
    { x: 23, y: 1.74 },
    { x: 24, y: 1.74 },
    { x: 25, y: 1.74 },
    { x: 27, y: 1.5 },
    { x: 28, y: 1.5 },
    { x: 29, y: 1.5 }
]

const gasoline = [
    { x: 0, y: 1.35 },
    { x: 1, y: 1.35 },
    { x: 2, y: 1.35 },
    { x: 3, y: 1.35 },
    { x: 4, y: 1.90 },
    { x: 5, y: 1.90 },
    { x: 6, y: 1.90 },
    { x: 7, y: 1.92 },
    { x: 8, y: 1.50 },
    { x: 9, y: 1.50 },
    { x: 10, y: 1.3 },
    { x: 11, y: 1.3 },
    { x: 12, y: 1.3 },
    { x: 13, y: 1.3 },
    { x: 14, y: 1.3 },
    { x: 15, y: 1.32 },
    { x: 16, y: 1.40 },
    { x: 17, y: 1.44 },
    { x: 18, y: 1.02 },
    { x: 19, y: 1.02 },
    { x: 20, y: 1.02 },
    { x: 21, y: 1.02 },
    { x: 22, y: 1.02 },
    { x: 23, y: 1.02 },
    { x: 24, y: 1.02 },
    { x: 25, y: 1.02 },
    { x: 27, y: 1.30 },
    { x: 28, y: 1.30 },
    { x: 29, y: 1.30 }
]

const lineSeries = chart.addLineSeries({ dataPattern: DataPatterns.horizontalProgressive })

const lineSeries2 = chart.addLineSeries({ dataPattern: DataPatterns.horizontalProgressive })

lineSeries2.add(diesel.map((point) => ({ x: point.x, y: point.y })))
lineSeries.add(gasoline.map((point) => ({ x: point.x, y: point.y })))


const markerA = chart.addChartMarkerXY()
    .setPointMarker((marker) => marker.setFillStyle((f => f.setColor(ColorHEX('#f00')))))
    .setMouseInteractions(false)
const markerB = chart.addChartMarkerXY()
    .setPointMarker((marker) => marker.setFillStyle((f => f.setColor(ColorHEX('#0f0')))))
    .setMouseInteractions(false)

function getClickInSeriesScale(point, scale) {
    const m = chart.engine.clientLocation2Engine(point.x, point.y)
    return translatePoint(m, chart.engine.scale, scale)
}

chart.onSeriesBackgroundMouseDragStop((obj, ev, b, start) => {
    let pointA = getClickInSeriesScale(start, lineSeries.scale)
    let pointB = getClickInSeriesScale({x:ev.clientX,y:ev.clientY}, lineSeries.scale)

    // move markes to start and end points
    markerA.setPosition(pointA)
    markerB.setPosition(pointB)
})
<script src="https://unpkg.com/@arction/lcjs@1.3.1/dist/lcjs.iife.js"></script>