lightningchart - 以编程方式拖动 Lightningchart 的图表
问题描述
我想使用键盘键(例如向上箭头向上平移图表,向下箭头向下平移图表等)拖动图表。
const lcjs = lightningChart({
overrideInteractionMouseButtons: {
chartXYPanMouseButton: 0,
chartXYRectangleZoomFitMouseButton: 2,
},
})
const chart = lcjs.ChartXY()
上面的代码用鼠标很好,但我尝试了类似下面的使用 javascript ,我尝试根据键盘上的箭头键移动图表。
function upArrowPress() {
move = 2;
lastpos_y1 = lastpos_y1 + move;
lastpos_y2 = lastpos_y2 + move;
for (var key in axis) {
axis[key].setScrollStrategy(undefined).setInterval(lastpos_y1[key],lastpos_y2[key])
}
}
上面的代码有效,但每个轴的移动方式不同,我无法获得所有轴平移在一起的原生效果。如何使用自定义函数实现平滑平移。谢谢。
解决方案
不能保证 X 轴和 Y 轴间隔在视觉上是相同的大小。这就是为什么当您将轴间隔设置为相同时,它仍然会导致视觉上不同的大小变化。
您需要根据每个系列比例方向上的像素大小来调整间隔变化。为此,您首先需要获取每个比例方向(X 和 Y)series.scale.x.getPixelSize()
和series.scale.y.getPixelSize()
. 这两个值是乘数,您可以使用它们将间隔更改为视觉上相同的变化。
const offsetX = 1 // offset should be -1,0,1 based on what keys are pressed
const origXInterval = series.axisX.getInterval();
const xIntervalSize = origXInterval.end - origXInterval.start
const pixelSizeX = series.scale.x.getPixelSize()
const newXIntervalStart = origXInterval.start + offsetX * pixelSizeX * 10
axisX.setInterval(newXIntervalStart, newXIntervalStart + xIntervalSize)
这里的关键是+ offsetX * pixelSizeX * 10
。这会将 X 间隔向左 (-1) 或右 (1) 偏移,即 10 个像素代表的间隔值。
要对所有轴和系列执行此操作,您需要遍历每个系列chart.getSeries().forEach(series=>{})
并偏移为任何系列找到的所有轴一次。一个轴可能被多个系列使用,因此如果您已经偏移了轴,则需要跟踪,否则平移将不同步。您可以使用 JS 轻松做到这一点Set
。检查轴是否已经在集合中processedAxisSet.has(series.axisX)
,如果不存在,则像以前一样进行偏移并将轴添加到集合processedAxisSet.add(series.axisX)
中。
请参阅下面的完整示例。这是一个现成的 html 文件,您可以将其复制并粘贴到本地文件系统,然后在浏览器中打开以查看它是否正常工作。我这样做是因为 iframe 会导致将事件附加到窗口时出现一些问题。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<!-- Flexbox styling to have the chart and header fill the page.
Chart will take as much space as possible. -->
<style>
html,
body {
height: 100%;
margin: 0;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
}
.box .row.header {
flex: 0 1 auto;
}
.box .row.content {
flex: 1 1 auto;
}
</style>
</head>
<body class="box">
<!-- Create div to render the chart into-->
<div id="target" class="row content"></div>
<!--IIFE assembly (lcjs.iife.js) is a standalone JS file,
which does not need any build tools,
such as NPM, to be installed-->
<!--Script source must be defined in it's own script tag-->
<script src="https://unpkg.com/@arction/lcjs@3.0.1/dist/lcjs.iife.js"></script>
<!--Actual chart related script tag-->
<script>
// Replace the contents of this script tag if you want to test code from our examples:
// https://www.arction.com/lightningchart-js-interactive-examples/
// Extract required parts from LightningChartJS.
const {
lightningChart
} = lcjs //Note: @arction/lcjs is not needed here, when using IIFE assembly
// Create a XY Chart.
const chart = lightningChart().ChartXY({
// Set the chart into a div with id, 'target'.
// Chart's size will automatically adjust to div's size.
container: 'target'
})
const axisX = chart.getDefaultAxisX();
const axisY = chart.getDefaultAxisY();
const axisX2 = chart.addAxisX({ opposite: true })
const axisY2 = chart.addAxisY({ opposite: true })
axisX.setScrollStrategy(undefined)
axisY.setScrollStrategy(undefined)
axisX2.setScrollStrategy(undefined)
axisY2.setScrollStrategy(undefined)
const lineSeries = chart.addLineSeries()
lineSeries.addArrayY([1, 2, 1, 2, 3, 4, 1, 2], 1, 1)
const pointSeries = chart.addPointSeries({
xAxis: axisX2,
yAxis: axisY2
})
pointSeries.addArrayY([2, 4, 1, 2, 7, 3, 4, 5, 1, 2], 1, 1)
// Create a keymap to track key states
const keymap = new Map();
keymap.set('ArrowUp', 0);
keymap.set('ArrowLeft', 0);
keymap.set('ArrowRight', 0);
keymap.set('ArrowDown', 0);
// attach listeners to keydown and keyup events to keep track of key states
// keydown is also used to trigger update to pan the chart based on keyboard input
document.addEventListener('keydown', function (ev) {
keymap.set(ev.code, 1);
updateKeyboardPan();
});
document.addEventListener('keyup', function (ev) {
keymap.set(ev.code, 0);
});
function updateKeyboardPan() {
// update offsets based on keyboard state
let offsetX = 0
let offsetY = 0
if (keymap.get('ArrowUp') === 1) {
offsetY -= 1
}
if (keymap.get('ArrowDown') === 1) {
offsetY += 1
}
if (keymap.get('ArrowLeft') === 1) {
offsetX += 1
}
if (keymap.get('ArrowRight') === 1) {
offsetX -= 1
}
// set for storing what axes have already been processed
const processedAxisSet = new Set()
chart.getSeries().forEach(series => {
// offset based on pixels only if the axis hasn't been processed this loop
if (!processedAxisSet.has(series.axisX)) {
// Get original state info
const origXInterval = series.axisX.getInterval();
const xIntervalSize = origXInterval.end - origXInterval.start
// get the pixel size for axis
const pixelSizeX = series.scale.x.getPixelSize()
const newXIntervalStart = origXInterval.start + offsetX * pixelSizeX * 10
// pixel size info is used to scale the change to be visually same size for both X and Y axis
series.axisX.setInterval(newXIntervalStart, newXIntervalStart + xIntervalSize)
// add the axis to the processed axis set
processedAxisSet.add(series.axisX)
}
// Do same for Y axis as was done for X axis
if (!processedAxisSet.has(series.axisY)) {
const origYInterval = series.axisY.getInterval();
const yIntervalSize = origYInterval.end - origYInterval.start
const pixelSizeY = series.scale.y.getPixelSize()
const newYIntervalStart = origYInterval.start + offsetY * pixelSizeY * 10
series.axisY.setInterval(newYIntervalStart, newYIntervalStart + yIntervalSize)
processedAxisSet.add(series.axisY)
}
})
}
</script>
</body>
</html>
推荐阅读
- php - Laravel optional select field
- visual-studio - MFC: CListCtrl background color of first row?
- python - 运行时 Spyder 一直显示旧代码
- c++ - Cython: Invalid index type 'int'
- java - 频率攻击,尝试打印时字符显示不正确(上为下,下为上)
- google-cloud-platform - 如何在对话流中重定向到与用户输入关键字相关的意图
- git - GitLab SSH 权限被拒绝(公钥)
- javascript - 找不到 Barba 包装纸
- testing - 对多个构建代理进行端到端测试?
- java - OnClickListener中的Android,通过方法部分更新图像