2016-07-08 24 views
1

私はapiから受け取ったデータでCanvasを構築していますが、これはすべて問題ありません。私はその次のコード `canvas.addEventListener( 'ホイール'、(イベントとの事実にstuckedだと、とにかく、数日である: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; 
    }) 
}` 

私はノーマルスケールでは右の座標を取得しますが、スケールするとすぐに増分エラーが発生します(基本的に実際のポイントとマウスカーソルの距離はますます大きくなります)。 Matrix私は以下の方法でラッパーとしてSVGメソッドを使用します。 `export class Positioning { static svg = document.createElementNS( 'http://www.w3.org/2000/svg'、 'svg'); private static 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()); 
} 

} `

私は、これは何とかcalingに関係しているが、私は本当にスケーリングのアカウントを取得し、比率を得るために、適切な操作を行う方法を見つけ出すことはできませんことを知っています。私はまた、この回答を確認しましたZoom Canvas to Mouse Cursorかなり正確ですが、実際に彼は私が再調整することができない何らかの方法でそれのアカウントを取得します。他の誰かが同じ問題に直面しましたか?

+0

あなたは正しいアイデアを持っています:すべての変換を[変換行列](http://simonsarris.com/blog/471-a-transformation-class-for-canvas-to-keep-track-変換マトリクスを変換した後、変換された座標と変換されていない座標を変換するためにマトリックスを使用します。 – markE

+0

ええ、私はかなり近くですが、私は困惑の最後の部分を理解できません、あなたは何を意味する変換されたとuntransformedの間で変換する行列を反転することによって?あなたが私のサービスがすでに行列を逆転しているのを見ることができるからです。 –

答えて

2

私はこの問題を解決しました。重要なことを忘れていました。私の変革を追跡しています。今では同じ問題に遭遇する可能性のある人に便利なコードをリンクします(Typescriptを使用していない場合は、cの入力を避けることができます)

基本的に私はSVG Matrixメソッドを使用して、キャンバスで

これは、createSVGMatrix()によって作成された変換されていないキャンバス(1,0,0,1,0,0)の基本Matrixを格納し、ネイティブ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); 
} 

}

Iキャンバス方法及びこの

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); 
} 
ようMatrixTransformationProxyを更新するための相対的な位置決めメソッドを呼び出すキャンバスメソッドのラッパーを使用して私のProxyMatrixに同期して私のキャンバス変換を維持してい

}

const sharedInstance = new CanvasMethods(); }

関連する問題