簡體   English   中英

縮放/平移后的畫布坐標

[英]Canvas Coordinate after scaling/Panning

我正在通過從api接收的一些數據來構建Canvas,這一切都很好。 無論如何,我仍然堅持以下事實:使用以下代碼`canvas.addEventListener('wheel',(event:MouseWheelEvent)=> {event.preventDefault();

    let coords = Positioning.transformedPoint(
      event.pageX - canvas.offsetLeft,
      event.pageY - canvas.offsetTop
    );

    canvasMethods.clear();
    canvasMethods.translate(coords.x, coords.y);

    if (event.wheelDeltaY > 0) {
      canvasMethods.scale(ZoomDirection.ZOOM_IN);
    } else if (event.wheelDeltaY < 0) {
      canvasMethods.scale(ZoomDirection.ZOOM_OUT);
    }

    canvasMethods.translate(-coords.x, -coords.y);

    this._renderFn();
  }, false);

  canvas.addEventListener('mousedown', (event: MouseEvent) => {
    event.preventDefault();

    this._dragging = true;
    this._dragStart = Positioning.transformedPoint(
      event.clientX - canvas.offsetLeft,
      event.clientY - canvas.offsetTop
    );
  }, false);

  canvas.addEventListener('dblclick', (event: MouseEvent) => {
    let coords = Positioning.transformedPoint(
      event.clientX - canvas.offsetLeft,
      event.clientY - canvas.offsetTop
    );
    this._clickFn(coords);
  });

  canvas.addEventListener('mousemove', (event: MouseEvent) => {
    if (this._dragging) {
      event.preventDefault();

      this._dragEnd = Positioning.transformedPoint(
        event.pageX - canvas.offsetLeft,
        event.pageY - canvas.offsetTop
      );

      let coords = Positioning.transformedPoint(
        event.clientX - canvas.offsetLeft,
        event.clientY - canvas.offsetTop
      );

      canvasMethods.translate(coords.x - this._dragStart.x, coords.y - this._dragStart.y);
      canvasMethods.clear();

      this._renderFn();
      this._dragStart = this._dragEnd;
    }
  }, false);

  canvas.addEventListener('mouseup', (event: MouseEvent) => {
    event.preventDefault();

    this._dragging = false;
    this._dragStart = null;
    this._dragEnd = null;
  })
}`

當我在法線刻度上時,我得到正確的坐標,但是一旦我縮放,我就會得到一個增量誤差(基本上,實際點和鼠標光標之間的距離越來越大),我不知道為什么。 為了計算矩陣中的坐標,我以以下方式使用SVG方法作為包裝器:導出類定位{static svg = document.createElementNS(' http://www.w3.org/2000/svg','svg ') ; 私人靜態xform = Positioning.svg.createSVGMatrix();

static transformedPoint(x: number, y: number): SVGPoint {
  let coords = Positioning.svg.createSVGPoint();

  coords.x = x;
  coords.y = y;

  return coords.matrixTransform(Positioning.xform.inverse());
}

}`

我知道這在某種程度上與縮放有關,但是我真的無法弄清楚如何對縮放進行考慮並進行適當的操作來獲取比例。 我也檢查了這個答案,“將畫布縮放到鼠標光標”是非常准確的,但實際上他以某種我無法協調的方式得到了解釋。 有人遇到過同樣的問題嗎?

我已經解決了這個問題,但我忘記了重要的事情,無法追蹤自己的轉型。 現在,我將鏈接代碼對可能遇到相同問題的人很有用(如果您不使用Typescript,可以避免鍵入c)

基本上,我使用SVG Matrix方法來跟蹤畫布中發生的情況。

該類通過在畫布中自身存儲由createSVGMatrix()創建的未轉換的canvas(1,0,0,1,0,0)的基本矩陣並通過正在更新的本機SVGMatrix方法跟蹤轉換來了解Canvas轉換的類原始矩陣。 然后,當我需要時,我只使用變換點方法就可以使鼠標后退的正確x,y坐標與矩陣成比例地縮放。

export class Positioning {
static svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
static MatrixTransformationProxy = Positioning.svg.createSVGMatrix();

static transformedPoint(x: number, y: number): SVGPoint {
  let coords = Positioning.svg.createSVGPoint();

  coords.x = x;
  coords.y = y;

  return coords.matrixTransform(Positioning.MatrixTransformationProxy.inverse());
}

static translateProxy(x: number, y: number) {
  Positioning.MatrixTransformationProxy = Positioning.MatrixTransformationProxy.translate(x, y);
}

static scaleUniformProxy(scaleValue: number) {
  Positioning.MatrixTransformationProxy = Positioning.MatrixTransformationProxy.scale(scaleValue);
}

}

我保持使用Proxy方法的包裝器將我的畫布轉換與ProxyMatrix同步,以使用畫布方法調用Canvas方法和相對Positioning方法來像這樣更新MatrixTransformationProxy

export class CanvasMethods {
static getSharedInstance(): CanvasMethods {
  return sharedInstance;
}

private _canvas: HTMLCanvasElement;

getCanvas(): HTMLCanvasElement {
  return this._canvas;
}

getContext(): CanvasRenderingContext2D {
  return this._canvas.getContext('2d');
}

registerCanvas(canvas: HTMLCanvasElement): void {
  this._canvas = canvas;
}

getCanvasBoundingRect(): BoundingRect {
  return new BoundingRect(0, 0, this._canvas.width, this._canvas.height);
}

clear(): void {
  this.getContext().save();
  this.getContext().setTransform(1, 0, 0, 1, 0, 0);
  this.getContext().clearRect(0, 0, this._canvas.width, this._canvas.height);
  this.getContext().restore();
}

scale(direction: ZoomDirection): void {
  let options = { //TODO get this from constructor options
    scaleValueOut: 0.8,
    scaleValueIn: 1.1
  };

  if (direction === ZoomDirection.ZOOM_OUT) {
    Positioning.scaleUniformProxy(options.scaleValueOut);
    this.getContext().scale(options.scaleValueOut, options.scaleValueOut);
  } else if (direction === ZoomDirection.ZOOM_IN) {
    Positioning.scaleUniformProxy(options.scaleValueIn);
    this.getContext().scale(options.scaleValueIn, options.scaleValueIn);
  }
}

translate(x: number, y: number): void {
  Positioning.translateProxy(x, y);
  this.getContext().translate(x, y);
}

}

const sharedInstance = new CanvasMethods(); }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM