在 LightningChartJS 中,有没有办法在 X 和 Y 的缩放比例始终相等的情况下进行拖动缩放?

问题描述

我的问题是当我拖动矩形缩放(gyazo gif)时,X 轴比 Y 轴宽。实际上,X 轴比 Y 轴放大的细节更多,图形的视觉效果看起来与原始图。

https://gyazo.com/749db917465a8037b7c5f21792f572ce

我正在寻找一种方法,如果我缩放矩形拖动,该功能类似于通过鼠标滚轮缩放,其中 x 和 y 缩放感觉相等。

解决方法

在这里您将找到一个示例,说明如何执行自定义缩放矩形而不是默认值并保持轴的比例。

// Extract required parts from LightningChartJS.
const {
  ColorRGBA,ColorHEX,emptyFill,SolidFill,SolidLine,translatePoint,_point,lightningChart
} = lcjs;

// Import data-generator from 'xydata'-library.
const {
  createProgressiveTraceGenerator
} = xydata


const chart = lightningChart()
    .ChartXY()
    // Disable default chart interactions with left mouse button.
    // .setMouseInteractionRectangleFit(false)
    .setMouseInteractionRectangleZoom(false)
    .setTitleFillStyle(emptyFill)

// generate data and creating the series
const series = chart.addLineSeries().setStrokeStyle(
    new SolidLine({
        fillStyle: new SolidFill({ color: ColorHEX('#fff') }),thickness: 2,}),)

 // generate data and create series
  createProgressiveTraceGenerator()
      .setNumberOfPoints(200)
      .generate()
      .toPromise()
      .then((data) => {
          return series.add(data)
      })
  
  // create zooming rect and dispose it
  const rect = chart
      .addRectangleSeries()
      .add({
          x: 0,y: 0,width: 0,height: 0,})
      .setFillStyle(new SolidFill({ color: ColorRGBA(255,255,30) }))
      .setStrokeStyle(
          new SolidLine({
              thickness: 2,fillStyle: new SolidFill({ color: ColorRGBA(255,255) }),)
      .dispose()
  
  // om Mouse drag restor rectange and set position and coordinates
      chart.onSeriesBackgroundMouseDrag((obj,event,button,startLocation,delta) => {
      if (button !== 0) return
  
      const startLocationOnScale = translatePoint(
          chart.engine.clientLocation2Engine(startLocation.x,startLocation.y),chart.engine.scale,series.scale,)
      const curLocationOnScale = translatePoint(chart.engine.clientLocation2Engine(event.x,event.y),series.scale)
  
          const x = Math.abs(series.getBoundaries().min.x) + Math.abs(series.getBoundaries().max.x)
      const y = Math.abs(series.getBoundaries().min.y) + Math.abs(series.getBoundaries().max.y)
      const ratio = x / y
      const width = Math.abs(curLocationOnScale.x - startLocationOnScale.x)
      const height = Math.abs(curLocationOnScale.y - startLocationOnScale.y)
      const heightDirection = curLocationOnScale.y - startLocationOnScale.y // check direction of rect
  
      // check for mouse direction to prevet fit and zoom conflict
      if (curLocationOnScale.x > startLocationOnScale.x) {
          rect.setDimensions({
              x: startLocationOnScale.x,y: startLocationOnScale.y,width: width > height * ratio ? width : height * ratio,height: width > height * ratio ? (heightDirection > 0 ? width : -width) / ratio : heightDirection,}).restore()
      } else {
          // prevent phantom rectangle if you change zoom to fit during the dragging
          rect.setDimensions({
              x: 0,}).dispose()
      }
  })
  
  
  // on mouse drag stop dispose rect and zoom relative to its dimensions
  chart.onSeriesBackgroundMouseDragStop((_,startLocation) => {
      if (button !== 0) return

      const rectZooom = rect.getDimensionsPositionAndSize()
      if (rectZooom.width !== 0) {
          chart.getDefaultAxisX().setInterval(rectZooom.x,(rectZooom.x + rectZooom.width),true,true)
          if(rectZooom.height > 0){
            chart.getDefaultAxisY().setInterval(rectZooom.y,(rectZooom.y + Math.abs(rectZooom.height)),true)
          }else{
              chart.getDefaultAxisY().setInterval((rectZooom.y - Math.abs(rectZooom.height)),rectZooom.y,true)
          }
      }
      rect.setDimensions({
          x: 0,}).dispose()
  })
<script src="https://unpkg.com/@arction/xydata@1.4.0/dist/xydata.iife.js"></script>
<script src="https://unpkg.com/@arction/lcjs@3.0.0/dist/lcjs.iife.js"></script>